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