GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mandoc/chars.c Lines: 0 25 0.0 %
Date: 2016-12-06 Branches: 0 20 0.0 %

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