fstat - Fix path construction for "wd".
[dragonfly.git] / usr.bin / mandoc / mdoc_macro.c
1 /*      $Id: mdoc_macro.c,v 1.42 2010/02/17 19:28:11 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         switch (tok) {
714         case (MDOC_An):
715                 /* FALLTHROUGH */
716         case (MDOC_Ar):
717                 /* FALLTHROUGH */
718         case (MDOC_Fl):
719                 /* FALLTHROUGH */
720         case (MDOC_Lk):
721                 /* FALLTHROUGH */
722         case (MDOC_Nm):
723                 /* FALLTHROUGH */
724         case (MDOC_Pa):
725                 nc = 1;
726                 break;
727         default:
728                 nc = 0;
729                 break;
730         }
731
732         for (arg = NULL;; ) {
733                 la = *pos;
734                 c = mdoc_argv(m, line, tok, &arg, pos, buf);
735
736                 if (ARGV_WORD == c) {
737                         *pos = la;
738                         break;
739                 }
740                 if (ARGV_EOLN == c)
741                         break;
742                 if (ARGV_ARG == c)
743                         continue;
744
745                 mdoc_argv_free(arg);
746                 return(0);
747         }
748
749         for (cnt = 0, lastpunct = 1;; ) {
750                 la = *pos;
751                 w = mdoc_args(m, line, pos, buf, tok, &p);
752
753                 if (ARGS_ERROR == w)
754                         return(0);
755                 if (ARGS_EOLN == w)
756                         break;
757                 if (ARGS_PUNCT == w)
758                         break;
759
760                 /* Quoted words shouldn't be looked-up. */
761
762                 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
763
764                 /*
765                  * In this case, we've located a submacro and must
766                  * execute it.  Close out scope, if open.  If no
767                  * elements have been generated, either create one (nc)
768                  * or raise a warning.
769                  */
770
771                 if (MDOC_MAX != c) {
772                         if (0 == lastpunct && ! rew_elem(m, tok))
773                                 return(0);
774                         if (nc && 0 == cnt) {
775                                 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
776                                         return(0);
777                                 if ( ! rew_last(m, m->last))
778                                         return(0);
779                         } else if ( ! nc && 0 == cnt) {
780                                 mdoc_argv_free(arg);
781                                 if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
782                                         return(0);
783                         }
784                         c = mdoc_macro(m, c, line, la, pos, buf);
785                         if (0 == c)
786                                 return(0);
787                         if (ppos > 1)
788                                 return(1);
789                         return(append_delims(m, line, pos, buf));
790                 }
791
792                 /*
793                  * Non-quote-enclosed punctuation.  Set up our scope, if
794                  * a word; rewind the scope, if a delimiter; then append
795                  * the word.
796                  */
797
798                 d = mdoc_isdelim(p);
799
800                 if (ARGS_QWORD != w && d) {
801                         if (0 == lastpunct && ! rew_elem(m, tok))
802                                 return(0);
803                         lastpunct = 1;
804                 } else if (lastpunct) {
805                         if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
806                                 return(0);
807                         lastpunct = 0;
808                 }
809
810                 if ( ! d)
811                         cnt++;
812                 if ( ! mdoc_word_alloc(m, line, la, p))
813                         return(0);
814
815                 /*
816                  * `Fl' macros have their scope re-opened with each new
817                  * word so that the `-' can be added to each one without
818                  * having to parse out spaces.
819                  */
820                 if (0 == lastpunct && MDOC_Fl == tok) {
821                         if ( ! rew_elem(m, tok))
822                                 return(0);
823                         lastpunct = 1;
824                 }
825         }
826
827         if (0 == lastpunct && ! rew_elem(m, tok))
828                 return(0);
829
830         /*
831          * If no elements have been collected and we're allowed to have
832          * empties (nc), open a scope and close it out.  Otherwise,
833          * raise a warning.
834          *
835          */
836         if (nc && 0 == cnt) {
837                 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
838                         return(0);
839                 if ( ! rew_last(m, m->last))
840                         return(0);
841         } else if ( ! nc && 0 == cnt) {
842                 mdoc_argv_free(arg);
843                 if ( ! mdoc_pwarn(m, line, ppos, EIGNE))
844                         return(0);
845         }
846
847         if (ppos > 1)
848                 return(1);
849         return(append_delims(m, line, pos, buf));
850 }
851
852
853 static int
854 blk_full(MACRO_PROT_ARGS)
855 {
856         int               c, lastarg, reopen, dohead;
857         struct mdoc_arg  *arg;
858         char             *p;
859
860         /*
861          * Whether to process a block-head section.  If this is
862          * non-zero, then a head will be opened for all line arguments.
863          * If not, then the head will always be empty and only a body
864          * will be opened, which will stay open at the eoln.
865          */
866
867         switch (tok) {
868         case (MDOC_Nd):
869                 dohead = 0;
870                 break;
871         default:
872                 dohead = 1;
873                 break;
874         }
875
876         if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
877                 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
878                         return(0);
879                 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
880                         return(0);
881         }
882
883         for (arg = NULL;; ) {
884                 lastarg = *pos;
885                 c = mdoc_argv(m, line, tok, &arg, pos, buf);
886
887                 if (ARGV_WORD == c) {
888                         *pos = lastarg;
889                         break;
890                 }
891
892                 if (ARGV_EOLN == c)
893                         break;
894                 if (ARGV_ARG == c)
895                         continue;
896
897                 mdoc_argv_free(arg);
898                 return(0);
899         }
900
901         if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
902                 return(0);
903
904         if (0 == buf[*pos]) {
905                 if ( ! mdoc_head_alloc(m, line, ppos, tok))
906                         return(0);
907                 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
908                         return(0);
909                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
910                         return(0);
911                 return(1);
912         }
913
914         if ( ! mdoc_head_alloc(m, line, ppos, tok))
915                 return(0);
916
917         /* Immediately close out head and enter body, if applicable. */
918
919         if (0 == dohead) {
920                 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
921                         return(0);
922                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
923                         return(0);
924         }
925
926         for (reopen = 0;; ) {
927                 lastarg = *pos;
928                 c = mdoc_args(m, line, pos, buf, tok, &p);
929
930                 if (ARGS_ERROR == c)
931                         return(0);
932                 if (ARGS_EOLN == c)
933                         break;
934                 if (ARGS_PHRASE == c) {
935                         assert(dohead);
936                         if (reopen && ! mdoc_head_alloc(m, line, ppos, tok))
937                                 return(0);
938                         /*
939                          * Phrases are self-contained macro phrases used
940                          * in the columnar output of a macro. They need
941                          * special handling.
942                          */
943                         if ( ! phrase(m, line, lastarg, buf))
944                                 return(0);
945                         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
946                                 return(0);
947
948                         reopen = 1;
949                         continue;
950                 }
951
952                 if (MDOC_MAX == (c = lookup(tok, p))) {
953                         if ( ! mdoc_word_alloc(m, line, lastarg, p))
954                                 return(0);
955                         continue;
956                 }
957
958                 if ( ! mdoc_macro(m, c, line, lastarg, pos, buf))
959                         return(0);
960                 break;
961         }
962
963         if (1 == ppos && ! append_delims(m, line, pos, buf))
964                 return(0);
965
966         /* If the body's already open, then just return. */
967         if (0 == dohead)
968                 return(1);
969
970         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
971                 return(0);
972         if ( ! mdoc_body_alloc(m, line, ppos, tok))
973                 return(0);
974
975         return(1);
976 }
977
978
979 static int
980 blk_part_imp(MACRO_PROT_ARGS)
981 {
982         int               la, c;
983         char             *p;
984         struct mdoc_node *blk, *body, *n;
985
986         /* If applicable, close out prior scopes. */
987
988         if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
989                 return(0);
990         /* Saved for later close-out. */
991         blk = m->last;
992         if ( ! mdoc_head_alloc(m, line, ppos, tok))
993                 return(0);
994         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
995                 return(0);
996         if ( ! mdoc_body_alloc(m, line, ppos, tok))
997                 return(0);
998         /* Saved for later close-out. */
999         body = m->last;
1000
1001         /* Body argument processing. */
1002
1003         for (;;) {
1004                 la = *pos;
1005                 c = mdoc_args(m, line, pos, buf, tok, &p);
1006                 assert(ARGS_PHRASE != c);
1007
1008                 if (ARGS_ERROR == c)
1009                         return(0);
1010                 if (ARGS_PUNCT == c)
1011                         break;
1012                 if (ARGS_EOLN == c)
1013                         break;
1014
1015                 if (MDOC_MAX == (c = lookup(tok, p))) {
1016                         if ( ! mdoc_word_alloc(m, line, la, p))
1017                                 return(0);
1018                         continue;
1019                 }
1020
1021                 if ( ! mdoc_macro(m, c, line, la, pos, buf))
1022                         return(0);
1023                 break;
1024         }
1025
1026         /*
1027          * If we can't rewind to our body, then our scope has already
1028          * been closed by another macro (like `Oc' closing `Op').  This
1029          * is ugly behaviour nodding its head to OpenBSD's overwhelming
1030          * crufty use of `Op' breakage--XXX, deprecate in time.
1031          */
1032         for (n = m->last; n; n = n->parent)
1033                 if (body == n)
1034                         break;
1035         if (NULL == n && ! mdoc_nwarn(m, body, EIMPBRK))
1036                 return(0);
1037         if (n && ! rew_last(m, body))
1038                 return(0);
1039
1040         /* Standard appending of delimiters. */
1041
1042         if (1 == ppos && ! append_delims(m, line, pos, buf))
1043                 return(0);
1044
1045         /* Rewind scope, if applicable. */
1046
1047         if (n && ! rew_last(m, blk))
1048                 return(0);
1049
1050         return(1);
1051 }
1052
1053
1054 static int
1055 blk_part_exp(MACRO_PROT_ARGS)
1056 {
1057         int               la, flushed, j, c, maxargs;
1058         char             *p;
1059
1060         /* Number of head arguments.  Only `Eo' has these, */
1061
1062         switch (tok) {
1063         case (MDOC_Eo):
1064                 maxargs = 1;
1065                 break;
1066         default:
1067                 maxargs = 0;
1068                 break;
1069         }
1070
1071         /* Begin the block scope. */
1072
1073         if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1074                 return(0);
1075
1076         /*
1077          * If no head arguments, open and then close out a head, noting
1078          * that we've flushed our terms.  `flushed' means that we've
1079          * flushed out the head and the body is open.
1080          */
1081
1082         if (0 == maxargs) {
1083                 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1084                         return(0);
1085                 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1086                         return(0);
1087                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1088                         return(0);
1089                 flushed = 1;
1090         } else {
1091                 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1092                         return(0);
1093                 flushed = 0;
1094         }
1095
1096         /* Process the head/head+body line arguments. */
1097
1098         for (j = 0; ; j++) {
1099                 la = *pos;
1100                 if (j == maxargs && ! flushed) {
1101                         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1102                                 return(0);
1103                         flushed = 1;
1104                         if ( ! mdoc_body_alloc(m, line, ppos, tok))
1105                                 return(0);
1106                 }
1107
1108                 c = mdoc_args(m, line, pos, buf, tok, &p);
1109                 assert(ARGS_PHRASE != c);
1110
1111                 if (ARGS_ERROR == c)
1112                         return(0);
1113                 if (ARGS_PUNCT == c)
1114                         break;
1115                 if (ARGS_EOLN == c)
1116                         break;
1117
1118                 if (MDOC_MAX != (c = lookup(tok, p))) {
1119                         if ( ! flushed) {
1120                                 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1121                                         return(0);
1122                                 flushed = 1;
1123                                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1124                                         return(0);
1125                         }
1126                         if ( ! mdoc_macro(m, c, line, la, pos, buf))
1127                                 return(0);
1128                         break;
1129                 }
1130
1131                 if ( ! flushed && mdoc_isdelim(p)) {
1132                         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1133                                 return(0);
1134                         flushed = 1;
1135                         if ( ! mdoc_body_alloc(m, line, ppos, tok))
1136                                 return(0);
1137                 }
1138
1139                 if ( ! mdoc_word_alloc(m, line, la, p))
1140                         return(0);
1141         }
1142
1143         /* Close the head and open the body, if applicable. */
1144
1145         if ( ! flushed) {
1146                 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1147                         return(0);
1148                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1149                         return(0);
1150         }
1151
1152         /* Standard appending of delimiters. */
1153
1154         if (ppos > 1)
1155                 return(1);
1156         return(append_delims(m, line, pos, buf));
1157 }
1158
1159
1160 static int
1161 in_line_argn(MACRO_PROT_ARGS)
1162 {
1163         int               la, flushed, j, c, maxargs;
1164         struct mdoc_arg  *arg;
1165         char             *p;
1166
1167         /* Fixed maximum arguments per macro, if applicable. */
1168
1169         switch (tok) {
1170         case (MDOC_Ap):
1171                 /* FALLTHROUGH */
1172         case (MDOC_No):
1173                 /* FALLTHROUGH */
1174         case (MDOC_Ns):
1175                 /* FALLTHROUGH */
1176         case (MDOC_Ux):
1177                 maxargs = 0;
1178                 break;
1179         case (MDOC_Xr):
1180                 maxargs = 2;
1181                 break;
1182         default:
1183                 maxargs = 1;
1184                 break;
1185         }
1186
1187         /* Macro argument processing. */
1188
1189         for (arg = NULL;; ) {
1190                 la = *pos;
1191                 c = mdoc_argv(m, line, tok, &arg, pos, buf);
1192
1193                 if (ARGV_WORD == c) {
1194                         *pos = la;
1195                         break;
1196                 }
1197
1198                 if (ARGV_EOLN == c)
1199                         break;
1200                 if (ARGV_ARG == c)
1201                         continue;
1202
1203                 mdoc_argv_free(arg);
1204                 return(0);
1205         }
1206
1207         /* Open the element scope. */
1208
1209         if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1210                 return(0);
1211
1212         /* Process element arguments. */
1213
1214         for (flushed = j = 0; ; j++) {
1215                 la = *pos;
1216
1217                 if (j == maxargs && ! flushed) {
1218                         if ( ! rew_elem(m, tok))
1219                                 return(0);
1220                         flushed = 1;
1221                 }
1222
1223                 c = mdoc_args(m, line, pos, buf, tok, &p);
1224
1225                 if (ARGS_ERROR == c)
1226                         return(0);
1227                 if (ARGS_PUNCT == c)
1228                         break;
1229                 if (ARGS_EOLN == c)
1230                         break;
1231
1232                 if (MDOC_MAX != (c = lookup(tok, p))) {
1233                         if ( ! flushed && ! rew_elem(m, tok))
1234                                 return(0);
1235                         flushed = 1;
1236                         if ( ! mdoc_macro(m, c, line, la, pos, buf))
1237                                 return(0);
1238                         break;
1239                 }
1240
1241                 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1242                                 ! flushed && mdoc_isdelim(p)) {
1243                         if ( ! rew_elem(m, tok))
1244                                 return(0);
1245                         flushed = 1;
1246                 }
1247
1248                 /*
1249                  * XXX: this is a hack to work around groff's ugliness
1250                  * as regards `Xr' and extraneous arguments.  It should
1251                  * ideally be deprecated behaviour, but because this is
1252                  * code is no here, it's unlikely to be removed.
1253                  */
1254                 if (MDOC_Xr == tok && j == maxargs) {
1255                         if ( ! mdoc_elem_alloc(m, line, ppos, MDOC_Ns, NULL))
1256                                 return(0);
1257                         if ( ! rew_elem(m, MDOC_Ns))
1258                                 return(0);
1259                 }
1260
1261                 if ( ! mdoc_word_alloc(m, line, la, p))
1262                         return(0);
1263         }
1264
1265         /* Close out and append delimiters. */
1266
1267         if ( ! flushed && ! rew_elem(m, tok))
1268                 return(0);
1269
1270         if (ppos > 1)
1271                 return(1);
1272         return(append_delims(m, line, pos, buf));
1273 }
1274
1275
1276 static int
1277 in_line_eoln(MACRO_PROT_ARGS)
1278 {
1279         int               c, w, la;
1280         struct mdoc_arg  *arg;
1281         char             *p;
1282
1283         assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1284
1285         /* Parse macro arguments. */
1286
1287         for (arg = NULL; ; ) {
1288                 la = *pos;
1289                 c = mdoc_argv(m, line, tok, &arg, pos, buf);
1290
1291                 if (ARGV_WORD == c) {
1292                         *pos = la;
1293                         break;
1294                 }
1295                 if (ARGV_EOLN == c)
1296                         break;
1297                 if (ARGV_ARG == c)
1298                         continue;
1299
1300                 mdoc_argv_free(arg);
1301                 return(0);
1302         }
1303
1304         /* Open element scope. */
1305
1306         if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1307                 return(0);
1308
1309         /* Parse argument terms. */
1310
1311         for (;;) {
1312                 la = *pos;
1313                 w = mdoc_args(m, line, pos, buf, tok, &p);
1314
1315                 if (ARGS_ERROR == w)
1316                         return(0);
1317                 if (ARGS_EOLN == w)
1318                         break;
1319
1320                 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p);
1321
1322                 if (MDOC_MAX != c) {
1323                         if ( ! rew_elem(m, tok))
1324                                 return(0);
1325                         return(mdoc_macro(m, c, line, la, pos, buf));
1326                 }
1327
1328                 if ( ! mdoc_word_alloc(m, line, la, p))
1329                         return(0);
1330         }
1331
1332         /* Close out (no delimiters). */
1333
1334         return(rew_elem(m, tok));
1335 }
1336
1337
1338 /* ARGSUSED */
1339 static int
1340 ctx_synopsis(MACRO_PROT_ARGS)
1341 {
1342
1343         /* If we're not in the SYNOPSIS, go straight to in-line. */
1344         if (SEC_SYNOPSIS != m->lastsec)
1345                 return(in_line(m, tok, line, ppos, pos, buf));
1346
1347         /* If we're a nested call, same place. */
1348         if (ppos > 1)
1349                 return(in_line(m, tok, line, ppos, pos, buf));
1350
1351         /*
1352          * XXX: this will open a block scope; however, if later we end
1353          * up formatting the block scope, then child nodes will inherit
1354          * the formatting.  Be careful.
1355          */
1356
1357         return(blk_part_imp(m, tok, line, ppos, pos, buf));
1358 }
1359
1360
1361 /* ARGSUSED */
1362 static int
1363 obsolete(MACRO_PROT_ARGS)
1364 {
1365
1366         return(mdoc_pwarn(m, line, ppos, EOBS));
1367 }
1368
1369
1370 /*
1371  * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1372  * They're unusual because they're basically free-form text until a
1373  * macro is encountered.
1374  */
1375 static int
1376 phrase(struct mdoc *m, int line, int ppos, char *buf)
1377 {
1378         int               c, w, la, pos;
1379         char             *p;
1380
1381         for (pos = ppos; ; ) {
1382                 la = pos;
1383
1384                 /* Note: no calling context! */
1385                 w = mdoc_zargs(m, line, &pos, buf, 0, &p);
1386
1387                 if (ARGS_ERROR == w)
1388                         return(0);
1389                 if (ARGS_EOLN == w)
1390                         break;
1391
1392                 c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(p);
1393
1394                 if (MDOC_MAX != c) {
1395                         if ( ! mdoc_macro(m, c, line, la, &pos, buf))
1396                                 return(0);
1397                         return(append_delims(m, line, &pos, buf));
1398                 }
1399
1400                 if ( ! mdoc_word_alloc(m, line, la, p))
1401                         return(0);
1402         }
1403
1404         return(1);
1405 }