Commit | Line | Data |
---|---|---|
99db7d0e | 1 | /* $Id: chars.c,v 1.79 2020/02/13 16:18:29 schwarze Exp $ */ |
80387638 | 2 | /* |
36342e81 | 3 | * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> |
99db7d0e SW |
4 | * Copyright (c) 2011, 2014, 2015, 2017, 2018, 2020 |
5 | * Ingo Schwarze <schwarze@openbsd.org> | |
80387638 SW |
6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any | |
8 | * purpose with or without fee is hereby granted, provided that the above | |
9 | * copyright notice and this permission notice appear in all copies. | |
10 | * | |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
18 | */ | |
80387638 | 19 | #include "config.h" |
54ba9607 SW |
20 | |
21 | #include <sys/types.h> | |
80387638 SW |
22 | |
23 | #include <assert.h> | |
a4c7eb57 | 24 | #include <ctype.h> |
54ba9607 SW |
25 | #include <stddef.h> |
26 | #include <stdint.h> | |
27 | #include <stdio.h> | |
80387638 SW |
28 | #include <stdlib.h> |
29 | #include <string.h> | |
30 | ||
31 | #include "mandoc.h" | |
070c62a6 | 32 | #include "mandoc_aux.h" |
54ba9607 | 33 | #include "mandoc_ohash.h" |
a4c7eb57 | 34 | #include "libmandoc.h" |
80387638 | 35 | |
80387638 | 36 | struct ln { |
54ba9607 | 37 | const char roffcode[16]; |
80387638 SW |
38 | const char *ascii; |
39 | int unicode; | |
80387638 SW |
40 | }; |
41 | ||
54ba9607 SW |
42 | /* Special break control characters. */ |
43 | static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' }; | |
44 | static const char ascii_break[2] = { ASCII_BREAK, '\0' }; | |
45 | ||
46 | static struct ln lines[] = { | |
47 | ||
48 | /* Spacing. */ | |
49 | { " ", ascii_nbrsp, 0x00a0 }, | |
50 | { "~", ascii_nbrsp, 0x00a0 }, | |
99db7d0e | 51 | { "0", ascii_nbrsp, 0x00a0 }, |
54ba9607 SW |
52 | { ":", ascii_break, 0 }, |
53 | ||
54 | /* Lines. */ | |
55 | { "ba", "|", 0x007c }, | |
56 | { "br", "|", 0x2502 }, | |
57 | { "ul", "_", 0x005f }, | |
58 | { "_", "_", 0x005f }, | |
59 | { "ru", "_", 0x005f }, | |
60 | { "rn", "-", 0x203e }, | |
61 | { "bb", "|", 0x00a6 }, | |
62 | { "sl", "/", 0x002f }, | |
63 | { "rs", "\\", 0x005c }, | |
64 | ||
65 | /* Text markers. */ | |
66 | { "ci", "O", 0x25cb }, | |
67 | { "bu", "+\bo", 0x2022 }, | |
68 | { "dd", "<**>", 0x2021 }, | |
69 | { "dg", "<*>", 0x2020 }, | |
70 | { "lz", "<>", 0x25ca }, | |
71 | { "sq", "[]", 0x25a1 }, | |
72 | { "ps", "<paragraph>", 0x00b6 }, | |
73 | { "sc", "<section>", 0x00a7 }, | |
74 | { "lh", "<=", 0x261c }, | |
75 | { "rh", "=>", 0x261e }, | |
76 | { "at", "@", 0x0040 }, | |
77 | { "sh", "#", 0x0023 }, | |
78 | { "CR", "<cr>", 0x21b5 }, | |
79 | { "OK", "\\/", 0x2713 }, | |
80 | { "CL", "C", 0x2663 }, | |
81 | { "SP", "S", 0x2660 }, | |
82 | { "HE", "H", 0x2665 }, | |
83 | { "DI", "D", 0x2666 }, | |
84 | ||
85 | /* Legal symbols. */ | |
86 | { "co", "(C)", 0x00a9 }, | |
87 | { "rg", "(R)", 0x00ae }, | |
88 | { "tm", "tm", 0x2122 }, | |
89 | ||
90 | /* Punctuation. */ | |
91 | { "em", "--", 0x2014 }, | |
92 | { "en", "-", 0x2013 }, | |
93 | { "hy", "-", 0x2010 }, | |
94 | { "e", "\\", 0x005c }, | |
95 | { ".", ".", 0x002e }, | |
96 | { "r!", "!", 0x00a1 }, | |
97 | { "r?", "?", 0x00bf }, | |
98 | ||
99 | /* Quotes. */ | |
100 | { "Bq", ",,", 0x201e }, | |
101 | { "bq", ",", 0x201a }, | |
102 | { "lq", "\"", 0x201c }, | |
103 | { "rq", "\"", 0x201d }, | |
104 | { "Lq", "\"", 0x201c }, | |
105 | { "Rq", "\"", 0x201d }, | |
106 | { "oq", "`", 0x2018 }, | |
107 | { "cq", "\'", 0x2019 }, | |
108 | { "aq", "\'", 0x0027 }, | |
109 | { "dq", "\"", 0x0022 }, | |
110 | { "Fo", "<<", 0x00ab }, | |
111 | { "Fc", ">>", 0x00bb }, | |
112 | { "fo", "<", 0x2039 }, | |
113 | { "fc", ">", 0x203a }, | |
114 | ||
115 | /* Brackets. */ | |
116 | { "lB", "[", 0x005b }, | |
117 | { "rB", "]", 0x005d }, | |
118 | { "lC", "{", 0x007b }, | |
119 | { "rC", "}", 0x007d }, | |
120 | { "la", "<", 0x27e8 }, | |
121 | { "ra", ">", 0x27e9 }, | |
122 | { "bv", "|", 0x23aa }, | |
123 | { "braceex", "|", 0x23aa }, | |
124 | { "bracketlefttp", "|", 0x23a1 }, | |
125 | { "bracketleftbt", "|", 0x23a3 }, | |
126 | { "bracketleftex", "|", 0x23a2 }, | |
127 | { "bracketrighttp", "|", 0x23a4 }, | |
128 | { "bracketrightbt", "|", 0x23a6 }, | |
129 | { "bracketrightex", "|", 0x23a5 }, | |
130 | { "lt", ",-", 0x23a7 }, | |
131 | { "bracelefttp", ",-", 0x23a7 }, | |
132 | { "lk", "{", 0x23a8 }, | |
133 | { "braceleftmid", "{", 0x23a8 }, | |
134 | { "lb", "`-", 0x23a9 }, | |
135 | { "braceleftbt", "`-", 0x23a9 }, | |
136 | { "braceleftex", "|", 0x23aa }, | |
137 | { "rt", "-.", 0x23ab }, | |
138 | { "bracerighttp", "-.", 0x23ab }, | |
139 | { "rk", "}", 0x23ac }, | |
140 | { "bracerightmid", "}", 0x23ac }, | |
141 | { "rb", "-\'", 0x23ad }, | |
142 | { "bracerightbt", "-\'", 0x23ad }, | |
143 | { "bracerightex", "|", 0x23aa }, | |
144 | { "parenlefttp", "/", 0x239b }, | |
145 | { "parenleftbt", "\\", 0x239d }, | |
146 | { "parenleftex", "|", 0x239c }, | |
147 | { "parenrighttp", "\\", 0x239e }, | |
148 | { "parenrightbt", "/", 0x23a0 }, | |
149 | { "parenrightex", "|", 0x239f }, | |
150 | ||
151 | /* Arrows and lines. */ | |
152 | { "<-", "<-", 0x2190 }, | |
153 | { "->", "->", 0x2192 }, | |
154 | { "<>", "<->", 0x2194 }, | |
155 | { "da", "|\bv", 0x2193 }, | |
156 | { "ua", "|\b^", 0x2191 }, | |
157 | { "va", "^v", 0x2195 }, | |
158 | { "lA", "<=", 0x21d0 }, | |
159 | { "rA", "=>", 0x21d2 }, | |
160 | { "hA", "<=>", 0x21d4 }, | |
161 | { "uA", "=\b^", 0x21d1 }, | |
162 | { "dA", "=\bv", 0x21d3 }, | |
163 | { "vA", "^=v", 0x21d5 }, | |
164 | { "an", "-", 0x23af }, | |
165 | ||
166 | /* Logic. */ | |
167 | { "AN", "^", 0x2227 }, | |
168 | { "OR", "v", 0x2228 }, | |
169 | { "no", "~", 0x00ac }, | |
170 | { "tno", "~", 0x00ac }, | |
171 | { "te", "<there\037exists>", 0x2203 }, | |
172 | { "fa", "<for\037all>", 0x2200 }, | |
173 | { "st", "<such\037that>", 0x220b }, | |
174 | { "tf", "<therefore>", 0x2234 }, | |
175 | { "3d", "<therefore>", 0x2234 }, | |
176 | { "or", "|", 0x007c }, | |
177 | ||
178 | /* Mathematicals. */ | |
179 | { "pl", "+", 0x002b }, | |
180 | { "mi", "-", 0x2212 }, | |
181 | { "-", "-", 0x002d }, | |
182 | { "-+", "-+", 0x2213 }, | |
183 | { "+-", "+-", 0x00b1 }, | |
184 | { "t+-", "+-", 0x00b1 }, | |
185 | { "pc", ".", 0x00b7 }, | |
186 | { "md", ".", 0x22c5 }, | |
187 | { "mu", "x", 0x00d7 }, | |
188 | { "tmu", "x", 0x00d7 }, | |
189 | { "c*", "O\bx", 0x2297 }, | |
190 | { "c+", "O\b+", 0x2295 }, | |
191 | { "di", "/", 0x00f7 }, | |
192 | { "tdi", "/", 0x00f7 }, | |
193 | { "f/", "/", 0x2044 }, | |
194 | { "**", "*", 0x2217 }, | |
195 | { "<=", "<=", 0x2264 }, | |
196 | { ">=", ">=", 0x2265 }, | |
197 | { "<<", "<<", 0x226a }, | |
198 | { ">>", ">>", 0x226b }, | |
199 | { "eq", "=", 0x003d }, | |
200 | { "!=", "!=", 0x2260 }, | |
201 | { "==", "==", 0x2261 }, | |
202 | { "ne", "!==", 0x2262 }, | |
203 | { "ap", "~", 0x223c }, | |
204 | { "|=", "-~", 0x2243 }, | |
205 | { "=~", "=~", 0x2245 }, | |
206 | { "~~", "~~", 0x2248 }, | |
207 | { "~=", "~=", 0x2248 }, | |
208 | { "pt", "<proportional\037to>", 0x221d }, | |
209 | { "es", "{}", 0x2205 }, | |
210 | { "mo", "<element\037of>", 0x2208 }, | |
211 | { "nm", "<not\037element\037of>", 0x2209 }, | |
212 | { "sb", "<proper\037subset>", 0x2282 }, | |
213 | { "nb", "<not\037subset>", 0x2284 }, | |
214 | { "sp", "<proper\037superset>", 0x2283 }, | |
215 | { "nc", "<not\037superset>", 0x2285 }, | |
216 | { "ib", "<subset\037or\037equal>", 0x2286 }, | |
217 | { "ip", "<superset\037or\037equal>", 0x2287 }, | |
218 | { "ca", "<intersection>", 0x2229 }, | |
219 | { "cu", "<union>", 0x222a }, | |
220 | { "/_", "<angle>", 0x2220 }, | |
221 | { "pp", "<perpendicular>", 0x22a5 }, | |
222 | { "is", "<integral>", 0x222b }, | |
223 | { "integral", "<integral>", 0x222b }, | |
224 | { "sum", "<sum>", 0x2211 }, | |
225 | { "product", "<product>", 0x220f }, | |
226 | { "coproduct", "<coproduct>", 0x2210 }, | |
227 | { "gr", "<nabla>", 0x2207 }, | |
228 | { "sr", "<sqrt>", 0x221a }, | |
229 | { "sqrt", "<sqrt>", 0x221a }, | |
230 | { "lc", "|~", 0x2308 }, | |
231 | { "rc", "~|", 0x2309 }, | |
232 | { "lf", "|_", 0x230a }, | |
233 | { "rf", "_|", 0x230b }, | |
234 | { "if", "<infinity>", 0x221e }, | |
235 | { "Ah", "<Aleph>", 0x2135 }, | |
236 | { "Im", "<Im>", 0x2111 }, | |
237 | { "Re", "<Re>", 0x211c }, | |
238 | { "wp", "p", 0x2118 }, | |
239 | { "pd", "<del>", 0x2202 }, | |
240 | { "-h", "/h", 0x210f }, | |
241 | { "hbar", "/h", 0x210f }, | |
242 | { "12", "1/2", 0x00bd }, | |
243 | { "14", "1/4", 0x00bc }, | |
244 | { "34", "3/4", 0x00be }, | |
245 | { "18", "1/8", 0x215B }, | |
246 | { "38", "3/8", 0x215C }, | |
247 | { "58", "5/8", 0x215D }, | |
248 | { "78", "7/8", 0x215E }, | |
249 | { "S1", "^1", 0x00B9 }, | |
250 | { "S2", "^2", 0x00B2 }, | |
251 | { "S3", "^3", 0x00B3 }, | |
252 | ||
253 | /* Ligatures. */ | |
254 | { "ff", "ff", 0xfb00 }, | |
255 | { "fi", "fi", 0xfb01 }, | |
256 | { "fl", "fl", 0xfb02 }, | |
257 | { "Fi", "ffi", 0xfb03 }, | |
258 | { "Fl", "ffl", 0xfb04 }, | |
259 | { "AE", "AE", 0x00c6 }, | |
260 | { "ae", "ae", 0x00e6 }, | |
261 | { "OE", "OE", 0x0152 }, | |
262 | { "oe", "oe", 0x0153 }, | |
263 | { "ss", "ss", 0x00df }, | |
264 | { "IJ", "IJ", 0x0132 }, | |
265 | { "ij", "ij", 0x0133 }, | |
266 | ||
267 | /* Accents. */ | |
268 | { "a\"", "\"", 0x02dd }, | |
269 | { "a-", "-", 0x00af }, | |
270 | { "a.", ".", 0x02d9 }, | |
271 | { "a^", "^", 0x005e }, | |
272 | { "aa", "\'", 0x00b4 }, | |
273 | { "\'", "\'", 0x00b4 }, | |
274 | { "ga", "`", 0x0060 }, | |
275 | { "`", "`", 0x0060 }, | |
276 | { "ab", "'\b`", 0x02d8 }, | |
277 | { "ac", ",", 0x00b8 }, | |
278 | { "ad", "\"", 0x00a8 }, | |
279 | { "ah", "v", 0x02c7 }, | |
280 | { "ao", "o", 0x02da }, | |
281 | { "a~", "~", 0x007e }, | |
282 | { "ho", ",", 0x02db }, | |
283 | { "ha", "^", 0x005e }, | |
284 | { "ti", "~", 0x007e }, | |
285 | { "u02DC", "~", 0x02dc }, | |
286 | ||
287 | /* Accented letters. */ | |
288 | { "'A", "'\bA", 0x00c1 }, | |
289 | { "'E", "'\bE", 0x00c9 }, | |
290 | { "'I", "'\bI", 0x00cd }, | |
291 | { "'O", "'\bO", 0x00d3 }, | |
292 | { "'U", "'\bU", 0x00da }, | |
293 | { "'Y", "'\bY", 0x00dd }, | |
294 | { "'a", "'\ba", 0x00e1 }, | |
295 | { "'e", "'\be", 0x00e9 }, | |
296 | { "'i", "'\bi", 0x00ed }, | |
297 | { "'o", "'\bo", 0x00f3 }, | |
298 | { "'u", "'\bu", 0x00fa }, | |
299 | { "'y", "'\by", 0x00fd }, | |
300 | { "`A", "`\bA", 0x00c0 }, | |
301 | { "`E", "`\bE", 0x00c8 }, | |
302 | { "`I", "`\bI", 0x00cc }, | |
303 | { "`O", "`\bO", 0x00d2 }, | |
304 | { "`U", "`\bU", 0x00d9 }, | |
305 | { "`a", "`\ba", 0x00e0 }, | |
306 | { "`e", "`\be", 0x00e8 }, | |
307 | { "`i", "`\bi", 0x00ec }, | |
308 | { "`o", "`\bo", 0x00f2 }, | |
309 | { "`u", "`\bu", 0x00f9 }, | |
310 | { "~A", "~\bA", 0x00c3 }, | |
311 | { "~N", "~\bN", 0x00d1 }, | |
312 | { "~O", "~\bO", 0x00d5 }, | |
313 | { "~a", "~\ba", 0x00e3 }, | |
314 | { "~n", "~\bn", 0x00f1 }, | |
315 | { "~o", "~\bo", 0x00f5 }, | |
316 | { ":A", "\"\bA", 0x00c4 }, | |
317 | { ":E", "\"\bE", 0x00cb }, | |
318 | { ":I", "\"\bI", 0x00cf }, | |
319 | { ":O", "\"\bO", 0x00d6 }, | |
320 | { ":U", "\"\bU", 0x00dc }, | |
321 | { ":a", "\"\ba", 0x00e4 }, | |
322 | { ":e", "\"\be", 0x00eb }, | |
323 | { ":i", "\"\bi", 0x00ef }, | |
324 | { ":o", "\"\bo", 0x00f6 }, | |
325 | { ":u", "\"\bu", 0x00fc }, | |
326 | { ":y", "\"\by", 0x00ff }, | |
327 | { "^A", "^\bA", 0x00c2 }, | |
328 | { "^E", "^\bE", 0x00ca }, | |
329 | { "^I", "^\bI", 0x00ce }, | |
330 | { "^O", "^\bO", 0x00d4 }, | |
331 | { "^U", "^\bU", 0x00db }, | |
332 | { "^a", "^\ba", 0x00e2 }, | |
333 | { "^e", "^\be", 0x00ea }, | |
334 | { "^i", "^\bi", 0x00ee }, | |
335 | { "^o", "^\bo", 0x00f4 }, | |
336 | { "^u", "^\bu", 0x00fb }, | |
337 | { ",C", ",\bC", 0x00c7 }, | |
338 | { ",c", ",\bc", 0x00e7 }, | |
339 | { "/L", "/\bL", 0x0141 }, | |
340 | { "/l", "/\bl", 0x0142 }, | |
341 | { "/O", "/\bO", 0x00d8 }, | |
342 | { "/o", "/\bo", 0x00f8 }, | |
343 | { "oA", "o\bA", 0x00c5 }, | |
344 | { "oa", "o\ba", 0x00e5 }, | |
345 | ||
346 | /* Special letters. */ | |
347 | { "-D", "Dh", 0x00d0 }, | |
348 | { "Sd", "dh", 0x00f0 }, | |
349 | { "TP", "Th", 0x00de }, | |
350 | { "Tp", "th", 0x00fe }, | |
351 | { ".i", "i", 0x0131 }, | |
352 | { ".j", "j", 0x0237 }, | |
353 | ||
354 | /* Currency. */ | |
355 | { "Do", "$", 0x0024 }, | |
356 | { "ct", "/\bc", 0x00a2 }, | |
357 | { "Eu", "EUR", 0x20ac }, | |
358 | { "eu", "EUR", 0x20ac }, | |
359 | { "Ye", "=\bY", 0x00a5 }, | |
360 | { "Po", "-\bL", 0x00a3 }, | |
361 | { "Cs", "o\bx", 0x00a4 }, | |
362 | { "Fn", ",\bf", 0x0192 }, | |
363 | ||
364 | /* Units. */ | |
365 | { "de", "<degree>", 0x00b0 }, | |
366 | { "%0", "<permille>", 0x2030 }, | |
367 | { "fm", "\'", 0x2032 }, | |
368 | { "sd", "''", 0x2033 }, | |
369 | { "mc", "<micro>", 0x00b5 }, | |
370 | { "Of", "_\ba", 0x00aa }, | |
371 | { "Om", "_\bo", 0x00ba }, | |
372 | ||
373 | /* Greek characters. */ | |
374 | { "*A", "A", 0x0391 }, | |
375 | { "*B", "B", 0x0392 }, | |
376 | { "*G", "<Gamma>", 0x0393 }, | |
377 | { "*D", "<Delta>", 0x0394 }, | |
378 | { "*E", "E", 0x0395 }, | |
379 | { "*Z", "Z", 0x0396 }, | |
380 | { "*Y", "H", 0x0397 }, | |
381 | { "*H", "<Theta>", 0x0398 }, | |
382 | { "*I", "I", 0x0399 }, | |
383 | { "*K", "K", 0x039a }, | |
384 | { "*L", "<Lambda>", 0x039b }, | |
385 | { "*M", "M", 0x039c }, | |
386 | { "*N", "N", 0x039d }, | |
387 | { "*C", "<Xi>", 0x039e }, | |
388 | { "*O", "O", 0x039f }, | |
389 | { "*P", "<Pi>", 0x03a0 }, | |
390 | { "*R", "P", 0x03a1 }, | |
391 | { "*S", "<Sigma>", 0x03a3 }, | |
392 | { "*T", "T", 0x03a4 }, | |
393 | { "*U", "Y", 0x03a5 }, | |
394 | { "*F", "<Phi>", 0x03a6 }, | |
395 | { "*X", "X", 0x03a7 }, | |
396 | { "*Q", "<Psi>", 0x03a8 }, | |
397 | { "*W", "<Omega>", 0x03a9 }, | |
398 | { "*a", "<alpha>", 0x03b1 }, | |
399 | { "*b", "<beta>", 0x03b2 }, | |
400 | { "*g", "<gamma>", 0x03b3 }, | |
401 | { "*d", "<delta>", 0x03b4 }, | |
402 | { "*e", "<epsilon>", 0x03b5 }, | |
403 | { "*z", "<zeta>", 0x03b6 }, | |
404 | { "*y", "<eta>", 0x03b7 }, | |
405 | { "*h", "<theta>", 0x03b8 }, | |
406 | { "*i", "<iota>", 0x03b9 }, | |
407 | { "*k", "<kappa>", 0x03ba }, | |
408 | { "*l", "<lambda>", 0x03bb }, | |
409 | { "*m", "<mu>", 0x03bc }, | |
410 | { "*n", "<nu>", 0x03bd }, | |
411 | { "*c", "<xi>", 0x03be }, | |
412 | { "*o", "o", 0x03bf }, | |
413 | { "*p", "<pi>", 0x03c0 }, | |
414 | { "*r", "<rho>", 0x03c1 }, | |
415 | { "*s", "<sigma>", 0x03c3 }, | |
416 | { "*t", "<tau>", 0x03c4 }, | |
417 | { "*u", "<upsilon>", 0x03c5 }, | |
418 | { "*f", "<phi>", 0x03d5 }, | |
419 | { "*x", "<chi>", 0x03c7 }, | |
420 | { "*q", "<psi>", 0x03c8 }, | |
421 | { "*w", "<omega>", 0x03c9 }, | |
422 | { "+h", "<theta>", 0x03d1 }, | |
423 | { "+f", "<phi>", 0x03c6 }, | |
424 | { "+p", "<pi>", 0x03d6 }, | |
425 | { "+e", "<epsilon>", 0x03f5 }, | |
426 | { "ts", "<sigma>", 0x03c2 }, | |
80387638 SW |
427 | }; |
428 | ||
54ba9607 | 429 | static struct ohash mchars; |
80387638 | 430 | |
070c62a6 | 431 | |
80387638 | 432 | void |
54ba9607 | 433 | mchars_free(void) |
80387638 | 434 | { |
80387638 | 435 | |
54ba9607 | 436 | ohash_delete(&mchars); |
80387638 SW |
437 | } |
438 | ||
54ba9607 | 439 | void |
a4c7eb57 | 440 | mchars_alloc(void) |
80387638 | 441 | { |
54ba9607 SW |
442 | size_t i; |
443 | unsigned int slot; | |
444 | ||
445 | mandoc_ohash_init(&mchars, 9, offsetof(struct ln, roffcode)); | |
446 | for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++) { | |
447 | slot = ohash_qlookup(&mchars, lines[i].roffcode); | |
448 | assert(ohash_find(&mchars, slot) == NULL); | |
449 | ohash_insert(&mchars, slot, lines + i); | |
80387638 | 450 | } |
80387638 SW |
451 | } |
452 | ||
80387638 | 453 | int |
54ba9607 | 454 | mchars_spec2cp(const char *p, size_t sz) |
80387638 SW |
455 | { |
456 | const struct ln *ln; | |
54ba9607 | 457 | const char *end; |
80387638 | 458 | |
54ba9607 SW |
459 | end = p + sz; |
460 | ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end)); | |
461 | return ln != NULL ? ln->unicode : -1; | |
80387638 SW |
462 | } |
463 | ||
54ba9607 | 464 | int |
a4c7eb57 | 465 | mchars_num2char(const char *p, size_t sz) |
60e1e752 | 466 | { |
070c62a6 | 467 | int i; |
60e1e752 | 468 | |
54ba9607 SW |
469 | i = mandoc_strntoi(p, sz, 10); |
470 | return i >= 0 && i < 256 ? i : -1; | |
60e1e752 SW |
471 | } |
472 | ||
a4c7eb57 SW |
473 | int |
474 | mchars_num2uc(const char *p, size_t sz) | |
80387638 | 475 | { |
070c62a6 | 476 | int i; |
80387638 | 477 | |
54ba9607 SW |
478 | i = mandoc_strntoi(p, sz, 16); |
479 | assert(i >= 0 && i <= 0x10FFFF); | |
480 | return i; | |
80387638 SW |
481 | } |
482 | ||
80387638 | 483 | const char * |
54ba9607 | 484 | mchars_spec2str(const char *p, size_t sz, size_t *rsz) |
80387638 SW |
485 | { |
486 | const struct ln *ln; | |
54ba9607 | 487 | const char *end; |
80387638 | 488 | |
54ba9607 SW |
489 | end = p + sz; |
490 | ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end)); | |
491 | if (ln == NULL) | |
492 | return NULL; | |
80387638 SW |
493 | |
494 | *rsz = strlen(ln->ascii); | |
54ba9607 | 495 | return ln->ascii; |
80387638 SW |
496 | } |
497 | ||
54ba9607 SW |
498 | const char * |
499 | mchars_uc2str(int uc) | |
80387638 | 500 | { |
54ba9607 | 501 | size_t i; |
80387638 | 502 | |
54ba9607 SW |
503 | for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++) |
504 | if (uc == lines[i].unicode) | |
505 | return lines[i].ascii; | |
506 | return "<?>"; | |
80387638 | 507 | } |