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