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