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