xref: /openbsd-src/usr.bin/mandoc/roff.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$Id: roff.c,v 1.94 2014/07/07 21:35:42 schwarze Exp $ */
2 /*
3  * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
4  * Copyright (c) 2010-2014 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 AUTHORS DISCLAIM ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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 <assert.h>
19 #include <ctype.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "mandoc.h"
25 #include "mandoc_aux.h"
26 #include "libroff.h"
27 #include "libmandoc.h"
28 
29 /* Maximum number of nested if-else conditionals. */
30 #define	RSTACK_MAX	128
31 
32 /* Maximum number of string expansions per line, to break infinite loops. */
33 #define	EXPAND_LIMIT	1000
34 
35 enum	rofft {
36 	ROFF_ad,
37 	ROFF_am,
38 	ROFF_ami,
39 	ROFF_am1,
40 	ROFF_as,
41 	ROFF_cc,
42 	ROFF_ce,
43 	ROFF_de,
44 	ROFF_dei,
45 	ROFF_de1,
46 	ROFF_ds,
47 	ROFF_el,
48 	ROFF_fam,
49 	ROFF_hw,
50 	ROFF_hy,
51 	ROFF_ie,
52 	ROFF_if,
53 	ROFF_ig,
54 	ROFF_it,
55 	ROFF_ne,
56 	ROFF_nh,
57 	ROFF_nr,
58 	ROFF_ns,
59 	ROFF_ps,
60 	ROFF_rm,
61 	ROFF_rr,
62 	ROFF_so,
63 	ROFF_ta,
64 	ROFF_tr,
65 	ROFF_Dd,
66 	ROFF_TH,
67 	ROFF_TS,
68 	ROFF_TE,
69 	ROFF_T_,
70 	ROFF_EQ,
71 	ROFF_EN,
72 	ROFF_cblock,
73 	ROFF_USERDEF,
74 	ROFF_MAX
75 };
76 
77 /*
78  * An incredibly-simple string buffer.
79  */
80 struct	roffstr {
81 	char		*p; /* nil-terminated buffer */
82 	size_t		 sz; /* saved strlen(p) */
83 };
84 
85 /*
86  * A key-value roffstr pair as part of a singly-linked list.
87  */
88 struct	roffkv {
89 	struct roffstr	 key;
90 	struct roffstr	 val;
91 	struct roffkv	*next; /* next in list */
92 };
93 
94 /*
95  * A single number register as part of a singly-linked list.
96  */
97 struct	roffreg {
98 	struct roffstr	 key;
99 	int		 val;
100 	struct roffreg	*next;
101 };
102 
103 struct	roff {
104 	struct mparse	*parse; /* parse point */
105 	int		 options; /* parse options */
106 	struct roffnode	*last; /* leaf of stack */
107 	int		 rstack[RSTACK_MAX]; /* stack of !`ie' rules */
108 	char		 control; /* control character */
109 	int		 rstackpos; /* position in rstack */
110 	struct roffreg	*regtab; /* number registers */
111 	struct roffkv	*strtab; /* user-defined strings & macros */
112 	struct roffkv	*xmbtab; /* multi-byte trans table (`tr') */
113 	struct roffstr	*xtab; /* single-byte trans table (`tr') */
114 	const char	*current_string; /* value of last called user macro */
115 	struct tbl_node	*first_tbl; /* first table parsed */
116 	struct tbl_node	*last_tbl; /* last table parsed */
117 	struct tbl_node	*tbl; /* current table being parsed */
118 	struct eqn_node	*last_eqn; /* last equation parsed */
119 	struct eqn_node	*first_eqn; /* first equation parsed */
120 	struct eqn_node	*eqn; /* current equation being parsed */
121 };
122 
123 struct	roffnode {
124 	enum rofft	 tok; /* type of node */
125 	struct roffnode	*parent; /* up one in stack */
126 	int		 line; /* parse line */
127 	int		 col; /* parse col */
128 	char		*name; /* node name, e.g. macro name */
129 	char		*end; /* end-rules: custom token */
130 	int		 endspan; /* end-rules: next-line or infty */
131 	int		 rule; /* current evaluation rule */
132 };
133 
134 #define	ROFF_ARGS	 struct roff *r, /* parse ctx */ \
135 			 enum rofft tok, /* tok of macro */ \
136 			 char **bufp, /* input buffer */ \
137 			 size_t *szp, /* size of input buffer */ \
138 			 int ln, /* parse line */ \
139 			 int ppos, /* original pos in buffer */ \
140 			 int pos, /* current pos in buffer */ \
141 			 int *offs /* reset offset of buffer data */
142 
143 typedef	enum rofferr (*roffproc)(ROFF_ARGS);
144 
145 struct	roffmac {
146 	const char	*name; /* macro name */
147 	roffproc	 proc; /* process new macro */
148 	roffproc	 text; /* process as child text of macro */
149 	roffproc	 sub; /* process as child of macro */
150 	int		 flags;
151 #define	ROFFMAC_STRUCT	(1 << 0) /* always interpret */
152 	struct roffmac	*next;
153 };
154 
155 struct	predef {
156 	const char	*name; /* predefined input name */
157 	const char	*str; /* replacement symbol */
158 };
159 
160 #define	PREDEF(__name, __str) \
161 	{ (__name), (__str) },
162 
163 static	enum rofft	 roffhash_find(const char *, size_t);
164 static	void		 roffhash_init(void);
165 static	void		 roffnode_cleanscope(struct roff *);
166 static	void		 roffnode_pop(struct roff *);
167 static	void		 roffnode_push(struct roff *, enum rofft,
168 				const char *, int, int);
169 static	enum rofferr	 roff_block(ROFF_ARGS);
170 static	enum rofferr	 roff_block_text(ROFF_ARGS);
171 static	enum rofferr	 roff_block_sub(ROFF_ARGS);
172 static	enum rofferr	 roff_cblock(ROFF_ARGS);
173 static	enum rofferr	 roff_cc(ROFF_ARGS);
174 static	void		 roff_ccond(struct roff *, int, int);
175 static	enum rofferr	 roff_cond(ROFF_ARGS);
176 static	enum rofferr	 roff_cond_text(ROFF_ARGS);
177 static	enum rofferr	 roff_cond_sub(ROFF_ARGS);
178 static	enum rofferr	 roff_ds(ROFF_ARGS);
179 static	int		 roff_evalcond(const char *, int *);
180 static	int		 roff_evalnum(const char *, int *, int *, int);
181 static	int		 roff_evalpar(const char *, int *, int *);
182 static	int		 roff_evalstrcond(const char *, int *);
183 static	void		 roff_free1(struct roff *);
184 static	void		 roff_freereg(struct roffreg *);
185 static	void		 roff_freestr(struct roffkv *);
186 static	size_t		 roff_getname(struct roff *, char **, int, int);
187 static	int		 roff_getnum(const char *, int *, int *);
188 static	int		 roff_getop(const char *, int *, char *);
189 static	int		 roff_getregn(const struct roff *,
190 				const char *, size_t);
191 static	int		 roff_getregro(const char *name);
192 static	const char	*roff_getstrn(const struct roff *,
193 				const char *, size_t);
194 static	enum rofferr	 roff_it(ROFF_ARGS);
195 static	enum rofferr	 roff_line_ignore(ROFF_ARGS);
196 static	enum rofferr	 roff_nr(ROFF_ARGS);
197 static	void		 roff_openeqn(struct roff *, const char *,
198 				int, int, const char *);
199 static	enum rofft	 roff_parse(struct roff *, char *, int *,
200 				int, int);
201 static	enum rofferr	 roff_parsetext(char **, size_t *, int, int *);
202 static	enum rofferr	 roff_res(struct roff *,
203 				char **, size_t *, int, int);
204 static	enum rofferr	 roff_rm(ROFF_ARGS);
205 static	enum rofferr	 roff_rr(ROFF_ARGS);
206 static	void		 roff_setstr(struct roff *,
207 				const char *, const char *, int);
208 static	void		 roff_setstrn(struct roffkv **, const char *,
209 				size_t, const char *, size_t, int);
210 static	enum rofferr	 roff_so(ROFF_ARGS);
211 static	enum rofferr	 roff_tr(ROFF_ARGS);
212 static	enum rofferr	 roff_Dd(ROFF_ARGS);
213 static	enum rofferr	 roff_TH(ROFF_ARGS);
214 static	enum rofferr	 roff_TE(ROFF_ARGS);
215 static	enum rofferr	 roff_TS(ROFF_ARGS);
216 static	enum rofferr	 roff_EQ(ROFF_ARGS);
217 static	enum rofferr	 roff_EN(ROFF_ARGS);
218 static	enum rofferr	 roff_T_(ROFF_ARGS);
219 static	enum rofferr	 roff_userdef(ROFF_ARGS);
220 
221 /* See roffhash_find() */
222 
223 #define	ASCII_HI	 126
224 #define	ASCII_LO	 33
225 #define	HASHWIDTH	(ASCII_HI - ASCII_LO + 1)
226 
227 static	struct roffmac	*hash[HASHWIDTH];
228 
229 static	struct roffmac	 roffs[ROFF_MAX] = {
230 	{ "ad", roff_line_ignore, NULL, NULL, 0, NULL },
231 	{ "am", roff_block, roff_block_text, roff_block_sub, 0, NULL },
232 	{ "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL },
233 	{ "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
234 	{ "as", roff_ds, NULL, NULL, 0, NULL },
235 	{ "cc", roff_cc, NULL, NULL, 0, NULL },
236 	{ "ce", roff_line_ignore, NULL, NULL, 0, NULL },
237 	{ "de", roff_block, roff_block_text, roff_block_sub, 0, NULL },
238 	{ "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL },
239 	{ "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
240 	{ "ds", roff_ds, NULL, NULL, 0, NULL },
241 	{ "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
242 	{ "fam", roff_line_ignore, NULL, NULL, 0, NULL },
243 	{ "hw", roff_line_ignore, NULL, NULL, 0, NULL },
244 	{ "hy", roff_line_ignore, NULL, NULL, 0, NULL },
245 	{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
246 	{ "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
247 	{ "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL },
248 	{ "it", roff_it, NULL, NULL, 0, NULL },
249 	{ "ne", roff_line_ignore, NULL, NULL, 0, NULL },
250 	{ "nh", roff_line_ignore, NULL, NULL, 0, NULL },
251 	{ "nr", roff_nr, NULL, NULL, 0, NULL },
252 	{ "ns", roff_line_ignore, NULL, NULL, 0, NULL },
253 	{ "ps", roff_line_ignore, NULL, NULL, 0, NULL },
254 	{ "rm", roff_rm, NULL, NULL, 0, NULL },
255 	{ "rr", roff_rr, NULL, NULL, 0, NULL },
256 	{ "so", roff_so, NULL, NULL, 0, NULL },
257 	{ "ta", roff_line_ignore, NULL, NULL, 0, NULL },
258 	{ "tr", roff_tr, NULL, NULL, 0, NULL },
259 	{ "Dd", roff_Dd, NULL, NULL, 0, NULL },
260 	{ "TH", roff_TH, NULL, NULL, 0, NULL },
261 	{ "TS", roff_TS, NULL, NULL, 0, NULL },
262 	{ "TE", roff_TE, NULL, NULL, 0, NULL },
263 	{ "T&", roff_T_, NULL, NULL, 0, NULL },
264 	{ "EQ", roff_EQ, NULL, NULL, 0, NULL },
265 	{ "EN", roff_EN, NULL, NULL, 0, NULL },
266 	{ ".", roff_cblock, NULL, NULL, 0, NULL },
267 	{ NULL, roff_userdef, NULL, NULL, 0, NULL },
268 };
269 
270 /* not currently implemented: Ds em Eq LP Me PP pp Or Rd Sf SH */
271 const	char *const __mdoc_reserved[] = {
272 	"Ac", "Ad", "An", "Ao", "Ap", "Aq", "Ar", "At",
273 	"Bc", "Bd", "Bf", "Bk", "Bl", "Bo", "Bq",
274 	"Brc", "Bro", "Brq", "Bsx", "Bt", "Bx",
275 	"Cd", "Cm", "Db", "Dc", "Dd", "Dl", "Do", "Dq",
276 	"Dt", "Dv", "Dx", "D1",
277 	"Ec", "Ed", "Ef", "Ek", "El", "Em",
278 	"En", "Eo", "Er", "Es", "Ev", "Ex",
279 	"Fa", "Fc", "Fd", "Fl", "Fn", "Fo", "Fr", "Ft", "Fx",
280 	"Hf", "Ic", "In", "It", "Lb", "Li", "Lk", "Lp",
281 	"Ms", "Mt", "Nd", "Nm", "No", "Ns", "Nx",
282 	"Oc", "Oo", "Op", "Os", "Ot", "Ox",
283 	"Pa", "Pc", "Pf", "Po", "Pp", "Pq",
284 	"Qc", "Ql", "Qo", "Qq", "Re", "Rs", "Rv",
285 	"Sc", "Sh", "Sm", "So", "Sq",
286 	"Ss", "St", "Sx", "Sy",
287 	"Ta", "Tn", "Ud", "Ux", "Va", "Vt", "Xc", "Xo", "Xr",
288 	"%A", "%B", "%C", "%D", "%I", "%J", "%N", "%O",
289 	"%P", "%Q", "%R", "%T", "%U", "%V",
290 	NULL
291 };
292 
293 /* not currently implemented: BT DE DS ME MT PT SY TQ YS */
294 const	char *const __man_reserved[] = {
295 	"AT", "B", "BI", "BR", "DT",
296 	"EE", "EN", "EQ", "EX", "HP", "I", "IB", "IP", "IR",
297 	"LP", "OP", "P", "PD", "PP",
298 	"R", "RB", "RE", "RI", "RS", "SB", "SH", "SM", "SS",
299 	"TE", "TH", "TP", "TS", "T&", "UC", "UE", "UR",
300 	NULL
301 };
302 
303 /* Array of injected predefined strings. */
304 #define	PREDEFS_MAX	 38
305 static	const struct predef predefs[PREDEFS_MAX] = {
306 #include "predefs.in"
307 };
308 
309 /* See roffhash_find() */
310 #define	ROFF_HASH(p)	(p[0] - ASCII_LO)
311 
312 static	int	 roffit_lines;  /* number of lines to delay */
313 static	char	*roffit_macro;  /* nil-terminated macro line */
314 
315 
316 static void
317 roffhash_init(void)
318 {
319 	struct roffmac	 *n;
320 	int		  buc, i;
321 
322 	for (i = 0; i < (int)ROFF_USERDEF; i++) {
323 		assert(roffs[i].name[0] >= ASCII_LO);
324 		assert(roffs[i].name[0] <= ASCII_HI);
325 
326 		buc = ROFF_HASH(roffs[i].name);
327 
328 		if (NULL != (n = hash[buc])) {
329 			for ( ; n->next; n = n->next)
330 				/* Do nothing. */ ;
331 			n->next = &roffs[i];
332 		} else
333 			hash[buc] = &roffs[i];
334 	}
335 }
336 
337 /*
338  * Look up a roff token by its name.  Returns ROFF_MAX if no macro by
339  * the nil-terminated string name could be found.
340  */
341 static enum rofft
342 roffhash_find(const char *p, size_t s)
343 {
344 	int		 buc;
345 	struct roffmac	*n;
346 
347 	/*
348 	 * libroff has an extremely simple hashtable, for the time
349 	 * being, which simply keys on the first character, which must
350 	 * be printable, then walks a chain.  It works well enough until
351 	 * optimised.
352 	 */
353 
354 	if (p[0] < ASCII_LO || p[0] > ASCII_HI)
355 		return(ROFF_MAX);
356 
357 	buc = ROFF_HASH(p);
358 
359 	if (NULL == (n = hash[buc]))
360 		return(ROFF_MAX);
361 	for ( ; n; n = n->next)
362 		if (0 == strncmp(n->name, p, s) && '\0' == n->name[(int)s])
363 			return((enum rofft)(n - roffs));
364 
365 	return(ROFF_MAX);
366 }
367 
368 /*
369  * Pop the current node off of the stack of roff instructions currently
370  * pending.
371  */
372 static void
373 roffnode_pop(struct roff *r)
374 {
375 	struct roffnode	*p;
376 
377 	assert(r->last);
378 	p = r->last;
379 
380 	r->last = r->last->parent;
381 	free(p->name);
382 	free(p->end);
383 	free(p);
384 }
385 
386 /*
387  * Push a roff node onto the instruction stack.  This must later be
388  * removed with roffnode_pop().
389  */
390 static void
391 roffnode_push(struct roff *r, enum rofft tok, const char *name,
392 		int line, int col)
393 {
394 	struct roffnode	*p;
395 
396 	p = mandoc_calloc(1, sizeof(struct roffnode));
397 	p->tok = tok;
398 	if (name)
399 		p->name = mandoc_strdup(name);
400 	p->parent = r->last;
401 	p->line = line;
402 	p->col = col;
403 	p->rule = p->parent ? p->parent->rule : 0;
404 
405 	r->last = p;
406 }
407 
408 static void
409 roff_free1(struct roff *r)
410 {
411 	struct tbl_node	*tbl;
412 	struct eqn_node	*e;
413 	int		 i;
414 
415 	while (NULL != (tbl = r->first_tbl)) {
416 		r->first_tbl = tbl->next;
417 		tbl_free(tbl);
418 	}
419 
420 	r->first_tbl = r->last_tbl = r->tbl = NULL;
421 
422 	while (NULL != (e = r->first_eqn)) {
423 		r->first_eqn = e->next;
424 		eqn_free(e);
425 	}
426 
427 	r->first_eqn = r->last_eqn = r->eqn = NULL;
428 
429 	while (r->last)
430 		roffnode_pop(r);
431 
432 	roff_freestr(r->strtab);
433 	roff_freestr(r->xmbtab);
434 
435 	r->strtab = r->xmbtab = NULL;
436 
437 	roff_freereg(r->regtab);
438 
439 	r->regtab = NULL;
440 
441 	if (r->xtab)
442 		for (i = 0; i < 128; i++)
443 			free(r->xtab[i].p);
444 
445 	free(r->xtab);
446 	r->xtab = NULL;
447 }
448 
449 void
450 roff_reset(struct roff *r)
451 {
452 
453 	roff_free1(r);
454 	r->control = 0;
455 }
456 
457 void
458 roff_free(struct roff *r)
459 {
460 
461 	roff_free1(r);
462 	free(r);
463 }
464 
465 struct roff *
466 roff_alloc(struct mparse *parse, int options)
467 {
468 	struct roff	*r;
469 
470 	r = mandoc_calloc(1, sizeof(struct roff));
471 	r->parse = parse;
472 	r->options = options;
473 	r->rstackpos = -1;
474 
475 	roffhash_init();
476 
477 	return(r);
478 }
479 
480 /*
481  * In the current line, expand escape sequences that tend to get
482  * used in numerical expressions and conditional requests.
483  * Also check the syntax of the remaining escape sequences.
484  */
485 static enum rofferr
486 roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
487 {
488 	char		 ubuf[24]; /* buffer to print the number */
489 	const char	*start;	/* start of the string to process */
490 	char		*stesc;	/* start of an escape sequence ('\\') */
491 	const char	*stnam;	/* start of the name, after "[(*" */
492 	const char	*cp;	/* end of the name, e.g. before ']' */
493 	const char	*res;	/* the string to be substituted */
494 	char		*nbuf;	/* new buffer to copy bufp to */
495 	size_t		 maxl;  /* expected length of the escape name */
496 	size_t		 naml;	/* actual length of the escape name */
497 	int		 expand_count;	/* to avoid infinite loops */
498 	int		 npos;	/* position in numeric expression */
499 	int		 arg_complete; /* argument not interrupted by eol */
500 	char		 term;	/* character terminating the escape */
501 
502 	expand_count = 0;
503 	start = *bufp + pos;
504 	stesc = strchr(start, '\0') - 1;
505 	while (stesc-- > start) {
506 
507 		/* Search backwards for the next backslash. */
508 
509 		if ('\\' != *stesc)
510 			continue;
511 
512 		/* If it is escaped, skip it. */
513 
514 		for (cp = stesc - 1; cp >= start; cp--)
515 			if ('\\' != *cp)
516 				break;
517 
518 		if (0 == (stesc - cp) % 2) {
519 			stesc = (char *)cp;
520 			continue;
521 		}
522 
523 		/* Decide whether to expand or to check only. */
524 
525 		term = '\0';
526 		cp = stesc + 1;
527 		switch (*cp) {
528 		case '*':
529 			res = NULL;
530 			break;
531 		case 'B':
532 			/* FALLTHROUGH */
533 		case 'w':
534 			term = cp[1];
535 			/* FALLTHROUGH */
536 		case 'n':
537 			res = ubuf;
538 			break;
539 		default:
540 			if (ESCAPE_ERROR == mandoc_escape(&cp, NULL, NULL))
541 				mandoc_vmsg(MANDOCERR_ESC_BAD,
542 				    r->parse, ln, (int)(stesc - *bufp),
543 				    "%.*s", (int)(cp - stesc), stesc);
544 			continue;
545 		}
546 
547 		if (EXPAND_LIMIT < ++expand_count) {
548 			mandoc_msg(MANDOCERR_ROFFLOOP, r->parse,
549 			    ln, (int)(stesc - *bufp), NULL);
550 			return(ROFF_IGN);
551 		}
552 
553 		/*
554 		 * The third character decides the length
555 		 * of the name of the string or register.
556 		 * Save a pointer to the name.
557 		 */
558 
559 		if ('\0' == term) {
560 			switch (*++cp) {
561 			case '\0':
562 				maxl = 0;
563 				break;
564 			case '(':
565 				cp++;
566 				maxl = 2;
567 				break;
568 			case '[':
569 				cp++;
570 				term = ']';
571 				maxl = 0;
572 				break;
573 			default:
574 				maxl = 1;
575 				break;
576 			}
577 		} else {
578 			cp += 2;
579 			maxl = 0;
580 		}
581 		stnam = cp;
582 
583 		/* Advance to the end of the name. */
584 
585 		arg_complete = 1;
586 		for (naml = 0; 0 == maxl || naml < maxl; naml++, cp++) {
587 			if ('\0' == *cp) {
588 				mandoc_msg(MANDOCERR_ESC_BAD, r->parse,
589 				    ln, (int)(stesc - *bufp), stesc);
590 				arg_complete = 0;
591 				break;
592 			}
593 			if (0 == maxl && *cp == term) {
594 				cp++;
595 				break;
596 			}
597 		}
598 
599 		/*
600 		 * Retrieve the replacement string; if it is
601 		 * undefined, resume searching for escapes.
602 		 */
603 
604 		switch (stesc[1]) {
605 		case '*':
606 			if (arg_complete)
607 				res = roff_getstrn(r, stnam, naml);
608 			break;
609 		case 'B':
610 			npos = 0;
611 			ubuf[0] = arg_complete &&
612 			    roff_evalnum(stnam, &npos, NULL, 0) &&
613 			    stnam + npos + 1 == cp ? '1' : '0';
614 			ubuf[1] = '\0';
615 			break;
616 		case 'n':
617 			if (arg_complete)
618 				(void)snprintf(ubuf, sizeof(ubuf), "%d",
619 				    roff_getregn(r, stnam, naml));
620 			else
621 				ubuf[0] = '\0';
622 			break;
623 		case 'w':
624 			/* use even incomplete args */
625 			(void)snprintf(ubuf, sizeof(ubuf), "%d",
626 			    24 * (int)naml);
627 			break;
628 		}
629 
630 		if (NULL == res) {
631 			mandoc_vmsg(MANDOCERR_STR_UNDEF,
632 			    r->parse, ln, (int)(stesc - *bufp),
633 			    "%.*s", (int)naml, stnam);
634 			res = "";
635 		}
636 
637 		/* Replace the escape sequence by the string. */
638 
639 		*stesc = '\0';
640 		*szp = mandoc_asprintf(&nbuf, "%s%s%s",
641 		    *bufp, res, cp) + 1;
642 
643 		/* Prepare for the next replacement. */
644 
645 		start = nbuf + pos;
646 		stesc = nbuf + (stesc - *bufp) + strlen(res);
647 		free(*bufp);
648 		*bufp = nbuf;
649 	}
650 	return(ROFF_CONT);
651 }
652 
653 /*
654  * Process text streams:
655  * Convert all breakable hyphens into ASCII_HYPH.
656  * Decrement and spring input line trap.
657  */
658 static enum rofferr
659 roff_parsetext(char **bufp, size_t *szp, int pos, int *offs)
660 {
661 	size_t		 sz;
662 	const char	*start;
663 	char		*p;
664 	int		 isz;
665 	enum mandoc_esc	 esc;
666 
667 	start = p = *bufp + pos;
668 
669 	while ('\0' != *p) {
670 		sz = strcspn(p, "-\\");
671 		p += sz;
672 
673 		if ('\0' == *p)
674 			break;
675 
676 		if ('\\' == *p) {
677 			/* Skip over escapes. */
678 			p++;
679 			esc = mandoc_escape((const char **)&p, NULL, NULL);
680 			if (ESCAPE_ERROR == esc)
681 				break;
682 			continue;
683 		} else if (p == start) {
684 			p++;
685 			continue;
686 		}
687 
688 		if (isalpha((unsigned char)p[-1]) &&
689 		    isalpha((unsigned char)p[1]))
690 			*p = ASCII_HYPH;
691 		p++;
692 	}
693 
694 	/* Spring the input line trap. */
695 	if (1 == roffit_lines) {
696 		isz = mandoc_asprintf(&p, "%s\n.%s", *bufp, roffit_macro);
697 		free(*bufp);
698 		*bufp = p;
699 		*szp = isz + 1;
700 		*offs = 0;
701 		free(roffit_macro);
702 		roffit_lines = 0;
703 		return(ROFF_REPARSE);
704 	} else if (1 < roffit_lines)
705 		--roffit_lines;
706 	return(ROFF_CONT);
707 }
708 
709 enum rofferr
710 roff_parseln(struct roff *r, int ln, char **bufp,
711 		size_t *szp, int pos, int *offs)
712 {
713 	enum rofft	 t;
714 	enum rofferr	 e;
715 	int		 ppos, ctl;
716 
717 	/*
718 	 * Run the reserved-word filter only if we have some reserved
719 	 * words to fill in.
720 	 */
721 
722 	e = roff_res(r, bufp, szp, ln, pos);
723 	if (ROFF_IGN == e)
724 		return(e);
725 	assert(ROFF_CONT == e);
726 
727 	ppos = pos;
728 	ctl = roff_getcontrol(r, *bufp, &pos);
729 
730 	/*
731 	 * First, if a scope is open and we're not a macro, pass the
732 	 * text through the macro's filter.  If a scope isn't open and
733 	 * we're not a macro, just let it through.
734 	 * Finally, if there's an equation scope open, divert it into it
735 	 * no matter our state.
736 	 */
737 
738 	if (r->last && ! ctl) {
739 		t = r->last->tok;
740 		assert(roffs[t].text);
741 		e = (*roffs[t].text)(r, t, bufp, szp, ln, pos, pos, offs);
742 		assert(ROFF_IGN == e || ROFF_CONT == e);
743 		if (ROFF_CONT != e)
744 			return(e);
745 	}
746 	if (r->eqn)
747 		return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
748 	if ( ! ctl) {
749 		if (r->tbl)
750 			return(tbl_read(r->tbl, ln, *bufp, pos));
751 		return(roff_parsetext(bufp, szp, pos, offs));
752 	}
753 
754 	/*
755 	 * If a scope is open, go to the child handler for that macro,
756 	 * as it may want to preprocess before doing anything with it.
757 	 * Don't do so if an equation is open.
758 	 */
759 
760 	if (r->last) {
761 		t = r->last->tok;
762 		assert(roffs[t].sub);
763 		return((*roffs[t].sub)(r, t, bufp, szp,
764 		    ln, ppos, pos, offs));
765 	}
766 
767 	/*
768 	 * Lastly, as we've no scope open, try to look up and execute
769 	 * the new macro.  If no macro is found, simply return and let
770 	 * the compilers handle it.
771 	 */
772 
773 	if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos, ln, ppos)))
774 		return(ROFF_CONT);
775 
776 	assert(roffs[t].proc);
777 	return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs));
778 }
779 
780 void
781 roff_endparse(struct roff *r)
782 {
783 
784 	if (r->last)
785 		mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,
786 		    r->last->line, r->last->col,
787 		    roffs[r->last->tok].name);
788 
789 	if (r->eqn) {
790 		mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,
791 		    r->eqn->eqn.ln, r->eqn->eqn.pos, "EQ");
792 		eqn_end(&r->eqn);
793 	}
794 
795 	if (r->tbl) {
796 		mandoc_msg(MANDOCERR_BLK_NOEND, r->parse,
797 		    r->tbl->line, r->tbl->pos, "TS");
798 		tbl_end(&r->tbl);
799 	}
800 }
801 
802 /*
803  * Parse a roff node's type from the input buffer.  This must be in the
804  * form of ".foo xxx" in the usual way.
805  */
806 static enum rofft
807 roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos)
808 {
809 	char		*cp;
810 	const char	*mac;
811 	size_t		 maclen;
812 	enum rofft	 t;
813 
814 	cp = buf + *pos;
815 
816 	if ('\0' == *cp || '"' == *cp || '\t' == *cp || ' ' == *cp)
817 		return(ROFF_MAX);
818 
819 	mac = cp;
820 	maclen = roff_getname(r, &cp, ln, ppos);
821 
822 	t = (r->current_string = roff_getstrn(r, mac, maclen))
823 	    ? ROFF_USERDEF : roffhash_find(mac, maclen);
824 
825 	if (ROFF_MAX != t)
826 		*pos = cp - buf;
827 
828 	return(t);
829 }
830 
831 static enum rofferr
832 roff_cblock(ROFF_ARGS)
833 {
834 
835 	/*
836 	 * A block-close `..' should only be invoked as a child of an
837 	 * ignore macro, otherwise raise a warning and just ignore it.
838 	 */
839 
840 	if (NULL == r->last) {
841 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
842 		    ln, ppos, "..");
843 		return(ROFF_IGN);
844 	}
845 
846 	switch (r->last->tok) {
847 	case ROFF_am:
848 		/* ROFF_am1 is remapped to ROFF_am in roff_block(). */
849 		/* FALLTHROUGH */
850 	case ROFF_ami:
851 		/* FALLTHROUGH */
852 	case ROFF_de:
853 		/* ROFF_de1 is remapped to ROFF_de in roff_block(). */
854 		/* FALLTHROUGH */
855 	case ROFF_dei:
856 		/* FALLTHROUGH */
857 	case ROFF_ig:
858 		break;
859 	default:
860 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
861 		    ln, ppos, "..");
862 		return(ROFF_IGN);
863 	}
864 
865 	if ((*bufp)[pos])
866 		mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos,
867 		    ".. %s", *bufp + pos);
868 
869 	roffnode_pop(r);
870 	roffnode_cleanscope(r);
871 	return(ROFF_IGN);
872 
873 }
874 
875 static void
876 roffnode_cleanscope(struct roff *r)
877 {
878 
879 	while (r->last) {
880 		if (--r->last->endspan != 0)
881 			break;
882 		roffnode_pop(r);
883 	}
884 }
885 
886 static void
887 roff_ccond(struct roff *r, int ln, int ppos)
888 {
889 
890 	if (NULL == r->last) {
891 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
892 		    ln, ppos, "\\}");
893 		return;
894 	}
895 
896 	switch (r->last->tok) {
897 	case ROFF_el:
898 		/* FALLTHROUGH */
899 	case ROFF_ie:
900 		/* FALLTHROUGH */
901 	case ROFF_if:
902 		break;
903 	default:
904 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
905 		    ln, ppos, "\\}");
906 		return;
907 	}
908 
909 	if (r->last->endspan > -1) {
910 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
911 		    ln, ppos, "\\}");
912 		return;
913 	}
914 
915 	roffnode_pop(r);
916 	roffnode_cleanscope(r);
917 	return;
918 }
919 
920 static enum rofferr
921 roff_block(ROFF_ARGS)
922 {
923 	const char	*name;
924 	char		*iname, *cp;
925 	size_t		 namesz;
926 
927 	/* Ignore groff compatibility mode for now. */
928 
929 	if (ROFF_de1 == tok)
930 		tok = ROFF_de;
931 	else if (ROFF_am1 == tok)
932 		tok = ROFF_am;
933 
934 	/* Parse the macro name argument. */
935 
936 	cp = *bufp + pos;
937 	if (ROFF_ig == tok) {
938 		iname = NULL;
939 		namesz = 0;
940 	} else {
941 		iname = cp;
942 		namesz = roff_getname(r, &cp, ln, ppos);
943 		iname[namesz] = '\0';
944 	}
945 
946 	/* Resolve the macro name argument if it is indirect. */
947 
948 	if (namesz && (ROFF_dei == tok || ROFF_ami == tok)) {
949 		if (NULL == (name = roff_getstrn(r, iname, namesz))) {
950 			mandoc_vmsg(MANDOCERR_STR_UNDEF,
951 			    r->parse, ln, (int)(iname - *bufp),
952 			    "%.*s", (int)namesz, iname);
953 			namesz = 0;
954 		} else
955 			namesz = strlen(name);
956 	} else
957 		name = iname;
958 
959 	if (0 == namesz && ROFF_ig != tok) {
960 		mandoc_msg(MANDOCERR_REQ_EMPTY, r->parse,
961 		    ln, ppos, roffs[tok].name);
962 		return(ROFF_IGN);
963 	}
964 
965 	roffnode_push(r, tok, name, ln, ppos);
966 
967 	/*
968 	 * At the beginning of a `de' macro, clear the existing string
969 	 * with the same name, if there is one.  New content will be
970 	 * appended from roff_block_text() in multiline mode.
971 	 */
972 
973 	if (ROFF_de == tok || ROFF_dei == tok)
974 		roff_setstrn(&r->strtab, name, namesz, "", 0, 0);
975 
976 	if ('\0' == *cp)
977 		return(ROFF_IGN);
978 
979 	/* Get the custom end marker. */
980 
981 	iname = cp;
982 	namesz = roff_getname(r, &cp, ln, ppos);
983 
984 	/* Resolve the end marker if it is indirect. */
985 
986 	if (namesz && (ROFF_dei == tok || ROFF_ami == tok)) {
987 		if (NULL == (name = roff_getstrn(r, iname, namesz))) {
988 			mandoc_vmsg(MANDOCERR_STR_UNDEF,
989 			    r->parse, ln, (int)(iname - *bufp),
990 			    "%.*s", (int)namesz, iname);
991 			namesz = 0;
992 		} else
993 			namesz = strlen(name);
994 	} else
995 		name = iname;
996 
997 	if (namesz)
998 		r->last->end = mandoc_strndup(name, namesz);
999 
1000 	if ('\0' != *cp)
1001 		mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse,
1002 		    ln, pos, ".%s ... %s", roffs[tok].name, cp);
1003 
1004 	return(ROFF_IGN);
1005 }
1006 
1007 static enum rofferr
1008 roff_block_sub(ROFF_ARGS)
1009 {
1010 	enum rofft	t;
1011 	int		i, j;
1012 
1013 	/*
1014 	 * First check whether a custom macro exists at this level.  If
1015 	 * it does, then check against it.  This is some of groff's
1016 	 * stranger behaviours.  If we encountered a custom end-scope
1017 	 * tag and that tag also happens to be a "real" macro, then we
1018 	 * need to try interpreting it again as a real macro.  If it's
1019 	 * not, then return ignore.  Else continue.
1020 	 */
1021 
1022 	if (r->last->end) {
1023 		for (i = pos, j = 0; r->last->end[j]; j++, i++)
1024 			if ((*bufp)[i] != r->last->end[j])
1025 				break;
1026 
1027 		if ('\0' == r->last->end[j] &&
1028 		    ('\0' == (*bufp)[i] ||
1029 		     ' '  == (*bufp)[i] ||
1030 		     '\t' == (*bufp)[i])) {
1031 			roffnode_pop(r);
1032 			roffnode_cleanscope(r);
1033 
1034 			while (' ' == (*bufp)[i] || '\t' == (*bufp)[i])
1035 				i++;
1036 
1037 			pos = i;
1038 			if (ROFF_MAX != roff_parse(r, *bufp, &pos, ln, ppos))
1039 				return(ROFF_RERUN);
1040 			return(ROFF_IGN);
1041 		}
1042 	}
1043 
1044 	/*
1045 	 * If we have no custom end-query or lookup failed, then try
1046 	 * pulling it out of the hashtable.
1047 	 */
1048 
1049 	t = roff_parse(r, *bufp, &pos, ln, ppos);
1050 
1051 	if (ROFF_cblock != t) {
1052 		if (ROFF_ig != tok)
1053 			roff_setstr(r, r->last->name, *bufp + ppos, 2);
1054 		return(ROFF_IGN);
1055 	}
1056 
1057 	assert(roffs[t].proc);
1058 	return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs));
1059 }
1060 
1061 static enum rofferr
1062 roff_block_text(ROFF_ARGS)
1063 {
1064 
1065 	if (ROFF_ig != tok)
1066 		roff_setstr(r, r->last->name, *bufp + pos, 2);
1067 
1068 	return(ROFF_IGN);
1069 }
1070 
1071 static enum rofferr
1072 roff_cond_sub(ROFF_ARGS)
1073 {
1074 	enum rofft	 t;
1075 	char		*ep;
1076 	int		 rr;
1077 
1078 	rr = r->last->rule;
1079 	roffnode_cleanscope(r);
1080 	t = roff_parse(r, *bufp, &pos, ln, ppos);
1081 
1082 	/*
1083 	 * Fully handle known macros when they are structurally
1084 	 * required or when the conditional evaluated to true.
1085 	 */
1086 
1087 	if ((ROFF_MAX != t) &&
1088 	    (rr || ROFFMAC_STRUCT & roffs[t].flags)) {
1089 		assert(roffs[t].proc);
1090 		return((*roffs[t].proc)(r, t, bufp, szp,
1091 		    ln, ppos, pos, offs));
1092 	}
1093 
1094 	/*
1095 	 * If `\}' occurs on a macro line without a preceding macro,
1096 	 * drop the line completely.
1097 	 */
1098 
1099 	ep = *bufp + pos;
1100 	if ('\\' == ep[0] && '}' == ep[1])
1101 		rr = 0;
1102 
1103 	/* Always check for the closing delimiter `\}'. */
1104 
1105 	while (NULL != (ep = strchr(ep, '\\'))) {
1106 		if ('}' == *(++ep)) {
1107 			*ep = '&';
1108 			roff_ccond(r, ln, ep - *bufp - 1);
1109 		}
1110 		++ep;
1111 	}
1112 	return(rr ? ROFF_CONT : ROFF_IGN);
1113 }
1114 
1115 static enum rofferr
1116 roff_cond_text(ROFF_ARGS)
1117 {
1118 	char		*ep;
1119 	int		 rr;
1120 
1121 	rr = r->last->rule;
1122 	roffnode_cleanscope(r);
1123 
1124 	ep = *bufp + pos;
1125 	while (NULL != (ep = strchr(ep, '\\'))) {
1126 		if ('}' == *(++ep)) {
1127 			*ep = '&';
1128 			roff_ccond(r, ln, ep - *bufp - 1);
1129 		}
1130 		++ep;
1131 	}
1132 	return(rr ? ROFF_CONT : ROFF_IGN);
1133 }
1134 
1135 /*
1136  * Parse a single signed integer number.  Stop at the first non-digit.
1137  * If there is at least one digit, return success and advance the
1138  * parse point, else return failure and let the parse point unchanged.
1139  * Ignore overflows, treat them just like the C language.
1140  */
1141 static int
1142 roff_getnum(const char *v, int *pos, int *res)
1143 {
1144 	int	 myres, n, p;
1145 
1146 	if (NULL == res)
1147 		res = &myres;
1148 
1149 	p = *pos;
1150 	n = v[p] == '-';
1151 	if (n)
1152 		p++;
1153 
1154 	for (*res = 0; isdigit((unsigned char)v[p]); p++)
1155 		*res = 10 * *res + v[p] - '0';
1156 	if (p == *pos + n)
1157 		return 0;
1158 
1159 	if (n)
1160 		*res = -*res;
1161 
1162 	*pos = p;
1163 	return 1;
1164 }
1165 
1166 /*
1167  * Evaluate a string comparison condition.
1168  * The first character is the delimiter.
1169  * Succeed if the string up to its second occurrence
1170  * matches the string up to its third occurence.
1171  * Advance the cursor after the third occurrence
1172  * or lacking that, to the end of the line.
1173  */
1174 static int
1175 roff_evalstrcond(const char *v, int *pos)
1176 {
1177 	const char	*s1, *s2, *s3;
1178 	int		 match;
1179 
1180 	match = 0;
1181 	s1 = v + *pos;		/* initial delimiter */
1182 	s2 = s1 + 1;		/* for scanning the first string */
1183 	s3 = strchr(s2, *s1);	/* for scanning the second string */
1184 
1185 	if (NULL == s3)		/* found no middle delimiter */
1186 		goto out;
1187 
1188 	while ('\0' != *++s3) {
1189 		if (*s2 != *s3) {  /* mismatch */
1190 			s3 = strchr(s3, *s1);
1191 			break;
1192 		}
1193 		if (*s3 == *s1) {  /* found the final delimiter */
1194 			match = 1;
1195 			break;
1196 		}
1197 		s2++;
1198 	}
1199 
1200 out:
1201 	if (NULL == s3)
1202 		s3 = strchr(s2, '\0');
1203 	else
1204 		s3++;
1205 	*pos = s3 - v;
1206 	return(match);
1207 }
1208 
1209 /*
1210  * Evaluate an optionally negated single character, numerical,
1211  * or string condition.
1212  */
1213 static int
1214 roff_evalcond(const char *v, int *pos)
1215 {
1216 	int	 wanttrue, number;
1217 
1218 	if ('!' == v[*pos]) {
1219 		wanttrue = 0;
1220 		(*pos)++;
1221 	} else
1222 		wanttrue = 1;
1223 
1224 	switch (v[*pos]) {
1225 	case 'n':
1226 		/* FALLTHROUGH */
1227 	case 'o':
1228 		(*pos)++;
1229 		return(wanttrue);
1230 	case 'c':
1231 		/* FALLTHROUGH */
1232 	case 'd':
1233 		/* FALLTHROUGH */
1234 	case 'e':
1235 		/* FALLTHROUGH */
1236 	case 'r':
1237 		/* FALLTHROUGH */
1238 	case 't':
1239 		(*pos)++;
1240 		return(!wanttrue);
1241 	default:
1242 		break;
1243 	}
1244 
1245 	if (roff_evalnum(v, pos, &number, 0))
1246 		return((number > 0) == wanttrue);
1247 	else
1248 		return(roff_evalstrcond(v, pos) == wanttrue);
1249 }
1250 
1251 static enum rofferr
1252 roff_line_ignore(ROFF_ARGS)
1253 {
1254 
1255 	return(ROFF_IGN);
1256 }
1257 
1258 static enum rofferr
1259 roff_cond(ROFF_ARGS)
1260 {
1261 
1262 	roffnode_push(r, tok, NULL, ln, ppos);
1263 
1264 	/*
1265 	 * An `.el' has no conditional body: it will consume the value
1266 	 * of the current rstack entry set in prior `ie' calls or
1267 	 * defaults to DENY.
1268 	 *
1269 	 * If we're not an `el', however, then evaluate the conditional.
1270 	 */
1271 
1272 	r->last->rule = ROFF_el == tok ?
1273 	    (r->rstackpos < 0 ? 0 : r->rstack[r->rstackpos--]) :
1274 	    roff_evalcond(*bufp, &pos);
1275 
1276 	/*
1277 	 * An if-else will put the NEGATION of the current evaluated
1278 	 * conditional into the stack of rules.
1279 	 */
1280 
1281 	if (ROFF_ie == tok) {
1282 		if (r->rstackpos == RSTACK_MAX - 1) {
1283 			mandoc_msg(MANDOCERR_MEM,
1284 			    r->parse, ln, ppos, NULL);
1285 			return(ROFF_ERR);
1286 		}
1287 		r->rstack[++r->rstackpos] = !r->last->rule;
1288 	}
1289 
1290 	/* If the parent has false as its rule, then so do we. */
1291 
1292 	if (r->last->parent && !r->last->parent->rule)
1293 		r->last->rule = 0;
1294 
1295 	/*
1296 	 * Determine scope.
1297 	 * If there is nothing on the line after the conditional,
1298 	 * not even whitespace, use next-line scope.
1299 	 */
1300 
1301 	if ('\0' == (*bufp)[pos]) {
1302 		r->last->endspan = 2;
1303 		goto out;
1304 	}
1305 
1306 	while (' ' == (*bufp)[pos])
1307 		pos++;
1308 
1309 	/* An opening brace requests multiline scope. */
1310 
1311 	if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) {
1312 		r->last->endspan = -1;
1313 		pos += 2;
1314 		goto out;
1315 	}
1316 
1317 	/*
1318 	 * Anything else following the conditional causes
1319 	 * single-line scope.  Warn if the scope contains
1320 	 * nothing but trailing whitespace.
1321 	 */
1322 
1323 	if ('\0' == (*bufp)[pos])
1324 		mandoc_msg(MANDOCERR_COND_EMPTY, r->parse,
1325 		    ln, ppos, roffs[tok].name);
1326 
1327 	r->last->endspan = 1;
1328 
1329 out:
1330 	*offs = pos;
1331 	return(ROFF_RERUN);
1332 }
1333 
1334 static enum rofferr
1335 roff_ds(ROFF_ARGS)
1336 {
1337 	char		*string;
1338 	const char	*name;
1339 	size_t		 namesz;
1340 
1341 	/*
1342 	 * The first word is the name of the string.
1343 	 * If it is empty or terminated by an escape sequence,
1344 	 * abort the `ds' request without defining anything.
1345 	 */
1346 
1347 	name = string = *bufp + pos;
1348 	if ('\0' == *name)
1349 		return(ROFF_IGN);
1350 
1351 	namesz = roff_getname(r, &string, ln, pos);
1352 	if ('\\' == name[namesz])
1353 		return(ROFF_IGN);
1354 
1355 	/* Read past the initial double-quote, if any. */
1356 	if ('"' == *string)
1357 		string++;
1358 
1359 	/* The rest is the value. */
1360 	roff_setstrn(&r->strtab, name, namesz, string, strlen(string),
1361 	    ROFF_as == tok);
1362 	return(ROFF_IGN);
1363 }
1364 
1365 /*
1366  * Parse a single operator, one or two characters long.
1367  * If the operator is recognized, return success and advance the
1368  * parse point, else return failure and let the parse point unchanged.
1369  */
1370 static int
1371 roff_getop(const char *v, int *pos, char *res)
1372 {
1373 
1374 	*res = v[*pos];
1375 
1376 	switch (*res) {
1377 	case '+':
1378 		/* FALLTHROUGH */
1379 	case '-':
1380 		/* FALLTHROUGH */
1381 	case '*':
1382 		/* FALLTHROUGH */
1383 	case '/':
1384 		/* FALLTHROUGH */
1385 	case '%':
1386 		/* FALLTHROUGH */
1387 	case '&':
1388 		/* FALLTHROUGH */
1389 	case ':':
1390 		break;
1391 	case '<':
1392 		switch (v[*pos + 1]) {
1393 		case '=':
1394 			*res = 'l';
1395 			(*pos)++;
1396 			break;
1397 		case '>':
1398 			*res = '!';
1399 			(*pos)++;
1400 			break;
1401 		case '?':
1402 			*res = 'i';
1403 			(*pos)++;
1404 			break;
1405 		default:
1406 			break;
1407 		}
1408 		break;
1409 	case '>':
1410 		switch (v[*pos + 1]) {
1411 		case '=':
1412 			*res = 'g';
1413 			(*pos)++;
1414 			break;
1415 		case '?':
1416 			*res = 'a';
1417 			(*pos)++;
1418 			break;
1419 		default:
1420 			break;
1421 		}
1422 		break;
1423 	case '=':
1424 		if ('=' == v[*pos + 1])
1425 			(*pos)++;
1426 		break;
1427 	default:
1428 		return(0);
1429 	}
1430 	(*pos)++;
1431 
1432 	return(*res);
1433 }
1434 
1435 /*
1436  * Evaluate either a parenthesized numeric expression
1437  * or a single signed integer number.
1438  */
1439 static int
1440 roff_evalpar(const char *v, int *pos, int *res)
1441 {
1442 
1443 	if ('(' != v[*pos])
1444 		return(roff_getnum(v, pos, res));
1445 
1446 	(*pos)++;
1447 	if ( ! roff_evalnum(v, pos, res, 1))
1448 		return(0);
1449 
1450 	/*
1451 	 * Omission of the closing parenthesis
1452 	 * is an error in validation mode,
1453 	 * but ignored in evaluation mode.
1454 	 */
1455 
1456 	if (')' == v[*pos])
1457 		(*pos)++;
1458 	else if (NULL == res)
1459 		return(0);
1460 
1461 	return(1);
1462 }
1463 
1464 /*
1465  * Evaluate a complete numeric expression.
1466  * Proceed left to right, there is no concept of precedence.
1467  */
1468 static int
1469 roff_evalnum(const char *v, int *pos, int *res, int skipwhite)
1470 {
1471 	int		 mypos, operand2;
1472 	char		 operator;
1473 
1474 	if (NULL == pos) {
1475 		mypos = 0;
1476 		pos = &mypos;
1477 	}
1478 
1479 	if (skipwhite)
1480 		while (isspace((unsigned char)v[*pos]))
1481 			(*pos)++;
1482 
1483 	if ( ! roff_evalpar(v, pos, res))
1484 		return(0);
1485 
1486 	while (1) {
1487 		if (skipwhite)
1488 			while (isspace((unsigned char)v[*pos]))
1489 				(*pos)++;
1490 
1491 		if ( ! roff_getop(v, pos, &operator))
1492 			break;
1493 
1494 		if (skipwhite)
1495 			while (isspace((unsigned char)v[*pos]))
1496 				(*pos)++;
1497 
1498 		if ( ! roff_evalpar(v, pos, &operand2))
1499 			return(0);
1500 
1501 		if (skipwhite)
1502 			while (isspace((unsigned char)v[*pos]))
1503 				(*pos)++;
1504 
1505 		if (NULL == res)
1506 			continue;
1507 
1508 		switch (operator) {
1509 		case '+':
1510 			*res += operand2;
1511 			break;
1512 		case '-':
1513 			*res -= operand2;
1514 			break;
1515 		case '*':
1516 			*res *= operand2;
1517 			break;
1518 		case '/':
1519 			*res /= operand2;
1520 			break;
1521 		case '%':
1522 			*res %= operand2;
1523 			break;
1524 		case '<':
1525 			*res = *res < operand2;
1526 			break;
1527 		case '>':
1528 			*res = *res > operand2;
1529 			break;
1530 		case 'l':
1531 			*res = *res <= operand2;
1532 			break;
1533 		case 'g':
1534 			*res = *res >= operand2;
1535 			break;
1536 		case '=':
1537 			*res = *res == operand2;
1538 			break;
1539 		case '!':
1540 			*res = *res != operand2;
1541 			break;
1542 		case '&':
1543 			*res = *res && operand2;
1544 			break;
1545 		case ':':
1546 			*res = *res || operand2;
1547 			break;
1548 		case 'i':
1549 			if (operand2 < *res)
1550 				*res = operand2;
1551 			break;
1552 		case 'a':
1553 			if (operand2 > *res)
1554 				*res = operand2;
1555 			break;
1556 		default:
1557 			abort();
1558 		}
1559 	}
1560 	return(1);
1561 }
1562 
1563 void
1564 roff_setreg(struct roff *r, const char *name, int val, char sign)
1565 {
1566 	struct roffreg	*reg;
1567 
1568 	/* Search for an existing register with the same name. */
1569 	reg = r->regtab;
1570 
1571 	while (reg && strcmp(name, reg->key.p))
1572 		reg = reg->next;
1573 
1574 	if (NULL == reg) {
1575 		/* Create a new register. */
1576 		reg = mandoc_malloc(sizeof(struct roffreg));
1577 		reg->key.p = mandoc_strdup(name);
1578 		reg->key.sz = strlen(name);
1579 		reg->val = 0;
1580 		reg->next = r->regtab;
1581 		r->regtab = reg;
1582 	}
1583 
1584 	if ('+' == sign)
1585 		reg->val += val;
1586 	else if ('-' == sign)
1587 		reg->val -= val;
1588 	else
1589 		reg->val = val;
1590 }
1591 
1592 /*
1593  * Handle some predefined read-only number registers.
1594  * For now, return -1 if the requested register is not predefined;
1595  * in case a predefined read-only register having the value -1
1596  * were to turn up, another special value would have to be chosen.
1597  */
1598 static int
1599 roff_getregro(const char *name)
1600 {
1601 
1602 	switch (*name) {
1603 	case 'A':  /* ASCII approximation mode is always off. */
1604 		return(0);
1605 	case 'g':  /* Groff compatibility mode is always on. */
1606 		return(1);
1607 	case 'H':  /* Fixed horizontal resolution. */
1608 		return (24);
1609 	case 'j':  /* Always adjust left margin only. */
1610 		return(0);
1611 	case 'T':  /* Some output device is always defined. */
1612 		return(1);
1613 	case 'V':  /* Fixed vertical resolution. */
1614 		return (40);
1615 	default:
1616 		return (-1);
1617 	}
1618 }
1619 
1620 int
1621 roff_getreg(const struct roff *r, const char *name)
1622 {
1623 	struct roffreg	*reg;
1624 	int		 val;
1625 
1626 	if ('.' == name[0] && '\0' != name[1] && '\0' == name[2]) {
1627 		val = roff_getregro(name + 1);
1628 		if (-1 != val)
1629 			return (val);
1630 	}
1631 
1632 	for (reg = r->regtab; reg; reg = reg->next)
1633 		if (0 == strcmp(name, reg->key.p))
1634 			return(reg->val);
1635 
1636 	return(0);
1637 }
1638 
1639 static int
1640 roff_getregn(const struct roff *r, const char *name, size_t len)
1641 {
1642 	struct roffreg	*reg;
1643 	int		 val;
1644 
1645 	if ('.' == name[0] && 2 == len) {
1646 		val = roff_getregro(name + 1);
1647 		if (-1 != val)
1648 			return (val);
1649 	}
1650 
1651 	for (reg = r->regtab; reg; reg = reg->next)
1652 		if (len == reg->key.sz &&
1653 		    0 == strncmp(name, reg->key.p, len))
1654 			return(reg->val);
1655 
1656 	return(0);
1657 }
1658 
1659 static void
1660 roff_freereg(struct roffreg *reg)
1661 {
1662 	struct roffreg	*old_reg;
1663 
1664 	while (NULL != reg) {
1665 		free(reg->key.p);
1666 		old_reg = reg;
1667 		reg = reg->next;
1668 		free(old_reg);
1669 	}
1670 }
1671 
1672 static enum rofferr
1673 roff_nr(ROFF_ARGS)
1674 {
1675 	char		*key, *val;
1676 	size_t		 keysz;
1677 	int		 iv;
1678 	char		 sign;
1679 
1680 	key = val = *bufp + pos;
1681 	if ('\0' == *key)
1682 		return(ROFF_IGN);
1683 
1684 	keysz = roff_getname(r, &val, ln, pos);
1685 	if ('\\' == key[keysz])
1686 		return(ROFF_IGN);
1687 	key[keysz] = '\0';
1688 
1689 	sign = *val;
1690 	if ('+' == sign || '-' == sign)
1691 		val++;
1692 
1693 	if (roff_evalnum(val, NULL, &iv, 0))
1694 		roff_setreg(r, key, iv, sign);
1695 
1696 	return(ROFF_IGN);
1697 }
1698 
1699 static enum rofferr
1700 roff_rr(ROFF_ARGS)
1701 {
1702 	struct roffreg	*reg, **prev;
1703 	char		*name, *cp;
1704 	size_t		 namesz;
1705 
1706 	name = cp = *bufp + pos;
1707 	if ('\0' == *name)
1708 		return(ROFF_IGN);
1709 	namesz = roff_getname(r, &cp, ln, pos);
1710 	name[namesz] = '\0';
1711 
1712 	prev = &r->regtab;
1713 	while (1) {
1714 		reg = *prev;
1715 		if (NULL == reg || !strcmp(name, reg->key.p))
1716 			break;
1717 		prev = &reg->next;
1718 	}
1719 	if (NULL != reg) {
1720 		*prev = reg->next;
1721 		free(reg->key.p);
1722 		free(reg);
1723 	}
1724 	return(ROFF_IGN);
1725 }
1726 
1727 static enum rofferr
1728 roff_rm(ROFF_ARGS)
1729 {
1730 	const char	 *name;
1731 	char		 *cp;
1732 	size_t		  namesz;
1733 
1734 	cp = *bufp + pos;
1735 	while ('\0' != *cp) {
1736 		name = cp;
1737 		namesz = roff_getname(r, &cp, ln, (int)(cp - *bufp));
1738 		roff_setstrn(&r->strtab, name, namesz, NULL, 0, 0);
1739 		if ('\\' == name[namesz])
1740 			break;
1741 	}
1742 	return(ROFF_IGN);
1743 }
1744 
1745 static enum rofferr
1746 roff_it(ROFF_ARGS)
1747 {
1748 	char		*cp;
1749 	size_t		 len;
1750 	int		 iv;
1751 
1752 	/* Parse the number of lines. */
1753 	cp = *bufp + pos;
1754 	len = strcspn(cp, " \t");
1755 	cp[len] = '\0';
1756 	if ((iv = mandoc_strntoi(cp, len, 10)) <= 0) {
1757 		mandoc_msg(MANDOCERR_NUMERIC, r->parse,
1758 		    ln, ppos, *bufp + 1);
1759 		return(ROFF_IGN);
1760 	}
1761 	cp += len + 1;
1762 
1763 	/* Arm the input line trap. */
1764 	roffit_lines = iv;
1765 	roffit_macro = mandoc_strdup(cp);
1766 	return(ROFF_IGN);
1767 }
1768 
1769 static enum rofferr
1770 roff_Dd(ROFF_ARGS)
1771 {
1772 	const char *const	*cp;
1773 
1774 	if (0 == ((MPARSE_MDOC | MPARSE_QUICK) & r->options))
1775 		for (cp = __mdoc_reserved; *cp; cp++)
1776 			roff_setstr(r, *cp, NULL, 0);
1777 
1778 	return(ROFF_CONT);
1779 }
1780 
1781 static enum rofferr
1782 roff_TH(ROFF_ARGS)
1783 {
1784 	const char *const	*cp;
1785 
1786 	if (0 == (MPARSE_QUICK & r->options))
1787 		for (cp = __man_reserved; *cp; cp++)
1788 			roff_setstr(r, *cp, NULL, 0);
1789 
1790 	return(ROFF_CONT);
1791 }
1792 
1793 static enum rofferr
1794 roff_TE(ROFF_ARGS)
1795 {
1796 
1797 	if (NULL == r->tbl)
1798 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
1799 		    ln, ppos, "TE");
1800 	else
1801 		tbl_end(&r->tbl);
1802 
1803 	return(ROFF_IGN);
1804 }
1805 
1806 static enum rofferr
1807 roff_T_(ROFF_ARGS)
1808 {
1809 
1810 	if (NULL == r->tbl)
1811 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse,
1812 		    ln, ppos, "T&");
1813 	else
1814 		tbl_restart(ppos, ln, r->tbl);
1815 
1816 	return(ROFF_IGN);
1817 }
1818 
1819 #if 0
1820 static int
1821 roff_closeeqn(struct roff *r)
1822 {
1823 
1824 	return(r->eqn && ROFF_EQN == eqn_end(&r->eqn) ? 1 : 0);
1825 }
1826 #endif
1827 
1828 static void
1829 roff_openeqn(struct roff *r, const char *name, int line,
1830 		int offs, const char *buf)
1831 {
1832 	struct eqn_node *e;
1833 	int		 poff;
1834 
1835 	assert(NULL == r->eqn);
1836 	e = eqn_alloc(name, offs, line, r->parse);
1837 
1838 	if (r->last_eqn)
1839 		r->last_eqn->next = e;
1840 	else
1841 		r->first_eqn = r->last_eqn = e;
1842 
1843 	r->eqn = r->last_eqn = e;
1844 
1845 	if (buf) {
1846 		poff = 0;
1847 		eqn_read(&r->eqn, line, buf, offs, &poff);
1848 	}
1849 }
1850 
1851 static enum rofferr
1852 roff_EQ(ROFF_ARGS)
1853 {
1854 
1855 	roff_openeqn(r, *bufp + pos, ln, ppos, NULL);
1856 	return(ROFF_IGN);
1857 }
1858 
1859 static enum rofferr
1860 roff_EN(ROFF_ARGS)
1861 {
1862 
1863 	mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, "EN");
1864 	return(ROFF_IGN);
1865 }
1866 
1867 static enum rofferr
1868 roff_TS(ROFF_ARGS)
1869 {
1870 	struct tbl_node	*tbl;
1871 
1872 	if (r->tbl) {
1873 		mandoc_msg(MANDOCERR_BLK_BROKEN, r->parse,
1874 		    ln, ppos, "TS breaks TS");
1875 		tbl_end(&r->tbl);
1876 	}
1877 
1878 	tbl = tbl_alloc(ppos, ln, r->parse);
1879 
1880 	if (r->last_tbl)
1881 		r->last_tbl->next = tbl;
1882 	else
1883 		r->first_tbl = r->last_tbl = tbl;
1884 
1885 	r->tbl = r->last_tbl = tbl;
1886 	return(ROFF_IGN);
1887 }
1888 
1889 static enum rofferr
1890 roff_cc(ROFF_ARGS)
1891 {
1892 	const char	*p;
1893 
1894 	p = *bufp + pos;
1895 
1896 	if ('\0' == *p || '.' == (r->control = *p++))
1897 		r->control = 0;
1898 
1899 	if ('\0' != *p)
1900 		mandoc_msg(MANDOCERR_ARGCOUNT, r->parse, ln, ppos, NULL);
1901 
1902 	return(ROFF_IGN);
1903 }
1904 
1905 static enum rofferr
1906 roff_tr(ROFF_ARGS)
1907 {
1908 	const char	*p, *first, *second;
1909 	size_t		 fsz, ssz;
1910 	enum mandoc_esc	 esc;
1911 
1912 	p = *bufp + pos;
1913 
1914 	if ('\0' == *p) {
1915 		mandoc_msg(MANDOCERR_ARGCOUNT, r->parse, ln, ppos, NULL);
1916 		return(ROFF_IGN);
1917 	}
1918 
1919 	while ('\0' != *p) {
1920 		fsz = ssz = 1;
1921 
1922 		first = p++;
1923 		if ('\\' == *first) {
1924 			esc = mandoc_escape(&p, NULL, NULL);
1925 			if (ESCAPE_ERROR == esc) {
1926 				mandoc_msg(MANDOCERR_ESC_BAD, r->parse,
1927 				    ln, (int)(p - *bufp), first);
1928 				return(ROFF_IGN);
1929 			}
1930 			fsz = (size_t)(p - first);
1931 		}
1932 
1933 		second = p++;
1934 		if ('\\' == *second) {
1935 			esc = mandoc_escape(&p, NULL, NULL);
1936 			if (ESCAPE_ERROR == esc) {
1937 				mandoc_msg(MANDOCERR_ESC_BAD, r->parse,
1938 				    ln, (int)(p - *bufp), second);
1939 				return(ROFF_IGN);
1940 			}
1941 			ssz = (size_t)(p - second);
1942 		} else if ('\0' == *second) {
1943 			mandoc_msg(MANDOCERR_ARGCOUNT, r->parse,
1944 			    ln, (int)(p - *bufp), NULL);
1945 			second = " ";
1946 			p--;
1947 		}
1948 
1949 		if (fsz > 1) {
1950 			roff_setstrn(&r->xmbtab, first, fsz,
1951 			    second, ssz, 0);
1952 			continue;
1953 		}
1954 
1955 		if (NULL == r->xtab)
1956 			r->xtab = mandoc_calloc(128,
1957 			    sizeof(struct roffstr));
1958 
1959 		free(r->xtab[(int)*first].p);
1960 		r->xtab[(int)*first].p = mandoc_strndup(second, ssz);
1961 		r->xtab[(int)*first].sz = ssz;
1962 	}
1963 
1964 	return(ROFF_IGN);
1965 }
1966 
1967 static enum rofferr
1968 roff_so(ROFF_ARGS)
1969 {
1970 	char *name;
1971 
1972 	name = *bufp + pos;
1973 	mandoc_vmsg(MANDOCERR_SO, r->parse, ln, ppos, ".so %s", name);
1974 
1975 	/*
1976 	 * Handle `so'.  Be EXTREMELY careful, as we shouldn't be
1977 	 * opening anything that's not in our cwd or anything beneath
1978 	 * it.  Thus, explicitly disallow traversing up the file-system
1979 	 * or using absolute paths.
1980 	 */
1981 
1982 	if ('/' == *name || strstr(name, "../") || strstr(name, "/..")) {
1983 		mandoc_vmsg(MANDOCERR_SO_PATH, r->parse, ln, ppos,
1984 		    ".so %s", name);
1985 		return(ROFF_ERR);
1986 	}
1987 
1988 	*offs = pos;
1989 	return(ROFF_SO);
1990 }
1991 
1992 static enum rofferr
1993 roff_userdef(ROFF_ARGS)
1994 {
1995 	const char	 *arg[9];
1996 	char		 *cp, *n1, *n2;
1997 	int		  i;
1998 
1999 	/*
2000 	 * Collect pointers to macro argument strings
2001 	 * and NUL-terminate them.
2002 	 */
2003 	cp = *bufp + pos;
2004 	for (i = 0; i < 9; i++)
2005 		arg[i] = '\0' == *cp ? "" :
2006 		    mandoc_getarg(r->parse, &cp, ln, &pos);
2007 
2008 	/*
2009 	 * Expand macro arguments.
2010 	 */
2011 	*szp = 0;
2012 	n1 = cp = mandoc_strdup(r->current_string);
2013 	while (NULL != (cp = strstr(cp, "\\$"))) {
2014 		i = cp[2] - '1';
2015 		if (0 > i || 8 < i) {
2016 			/* Not an argument invocation. */
2017 			cp += 2;
2018 			continue;
2019 		}
2020 		*cp = '\0';
2021 		*szp = mandoc_asprintf(&n2, "%s%s%s",
2022 		    n1, arg[i], cp + 3) + 1;
2023 		cp = n2 + (cp - n1);
2024 		free(n1);
2025 		n1 = n2;
2026 	}
2027 
2028 	/*
2029 	 * Replace the macro invocation
2030 	 * by the expanded macro.
2031 	 */
2032 	free(*bufp);
2033 	*bufp = n1;
2034 	if (0 == *szp)
2035 		*szp = strlen(*bufp) + 1;
2036 
2037 	return(*szp > 1 && '\n' == (*bufp)[(int)*szp - 2] ?
2038 	   ROFF_REPARSE : ROFF_APPEND);
2039 }
2040 
2041 static size_t
2042 roff_getname(struct roff *r, char **cpp, int ln, int pos)
2043 {
2044 	char	 *name, *cp;
2045 	size_t	  namesz;
2046 
2047 	name = *cpp;
2048 	if ('\0' == *name)
2049 		return(0);
2050 
2051 	/* Read until end of name and terminate it with NUL. */
2052 	for (cp = name; 1; cp++) {
2053 		if ('\0' == *cp || ' ' == *cp) {
2054 			namesz = cp - name;
2055 			break;
2056 		}
2057 		if ('\\' != *cp)
2058 			continue;
2059 		namesz = cp - name;
2060 		if ('{' == cp[1] || '}' == cp[1])
2061 			break;
2062 		cp++;
2063 		if ('\\' == *cp)
2064 			continue;
2065 		mandoc_msg(MANDOCERR_NAMESC, r->parse, ln, pos, NULL);
2066 		mandoc_escape((const char **)&cp, NULL, NULL);
2067 		break;
2068 	}
2069 
2070 	/* Read past spaces. */
2071 	while (' ' == *cp)
2072 		cp++;
2073 
2074 	*cpp = cp;
2075 	return(namesz);
2076 }
2077 
2078 /*
2079  * Store *string into the user-defined string called *name.
2080  * To clear an existing entry, call with (*r, *name, NULL, 0).
2081  * append == 0: replace mode
2082  * append == 1: single-line append mode
2083  * append == 2: multiline append mode, append '\n' after each call
2084  */
2085 static void
2086 roff_setstr(struct roff *r, const char *name, const char *string,
2087 	int append)
2088 {
2089 
2090 	roff_setstrn(&r->strtab, name, strlen(name), string,
2091 	    string ? strlen(string) : 0, append);
2092 }
2093 
2094 static void
2095 roff_setstrn(struct roffkv **r, const char *name, size_t namesz,
2096 		const char *string, size_t stringsz, int append)
2097 {
2098 	struct roffkv	*n;
2099 	char		*c;
2100 	int		 i;
2101 	size_t		 oldch, newch;
2102 
2103 	/* Search for an existing string with the same name. */
2104 	n = *r;
2105 
2106 	while (n && (namesz != n->key.sz ||
2107 			strncmp(n->key.p, name, namesz)))
2108 		n = n->next;
2109 
2110 	if (NULL == n) {
2111 		/* Create a new string table entry. */
2112 		n = mandoc_malloc(sizeof(struct roffkv));
2113 		n->key.p = mandoc_strndup(name, namesz);
2114 		n->key.sz = namesz;
2115 		n->val.p = NULL;
2116 		n->val.sz = 0;
2117 		n->next = *r;
2118 		*r = n;
2119 	} else if (0 == append) {
2120 		free(n->val.p);
2121 		n->val.p = NULL;
2122 		n->val.sz = 0;
2123 	}
2124 
2125 	if (NULL == string)
2126 		return;
2127 
2128 	/*
2129 	 * One additional byte for the '\n' in multiline mode,
2130 	 * and one for the terminating '\0'.
2131 	 */
2132 	newch = stringsz + (1 < append ? 2u : 1u);
2133 
2134 	if (NULL == n->val.p) {
2135 		n->val.p = mandoc_malloc(newch);
2136 		*n->val.p = '\0';
2137 		oldch = 0;
2138 	} else {
2139 		oldch = n->val.sz;
2140 		n->val.p = mandoc_realloc(n->val.p, oldch + newch);
2141 	}
2142 
2143 	/* Skip existing content in the destination buffer. */
2144 	c = n->val.p + (int)oldch;
2145 
2146 	/* Append new content to the destination buffer. */
2147 	i = 0;
2148 	while (i < (int)stringsz) {
2149 		/*
2150 		 * Rudimentary roff copy mode:
2151 		 * Handle escaped backslashes.
2152 		 */
2153 		if ('\\' == string[i] && '\\' == string[i + 1])
2154 			i++;
2155 		*c++ = string[i++];
2156 	}
2157 
2158 	/* Append terminating bytes. */
2159 	if (1 < append)
2160 		*c++ = '\n';
2161 
2162 	*c = '\0';
2163 	n->val.sz = (int)(c - n->val.p);
2164 }
2165 
2166 static const char *
2167 roff_getstrn(const struct roff *r, const char *name, size_t len)
2168 {
2169 	const struct roffkv *n;
2170 	int i;
2171 
2172 	for (n = r->strtab; n; n = n->next)
2173 		if (0 == strncmp(name, n->key.p, len) &&
2174 		    '\0' == n->key.p[(int)len])
2175 			return(n->val.p);
2176 
2177 	for (i = 0; i < PREDEFS_MAX; i++)
2178 		if (0 == strncmp(name, predefs[i].name, len) &&
2179 				'\0' == predefs[i].name[(int)len])
2180 			return(predefs[i].str);
2181 
2182 	return(NULL);
2183 }
2184 
2185 static void
2186 roff_freestr(struct roffkv *r)
2187 {
2188 	struct roffkv	 *n, *nn;
2189 
2190 	for (n = r; n; n = nn) {
2191 		free(n->key.p);
2192 		free(n->val.p);
2193 		nn = n->next;
2194 		free(n);
2195 	}
2196 }
2197 
2198 const struct tbl_span *
2199 roff_span(const struct roff *r)
2200 {
2201 
2202 	return(r->tbl ? tbl_span(r->tbl) : NULL);
2203 }
2204 
2205 const struct eqn *
2206 roff_eqn(const struct roff *r)
2207 {
2208 
2209 	return(r->last_eqn ? &r->last_eqn->eqn : NULL);
2210 }
2211 
2212 /*
2213  * Duplicate an input string, making the appropriate character
2214  * conversations (as stipulated by `tr') along the way.
2215  * Returns a heap-allocated string with all the replacements made.
2216  */
2217 char *
2218 roff_strdup(const struct roff *r, const char *p)
2219 {
2220 	const struct roffkv *cp;
2221 	char		*res;
2222 	const char	*pp;
2223 	size_t		 ssz, sz;
2224 	enum mandoc_esc	 esc;
2225 
2226 	if (NULL == r->xmbtab && NULL == r->xtab)
2227 		return(mandoc_strdup(p));
2228 	else if ('\0' == *p)
2229 		return(mandoc_strdup(""));
2230 
2231 	/*
2232 	 * Step through each character looking for term matches
2233 	 * (remember that a `tr' can be invoked with an escape, which is
2234 	 * a glyph but the escape is multi-character).
2235 	 * We only do this if the character hash has been initialised
2236 	 * and the string is >0 length.
2237 	 */
2238 
2239 	res = NULL;
2240 	ssz = 0;
2241 
2242 	while ('\0' != *p) {
2243 		if ('\\' != *p && r->xtab && r->xtab[(int)*p].p) {
2244 			sz = r->xtab[(int)*p].sz;
2245 			res = mandoc_realloc(res, ssz + sz + 1);
2246 			memcpy(res + ssz, r->xtab[(int)*p].p, sz);
2247 			ssz += sz;
2248 			p++;
2249 			continue;
2250 		} else if ('\\' != *p) {
2251 			res = mandoc_realloc(res, ssz + 2);
2252 			res[ssz++] = *p++;
2253 			continue;
2254 		}
2255 
2256 		/* Search for term matches. */
2257 		for (cp = r->xmbtab; cp; cp = cp->next)
2258 			if (0 == strncmp(p, cp->key.p, cp->key.sz))
2259 				break;
2260 
2261 		if (NULL != cp) {
2262 			/*
2263 			 * A match has been found.
2264 			 * Append the match to the array and move
2265 			 * forward by its keysize.
2266 			 */
2267 			res = mandoc_realloc(res,
2268 			    ssz + cp->val.sz + 1);
2269 			memcpy(res + ssz, cp->val.p, cp->val.sz);
2270 			ssz += cp->val.sz;
2271 			p += (int)cp->key.sz;
2272 			continue;
2273 		}
2274 
2275 		/*
2276 		 * Handle escapes carefully: we need to copy
2277 		 * over just the escape itself, or else we might
2278 		 * do replacements within the escape itself.
2279 		 * Make sure to pass along the bogus string.
2280 		 */
2281 		pp = p++;
2282 		esc = mandoc_escape(&p, NULL, NULL);
2283 		if (ESCAPE_ERROR == esc) {
2284 			sz = strlen(pp);
2285 			res = mandoc_realloc(res, ssz + sz + 1);
2286 			memcpy(res + ssz, pp, sz);
2287 			break;
2288 		}
2289 		/*
2290 		 * We bail out on bad escapes.
2291 		 * No need to warn: we already did so when
2292 		 * roff_res() was called.
2293 		 */
2294 		sz = (int)(p - pp);
2295 		res = mandoc_realloc(res, ssz + sz + 1);
2296 		memcpy(res + ssz, pp, sz);
2297 		ssz += sz;
2298 	}
2299 
2300 	res[(int)ssz] = '\0';
2301 	return(res);
2302 }
2303 
2304 /*
2305  * Find out whether a line is a macro line or not.
2306  * If it is, adjust the current position and return one; if it isn't,
2307  * return zero and don't change the current position.
2308  * If the control character has been set with `.cc', then let that grain
2309  * precedence.
2310  * This is slighly contrary to groff, where using the non-breaking
2311  * control character when `cc' has been invoked will cause the
2312  * non-breaking macro contents to be printed verbatim.
2313  */
2314 int
2315 roff_getcontrol(const struct roff *r, const char *cp, int *ppos)
2316 {
2317 	int		pos;
2318 
2319 	pos = *ppos;
2320 
2321 	if (0 != r->control && cp[pos] == r->control)
2322 		pos++;
2323 	else if (0 != r->control)
2324 		return(0);
2325 	else if ('\\' == cp[pos] && '.' == cp[pos + 1])
2326 		pos += 2;
2327 	else if ('.' == cp[pos] || '\'' == cp[pos])
2328 		pos++;
2329 	else
2330 		return(0);
2331 
2332 	while (' ' == cp[pos] || '\t' == cp[pos])
2333 		pos++;
2334 
2335 	*ppos = pos;
2336 	return(1);
2337 }
2338