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