xref: /openbsd-src/usr.bin/mandoc/mdoc_macro.c (revision 7bbe964f6b7d22ad07ca46292495604f942eba4e)
1 /*	$Id: mdoc_macro.c,v 1.25 2009/10/27 21:40:07 schwarze Exp $ */
2 /*
3  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include <assert.h>
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include "libmdoc.h"
24 
25 #define	REWIND_REWIND	(1 << 0)
26 #define	REWIND_NOHALT	(1 << 1)
27 #define	REWIND_HALT	(1 << 2)
28 
29 static	int	  obsolete(MACRO_PROT_ARGS);
30 static	int	  blk_part_exp(MACRO_PROT_ARGS);
31 static	int	  in_line_eoln(MACRO_PROT_ARGS);
32 static	int	  in_line_argn(MACRO_PROT_ARGS);
33 static	int	  in_line(MACRO_PROT_ARGS);
34 static	int	  blk_full(MACRO_PROT_ARGS);
35 static	int	  blk_exp_close(MACRO_PROT_ARGS);
36 static	int	  blk_part_imp(MACRO_PROT_ARGS);
37 
38 static	int	  phrase(struct mdoc *, int, int, char *);
39 static	int	  rew_dohalt(int, enum mdoc_type,
40 			const struct mdoc_node *);
41 static	int	  rew_alt(int);
42 static	int	  rew_dobreak(int, const struct mdoc_node *);
43 static	int	  rew_elem(struct mdoc *, int);
44 static	int	  rew_sub(enum mdoc_type, struct mdoc *,
45 			int, int, int);
46 static	int	  rew_last(struct mdoc *,
47 			const struct mdoc_node *);
48 static	int	  append_delims(struct mdoc *, int, int *, char *);
49 static	int	  lookup(int, const char *);
50 static	int	  lookup_raw(const char *);
51 static	int	  swarn(struct mdoc *, enum mdoc_type, int, int,
52 			const struct mdoc_node *);
53 
54 /* Central table of library: who gets parsed how. */
55 
56 const	struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
57 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
58 	{ in_line_eoln, MDOC_PROLOGUE }, /* Dd */
59 	{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */
60 	{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
61 	{ blk_full, 0 }, /* Sh */
62 	{ blk_full, 0 }, /* Ss */
63 	{ in_line_eoln, 0 }, /* Pp */
64 	{ blk_part_imp, MDOC_PARSED }, /* D1 */
65 	{ blk_part_imp, MDOC_PARSED }, /* Dl */
66 	{ blk_full, MDOC_EXPLICIT }, /* Bd */
67 	{ blk_exp_close, MDOC_EXPLICIT }, /* Ed */
68 	{ blk_full, MDOC_EXPLICIT }, /* Bl */
69 	{ blk_exp_close, MDOC_EXPLICIT }, /* El */
70 	{ blk_full, MDOC_PARSED }, /* It */
71 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
72 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
73 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
74 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
75 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
76 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
77 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
78 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
79 	{ in_line_eoln, 0 }, /* Ex */
80 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
81 	{ in_line_eoln, 0 }, /* Fd */
82 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
83 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
84 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
85 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
86 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
87 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
88 	{ blk_full, 0 }, /* Nd */
89 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
90 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
91 	{ obsolete, 0 }, /* Ot */
92 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
93 	{ in_line_eoln, 0 }, /* Rv */
94 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
95 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
96 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
97 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
98 	{ in_line_eoln, 0 }, /* %A */
99 	{ in_line_eoln, 0 }, /* %B */
100 	{ in_line_eoln, 0 }, /* %D */
101 	{ in_line_eoln, 0 }, /* %I */
102 	{ in_line_eoln, 0 }, /* %J */
103 	{ in_line_eoln, 0 }, /* %N */
104 	{ in_line_eoln, 0 }, /* %O */
105 	{ in_line_eoln, 0 }, /* %P */
106 	{ in_line_eoln, 0 }, /* %R */
107 	{ in_line_eoln, 0 }, /* %T */
108 	{ in_line_eoln, 0 }, /* %V */
109 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
110 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
111 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
112 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
113 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
114 	{ blk_full, MDOC_EXPLICIT }, /* Bf */
115 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
116 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
117 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
118 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
119 	{ in_line_eoln, 0 }, /* Db */
120 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
121 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
122 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
123 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
124 	{ blk_exp_close, MDOC_EXPLICIT }, /* Ef */
125 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
126 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
127 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
128 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
129 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */
130 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
131 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
132 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
133 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
134 	{ in_line_argn, MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
135 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
136 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
137 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
138 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
139 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
140 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
141 	{ blk_exp_close, MDOC_EXPLICIT }, /* Re */
142 	{ blk_full, MDOC_EXPLICIT }, /* Rs */
143 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
144 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
145 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
146 	{ in_line_eoln, 0 }, /* Sm */
147 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
148 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
149 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
150 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
151 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
152 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
153 	{ blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
154 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
155 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
156 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
157 	{ blk_full, MDOC_EXPLICIT }, /* Bk */
158 	{ blk_exp_close, MDOC_EXPLICIT }, /* Ek */
159 	{ in_line_eoln, 0 }, /* Bt */
160 	{ in_line_eoln, 0 }, /* Hf */
161 	{ obsolete, 0 }, /* Fr */
162 	{ in_line_eoln, 0 }, /* Ud */
163 	{ in_line_eoln, 0 }, /* Lb */
164 	{ in_line_eoln, 0 }, /* Lp */
165 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
166 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
167 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
168 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
169 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
170 	{ in_line_eoln, 0 }, /* %C */
171 	{ obsolete, 0 }, /* Es */
172 	{ obsolete, 0 }, /* En */
173 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
174 	{ in_line_eoln, 0 }, /* %Q */
175 	{ in_line_eoln, 0 }, /* br */
176 	{ in_line_eoln, 0 }, /* sp */
177 	{ in_line_eoln, 0 }, /* %U */
178 };
179 
180 const	struct mdoc_macro * const mdoc_macros = __mdoc_macros;
181 
182 
183 static int
184 swarn(struct mdoc *mdoc, enum mdoc_type type,
185 		int line, int pos, const struct mdoc_node *p)
186 {
187 	const char	*n, *t, *tt;
188 
189 	n = t = "<root>";
190 	tt = "block";
191 
192 	switch (type) {
193 	case (MDOC_BODY):
194 		tt = "multi-line";
195 		break;
196 	case (MDOC_HEAD):
197 		tt = "line";
198 		break;
199 	default:
200 		break;
201 	}
202 
203 	switch (p->type) {
204 	case (MDOC_BLOCK):
205 		n = mdoc_macronames[p->tok];
206 		t = "block";
207 		break;
208 	case (MDOC_BODY):
209 		n = mdoc_macronames[p->tok];
210 		t = "multi-line";
211 		break;
212 	case (MDOC_HEAD):
213 		n = mdoc_macronames[p->tok];
214 		t = "line";
215 		break;
216 	default:
217 		break;
218 	}
219 
220 	if ( ! (MDOC_IGN_SCOPE & mdoc->pflags))
221 		return(mdoc_verr(mdoc, line, pos,
222 				"%s scope breaks %s scope of %s",
223 				tt, t, n));
224 	return(mdoc_vwarn(mdoc, line, pos,
225 				"%s scope breaks %s scope of %s",
226 				tt, t, n));
227 }
228 
229 
230 /*
231  * This is called at the end of parsing.  It must traverse up the tree,
232  * closing out open [implicit] scopes.  Obviously, open explicit scopes
233  * are errors.
234  */
235 int
236 mdoc_macroend(struct mdoc *m)
237 {
238 	struct mdoc_node *n;
239 
240 	/* Scan for open explicit scopes. */
241 
242 	n = MDOC_VALID & m->last->flags ?  m->last->parent : m->last;
243 
244 	for ( ; n; n = n->parent) {
245 		if (MDOC_BLOCK != n->type)
246 			continue;
247 		if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
248 			continue;
249 		return(mdoc_nerr(m, n, EOPEN));
250 	}
251 
252 	/* Rewind to the first. */
253 
254 	return(rew_last(m, m->first));
255 }
256 
257 
258 /*
259  * Look up a macro from within a subsequent context.
260  */
261 static int
262 lookup(int from, const char *p)
263 {
264 	/* FIXME: make -diag lists be un-PARSED. */
265 
266 	if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
267 		return(MDOC_MAX);
268 	return(lookup_raw(p));
269 }
270 
271 
272 /*
273  * Lookup a macro following the initial line macro.
274  */
275 static int
276 lookup_raw(const char *p)
277 {
278 	int		 res;
279 
280 	if (MDOC_MAX == (res = mdoc_hash_find(p)))
281 		return(MDOC_MAX);
282 	if (MDOC_CALLABLE & mdoc_macros[res].flags)
283 		return(res);
284 	return(MDOC_MAX);
285 }
286 
287 
288 static int
289 rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
290 {
291 
292 	assert(to);
293 	mdoc->next = MDOC_NEXT_SIBLING;
294 
295 	/* LINTED */
296 	while (mdoc->last != to) {
297 		if ( ! mdoc_valid_post(mdoc))
298 			return(0);
299 		if ( ! mdoc_action_post(mdoc))
300 			return(0);
301 		mdoc->last = mdoc->last->parent;
302 		assert(mdoc->last);
303 	}
304 
305 	if ( ! mdoc_valid_post(mdoc))
306 		return(0);
307 	return(mdoc_action_post(mdoc));
308 }
309 
310 
311 /*
312  * Return the opening macro of a closing one, e.g., `Ec' has `Eo' as its
313  * matching pair.
314  */
315 static int
316 rew_alt(int tok)
317 {
318 	switch (tok) {
319 	case (MDOC_Ac):
320 		return(MDOC_Ao);
321 	case (MDOC_Bc):
322 		return(MDOC_Bo);
323 	case (MDOC_Brc):
324 		return(MDOC_Bro);
325 	case (MDOC_Dc):
326 		return(MDOC_Do);
327 	case (MDOC_Ec):
328 		return(MDOC_Eo);
329 	case (MDOC_Ed):
330 		return(MDOC_Bd);
331 	case (MDOC_Ef):
332 		return(MDOC_Bf);
333 	case (MDOC_Ek):
334 		return(MDOC_Bk);
335 	case (MDOC_El):
336 		return(MDOC_Bl);
337 	case (MDOC_Fc):
338 		return(MDOC_Fo);
339 	case (MDOC_Oc):
340 		return(MDOC_Oo);
341 	case (MDOC_Pc):
342 		return(MDOC_Po);
343 	case (MDOC_Qc):
344 		return(MDOC_Qo);
345 	case (MDOC_Re):
346 		return(MDOC_Rs);
347 	case (MDOC_Sc):
348 		return(MDOC_So);
349 	case (MDOC_Xc):
350 		return(MDOC_Xo);
351 	default:
352 		break;
353 	}
354 	abort();
355 	/* NOTREACHED */
356 }
357 
358 
359 /*
360  * Rewind rules.  This indicates whether to stop rewinding
361  * (REWIND_HALT) without touching our current scope, stop rewinding and
362  * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
363  * The scope-closing and so on occurs in the various rew_* routines.
364  */
365 static int
366 rew_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
367 {
368 
369 	if (MDOC_ROOT == p->type)
370 		return(REWIND_HALT);
371 	if (MDOC_VALID & p->flags)
372 		return(REWIND_NOHALT);
373 
374 	switch (tok) {
375 	case (MDOC_Aq):
376 		/* FALLTHROUGH */
377 	case (MDOC_Bq):
378 		/* FALLTHROUGH */
379 	case (MDOC_Brq):
380 		/* FALLTHROUGH */
381 	case (MDOC_D1):
382 		/* FALLTHROUGH */
383 	case (MDOC_Dl):
384 		/* FALLTHROUGH */
385 	case (MDOC_Dq):
386 		/* FALLTHROUGH */
387 	case (MDOC_Op):
388 		/* FALLTHROUGH */
389 	case (MDOC_Pq):
390 		/* FALLTHROUGH */
391 	case (MDOC_Ql):
392 		/* FALLTHROUGH */
393 	case (MDOC_Qq):
394 		/* FALLTHROUGH */
395 	case (MDOC_Sq):
396 		assert(MDOC_TAIL != type);
397 		if (type == p->type && tok == p->tok)
398 			return(REWIND_REWIND);
399 		break;
400 	case (MDOC_It):
401 		assert(MDOC_TAIL != type);
402 		if (type == p->type && tok == p->tok)
403 			return(REWIND_REWIND);
404 		if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
405 			return(REWIND_HALT);
406 		break;
407 	case (MDOC_Sh):
408 		if (type == p->type && tok == p->tok)
409 			return(REWIND_REWIND);
410 		break;
411 	case (MDOC_Nd):
412 		/* FALLTHROUGH */
413 	case (MDOC_Ss):
414 		assert(MDOC_TAIL != type);
415 		if (type == p->type && tok == p->tok)
416 			return(REWIND_REWIND);
417 		if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
418 			return(REWIND_HALT);
419 		break;
420 	case (MDOC_Ao):
421 		/* FALLTHROUGH */
422 	case (MDOC_Bd):
423 		/* FALLTHROUGH */
424 	case (MDOC_Bf):
425 		/* FALLTHROUGH */
426 	case (MDOC_Bk):
427 		/* FALLTHROUGH */
428 	case (MDOC_Bl):
429 		/* FALLTHROUGH */
430 	case (MDOC_Bo):
431 		/* FALLTHROUGH */
432 	case (MDOC_Bro):
433 		/* FALLTHROUGH */
434 	case (MDOC_Do):
435 		/* FALLTHROUGH */
436 	case (MDOC_Eo):
437 		/* FALLTHROUGH */
438 	case (MDOC_Fo):
439 		/* FALLTHROUGH */
440 	case (MDOC_Oo):
441 		/* FALLTHROUGH */
442 	case (MDOC_Po):
443 		/* FALLTHROUGH */
444 	case (MDOC_Qo):
445 		/* FALLTHROUGH */
446 	case (MDOC_Rs):
447 		/* FALLTHROUGH */
448 	case (MDOC_So):
449 		/* FALLTHROUGH */
450 	case (MDOC_Xo):
451 		if (type == p->type && tok == p->tok)
452 			return(REWIND_REWIND);
453 		break;
454 	/* Multi-line explicit scope close. */
455 	case (MDOC_Ac):
456 		/* FALLTHROUGH */
457 	case (MDOC_Bc):
458 		/* FALLTHROUGH */
459 	case (MDOC_Brc):
460 		/* FALLTHROUGH */
461 	case (MDOC_Dc):
462 		/* FALLTHROUGH */
463 	case (MDOC_Ec):
464 		/* FALLTHROUGH */
465 	case (MDOC_Ed):
466 		/* FALLTHROUGH */
467 	case (MDOC_Ek):
468 		/* FALLTHROUGH */
469 	case (MDOC_El):
470 		/* FALLTHROUGH */
471 	case (MDOC_Fc):
472 		/* FALLTHROUGH */
473 	case (MDOC_Ef):
474 		/* FALLTHROUGH */
475 	case (MDOC_Oc):
476 		/* FALLTHROUGH */
477 	case (MDOC_Pc):
478 		/* FALLTHROUGH */
479 	case (MDOC_Qc):
480 		/* FALLTHROUGH */
481 	case (MDOC_Re):
482 		/* FALLTHROUGH */
483 	case (MDOC_Sc):
484 		/* FALLTHROUGH */
485 	case (MDOC_Xc):
486 		if (type == p->type && rew_alt(tok) == p->tok)
487 			return(REWIND_REWIND);
488 		break;
489 	default:
490 		abort();
491 		/* NOTREACHED */
492 	}
493 
494 	return(REWIND_NOHALT);
495 }
496 
497 
498 /*
499  * See if we can break an encountered scope (the rew_dohalt has returned
500  * REWIND_NOHALT).
501  */
502 static int
503 rew_dobreak(int tok, const struct mdoc_node *p)
504 {
505 
506 	assert(MDOC_ROOT != p->type);
507 	if (MDOC_ELEM == p->type)
508 		return(1);
509 	if (MDOC_TEXT == p->type)
510 		return(1);
511 	if (MDOC_VALID & p->flags)
512 		return(1);
513 
514 	switch (tok) {
515 	case (MDOC_It):
516 		return(MDOC_It == p->tok);
517 	case (MDOC_Nd):
518 		return(MDOC_Nd == p->tok);
519 	case (MDOC_Ss):
520 		return(MDOC_Ss == p->tok);
521 	case (MDOC_Sh):
522 		if (MDOC_Nd == p->tok)
523 			return(1);
524 		if (MDOC_Ss == p->tok)
525 			return(1);
526 		return(MDOC_Sh == p->tok);
527 	case (MDOC_El):
528 		if (MDOC_It == p->tok)
529 			return(1);
530 		break;
531 	case (MDOC_Oc):
532 		/* XXX - experimental! */
533 		if (MDOC_Op == p->tok)
534 			return(1);
535 		break;
536 	default:
537 		break;
538 	}
539 
540 	if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
541 		return(p->tok == rew_alt(tok));
542 	else if (MDOC_BLOCK == p->type)
543 		return(1);
544 
545 	return(tok == p->tok);
546 }
547 
548 
549 static int
550 rew_elem(struct mdoc *mdoc, int tok)
551 {
552 	struct mdoc_node *n;
553 
554 	n = mdoc->last;
555 	if (MDOC_ELEM != n->type)
556 		n = n->parent;
557 	assert(MDOC_ELEM == n->type);
558 	assert(tok == n->tok);
559 
560 	return(rew_last(mdoc, n));
561 }
562 
563 
564 static int
565 rew_sub(enum mdoc_type t, struct mdoc *m,
566 		int tok, int line, int ppos)
567 {
568 	struct mdoc_node *n;
569 	int		  c;
570 
571 	/* LINTED */
572 	for (n = m->last; n; n = n->parent) {
573 		c = rew_dohalt(tok, t, n);
574 		if (REWIND_HALT == c) {
575 			if (MDOC_BLOCK != t)
576 				return(1);
577 			if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))
578 				return(1);
579 			return(mdoc_perr(m, line, ppos, ENOCTX));
580 		}
581 		if (REWIND_REWIND == c)
582 			break;
583 		else if (rew_dobreak(tok, n))
584 			continue;
585 		if ( ! swarn(m, t, line, ppos, n))
586 			return(0);
587 	}
588 
589 	assert(n);
590 	return(rew_last(m, n));
591 }
592 
593 
594 static int
595 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
596 {
597 	int		 c, lastarg;
598 	char		*p;
599 
600 	if (0 == buf[*pos])
601 		return(1);
602 
603 	for (;;) {
604 		lastarg = *pos;
605 		c = mdoc_zargs(mdoc, line, pos, buf, ARGS_NOWARN, &p);
606 		assert(ARGS_PHRASE != c);
607 
608 		if (ARGS_ERROR == c)
609 			return(0);
610 		else if (ARGS_EOLN == c)
611 			break;
612 		assert(mdoc_isdelim(p));
613 		if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
614 			return(0);
615 	}
616 
617 	return(1);
618 }
619 
620 
621 /*
622  * Close out block partial/full explicit.
623  */
624 static int
625 blk_exp_close(MACRO_PROT_ARGS)
626 {
627 	int	 	 j, c, lastarg, maxargs, flushed;
628 	char		*p;
629 
630 	switch (tok) {
631 	case (MDOC_Ec):
632 		maxargs = 1;
633 		break;
634 	default:
635 		maxargs = 0;
636 		break;
637 	}
638 
639 	if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
640 		if (buf[*pos])
641 			if ( ! mdoc_pwarn(m, line, ppos, ENOLINE))
642 				return(0);
643 
644 		if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
645 			return(0);
646 		return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
647 	}
648 
649 	if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
650 		return(0);
651 
652 	if (maxargs > 0)
653 		if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
654 			return(0);
655 
656 	for (flushed = j = 0; ; j++) {
657 		lastarg = *pos;
658 
659 		if (j == maxargs && ! flushed) {
660 			if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
661 				return(0);
662 			flushed = 1;
663 		}
664 
665 		c = mdoc_args(m, line, pos, buf, tok, &p);
666 
667 		if (ARGS_ERROR == c)
668 			return(0);
669 		if (ARGS_PUNCT == c)
670 			break;
671 		if (ARGS_EOLN == c)
672 			break;
673 
674 		if (MDOC_MAX != (c = lookup(tok, p))) {
675 			if ( ! flushed) {
676 				if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
677 					return(0);
678 				flushed = 1;
679 			}
680 			if ( ! mdoc_macro(m, c, line, lastarg, pos, buf))
681 				return(0);
682 			break;
683 		}
684 
685 		if ( ! mdoc_word_alloc(m, line, lastarg, p))
686 			return(0);
687 	}
688 
689 	if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
690 		return(0);
691 
692 	if (ppos > 1)
693 		return(1);
694 	return(append_delims(m, line, pos, buf));
695 }
696 
697 
698 static int
699 in_line(MACRO_PROT_ARGS)
700 {
701 	int		  la, lastpunct, c, w, cnt, d, nc;
702 	struct mdoc_arg	 *arg;
703 	char		 *p;
704 
705 	/*
706 	 * Whether we allow ignored elements (those without content,
707 	 * usually because of reserved words) to squeak by.
708 	 */
709 	switch (tok) {
710 	case (MDOC_An):
711 		/* FALLTHROUGH */
712 	case (MDOC_Ar):
713 		/* FALLTHROUGH */
714 	case (MDOC_Fl):
715 		/* FALLTHROUGH */
716 	case (MDOC_Lk):
717 		/* FALLTHROUGH */
718 	case (MDOC_Nm):
719 		/* FALLTHROUGH */
720 	case (MDOC_Pa):
721 		nc = 1;
722 		break;
723 	default:
724 		nc = 0;
725 		break;
726 	}
727 
728 	for (arg = NULL;; ) {
729 		la = *pos;
730 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
731 
732 		if (ARGV_WORD == c) {
733 			*pos = la;
734 			break;
735 		}
736 		if (ARGV_EOLN == c)
737 			break;
738 		if (ARGV_ARG == c)
739 			continue;
740 
741 		mdoc_argv_free(arg);
742 		return(0);
743 	}
744 
745 	for (cnt = 0, lastpunct = 1;; ) {
746 		la = *pos;
747 		w = mdoc_args(m, line, pos, buf, tok, &p);
748 
749 		if (ARGS_ERROR == w)
750 			return(0);
751 		if (ARGS_EOLN == w)
752 			break;
753 		if (ARGS_PUNCT == w)
754 			break;
755 
756 		/* Quoted words shouldn't be looked-up. */
757 
758 		c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
759 
760 		/*
761 		 * In this case, we've located a submacro and must
762 		 * execute it.  Close out scope, if open.  If no
763 		 * elements have been generated, either create one (nc)
764 		 * or raise a warning.
765 		 */
766 
767 		if (MDOC_MAX != c) {
768 			if (0 == lastpunct && ! rew_elem(m, tok))
769 				return(0);
770 			if (nc && 0 == cnt) {
771 				if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
772 					return(0);
773 				if ( ! rew_last(m, m->last))
774 					return(0);
775 			} else if ( ! nc && 0 == cnt) {
776 				mdoc_argv_free(arg);
777 				if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
778 					return(0);
779 			}
780 			c = mdoc_macro(m, c, line, la, pos, buf);
781 			if (0 == c)
782 				return(0);
783 			if (ppos > 1)
784 				return(1);
785 			return(append_delims(m, line, pos, buf));
786 		}
787 
788 		/*
789 		 * Non-quote-enclosed punctuation.  Set up our scope, if
790 		 * a word; rewind the scope, if a delimiter; then append
791 		 * the word.
792 		 */
793 
794 		d = mdoc_isdelim(p);
795 
796 		if (ARGS_QWORD != w && d) {
797 			if (0 == lastpunct && ! rew_elem(m, tok))
798 				return(0);
799 			lastpunct = 1;
800 		} else if (lastpunct) {
801 			if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
802 				return(0);
803 			lastpunct = 0;
804 		}
805 
806 		if ( ! d)
807 			cnt++;
808 		if ( ! mdoc_word_alloc(m, line, la, p))
809 			return(0);
810 	}
811 
812 	if (0 == lastpunct && ! rew_elem(m, tok))
813 		return(0);
814 
815 	/*
816 	 * If no elements have been collected and we're allowed to have
817 	 * empties (nc), open a scope and close it out.  Otherwise,
818 	 * raise a warning.
819 	 *
820 	 */
821 	if (nc && 0 == cnt) {
822 		if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
823 			return(0);
824 		if ( ! rew_last(m, m->last))
825 			return(0);
826 	} else if ( ! nc && 0 == cnt) {
827 		mdoc_argv_free(arg);
828 		if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
829 			return(0);
830 	}
831 
832 	if (ppos > 1)
833 		return(1);
834 	return(append_delims(m, line, pos, buf));
835 }
836 
837 
838 static int
839 blk_full(MACRO_PROT_ARGS)
840 {
841 	int		  c, lastarg, reopen, dohead;
842 	struct mdoc_arg	 *arg;
843 	char		 *p;
844 
845 	/*
846 	 * Whether to process a block-head section.  If this is
847 	 * non-zero, then a head will be opened for all line arguments.
848 	 * If not, then the head will always be empty and only a body
849 	 * will be opened, which will stay open at the eoln.
850 	 */
851 
852 	switch (tok) {
853 	case (MDOC_Nd):
854 		dohead = 0;
855 		break;
856 	default:
857 		dohead = 1;
858 		break;
859 	}
860 
861 	if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
862 		if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
863 			return(0);
864 		if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
865 			return(0);
866 	}
867 
868 	for (arg = NULL;; ) {
869 		lastarg = *pos;
870 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
871 
872 		if (ARGV_WORD == c) {
873 			*pos = lastarg;
874 			break;
875 		}
876 
877 		if (ARGV_EOLN == c)
878 			break;
879 		if (ARGV_ARG == c)
880 			continue;
881 
882 		mdoc_argv_free(arg);
883 		return(0);
884 	}
885 
886 	if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
887 		return(0);
888 
889 	if (0 == buf[*pos]) {
890 		if ( ! mdoc_head_alloc(m, line, ppos, tok))
891 			return(0);
892 		if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
893 			return(0);
894 		if ( ! mdoc_body_alloc(m, line, ppos, tok))
895 			return(0);
896 		return(1);
897 	}
898 
899 	if ( ! mdoc_head_alloc(m, line, ppos, tok))
900 		return(0);
901 
902 	/* Immediately close out head and enter body, if applicable. */
903 
904 	if (0 == dohead) {
905 		if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
906 			return(0);
907 		if ( ! mdoc_body_alloc(m, line, ppos, tok))
908 			return(0);
909 	}
910 
911 	for (reopen = 0;; ) {
912 		lastarg = *pos;
913 		c = mdoc_args(m, line, pos, buf, tok, &p);
914 
915 		if (ARGS_ERROR == c)
916 			return(0);
917 		if (ARGS_EOLN == c)
918 			break;
919 		if (ARGS_PHRASE == c) {
920 			assert(dohead);
921 			if (reopen && ! mdoc_head_alloc(m, line, ppos, tok))
922 				return(0);
923 			/*
924 			 * Phrases are self-contained macro phrases used
925 			 * in the columnar output of a macro. They need
926 			 * special handling.
927 			 */
928 			if ( ! phrase(m, line, lastarg, buf))
929 				return(0);
930 			if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
931 				return(0);
932 
933 			reopen = 1;
934 			continue;
935 		}
936 
937 		if (MDOC_MAX == (c = lookup(tok, p))) {
938 			if ( ! mdoc_word_alloc(m, line, lastarg, p))
939 				return(0);
940 			continue;
941 		}
942 
943 		if ( ! mdoc_macro(m, c, line, lastarg, pos, buf))
944 			return(0);
945 		break;
946 	}
947 
948 	if (1 == ppos && ! append_delims(m, line, pos, buf))
949 		return(0);
950 
951 	/* If the body's already open, then just return. */
952 	if (0 == dohead)
953 		return(1);
954 
955 	if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
956 		return(0);
957 	if ( ! mdoc_body_alloc(m, line, ppos, tok))
958 		return(0);
959 
960 	return(1);
961 }
962 
963 
964 static int
965 blk_part_imp(MACRO_PROT_ARGS)
966 {
967 	int		  la, c;
968 	char		 *p;
969 	struct mdoc_node *blk, *body, *n;
970 
971 	/* If applicable, close out prior scopes. */
972 
973 	if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
974 		return(0);
975 	/* Saved for later close-out. */
976 	blk = m->last;
977 	if ( ! mdoc_head_alloc(m, line, ppos, tok))
978 		return(0);
979 	if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
980 		return(0);
981 	if ( ! mdoc_body_alloc(m, line, ppos, tok))
982 		return(0);
983 	/* Saved for later close-out. */
984 	body = m->last;
985 
986 	/* Body argument processing. */
987 
988 	for (;;) {
989 		la = *pos;
990 		c = mdoc_args(m, line, pos, buf, tok, &p);
991 		assert(ARGS_PHRASE != c);
992 
993 		if (ARGS_ERROR == c)
994 			return(0);
995 		if (ARGS_PUNCT == c)
996 			break;
997 		if (ARGS_EOLN == c)
998 			break;
999 
1000 		if (MDOC_MAX == (c = lookup(tok, p))) {
1001 			if ( ! mdoc_word_alloc(m, line, la, p))
1002 				return(0);
1003 			continue;
1004 		}
1005 
1006 		if ( ! mdoc_macro(m, c, line, la, pos, buf))
1007 			return(0);
1008 		break;
1009 	}
1010 
1011 	/*
1012 	 * If we can't rewind to our body, then our scope has already
1013 	 * been closed by another macro (like `Oc' closing `Op').  This
1014 	 * is ugly behaviour nodding its head to OpenBSD's overwhelming
1015 	 * crufty use of `Op' breakage--XXX, deprecate in time.
1016 	 */
1017 	for (n = m->last; n; n = n->parent)
1018 		if (body == n)
1019 			break;
1020 	if (NULL == n && ! mdoc_nwarn(m, body, EIMPBRK))
1021 		return(0);
1022 	if (n && ! rew_last(m, body))
1023 		return(0);
1024 
1025 	/* Standard appending of delimiters. */
1026 
1027 	if (1 == ppos && ! append_delims(m, line, pos, buf))
1028 		return(0);
1029 
1030 	/* Rewind scope, if applicable. */
1031 
1032 	if (n && ! rew_last(m, blk))
1033 		return(0);
1034 
1035 	return(1);
1036 }
1037 
1038 
1039 static int
1040 blk_part_exp(MACRO_PROT_ARGS)
1041 {
1042 	int		  la, flushed, j, c, maxargs;
1043 	char		 *p;
1044 
1045 	/* Number of head arguments.  Only `Eo' has these, */
1046 
1047 	switch (tok) {
1048 	case (MDOC_Eo):
1049 		maxargs = 1;
1050 		break;
1051 	default:
1052 		maxargs = 0;
1053 		break;
1054 	}
1055 
1056 	/* Begin the block scope. */
1057 
1058 	if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1059 		return(0);
1060 
1061 	/*
1062 	 * If no head arguments, open and then close out a head, noting
1063 	 * that we've flushed our terms.  `flushed' means that we've
1064 	 * flushed out the head and the body is open.
1065 	 */
1066 
1067 	if (0 == maxargs) {
1068 		if ( ! mdoc_head_alloc(m, line, ppos, tok))
1069 			return(0);
1070 		if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1071 			return(0);
1072 		if ( ! mdoc_body_alloc(m, line, ppos, tok))
1073 			return(0);
1074 		flushed = 1;
1075 	} else {
1076 		if ( ! mdoc_head_alloc(m, line, ppos, tok))
1077 			return(0);
1078 		flushed = 0;
1079 	}
1080 
1081 	/* Process the head/head+body line arguments. */
1082 
1083 	for (j = 0; ; j++) {
1084 		la = *pos;
1085 		if (j == maxargs && ! flushed) {
1086 			if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1087 				return(0);
1088 			flushed = 1;
1089 			if ( ! mdoc_body_alloc(m, line, ppos, tok))
1090 				return(0);
1091 		}
1092 
1093 		c = mdoc_args(m, line, pos, buf, tok, &p);
1094 		assert(ARGS_PHRASE != c);
1095 
1096 		if (ARGS_ERROR == c)
1097 			return(0);
1098 		if (ARGS_PUNCT == c)
1099 			break;
1100 		if (ARGS_EOLN == c)
1101 			break;
1102 
1103 		if (MDOC_MAX != (c = lookup(tok, p))) {
1104 			if ( ! flushed) {
1105 				if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1106 					return(0);
1107 				flushed = 1;
1108 				if ( ! mdoc_body_alloc(m, line, ppos, tok))
1109 					return(0);
1110 			}
1111 			if ( ! mdoc_macro(m, c, line, la, pos, buf))
1112 				return(0);
1113 			break;
1114 		}
1115 
1116 		if ( ! flushed && mdoc_isdelim(p)) {
1117 			if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1118 				return(0);
1119 			flushed = 1;
1120 			if ( ! mdoc_body_alloc(m, line, ppos, tok))
1121 				return(0);
1122 		}
1123 
1124 		if ( ! mdoc_word_alloc(m, line, la, p))
1125 			return(0);
1126 	}
1127 
1128 	/* Close the head and open the body, if applicable. */
1129 
1130 	if ( ! flushed) {
1131 		if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1132 			return(0);
1133 		if ( ! mdoc_body_alloc(m, line, ppos, tok))
1134 			return(0);
1135 	}
1136 
1137 	/* Standard appending of delimiters. */
1138 
1139 	if (ppos > 1)
1140 		return(1);
1141 	return(append_delims(m, line, pos, buf));
1142 }
1143 
1144 
1145 static int
1146 in_line_argn(MACRO_PROT_ARGS)
1147 {
1148 	int		  la, flushed, j, c, maxargs;
1149 	struct mdoc_arg	 *arg;
1150 	char		 *p;
1151 
1152 	/* Fixed maximum arguments per macro, if applicable. */
1153 
1154 	switch (tok) {
1155 	case (MDOC_Ap):
1156 		/* FALLTHROUGH */
1157 	case (MDOC_No):
1158 		/* FALLTHROUGH */
1159 	case (MDOC_Ns):
1160 		/* FALLTHROUGH */
1161 	case (MDOC_Ux):
1162 		maxargs = 0;
1163 		break;
1164 	default:
1165 		maxargs = 1;
1166 		break;
1167 	}
1168 
1169 	/* Macro argument processing. */
1170 
1171 	for (arg = NULL;; ) {
1172 		la = *pos;
1173 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
1174 
1175 		if (ARGV_WORD == c) {
1176 			*pos = la;
1177 			break;
1178 		}
1179 
1180 		if (ARGV_EOLN == c)
1181 			break;
1182 		if (ARGV_ARG == c)
1183 			continue;
1184 
1185 		mdoc_argv_free(arg);
1186 		return(0);
1187 	}
1188 
1189 	/* Open the element scope. */
1190 
1191 	if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1192 		return(0);
1193 
1194 	/* Process element arguments. */
1195 
1196 	for (flushed = j = 0; ; j++) {
1197 		la = *pos;
1198 
1199 		if (j == maxargs && ! flushed) {
1200 			if ( ! rew_elem(m, tok))
1201 				return(0);
1202 			flushed = 1;
1203 		}
1204 
1205 		c = mdoc_args(m, line, pos, buf, tok, &p);
1206 
1207 		if (ARGS_ERROR == c)
1208 			return(0);
1209 		if (ARGS_PUNCT == c)
1210 			break;
1211 		if (ARGS_EOLN == c)
1212 			break;
1213 
1214 		if (MDOC_MAX != (c = lookup(tok, p))) {
1215 			if ( ! flushed && ! rew_elem(m, tok))
1216 				return(0);
1217 			flushed = 1;
1218 			if ( ! mdoc_macro(m, c, line, la, pos, buf))
1219 				return(0);
1220 			break;
1221 		}
1222 
1223 		if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1224 				! flushed && mdoc_isdelim(p)) {
1225 			if ( ! rew_elem(m, tok))
1226 				return(0);
1227 			flushed = 1;
1228 		}
1229 
1230 		if ( ! mdoc_word_alloc(m, line, la, p))
1231 			return(0);
1232 	}
1233 
1234 	/* Close out and append delimiters. */
1235 
1236 	if ( ! flushed && ! rew_elem(m, tok))
1237 		return(0);
1238 
1239 	if (ppos > 1)
1240 		return(1);
1241 	return(append_delims(m, line, pos, buf));
1242 }
1243 
1244 
1245 static int
1246 in_line_eoln(MACRO_PROT_ARGS)
1247 {
1248 	int		  c, w, la;
1249 	struct mdoc_arg	 *arg;
1250 	char		 *p;
1251 
1252 	assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1253 
1254 	/* Parse macro arguments. */
1255 
1256 	for (arg = NULL; ; ) {
1257 		la = *pos;
1258 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
1259 
1260 		if (ARGV_WORD == c) {
1261 			*pos = la;
1262 			break;
1263 		}
1264 		if (ARGV_EOLN == c)
1265 			break;
1266 		if (ARGV_ARG == c)
1267 			continue;
1268 
1269 		mdoc_argv_free(arg);
1270 		return(0);
1271 	}
1272 
1273 	/* Open element scope. */
1274 
1275 	if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1276 		return(0);
1277 
1278 	/* Parse argument terms. */
1279 
1280 	for (;;) {
1281 		la = *pos;
1282 		w = mdoc_args(m, line, pos, buf, tok, &p);
1283 
1284 		if (ARGS_ERROR == w)
1285 			return(0);
1286 		if (ARGS_EOLN == w)
1287 			break;
1288 
1289 		c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
1290 
1291 		if (MDOC_MAX != c) {
1292 			if ( ! rew_elem(m, tok))
1293 				return(0);
1294 			return(mdoc_macro(m, c, line, la, pos, buf));
1295 		}
1296 
1297 		if ( ! mdoc_word_alloc(m, line, la, p))
1298 			return(0);
1299 	}
1300 
1301 	/* Close out (no delimiters). */
1302 
1303 	return(rew_elem(m, tok));
1304 }
1305 
1306 
1307 /* ARGSUSED */
1308 static int
1309 obsolete(MACRO_PROT_ARGS)
1310 {
1311 
1312 	return(mdoc_pwarn(m, line, ppos, EOBS));
1313 }
1314 
1315 
1316 /*
1317  * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1318  * They're unusual because they're basically free-form text until a
1319  * macro is encountered.
1320  */
1321 static int
1322 phrase(struct mdoc *m, int line, int ppos, char *buf)
1323 {
1324 	int		  c, w, la, pos;
1325 	char		 *p;
1326 
1327 	for (pos = ppos; ; ) {
1328 		la = pos;
1329 
1330 		/* Note: no calling context! */
1331 		w = mdoc_zargs(m, line, &pos, buf, 0, &p);
1332 
1333 		if (ARGS_ERROR == w)
1334 			return(0);
1335 		if (ARGS_EOLN == w)
1336 			break;
1337 
1338 		c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(p);
1339 
1340 		if (MDOC_MAX != c) {
1341 			if ( ! mdoc_macro(m, c, line, la, &pos, buf))
1342 				return(0);
1343 			return(append_delims(m, line, &pos, buf));
1344 		}
1345 
1346 		if ( ! mdoc_word_alloc(m, line, la, p))
1347 			return(0);
1348 	}
1349 
1350 	return(1);
1351 }
1352 
1353 
1354