xref: /openbsd-src/usr.bin/mandoc/mdoc_macro.c (revision cd1eb269cafb12c415be1749cd4a4b5422710415)
1 /*	$Id: mdoc_macro.c,v 1.35 2010/04/07 23:15:05 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 #include <time.h>
23 
24 #include "libmdoc.h"
25 
26 enum	rew {
27 	REWIND_REWIND,
28 	REWIND_NOHALT,
29 	REWIND_HALT
30 };
31 
32 static	int	  ctx_synopsis(MACRO_PROT_ARGS);
33 static	int	  obsolete(MACRO_PROT_ARGS);
34 static	int	  blk_part_exp(MACRO_PROT_ARGS);
35 static	int	  in_line_eoln(MACRO_PROT_ARGS);
36 static	int	  in_line_argn(MACRO_PROT_ARGS);
37 static	int	  in_line(MACRO_PROT_ARGS);
38 static	int	  blk_full(MACRO_PROT_ARGS);
39 static	int	  blk_exp_close(MACRO_PROT_ARGS);
40 static	int	  blk_part_imp(MACRO_PROT_ARGS);
41 
42 static	int	  phrase(struct mdoc *, int, int, char *);
43 static	enum rew  rew_dohalt(enum mdoct, enum mdoc_type,
44 			const struct mdoc_node *);
45 static	enum mdoct rew_alt(enum mdoct);
46 static	int	  rew_dobreak(enum mdoct, const struct mdoc_node *);
47 static	int	  rew_elem(struct mdoc *, enum mdoct);
48 static	int	  rew_sub(enum mdoc_type, struct mdoc *,
49 			enum mdoct, int, int);
50 static	int	  rew_last(struct mdoc *,
51 			const struct mdoc_node *);
52 static	int	  append_delims(struct mdoc *, int, int *, char *);
53 static	int	  lookup(int, const char *);
54 static	int	  lookup_raw(const char *);
55 static	int	  swarn(struct mdoc *, enum mdoc_type, int, int,
56 			const struct mdoc_node *);
57 
58 /* Central table of library: who gets parsed how. */
59 
60 const	struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
61 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
62 	{ in_line_eoln, MDOC_PROLOGUE }, /* Dd */
63 	{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */
64 	{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
65 	{ blk_full, 0 }, /* Sh */
66 	{ blk_full, 0 }, /* Ss */
67 	{ in_line_eoln, 0 }, /* Pp */
68 	{ blk_part_imp, MDOC_PARSED }, /* D1 */
69 	{ blk_part_imp, MDOC_PARSED }, /* Dl */
70 	{ blk_full, MDOC_EXPLICIT }, /* Bd */
71 	{ blk_exp_close, MDOC_EXPLICIT }, /* Ed */
72 	{ blk_full, MDOC_EXPLICIT }, /* Bl */
73 	{ blk_exp_close, MDOC_EXPLICIT }, /* El */
74 	{ blk_full, MDOC_PARSED }, /* It */
75 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
76 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
77 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
78 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
79 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
80 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
81 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
82 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
83 	{ in_line_eoln, 0 }, /* Ex */
84 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
85 	{ in_line_eoln, 0 }, /* Fd */
86 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
87 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
88 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
89 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
90 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
91 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
92 	{ blk_full, 0 }, /* Nd */
93 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
94 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
95 	{ obsolete, 0 }, /* Ot */
96 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
97 	{ in_line_eoln, 0 }, /* Rv */
98 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
99 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
100 	{ ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
101 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
102 	{ in_line_eoln, 0 }, /* %A */
103 	{ in_line_eoln, 0 }, /* %B */
104 	{ in_line_eoln, 0 }, /* %D */
105 	{ in_line_eoln, 0 }, /* %I */
106 	{ in_line_eoln, 0 }, /* %J */
107 	{ in_line_eoln, 0 }, /* %N */
108 	{ in_line_eoln, 0 }, /* %O */
109 	{ in_line_eoln, 0 }, /* %P */
110 	{ in_line_eoln, 0 }, /* %R */
111 	{ in_line_eoln, 0 }, /* %T */
112 	{ in_line_eoln, 0 }, /* %V */
113 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
114 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
115 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
116 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
117 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
118 	{ blk_full, MDOC_EXPLICIT }, /* Bf */
119 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
120 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
121 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
122 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
123 	{ in_line_eoln, 0 }, /* Db */
124 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
125 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
126 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
127 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
128 	{ blk_exp_close, MDOC_EXPLICIT }, /* Ef */
129 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
130 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
131 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
132 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
133 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */
134 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
135 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
136 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
137 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
138 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
139 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
140 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
141 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
142 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
143 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
144 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
145 	{ blk_exp_close, MDOC_EXPLICIT }, /* Re */
146 	{ blk_full, MDOC_EXPLICIT }, /* Rs */
147 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
148 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
149 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
150 	{ in_line_eoln, 0 }, /* Sm */
151 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
152 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
153 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
154 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
155 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
156 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
157 	{ blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
158 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
159 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
160 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
161 	{ blk_full, MDOC_EXPLICIT }, /* Bk */
162 	{ blk_exp_close, MDOC_EXPLICIT }, /* Ek */
163 	{ in_line_eoln, 0 }, /* Bt */
164 	{ in_line_eoln, 0 }, /* Hf */
165 	{ obsolete, 0 }, /* Fr */
166 	{ in_line_eoln, 0 }, /* Ud */
167 	{ in_line_eoln, 0 }, /* Lb */
168 	{ in_line_eoln, 0 }, /* Lp */
169 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
170 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
171 	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
172 	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
173 	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
174 	{ in_line_eoln, 0 }, /* %C */
175 	{ obsolete, 0 }, /* Es */
176 	{ obsolete, 0 }, /* En */
177 	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
178 	{ in_line_eoln, 0 }, /* %Q */
179 	{ in_line_eoln, 0 }, /* br */
180 	{ in_line_eoln, 0 }, /* sp */
181 	{ in_line_eoln, 0 }, /* %U */
182 	{ NULL, 0 }, /* eos */
183 };
184 
185 const	struct mdoc_macro * const mdoc_macros = __mdoc_macros;
186 
187 
188 static int
189 swarn(struct mdoc *mdoc, enum mdoc_type type,
190 		int line, int pos, const struct mdoc_node *p)
191 {
192 	const char	*n, *t, *tt;
193 
194 	n = t = "<root>";
195 	tt = "block";
196 
197 	switch (type) {
198 	case (MDOC_BODY):
199 		tt = "multi-line";
200 		break;
201 	case (MDOC_HEAD):
202 		tt = "line";
203 		break;
204 	default:
205 		break;
206 	}
207 
208 	switch (p->type) {
209 	case (MDOC_BLOCK):
210 		n = mdoc_macronames[p->tok];
211 		t = "block";
212 		break;
213 	case (MDOC_BODY):
214 		n = mdoc_macronames[p->tok];
215 		t = "multi-line";
216 		break;
217 	case (MDOC_HEAD):
218 		n = mdoc_macronames[p->tok];
219 		t = "line";
220 		break;
221 	default:
222 		break;
223 	}
224 
225 	if ( ! (MDOC_IGN_SCOPE & mdoc->pflags))
226 		return(mdoc_verr(mdoc, line, pos,
227 				"%s scope breaks %s scope of %s",
228 				tt, t, n));
229 	return(mdoc_vwarn(mdoc, line, pos,
230 				"%s scope breaks %s scope of %s",
231 				tt, t, n));
232 }
233 
234 
235 /*
236  * This is called at the end of parsing.  It must traverse up the tree,
237  * closing out open [implicit] scopes.  Obviously, open explicit scopes
238  * are errors.
239  */
240 int
241 mdoc_macroend(struct mdoc *m)
242 {
243 	struct mdoc_node *n;
244 
245 	/* Scan for open explicit scopes. */
246 
247 	n = MDOC_VALID & m->last->flags ?  m->last->parent : m->last;
248 
249 	for ( ; n; n = n->parent) {
250 		if (MDOC_BLOCK != n->type)
251 			continue;
252 		if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
253 			continue;
254 		return(mdoc_nerr(m, n, EOPEN));
255 	}
256 
257 	/* Rewind to the first. */
258 
259 	return(rew_last(m, m->first));
260 }
261 
262 
263 /*
264  * Look up a macro from within a subsequent context.
265  */
266 static int
267 lookup(int from, const char *p)
268 {
269 	/* FIXME: make -diag lists be un-PARSED. */
270 
271 	if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
272 		return(MDOC_MAX);
273 	return(lookup_raw(p));
274 }
275 
276 
277 /*
278  * Lookup a macro following the initial line macro.
279  */
280 static int
281 lookup_raw(const char *p)
282 {
283 	int		 res;
284 
285 	if (MDOC_MAX == (res = mdoc_hash_find(p)))
286 		return(MDOC_MAX);
287 	if (MDOC_CALLABLE & mdoc_macros[res].flags)
288 		return(res);
289 	return(MDOC_MAX);
290 }
291 
292 
293 static int
294 rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
295 {
296 
297 	assert(to);
298 	mdoc->next = MDOC_NEXT_SIBLING;
299 
300 	/* LINTED */
301 	while (mdoc->last != to) {
302 		if ( ! mdoc_valid_post(mdoc))
303 			return(0);
304 		if ( ! mdoc_action_post(mdoc))
305 			return(0);
306 		mdoc->last = mdoc->last->parent;
307 		assert(mdoc->last);
308 	}
309 
310 	if ( ! mdoc_valid_post(mdoc))
311 		return(0);
312 	return(mdoc_action_post(mdoc));
313 }
314 
315 
316 /*
317  * Return the opening macro of a closing one, e.g., `Ec' has `Eo' as its
318  * matching pair.
319  */
320 static enum mdoct
321 rew_alt(enum mdoct tok)
322 {
323 	switch (tok) {
324 	case (MDOC_Ac):
325 		return(MDOC_Ao);
326 	case (MDOC_Bc):
327 		return(MDOC_Bo);
328 	case (MDOC_Brc):
329 		return(MDOC_Bro);
330 	case (MDOC_Dc):
331 		return(MDOC_Do);
332 	case (MDOC_Ec):
333 		return(MDOC_Eo);
334 	case (MDOC_Ed):
335 		return(MDOC_Bd);
336 	case (MDOC_Ef):
337 		return(MDOC_Bf);
338 	case (MDOC_Ek):
339 		return(MDOC_Bk);
340 	case (MDOC_El):
341 		return(MDOC_Bl);
342 	case (MDOC_Fc):
343 		return(MDOC_Fo);
344 	case (MDOC_Oc):
345 		return(MDOC_Oo);
346 	case (MDOC_Pc):
347 		return(MDOC_Po);
348 	case (MDOC_Qc):
349 		return(MDOC_Qo);
350 	case (MDOC_Re):
351 		return(MDOC_Rs);
352 	case (MDOC_Sc):
353 		return(MDOC_So);
354 	case (MDOC_Xc):
355 		return(MDOC_Xo);
356 	default:
357 		break;
358 	}
359 	abort();
360 	/* NOTREACHED */
361 }
362 
363 
364 /*
365  * Rewind rules.  This indicates whether to stop rewinding
366  * (REWIND_HALT) without touching our current scope, stop rewinding and
367  * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
368  * The scope-closing and so on occurs in the various rew_* routines.
369  */
370 static enum rew
371 rew_dohalt(enum mdoct tok, enum mdoc_type type,
372 		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(enum mdoct 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 		if (MDOC_Op == p->tok)
541 			return(1);
542 		break;
543 	default:
544 		break;
545 	}
546 
547 	if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
548 		return(p->tok == rew_alt(tok));
549 	else if (MDOC_BLOCK == p->type)
550 		return(1);
551 
552 	return(tok == p->tok);
553 }
554 
555 
556 static int
557 rew_elem(struct mdoc *mdoc, enum mdoct tok)
558 {
559 	struct mdoc_node *n;
560 
561 	n = mdoc->last;
562 	if (MDOC_ELEM != n->type)
563 		n = n->parent;
564 	assert(MDOC_ELEM == n->type);
565 	assert(tok == n->tok);
566 
567 	return(rew_last(mdoc, n));
568 }
569 
570 
571 static int
572 rew_sub(enum mdoc_type t, struct mdoc *m,
573 		enum mdoct tok, int line, int ppos)
574 {
575 	struct mdoc_node *n;
576 	enum rew	  c;
577 
578 	/* LINTED */
579 	for (n = m->last; n; n = n->parent) {
580 		c = rew_dohalt(tok, t, n);
581 		if (REWIND_HALT == c) {
582 			if (MDOC_BLOCK != t)
583 				return(1);
584 			if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))
585 				return(1);
586 			return(mdoc_perr(m, line, ppos, ENOCTX));
587 		}
588 		if (REWIND_REWIND == c)
589 			break;
590 		else if (rew_dobreak(tok, n))
591 			continue;
592 		if ( ! swarn(m, t, line, ppos, n))
593 			return(0);
594 	}
595 
596 	assert(n);
597 	if ( ! rew_last(m, n))
598 		return(0);
599 
600 	/*
601 	 * The current block extends an enclosing block beyond a line
602 	 * break.  Now that the current block ends, close the enclosing
603 	 * block, too.
604 	 */
605 	if (NULL != (n = n->pending)) {
606 		assert(MDOC_HEAD == n->type);
607 		if ( ! rew_last(m, n))
608 			return(0);
609 		if ( ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
610 			return(0);
611 	}
612 	return(1);
613 }
614 
615 
616 static int
617 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
618 {
619 	int		 c, lastarg;
620 	char		*p;
621 
622 	if (0 == buf[*pos])
623 		return(1);
624 
625 	for (;;) {
626 		lastarg = *pos;
627 		c = mdoc_zargs(mdoc, line, pos, buf, ARGS_NOWARN, &p);
628 		assert(ARGS_PHRASE != c);
629 
630 		if (ARGS_ERROR == c)
631 			return(0);
632 		else if (ARGS_EOLN == c)
633 			break;
634 		assert(mdoc_isdelim(p));
635 		if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
636 			return(0);
637 	}
638 
639 	return(1);
640 }
641 
642 
643 /*
644  * Close out block partial/full explicit.
645  */
646 static int
647 blk_exp_close(MACRO_PROT_ARGS)
648 {
649 	int	 	 j, c, lastarg, maxargs, flushed;
650 	char		*p;
651 
652 	switch (tok) {
653 	case (MDOC_Ec):
654 		maxargs = 1;
655 		break;
656 	default:
657 		maxargs = 0;
658 		break;
659 	}
660 
661 	if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
662 		if (buf[*pos])
663 			if ( ! mdoc_pwarn(m, line, ppos, ENOLINE))
664 				return(0);
665 
666 		if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
667 			return(0);
668 		return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
669 	}
670 
671 	if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
672 		return(0);
673 
674 	if (maxargs > 0)
675 		if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
676 			return(0);
677 
678 	for (flushed = j = 0; ; j++) {
679 		lastarg = *pos;
680 
681 		if (j == maxargs && ! flushed) {
682 			if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
683 				return(0);
684 			flushed = 1;
685 		}
686 
687 		c = mdoc_args(m, line, pos, buf, tok, &p);
688 
689 		if (ARGS_ERROR == c)
690 			return(0);
691 		if (ARGS_PUNCT == c)
692 			break;
693 		if (ARGS_EOLN == c)
694 			break;
695 
696 		if (MDOC_MAX != (c = lookup(tok, p))) {
697 			if ( ! flushed) {
698 				if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
699 					return(0);
700 				flushed = 1;
701 			}
702 			if ( ! mdoc_macro(m, c, line, lastarg, pos, buf))
703 				return(0);
704 			break;
705 		}
706 
707 		if ( ! mdoc_word_alloc(m, line, lastarg, p))
708 			return(0);
709 	}
710 
711 	if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
712 		return(0);
713 
714 	if (ppos > 1)
715 		return(1);
716 	return(append_delims(m, line, pos, buf));
717 }
718 
719 
720 static int
721 in_line(MACRO_PROT_ARGS)
722 {
723 	int		  la, lastpunct, c, w, cnt, d, nc;
724 	struct mdoc_arg	 *arg;
725 	char		 *p;
726 
727 	/*
728 	 * Whether we allow ignored elements (those without content,
729 	 * usually because of reserved words) to squeak by.
730 	 */
731 
732 	switch (tok) {
733 	case (MDOC_An):
734 		/* FALLTHROUGH */
735 	case (MDOC_Ar):
736 		/* FALLTHROUGH */
737 	case (MDOC_Fl):
738 		/* FALLTHROUGH */
739 	case (MDOC_Lk):
740 		/* FALLTHROUGH */
741 	case (MDOC_Nm):
742 		/* FALLTHROUGH */
743 	case (MDOC_Pa):
744 		nc = 1;
745 		break;
746 	default:
747 		nc = 0;
748 		break;
749 	}
750 
751 	for (arg = NULL;; ) {
752 		la = *pos;
753 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
754 
755 		if (ARGV_WORD == c) {
756 			*pos = la;
757 			break;
758 		}
759 		if (ARGV_EOLN == c)
760 			break;
761 		if (ARGV_ARG == c)
762 			continue;
763 
764 		mdoc_argv_free(arg);
765 		return(0);
766 	}
767 
768 	for (cnt = 0, lastpunct = 1;; ) {
769 		la = *pos;
770 		w = mdoc_args(m, line, pos, buf, tok, &p);
771 
772 		if (ARGS_ERROR == w)
773 			return(0);
774 		if (ARGS_EOLN == w)
775 			break;
776 		if (ARGS_PUNCT == w)
777 			break;
778 
779 		/* Quoted words shouldn't be looked-up. */
780 
781 		c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
782 
783 		/*
784 		 * In this case, we've located a submacro and must
785 		 * execute it.  Close out scope, if open.  If no
786 		 * elements have been generated, either create one (nc)
787 		 * or raise a warning.
788 		 */
789 
790 		if (MDOC_MAX != c) {
791 			if (0 == lastpunct && ! rew_elem(m, tok))
792 				return(0);
793 			if (nc && 0 == cnt) {
794 				if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
795 					return(0);
796 				if ( ! rew_last(m, m->last))
797 					return(0);
798 			} else if ( ! nc && 0 == cnt) {
799 				mdoc_argv_free(arg);
800 				if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
801 					return(0);
802 			}
803 			c = mdoc_macro(m, c, line, la, pos, buf);
804 			if (0 == c)
805 				return(0);
806 			if (ppos > 1)
807 				return(1);
808 			return(append_delims(m, line, pos, buf));
809 		}
810 
811 		/*
812 		 * Non-quote-enclosed punctuation.  Set up our scope, if
813 		 * a word; rewind the scope, if a delimiter; then append
814 		 * the word.
815 		 */
816 
817 		d = ARGS_QWORD == w ? 0 : mdoc_isdelim(p);
818 
819 		if (ARGS_QWORD != w && d) {
820 			if (0 == lastpunct && ! rew_elem(m, tok))
821 				return(0);
822 			lastpunct = 1;
823 		} else if (lastpunct) {
824 			if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
825 				return(0);
826 			lastpunct = 0;
827 		}
828 
829 		if ( ! d)
830 			cnt++;
831 		if ( ! mdoc_word_alloc(m, line, la, p))
832 			return(0);
833 
834 		/*
835 		 * `Fl' macros have their scope re-opened with each new
836 		 * word so that the `-' can be added to each one without
837 		 * having to parse out spaces.
838 		 */
839 		if (0 == lastpunct && MDOC_Fl == tok) {
840 			if ( ! rew_elem(m, tok))
841 				return(0);
842 			lastpunct = 1;
843 		}
844 	}
845 
846 	if (0 == lastpunct && ! rew_elem(m, tok))
847 		return(0);
848 
849 	/*
850 	 * If no elements have been collected and we're allowed to have
851 	 * empties (nc), open a scope and close it out.  Otherwise,
852 	 * raise a warning.
853 	 */
854 
855 	if (nc && 0 == cnt) {
856 		if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
857 			return(0);
858 		if ( ! rew_last(m, m->last))
859 			return(0);
860 	} else if ( ! nc && 0 == cnt) {
861 		mdoc_argv_free(arg);
862 		if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
863 			return(0);
864 	}
865 
866 	if (ppos > 1)
867 		return(1);
868 	return(append_delims(m, line, pos, buf));
869 }
870 
871 
872 static int
873 blk_full(MACRO_PROT_ARGS)
874 {
875 	int		  c, la;
876 	struct mdoc_arg	 *arg;
877 	struct mdoc_node *head; /* save of head macro */
878 	struct mdoc_node *body; /* save of body macro */
879 	struct mdoc_node *n;
880 	char		 *p;
881 
882 	/* Close out prior implicit scope. */
883 
884 	if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
885 		if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
886 			return(0);
887 		if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
888 			return(0);
889 	}
890 
891 	/*
892 	 * This routine accomodates implicitly- and explicitly-scoped
893 	 * macro openings.  Implicit ones first close out prior scope
894 	 * (seen above).  Delay opening the head until necessary to
895 	 * allow leading punctuation to print.  Special consideration
896 	 * for `It -column', which has phrase-part syntax instead of
897 	 * regular child nodes.
898 	 */
899 
900 	for (arg = NULL;; ) {
901 		la = *pos;
902 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
903 
904 		if (ARGV_WORD == c) {
905 			*pos = la;
906 			break;
907 		}
908 
909 		if (ARGV_EOLN == c)
910 			break;
911 		if (ARGV_ARG == c)
912 			continue;
913 
914 		mdoc_argv_free(arg);
915 		return(0);
916 	}
917 
918 	if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
919 		return(0);
920 
921 	head = body = NULL;
922 
923 	/*
924 	 * The `Nd' macro has all arguments in its body: it's a hybrid
925 	 * of block partial-explicit and full-implicit.  Stupid.
926 	 */
927 
928 	if (MDOC_Nd == tok) {
929 		if ( ! mdoc_head_alloc(m, line, ppos, tok))
930 			return(0);
931 		head = m->last;
932 		if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
933 			return(0);
934 		if ( ! mdoc_body_alloc(m, line, ppos, tok))
935 			return(0);
936 		body = m->last;
937 	}
938 
939 	for (;;) {
940 		la = *pos;
941 		c = mdoc_args(m, line, pos, buf, tok, &p);
942 
943 		if (ARGS_ERROR == c)
944 			return(0);
945 		if (ARGS_EOLN == c)
946 			break;
947 
948 /*
949  * XXX Temporarily disable the handling of leading punctuation.
950  *     We must investigate the fallout before enabling this.
951  */
952 #if 0
953 		/* Don't emit leading punct. for phrases. */
954 
955 		if (NULL == head && ARGS_PHRASE != c &&
956 				ARGS_QWORD != c &&
957 				1 == mdoc_isdelim(p)) {
958 			if ( ! mdoc_word_alloc(m, line, la, p))
959 				return(0);
960 			continue;
961 		}
962 #endif
963 
964 		/* Always re-open head for phrases. */
965 
966 		if (NULL == head || ARGS_PHRASE == c) {
967 			if ( ! mdoc_head_alloc(m, line, ppos, tok))
968 				return(0);
969 			head = m->last;
970 		}
971 
972 		if (ARGS_PHRASE == c) {
973 			if ( ! phrase(m, line, la, buf))
974 				return(0);
975 			if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
976 				return(0);
977 			continue;
978 		}
979 
980 		c = lookup(tok, p);
981 		if (MDOC_MAX != c) {
982 			if ( ! mdoc_macro(m, c, line, la, pos, buf))
983 				return(0);
984 			break;
985 		}
986 		if ( ! mdoc_word_alloc(m, line, la, p))
987 			return(0);
988 
989 	}
990 
991 	if (NULL == head) {
992 		if ( ! mdoc_head_alloc(m, line, ppos, tok))
993 			return(0);
994 		head = m->last;
995 	}
996 
997 	if (1 == ppos && ! append_delims(m, line, pos, buf))
998 		return(0);
999 
1000 	/* If we've already opened our body, exit now. */
1001 
1002 	if (NULL != body)
1003 		return(1);
1004 
1005 	/*
1006 	 * If there is an open (i.e., unvalidated) sub-block requiring
1007 	 * explicit close-out, postpone switching the current block from
1008 	 * head to body until the rew_sub() call closing out that
1009 	 * sub-block.
1010 	 */
1011 	for (n = m->last; n && n != head; n = n->parent) {
1012 		if (MDOC_BLOCK == n->type &&
1013 				MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1014 				! (MDOC_VALID & n->flags)) {
1015 			assert( ! (MDOC_ACTED & n->flags));
1016 			n->pending = head;
1017 			return(1);
1018 		}
1019 	}
1020 	/* Close out scopes to remain in a consistent state. */
1021 
1022 	if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1023 		return(0);
1024 	if ( ! mdoc_body_alloc(m, line, ppos, tok))
1025 		return(0);
1026 
1027 	return(1);
1028 }
1029 
1030 
1031 static int
1032 blk_part_imp(MACRO_PROT_ARGS)
1033 {
1034 	int		  la, c;
1035 	char		 *p;
1036 	struct mdoc_node *blk; /* saved block context */
1037 	struct mdoc_node *body; /* saved body context */
1038 	struct mdoc_node *n;
1039 
1040 	/*
1041 	 * A macro that spans to the end of the line.  This is generally
1042 	 * (but not necessarily) called as the first macro.  The block
1043 	 * has a head as the immediate child, which is always empty,
1044 	 * followed by zero or more opening punctuation nodes, then the
1045 	 * body (which may be empty, depending on the macro), then zero
1046 	 * or more closing punctuation nodes.
1047 	 */
1048 
1049 	if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1050 		return(0);
1051 
1052 	blk = m->last;
1053 
1054 	if ( ! mdoc_head_alloc(m, line, ppos, tok))
1055 		return(0);
1056 	if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1057 		return(0);
1058 
1059 	/*
1060 	 * Open the body scope "on-demand", that is, after we've
1061 	 * processed all our the leading delimiters (open parenthesis,
1062 	 * etc.).
1063 	 */
1064 
1065 	for (body = NULL; ; ) {
1066 		la = *pos;
1067 		c = mdoc_args(m, line, pos, buf, tok, &p);
1068 
1069 		assert(ARGS_PHRASE != c);
1070 
1071 		if (ARGS_ERROR == c)
1072 			return(0);
1073 		if (ARGS_EOLN == c)
1074 			break;
1075 		if (ARGS_PUNCT == c)
1076 			break;
1077 
1078 /*
1079  * XXX Temporarily disable the handling of leading punctuation.
1080  *     We must investigate the fallout before enabling this.
1081  */
1082 #if 0
1083 		if (NULL == body && ARGS_QWORD != c &&
1084 				1 == mdoc_isdelim(p)) {
1085 			if ( ! mdoc_word_alloc(m, line, la, p))
1086 				return(0);
1087 			continue;
1088 		}
1089 #endif
1090 
1091 		if (NULL == body) {
1092 		       if ( ! mdoc_body_alloc(m, line, ppos, tok))
1093 			       return(0);
1094 			body = m->last;
1095 		}
1096 
1097 		if (MDOC_MAX != (c = lookup(tok, p))) {
1098 			if ( ! mdoc_macro(m, c, line, la, pos, buf))
1099 				return(0);
1100 			break;
1101 		}
1102 
1103 		if ( ! mdoc_word_alloc(m, line, la, p))
1104 			return(0);
1105 	}
1106 
1107 	/* Clean-ups to leave in a consistent state. */
1108 
1109 	if (NULL == body) {
1110 		if ( ! mdoc_body_alloc(m, line, ppos, tok))
1111 			return(0);
1112 		body = m->last;
1113 	}
1114 
1115 	/*
1116 	 * If we can't rewind to our body, then our scope has already
1117 	 * been closed by another macro (like `Oc' closing `Op').  This
1118 	 * is ugly behaviour nodding its head to OpenBSD's overwhelming
1119 	 * crufty use of `Op' breakage.
1120 	 */
1121 	for (n = m->last; n; n = n->parent)
1122 		if (body == n)
1123 			break;
1124 
1125 	if (NULL == n && ! mdoc_nwarn(m, body, EIMPBRK))
1126 		return(0);
1127 
1128 	if (n && ! rew_last(m, body))
1129 		return(0);
1130 
1131 	/* Standard appending of delimiters. */
1132 
1133 	if (1 == ppos && ! append_delims(m, line, pos, buf))
1134 		return(0);
1135 
1136 	/* Rewind scope, if applicable. */
1137 
1138 	if (n && ! rew_last(m, blk))
1139 		return(0);
1140 
1141 	return(1);
1142 }
1143 
1144 
1145 static int
1146 blk_part_exp(MACRO_PROT_ARGS)
1147 {
1148 	int		  la, c;
1149 	struct mdoc_node *head; /* keep track of head */
1150 	struct mdoc_node *body; /* keep track of body */
1151 	char		 *p;
1152 
1153 	/*
1154 	 * The opening of an explicit macro having zero or more leading
1155 	 * punctuation nodes; a head with optional single element (the
1156 	 * case of `Eo'); and a body that may be empty.
1157 	 */
1158 
1159 	if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1160 		return(0);
1161 
1162 	for (head = body = NULL; ; ) {
1163 		la = *pos;
1164 		c = mdoc_args(m, line, pos, buf, tok, &p);
1165 
1166 		if (ARGS_ERROR == c)
1167 			return(0);
1168 		if (ARGS_PUNCT == c)
1169 			break;
1170 		if (ARGS_EOLN == c)
1171 			break;
1172 
1173 		assert(ARGS_PHRASE != c);
1174 
1175 /*
1176  * XXX Temporarily disable the handling of leading punctuation.
1177  *     We must investigate the fallout before enabling this.
1178  */
1179 #if 0
1180 		/* Flush out leading punctuation. */
1181 
1182 		if (NULL == head && ARGS_QWORD != c &&
1183 				1 == mdoc_isdelim(p)) {
1184 			assert(NULL == body);
1185 			if ( ! mdoc_word_alloc(m, line, la, p))
1186 				return(0);
1187 			continue;
1188 		}
1189 #endif
1190 
1191 		if (NULL == head) {
1192 			assert(NULL == body);
1193 			if ( ! mdoc_head_alloc(m, line, ppos, tok))
1194 				return(0);
1195 			head = m->last;
1196 		}
1197 
1198 		/*
1199 		 * `Eo' gobbles any data into the head, but most other
1200 		 * macros just immediately close out and begin the body.
1201 		 */
1202 
1203 		if (NULL == body) {
1204 			assert(head);
1205 			/* No check whether it's a macro! */
1206 			if (MDOC_Eo == tok)
1207 				if ( ! mdoc_word_alloc(m, line, la, p))
1208 					return(0);
1209 
1210 			if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1211 				return(0);
1212 			if ( ! mdoc_body_alloc(m, line, ppos, tok))
1213 				return(0);
1214 			body = m->last;
1215 
1216 			if (MDOC_Eo == tok)
1217 				continue;
1218 		}
1219 
1220 		assert(NULL != head && NULL != body);
1221 
1222 		if (MDOC_MAX != (c = lookup(tok, p))) {
1223 			if ( ! mdoc_macro(m, c, line, la, pos, buf))
1224 				return(0);
1225 			break;
1226 		}
1227 
1228 		if ( ! mdoc_word_alloc(m, line, la, p))
1229 			return(0);
1230 	}
1231 
1232 	/* Clean-up to leave in a consistent state. */
1233 
1234 	if (NULL == head) {
1235 		if ( ! mdoc_head_alloc(m, line, ppos, tok))
1236 			return(0);
1237 		head = m->last;
1238 	}
1239 
1240 	if (NULL == body) {
1241 		if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1242 			return(0);
1243 		if ( ! mdoc_body_alloc(m, line, ppos, tok))
1244 			return(0);
1245 		body = m->last;
1246 	}
1247 
1248 	/* Standard appending of delimiters. */
1249 
1250 	if (ppos > 1)
1251 		return(1);
1252 
1253 	return(append_delims(m, line, pos, buf));
1254 }
1255 
1256 
1257 static int
1258 in_line_argn(MACRO_PROT_ARGS)
1259 {
1260 	int		  la, flushed, j, c, maxargs;
1261 	struct mdoc_arg	 *arg;
1262 	char		 *p;
1263 
1264 	/*
1265 	 * A line macro that has a fixed number of arguments (maxargs).
1266 	 * Only open the scope once the first non-leading-punctuation is
1267 	 * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then
1268 	 * keep it open until the maximum number of arguments are
1269 	 * exhausted.
1270 	 */
1271 
1272 	switch (tok) {
1273 	case (MDOC_Ap):
1274 		/* FALLTHROUGH */
1275 	case (MDOC_No):
1276 		/* FALLTHROUGH */
1277 	case (MDOC_Ns):
1278 		/* FALLTHROUGH */
1279 	case (MDOC_Ux):
1280 		maxargs = 0;
1281 		break;
1282 	case (MDOC_Xr):
1283 		maxargs = 2;
1284 		break;
1285 	default:
1286 		maxargs = 1;
1287 		break;
1288 	}
1289 
1290 	for (arg = NULL; ; ) {
1291 		la = *pos;
1292 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
1293 
1294 		if (ARGV_WORD == c) {
1295 			*pos = la;
1296 			break;
1297 		}
1298 
1299 		if (ARGV_EOLN == c)
1300 			break;
1301 		if (ARGV_ARG == c)
1302 			continue;
1303 
1304 		mdoc_argv_free(arg);
1305 		return(0);
1306 	}
1307 
1308 	for (flushed = j = 0; ; ) {
1309 		la = *pos;
1310 		c = mdoc_args(m, line, pos, buf, tok, &p);
1311 
1312 		if (ARGS_ERROR == c)
1313 			return(0);
1314 		if (ARGS_PUNCT == c)
1315 			break;
1316 		if (ARGS_EOLN == c)
1317 			break;
1318 
1319 /*
1320  * XXX Temporarily disable the handling of leading punctuation.
1321  *     We must investigate the fallout before enabling this.
1322  */
1323 #if 0
1324 		if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1325 				ARGS_QWORD != c &&
1326 				0 == j && 1 == mdoc_isdelim(p)) {
1327 			if ( ! mdoc_word_alloc(m, line, la, p))
1328 				return(0);
1329 			continue;
1330 		} else
1331 #endif
1332 		if (0 == j)
1333 		       if ( ! mdoc_elem_alloc(m, line, la, tok, arg))
1334 			       return(0);
1335 
1336 		if (j == maxargs && ! flushed) {
1337 			if ( ! rew_elem(m, tok))
1338 				return(0);
1339 			flushed = 1;
1340 		}
1341 
1342 		if (MDOC_MAX != (c = lookup(tok, p))) {
1343 			if ( ! flushed && ! rew_elem(m, tok))
1344 				return(0);
1345 			flushed = 1;
1346 			if ( ! mdoc_macro(m, c, line, la, pos, buf))
1347 				return(0);
1348 			j++;
1349 			break;
1350 		}
1351 
1352 		if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1353 				ARGS_QWORD != c &&
1354 				! flushed && mdoc_isdelim(p)) {
1355 			if ( ! rew_elem(m, tok))
1356 				return(0);
1357 			flushed = 1;
1358 		}
1359 
1360 		/*
1361 		 * XXX: this is a hack to work around groff's ugliness
1362 		 * as regards `Xr' and extraneous arguments.  It should
1363 		 * ideally be deprecated behaviour, but because this is
1364 		 * code is no here, it's unlikely to be removed.
1365 		 */
1366 		if (MDOC_Xr == tok && j == maxargs) {
1367 			if ( ! mdoc_elem_alloc(m, line, la, MDOC_Ns, NULL))
1368 				return(0);
1369 			if ( ! rew_elem(m, MDOC_Ns))
1370 				return(0);
1371 		}
1372 
1373 		if ( ! mdoc_word_alloc(m, line, la, p))
1374 			return(0);
1375 		j++;
1376 	}
1377 
1378 	if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg))
1379 	       return(0);
1380 
1381 	/* Close out in a consistent state. */
1382 
1383 	if ( ! flushed && ! rew_elem(m, tok))
1384 		return(0);
1385 
1386 	if (ppos > 1)
1387 		return(1);
1388 	return(append_delims(m, line, pos, buf));
1389 }
1390 
1391 
1392 static int
1393 in_line_eoln(MACRO_PROT_ARGS)
1394 {
1395 	int		  c, w, la;
1396 	struct mdoc_arg	 *arg;
1397 	char		 *p;
1398 
1399 	assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1400 
1401 	/* Parse macro arguments. */
1402 
1403 	for (arg = NULL; ; ) {
1404 		la = *pos;
1405 		c = mdoc_argv(m, line, tok, &arg, pos, buf);
1406 
1407 		if (ARGV_WORD == c) {
1408 			*pos = la;
1409 			break;
1410 		}
1411 		if (ARGV_EOLN == c)
1412 			break;
1413 		if (ARGV_ARG == c)
1414 			continue;
1415 
1416 		mdoc_argv_free(arg);
1417 		return(0);
1418 	}
1419 
1420 	/* Open element scope. */
1421 
1422 	if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1423 		return(0);
1424 
1425 	/* Parse argument terms. */
1426 
1427 	for (;;) {
1428 		la = *pos;
1429 		w = mdoc_args(m, line, pos, buf, tok, &p);
1430 
1431 		if (ARGS_ERROR == w)
1432 			return(0);
1433 		if (ARGS_EOLN == w)
1434 			break;
1435 
1436 		c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
1437 
1438 		if (MDOC_MAX != c) {
1439 			if ( ! rew_elem(m, tok))
1440 				return(0);
1441 			return(mdoc_macro(m, c, line, la, pos, buf));
1442 		}
1443 
1444 		if ( ! mdoc_word_alloc(m, line, la, p))
1445 			return(0);
1446 	}
1447 
1448 	/* Close out (no delimiters). */
1449 
1450 	return(rew_elem(m, tok));
1451 }
1452 
1453 
1454 /* ARGSUSED */
1455 static int
1456 ctx_synopsis(MACRO_PROT_ARGS)
1457 {
1458 
1459 	/* If we're not in the SYNOPSIS, go straight to in-line. */
1460 	if (SEC_SYNOPSIS != m->lastsec)
1461 		return(in_line(m, tok, line, ppos, pos, buf));
1462 
1463 	/* If we're a nested call, same place. */
1464 	if (ppos > 1)
1465 		return(in_line(m, tok, line, ppos, pos, buf));
1466 
1467 	/*
1468 	 * XXX: this will open a block scope; however, if later we end
1469 	 * up formatting the block scope, then child nodes will inherit
1470 	 * the formatting.  Be careful.
1471 	 */
1472 
1473 	return(blk_part_imp(m, tok, line, ppos, pos, buf));
1474 }
1475 
1476 
1477 /* ARGSUSED */
1478 static int
1479 obsolete(MACRO_PROT_ARGS)
1480 {
1481 
1482 	return(mdoc_pwarn(m, line, ppos, EOBS));
1483 }
1484 
1485 
1486 /*
1487  * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1488  * They're unusual because they're basically free-form text until a
1489  * macro is encountered.
1490  */
1491 static int
1492 phrase(struct mdoc *m, int line, int ppos, char *buf)
1493 {
1494 	int		  c, w, la, pos;
1495 	char		 *p;
1496 
1497 	for (pos = ppos; ; ) {
1498 		la = pos;
1499 
1500 		/* Note: no calling context! */
1501 		w = mdoc_zargs(m, line, &pos, buf, 0, &p);
1502 
1503 		if (ARGS_ERROR == w)
1504 			return(0);
1505 		if (ARGS_EOLN == w)
1506 			break;
1507 
1508 		c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(p);
1509 
1510 		if (MDOC_MAX != c) {
1511 			if ( ! mdoc_macro(m, c, line, la, &pos, buf))
1512 				return(0);
1513 			return(append_delims(m, line, &pos, buf));
1514 		}
1515 
1516 		if ( ! mdoc_word_alloc(m, line, la, p))
1517 			return(0);
1518 	}
1519 
1520 	return(1);
1521 }
1522 
1523 
1524