b334b4e4021a3c14f69d320e03b2aad6fe93204f
[dragonfly.git] / contrib / mdocml / mdoc_macro.c
1 /*      $Id: mdoc_macro.c,v 1.106 2011/03/22 14:33:05 kristaps Exp $ */
2 /*
3  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
4  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <assert.h>
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <time.h>
28
29 #include "mdoc.h"
30 #include "mandoc.h"
31 #include "libmdoc.h"
32 #include "libmandoc.h"
33
34 enum    rew {   /* see rew_dohalt() */
35         REWIND_NONE,
36         REWIND_THIS,
37         REWIND_MORE,
38         REWIND_FORCE,
39         REWIND_LATER,
40         REWIND_ERROR
41 };
42
43 static  int             blk_full(MACRO_PROT_ARGS);
44 static  int             blk_exp_close(MACRO_PROT_ARGS);
45 static  int             blk_part_exp(MACRO_PROT_ARGS);
46 static  int             blk_part_imp(MACRO_PROT_ARGS);
47 static  int             ctx_synopsis(MACRO_PROT_ARGS);
48 static  int             in_line_eoln(MACRO_PROT_ARGS);
49 static  int             in_line_argn(MACRO_PROT_ARGS);
50 static  int             in_line(MACRO_PROT_ARGS);
51 static  int             obsolete(MACRO_PROT_ARGS);
52 static  int             phrase_ta(MACRO_PROT_ARGS);
53
54 static  int             dword(struct mdoc *, int, int, 
55                                 const char *, enum mdelim);
56 static  int             append_delims(struct mdoc *, 
57                                 int, int *, char *);
58 static  enum mdoct      lookup(enum mdoct, const char *);
59 static  enum mdoct      lookup_raw(const char *);
60 static  int             make_pending(struct mdoc_node *, enum mdoct,
61                                 struct mdoc *, int, int);
62 static  int             phrase(struct mdoc *, int, int, char *);
63 static  enum mdoct      rew_alt(enum mdoct);
64 static  enum rew        rew_dohalt(enum mdoct, enum mdoc_type, 
65                                 const struct mdoc_node *);
66 static  int             rew_elem(struct mdoc *, enum mdoct);
67 static  int             rew_last(struct mdoc *, 
68                                 const struct mdoc_node *);
69 static  int             rew_sub(enum mdoc_type, struct mdoc *, 
70                                 enum mdoct, int, int);
71
72 const   struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
73         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
74         { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
75         { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
76         { in_line_eoln, MDOC_PROLOGUE }, /* Os */
77         { blk_full, 0 }, /* Sh */
78         { blk_full, 0 }, /* Ss */ 
79         { in_line_eoln, 0 }, /* Pp */ 
80         { blk_part_imp, MDOC_PARSED }, /* D1 */
81         { blk_part_imp, MDOC_PARSED }, /* Dl */
82         { blk_full, MDOC_EXPLICIT }, /* Bd */
83         { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
84         { blk_full, MDOC_EXPLICIT }, /* Bl */
85         { blk_exp_close, MDOC_EXPLICIT }, /* El */
86         { blk_full, MDOC_PARSED }, /* It */
87         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ 
88         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
89         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
90         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
91         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
92         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ 
93         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ 
94         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ 
95         { in_line_eoln, 0 }, /* Ex */
96         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ 
97         { in_line_eoln, 0 }, /* Fd */ 
98         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
99         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ 
100         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ 
101         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ 
102         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
103         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
104         { blk_full, 0 }, /* Nd */ 
105         { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ 
106         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
107         { obsolete, 0 }, /* Ot */
108         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
109         { in_line_eoln, 0 }, /* Rv */
110         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 
111         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
112         { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ 
113         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
114         { in_line_eoln, 0 }, /* %A */
115         { in_line_eoln, 0 }, /* %B */
116         { in_line_eoln, 0 }, /* %D */
117         { in_line_eoln, 0 }, /* %I */
118         { in_line_eoln, 0 }, /* %J */
119         { in_line_eoln, 0 }, /* %N */
120         { in_line_eoln, 0 }, /* %O */
121         { in_line_eoln, 0 }, /* %P */
122         { in_line_eoln, 0 }, /* %R */
123         { in_line_eoln, 0 }, /* %T */
124         { in_line_eoln, 0 }, /* %V */
125         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
126         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
127         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
128         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
129         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
130         { blk_full, MDOC_EXPLICIT }, /* Bf */ 
131         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
132         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
133         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
134         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
135         { in_line_eoln, 0 }, /* Db */
136         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
137         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
138         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
139         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
140         { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
141         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ 
142         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
143         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
144         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
145         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* No */
146         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Ns */
147         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
148         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
149         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
150         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
151         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
152         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
153         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
154         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
155         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
156         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
157         { blk_exp_close, MDOC_EXPLICIT }, /* Re */
158         { blk_full, MDOC_EXPLICIT }, /* Rs */
159         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
160         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
161         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
162         { in_line_eoln, 0 }, /* Sm */
163         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
164         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
165         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
166         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
167         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
168         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
169         { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ 
170         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ 
171         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
172         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
173         { blk_full, MDOC_EXPLICIT }, /* Bk */
174         { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
175         { in_line_eoln, 0 }, /* Bt */
176         { in_line_eoln, 0 }, /* Hf */
177         { obsolete, 0 }, /* Fr */
178         { in_line_eoln, 0 }, /* Ud */
179         { in_line, 0 }, /* Lb */
180         { in_line_eoln, 0 }, /* Lp */ 
181         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ 
182         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ 
183         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
184         { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
185         { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
186         { in_line_eoln, 0 }, /* %C */
187         { obsolete, 0 }, /* Es */
188         { obsolete, 0 }, /* En */
189         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
190         { in_line_eoln, 0 }, /* %Q */
191         { in_line_eoln, 0 }, /* br */
192         { in_line_eoln, 0 }, /* sp */
193         { in_line_eoln, 0 }, /* %U */
194         { phrase_ta, MDOC_CALLABLE | MDOC_PARSED }, /* Ta */
195 };
196
197 const   struct mdoc_macro * const mdoc_macros = __mdoc_macros;
198
199
200 /*
201  * This is called at the end of parsing.  It must traverse up the tree,
202  * closing out open [implicit] scopes.  Obviously, open explicit scopes
203  * are errors.
204  */
205 int
206 mdoc_macroend(struct mdoc *m)
207 {
208         struct mdoc_node *n;
209
210         /* Scan for open explicit scopes. */
211
212         n = MDOC_VALID & m->last->flags ?  m->last->parent : m->last;
213
214         for ( ; n; n = n->parent)
215                 if (MDOC_BLOCK == n->type &&
216                     MDOC_EXPLICIT & mdoc_macros[n->tok].flags)
217                         mdoc_nmsg(m, n, MANDOCERR_SCOPEEXIT);
218
219         /* Rewind to the first. */
220
221         return(rew_last(m, m->first));
222 }
223
224
225 /*
226  * Look up a macro from within a subsequent context.
227  */
228 static enum mdoct
229 lookup(enum mdoct from, const char *p)
230 {
231         /* FIXME: make -diag lists be un-PARSED. */
232
233         if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
234                 return(MDOC_MAX);
235         return(lookup_raw(p));
236 }
237
238
239 /*
240  * Lookup a macro following the initial line macro.
241  */
242 static enum mdoct
243 lookup_raw(const char *p)
244 {
245         enum mdoct       res;
246
247         if (MDOC_MAX == (res = mdoc_hash_find(p)))
248                 return(MDOC_MAX);
249         if (MDOC_CALLABLE & mdoc_macros[res].flags)
250                 return(res);
251         return(MDOC_MAX);
252 }
253
254
255 static int
256 rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
257 {
258         struct mdoc_node *n, *np;
259
260         assert(to);
261         mdoc->next = MDOC_NEXT_SIBLING;
262
263         /* LINTED */
264         while (mdoc->last != to) {
265                 /*
266                  * Save the parent here, because we may delete the
267                  * m->last node in the post-validation phase and reset
268                  * it to m->last->parent, causing a step in the closing
269                  * out to be lost.
270                  */
271                 np = mdoc->last->parent;
272                 if ( ! mdoc_valid_post(mdoc))
273                         return(0);
274                 n = mdoc->last;
275                 mdoc->last = np;
276                 assert(mdoc->last);
277                 mdoc->last->last = n;
278         }
279
280         return(mdoc_valid_post(mdoc));
281 }
282
283
284 /*
285  * For a block closing macro, return the corresponding opening one.
286  * Otherwise, return the macro itself.
287  */
288 static enum mdoct
289 rew_alt(enum mdoct tok)
290 {
291         switch (tok) {
292         case (MDOC_Ac):
293                 return(MDOC_Ao);
294         case (MDOC_Bc):
295                 return(MDOC_Bo);
296         case (MDOC_Brc):
297                 return(MDOC_Bro);
298         case (MDOC_Dc):
299                 return(MDOC_Do);
300         case (MDOC_Ec):
301                 return(MDOC_Eo);
302         case (MDOC_Ed):
303                 return(MDOC_Bd);
304         case (MDOC_Ef):
305                 return(MDOC_Bf);
306         case (MDOC_Ek):
307                 return(MDOC_Bk);
308         case (MDOC_El):
309                 return(MDOC_Bl);
310         case (MDOC_Fc):
311                 return(MDOC_Fo);
312         case (MDOC_Oc):
313                 return(MDOC_Oo);
314         case (MDOC_Pc):
315                 return(MDOC_Po);
316         case (MDOC_Qc):
317                 return(MDOC_Qo);
318         case (MDOC_Re):
319                 return(MDOC_Rs);
320         case (MDOC_Sc):
321                 return(MDOC_So);
322         case (MDOC_Xc):
323                 return(MDOC_Xo);
324         default:
325                 return(tok);
326         }
327         /* NOTREACHED */
328 }
329
330
331 /*
332  * Rewinding to tok, how do we have to handle *p?
333  * REWIND_NONE: *p would delimit tok, but no tok scope is open
334  *   inside *p, so there is no need to rewind anything at all.
335  * REWIND_THIS: *p matches tok, so rewind *p and nothing else.
336  * REWIND_MORE: *p is implicit, rewind it and keep searching for tok.
337  * REWIND_FORCE: *p is explicit, but tok is full, force rewinding *p.
338  * REWIND_LATER: *p is explicit and still open, postpone rewinding.
339  * REWIND_ERROR: No tok block is open at all.
340  */
341 static enum rew
342 rew_dohalt(enum mdoct tok, enum mdoc_type type, 
343                 const struct mdoc_node *p)
344 {
345
346         /*
347          * No matching token, no delimiting block, no broken block.
348          * This can happen when full implicit macros are called for
349          * the first time but try to rewind their previous
350          * instance anyway.
351          */
352         if (MDOC_ROOT == p->type)
353                 return(MDOC_BLOCK == type &&
354                     MDOC_EXPLICIT & mdoc_macros[tok].flags ?
355                     REWIND_ERROR : REWIND_NONE);
356
357         /*
358          * When starting to rewind, skip plain text 
359          * and nodes that have already been rewound.
360          */
361         if (MDOC_TEXT == p->type || MDOC_VALID & p->flags)
362                 return(REWIND_MORE);
363
364         /*
365          * The easiest case:  Found a matching token.
366          * This applies to both blocks and elements.
367          */
368         tok = rew_alt(tok);
369         if (tok == p->tok)
370                 return(p->end ? REWIND_NONE :
371                     type == p->type ? REWIND_THIS : REWIND_MORE);
372
373         /*
374          * While elements do require rewinding for themselves,
375          * they never affect rewinding of other nodes.
376          */
377         if (MDOC_ELEM == p->type)
378                 return(REWIND_MORE);
379
380         /*
381          * Blocks delimited by our target token get REWIND_MORE.
382          * Blocks delimiting our target token get REWIND_NONE. 
383          */
384         switch (tok) {
385         case (MDOC_Bl):
386                 if (MDOC_It == p->tok)
387                         return(REWIND_MORE);
388                 break;
389         case (MDOC_It):
390                 if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
391                         return(REWIND_NONE);
392                 break;
393         /*
394          * XXX Badly nested block handling still fails badly
395          * when one block is breaking two blocks of the same type.
396          * This is an incomplete and extremely ugly workaround,
397          * required to let the OpenBSD tree build.
398          */
399         case (MDOC_Oo):
400                 if (MDOC_Op == p->tok)
401                         return(REWIND_MORE);
402                 break;
403         case (MDOC_Nm):
404                 return(REWIND_NONE);
405         case (MDOC_Nd):
406                 /* FALLTHROUGH */
407         case (MDOC_Ss):
408                 if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
409                         return(REWIND_NONE);
410                 /* FALLTHROUGH */
411         case (MDOC_Sh):
412                 if (MDOC_Nd == p->tok || MDOC_Ss == p->tok ||
413                     MDOC_Sh == p->tok)
414                         return(REWIND_MORE);
415                 break;
416         default:
417                 break;
418         }
419
420         /*
421          * Default block rewinding rules.
422          * In particular, always skip block end markers,
423          * and let all blocks rewind Nm children.
424          */
425         if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok ||
426             (MDOC_BLOCK == p->type &&
427             ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)))
428                 return(REWIND_MORE);
429
430         /*
431          * By default, closing out full blocks
432          * forces closing of broken explicit blocks,
433          * while closing out partial blocks
434          * allows delayed rewinding by default.
435          */
436         return (&blk_full == mdoc_macros[tok].fp ?
437             REWIND_FORCE : REWIND_LATER);
438 }
439
440
441 static int
442 rew_elem(struct mdoc *mdoc, enum mdoct tok)
443 {
444         struct mdoc_node *n;
445
446         n = mdoc->last;
447         if (MDOC_ELEM != n->type)
448                 n = n->parent;
449         assert(MDOC_ELEM == n->type);
450         assert(tok == n->tok);
451
452         return(rew_last(mdoc, n));
453 }
454
455
456 /*
457  * We are trying to close a block identified by tok,
458  * but the child block *broken is still open.
459  * Thus, postpone closing the tok block
460  * until the rew_sub call closing *broken.
461  */
462 static int
463 make_pending(struct mdoc_node *broken, enum mdoct tok,
464                 struct mdoc *m, int line, int ppos)
465 {
466         struct mdoc_node *breaker;
467
468         /*
469          * Iterate backwards, searching for the block matching tok,
470          * that is, the block breaking the *broken block.
471          */
472         for (breaker = broken->parent; breaker; breaker = breaker->parent) {
473
474                 /*
475                  * If the *broken block had already been broken before
476                  * and we encounter its breaker, make the tok block
477                  * pending on the inner breaker.
478                  * Graphically, "[A breaker=[B broken=[C->B B] tok=A] C]"
479                  * becomes "[A broken=[B [C->B B] tok=A] C]"
480                  * and finally "[A [B->A [C->B B] A] C]".
481                  */
482                 if (breaker == broken->pending) {
483                         broken = breaker;
484                         continue;
485                 }
486
487                 if (REWIND_THIS != rew_dohalt(tok, MDOC_BLOCK, breaker))
488                         continue;
489                 if (MDOC_BODY == broken->type)
490                         broken = broken->parent;
491
492                 /*
493                  * Found the breaker.
494                  * If another, outer breaker is already pending on
495                  * the *broken block, we must not clobber the link
496                  * to the outer breaker, but make it pending on the
497                  * new, now inner breaker.
498                  * Graphically, "[A breaker=[B broken=[C->A A] tok=B] C]"
499                  * becomes "[A breaker=[B->A broken=[C A] tok=B] C]"
500                  * and finally "[A [B->A [C->B A] B] C]".
501                  */
502                 if (broken->pending) {
503                         struct mdoc_node *taker;
504
505                         /*
506                          * If the breaker had also been broken before,
507                          * it cannot take on the outer breaker itself,
508                          * but must hand it on to its own breakers.
509                          * Graphically, this is the following situation:
510                          * "[A [B breaker=[C->B B] broken=[D->A A] tok=C] D]"
511                          * "[A taker=[B->A breaker=[C->B B] [D->C A] C] D]"
512                          */
513                         taker = breaker;
514                         while (taker->pending)
515                                 taker = taker->pending;
516                         taker->pending = broken->pending;
517                 }
518                 broken->pending = breaker;
519                 mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos,
520                                 "%s breaks %s", mdoc_macronames[tok],
521                                 mdoc_macronames[broken->tok]);
522                 return(1);
523         }
524
525         /*
526          * Found no matching block for tok.
527          * Are you trying to close a block that is not open?
528          */
529         return(0);
530 }
531
532
533 static int
534 rew_sub(enum mdoc_type t, struct mdoc *m, 
535                 enum mdoct tok, int line, int ppos)
536 {
537         struct mdoc_node *n;
538
539         n = m->last;
540         while (n) {
541                 switch (rew_dohalt(tok, t, n)) {
542                 case (REWIND_NONE):
543                         return(1);
544                 case (REWIND_THIS):
545                         break;
546                 case (REWIND_FORCE):
547                         mandoc_vmsg(MANDOCERR_SCOPEBROKEN, m->parse, 
548                                         line, ppos, "%s breaks %s", 
549                                         mdoc_macronames[tok],
550                                         mdoc_macronames[n->tok]);
551                         /* FALLTHROUGH */
552                 case (REWIND_MORE):
553                         n = n->parent;
554                         continue;
555                 case (REWIND_LATER):
556                         if (make_pending(n, tok, m, line, ppos) ||
557                             MDOC_BLOCK != t)
558                                 return(1);
559                         /* FALLTHROUGH */
560                 case (REWIND_ERROR):
561                         mdoc_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);
562                         return(1);
563                 }
564                 break;
565         }
566
567         assert(n);
568         if ( ! rew_last(m, n))
569                 return(0);
570
571         /*
572          * The current block extends an enclosing block.
573          * Now that the current block ends, close the enclosing block, too.
574          */
575         while (NULL != (n = n->pending)) {
576                 if ( ! rew_last(m, n))
577                         return(0);
578                 if (MDOC_HEAD == n->type &&
579                     ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
580                         return(0);
581         }
582
583         return(1);
584 }
585
586 /*
587  * Allocate a word and check whether it's punctuation or not.
588  * Punctuation consists of those tokens found in mdoc_isdelim().
589  */
590 static int
591 dword(struct mdoc *m, int line, 
592                 int col, const char *p, enum mdelim d)
593 {
594         
595         if (DELIM_MAX == d)
596                 d = mdoc_isdelim(p);
597
598         if ( ! mdoc_word_alloc(m, line, col, p))
599                 return(0);
600
601         if (DELIM_OPEN == d)
602                 m->last->flags |= MDOC_DELIMO;
603         else if (DELIM_CLOSE == d)
604                 m->last->flags |= MDOC_DELIMC;
605
606         return(1);
607 }
608
609 static int
610 append_delims(struct mdoc *m, int line, int *pos, char *buf)
611 {
612         int              la;
613         enum margserr    ac;
614         char            *p;
615
616         if ('\0' == buf[*pos])
617                 return(1);
618
619         for (;;) {
620                 la = *pos;
621                 ac = mdoc_zargs(m, line, pos, buf, ARGS_NOWARN, &p);
622
623                 if (ARGS_ERROR == ac)
624                         return(0);
625                 else if (ARGS_EOLN == ac)
626                         break;
627
628                 dword(m, line, la, p, DELIM_MAX);
629
630                 /*
631                  * If we encounter end-of-sentence symbols, then trigger
632                  * the double-space.
633                  *
634                  * XXX: it's easy to allow this to propogate outward to
635                  * the last symbol, such that `. )' will cause the
636                  * correct double-spacing.  However, (1) groff isn't
637                  * smart enough to do this and (2) it would require
638                  * knowing which symbols break this behaviour, for
639                  * example, `.  ;' shouldn't propogate the double-space.
640                  */
641                 if (mandoc_eos(p, strlen(p), 0))
642                         m->last->flags |= MDOC_EOS;
643         }
644
645         return(1);
646 }
647
648
649 /*
650  * Close out block partial/full explicit.  
651  */
652 static int
653 blk_exp_close(MACRO_PROT_ARGS)
654 {
655         struct mdoc_node *body;         /* Our own body. */
656         struct mdoc_node *later;        /* A sub-block starting later. */
657         struct mdoc_node *n;            /* For searching backwards. */
658
659         int              j, lastarg, maxargs, flushed, nl;
660         enum margserr    ac;
661         enum mdoct       atok, ntok;
662         char            *p;
663
664         nl = MDOC_NEWLINE & m->flags;
665
666         switch (tok) {
667         case (MDOC_Ec):
668                 maxargs = 1;
669                 break;
670         default:
671                 maxargs = 0;
672                 break;
673         }
674
675         /*
676          * Search backwards for beginnings of blocks,
677          * both of our own and of pending sub-blocks.
678          */
679         atok = rew_alt(tok);
680         body = later = NULL;
681         for (n = m->last; n; n = n->parent) {
682                 if (MDOC_VALID & n->flags)
683                         continue;
684
685                 /* Remember the start of our own body. */
686                 if (MDOC_BODY == n->type && atok == n->tok) {
687                         if (ENDBODY_NOT == n->end)
688                                 body = n;
689                         continue;
690                 }
691
692                 if (MDOC_BLOCK != n->type || MDOC_Nm == n->tok)
693                         continue;
694                 if (atok == n->tok) {
695                         assert(body);
696
697                         /*
698                          * Found the start of our own block.
699                          * When there is no pending sub block,
700                          * just proceed to closing out.
701                          */
702                         if (NULL == later)
703                                 break;
704
705                         /* 
706                          * When there is a pending sub block,
707                          * postpone closing out the current block
708                          * until the rew_sub() closing out the sub-block.
709                          */
710                         make_pending(later, tok, m, line, ppos);
711
712                         /*
713                          * Mark the place where the formatting - but not
714                          * the scope - of the current block ends.
715                          */
716                         if ( ! mdoc_endbody_alloc(m, line, ppos,
717                             atok, body, ENDBODY_SPACE))
718                                 return(0);
719                         break;
720                 }
721
722                 /*
723                  * When finding an open sub block, remember the last
724                  * open explicit block, or, in case there are only
725                  * implicit ones, the first open implicit block.
726                  */
727                 if (later &&
728                     MDOC_EXPLICIT & mdoc_macros[later->tok].flags)
729                         continue;
730                 if (MDOC_CALLABLE & mdoc_macros[n->tok].flags)
731                         later = n;
732         }
733
734         if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
735                 /* FIXME: do this in validate */
736                 if (buf[*pos]) 
737                         mdoc_pmsg(m, line, ppos, MANDOCERR_ARGSLOST);
738
739                 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
740                         return(0);
741                 return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
742         }
743
744         if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
745                 return(0);
746
747         if (NULL == later && maxargs > 0) 
748                 if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
749                         return(0);
750
751         for (flushed = j = 0; ; j++) {
752                 lastarg = *pos;
753
754                 if (j == maxargs && ! flushed) {
755                         if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
756                                 return(0);
757                         flushed = 1;
758                 }
759
760                 ac = mdoc_args(m, line, pos, buf, tok, &p);
761
762                 if (ARGS_ERROR == ac)
763                         return(0);
764                 if (ARGS_PUNCT == ac)
765                         break;
766                 if (ARGS_EOLN == ac)
767                         break;
768
769                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
770
771                 if (MDOC_MAX == ntok) {
772                         if ( ! dword(m, line, lastarg, p, DELIM_MAX))
773                                 return(0);
774                         continue;
775                 }
776
777                 if ( ! flushed) {
778                         if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
779                                 return(0);
780                         flushed = 1;
781                 }
782                 if ( ! mdoc_macro(m, ntok, line, lastarg, pos, buf))
783                         return(0);
784                 break;
785         }
786
787         if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
788                 return(0);
789
790         if ( ! nl)
791                 return(1);
792         return(append_delims(m, line, pos, buf));
793 }
794
795
796 static int
797 in_line(MACRO_PROT_ARGS)
798 {
799         int              la, scope, cnt, nc, nl;
800         enum margverr    av;
801         enum mdoct       ntok;
802         enum margserr    ac;
803         enum mdelim      d;
804         struct mdoc_arg *arg;
805         char            *p;
806
807         nl = MDOC_NEWLINE & m->flags;
808
809         /*
810          * Whether we allow ignored elements (those without content,
811          * usually because of reserved words) to squeak by.
812          */
813
814         switch (tok) {
815         case (MDOC_An):
816                 /* FALLTHROUGH */
817         case (MDOC_Ar):
818                 /* FALLTHROUGH */
819         case (MDOC_Fl):
820                 /* FALLTHROUGH */
821         case (MDOC_Mt):
822                 /* FALLTHROUGH */
823         case (MDOC_Nm):
824                 /* FALLTHROUGH */
825         case (MDOC_Pa):
826                 nc = 1;
827                 break;
828         default:
829                 nc = 0;
830                 break;
831         }
832
833         for (arg = NULL;; ) {
834                 la = *pos;
835                 av = mdoc_argv(m, line, tok, &arg, pos, buf);
836
837                 if (ARGV_WORD == av) {
838                         *pos = la;
839                         break;
840                 } 
841                 if (ARGV_EOLN == av)
842                         break;
843                 if (ARGV_ARG == av)
844                         continue;
845
846                 mdoc_argv_free(arg);
847                 return(0);
848         }
849
850         for (cnt = scope = 0;; ) {
851                 la = *pos;
852                 ac = mdoc_args(m, line, pos, buf, tok, &p);
853
854                 if (ARGS_ERROR == ac)
855                         return(0);
856                 if (ARGS_EOLN == ac)
857                         break;
858                 if (ARGS_PUNCT == ac)
859                         break;
860
861                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
862
863                 /* 
864                  * In this case, we've located a submacro and must
865                  * execute it.  Close out scope, if open.  If no
866                  * elements have been generated, either create one (nc)
867                  * or raise a warning.
868                  */
869
870                 if (MDOC_MAX != ntok) {
871                         if (scope && ! rew_elem(m, tok))
872                                 return(0);
873                         if (nc && 0 == cnt) {
874                                 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
875                                         return(0);
876                                 if ( ! rew_last(m, m->last))
877                                         return(0);
878                         } else if ( ! nc && 0 == cnt) {
879                                 mdoc_argv_free(arg);
880                                 mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY);
881                         }
882
883                         if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
884                                 return(0);
885                         if ( ! nl)
886                                 return(1);
887                         return(append_delims(m, line, pos, buf));
888                 } 
889
890                 /* 
891                  * Non-quote-enclosed punctuation.  Set up our scope, if
892                  * a word; rewind the scope, if a delimiter; then append
893                  * the word. 
894                  */
895
896                 d = ARGS_QWORD == ac ? DELIM_NONE : mdoc_isdelim(p);
897
898                 if (DELIM_NONE != d) {
899                         /*
900                          * If we encounter closing punctuation, no word
901                          * has been omitted, no scope is open, and we're
902                          * allowed to have an empty element, then start
903                          * a new scope.  `Ar', `Fl', and `Li', only do
904                          * this once per invocation.  There may be more
905                          * of these (all of them?).
906                          */
907                         if (0 == cnt && (nc || MDOC_Li == tok) && 
908                                         DELIM_CLOSE == d && ! scope) {
909                                 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
910                                         return(0);
911                                 if (MDOC_Ar == tok || MDOC_Li == tok || 
912                                                 MDOC_Fl == tok)
913                                         cnt++;
914                                 scope = 1;
915                         }
916                         /*
917                          * Close out our scope, if one is open, before
918                          * any punctuation.
919                          */
920                         if (scope && ! rew_elem(m, tok))
921                                 return(0);
922                         scope = 0;
923                 } else if ( ! scope) {
924                         if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
925                                 return(0);
926                         scope = 1;
927                 }
928
929                 if (DELIM_NONE == d)
930                         cnt++;
931
932                 if ( ! dword(m, line, la, p, d))
933                         return(0);
934
935                 /*
936                  * `Fl' macros have their scope re-opened with each new
937                  * word so that the `-' can be added to each one without
938                  * having to parse out spaces.
939                  */
940                 if (scope && MDOC_Fl == tok) {
941                         if ( ! rew_elem(m, tok))
942                                 return(0);
943                         scope = 0;
944                 }
945         }
946
947         if (scope && ! rew_elem(m, tok))
948                 return(0);
949
950         /*
951          * If no elements have been collected and we're allowed to have
952          * empties (nc), open a scope and close it out.  Otherwise,
953          * raise a warning.
954          */
955
956         if (nc && 0 == cnt) {
957                 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
958                         return(0);
959                 if ( ! rew_last(m, m->last))
960                         return(0);
961         } else if ( ! nc && 0 == cnt) {
962                 mdoc_argv_free(arg);
963                 mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY);
964         }
965
966         if ( ! nl)
967                 return(1);
968         return(append_delims(m, line, pos, buf));
969 }
970
971
972 static int
973 blk_full(MACRO_PROT_ARGS)
974 {
975         int               la, nl;
976         struct mdoc_arg  *arg;
977         struct mdoc_node *head; /* save of head macro */
978         struct mdoc_node *body; /* save of body macro */
979         struct mdoc_node *n;
980         enum mdoc_type    mtt;
981         enum mdoct        ntok;
982         enum margserr     ac, lac;
983         enum margverr     av;
984         char             *p;
985
986         nl = MDOC_NEWLINE & m->flags;
987
988         /* Close out prior implicit scope. */
989
990         if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
991                 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
992                         return(0);
993                 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
994                         return(0);
995         }
996
997         /*
998          * This routine accomodates implicitly- and explicitly-scoped
999          * macro openings.  Implicit ones first close out prior scope
1000          * (seen above).  Delay opening the head until necessary to
1001          * allow leading punctuation to print.  Special consideration
1002          * for `It -column', which has phrase-part syntax instead of
1003          * regular child nodes.
1004          */
1005
1006         for (arg = NULL;; ) {
1007                 la = *pos;
1008                 av = mdoc_argv(m, line, tok, &arg, pos, buf);
1009
1010                 if (ARGV_WORD == av) {
1011                         *pos = la;
1012                         break;
1013                 } 
1014
1015                 if (ARGV_EOLN == av)
1016                         break;
1017                 if (ARGV_ARG == av)
1018                         continue;
1019
1020                 mdoc_argv_free(arg);
1021                 return(0);
1022         }
1023
1024         if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
1025                 return(0);
1026
1027         head = body = NULL;
1028
1029         /*
1030          * The `Nd' macro has all arguments in its body: it's a hybrid
1031          * of block partial-explicit and full-implicit.  Stupid.
1032          */
1033
1034         if (MDOC_Nd == tok) {
1035                 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1036                         return(0);
1037                 head = m->last;
1038                 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1039                         return(0);
1040                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1041                         return(0);
1042                 body = m->last;
1043         } 
1044
1045         ac = ARGS_ERROR;
1046
1047         for ( ; ; ) {
1048                 la = *pos;
1049                 /* Initialise last-phrase-type with ARGS_PEND. */
1050                 lac = ARGS_ERROR == ac ? ARGS_PEND : ac;
1051                 ac = mdoc_args(m, line, pos, buf, tok, &p);
1052
1053                 if (ARGS_PUNCT == ac)
1054                         break;
1055
1056                 if (ARGS_ERROR == ac)
1057                         return(0);
1058
1059                 if (ARGS_EOLN == ac) {
1060                         if (ARGS_PPHRASE != lac && ARGS_PHRASE != lac)
1061                                 break;
1062                         /*
1063                          * This is necessary: if the last token on a
1064                          * line is a `Ta' or tab, then we'll get
1065                          * ARGS_EOLN, so we must be smart enough to
1066                          * reopen our scope if the last parse was a
1067                          * phrase or partial phrase.
1068                          */
1069                         if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
1070                                 return(0);
1071                         if ( ! mdoc_body_alloc(m, line, ppos, tok))
1072                                 return(0);
1073                         body = m->last;
1074                         break;
1075                 }
1076
1077                 /* 
1078                  * Emit leading punctuation (i.e., punctuation before
1079                  * the MDOC_HEAD) for non-phrase types.
1080                  */
1081
1082                 if (NULL == head && 
1083                                 ARGS_PEND != ac &&
1084                                 ARGS_PHRASE != ac &&
1085                                 ARGS_PPHRASE != ac &&
1086                                 ARGS_QWORD != ac &&
1087                                 DELIM_OPEN == mdoc_isdelim(p)) {
1088                         if ( ! dword(m, line, la, p, DELIM_OPEN))
1089                                 return(0);
1090                         continue;
1091                 }
1092
1093                 /* Open a head if one hasn't been opened. */
1094
1095                 if (NULL == head) {
1096                         if ( ! mdoc_head_alloc(m, line, ppos, tok))
1097                                 return(0);
1098                         head = m->last;
1099                 }
1100
1101                 if (ARGS_PHRASE == ac || 
1102                                 ARGS_PEND == ac ||
1103                                 ARGS_PPHRASE == ac) {
1104                         /*
1105                          * If we haven't opened a body yet, rewind the
1106                          * head; if we have, rewind that instead.
1107                          */
1108
1109                         mtt = body ? MDOC_BODY : MDOC_HEAD;
1110                         if ( ! rew_sub(mtt, m, tok, line, ppos))
1111                                 return(0);
1112                         
1113                         /* Then allocate our body context. */
1114
1115                         if ( ! mdoc_body_alloc(m, line, ppos, tok))
1116                                 return(0);
1117                         body = m->last;
1118
1119                         /*
1120                          * Process phrases: set whether we're in a
1121                          * partial-phrase (this effects line handling)
1122                          * then call down into the phrase parser.
1123                          */
1124
1125                         if (ARGS_PPHRASE == ac)
1126                                 m->flags |= MDOC_PPHRASE;
1127                         if (ARGS_PEND == ac && ARGS_PPHRASE == lac)
1128                                 m->flags |= MDOC_PPHRASE;
1129
1130                         if ( ! phrase(m, line, la, buf))
1131                                 return(0);
1132
1133                         m->flags &= ~MDOC_PPHRASE;
1134                         continue;
1135                 }
1136
1137                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1138
1139                 if (MDOC_MAX == ntok) {
1140                         if ( ! dword(m, line, la, p, DELIM_MAX))
1141                                 return(0);
1142                         continue;
1143                 }
1144
1145                 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1146                         return(0);
1147                 break;
1148         }
1149
1150         if (NULL == head) {
1151                 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1152                         return(0);
1153                 head = m->last;
1154         }
1155         
1156         if (nl && ! append_delims(m, line, pos, buf))
1157                 return(0);
1158
1159         /* If we've already opened our body, exit now. */
1160
1161         if (NULL != body)
1162                 goto out;
1163
1164         /*
1165          * If there is an open (i.e., unvalidated) sub-block requiring
1166          * explicit close-out, postpone switching the current block from
1167          * head to body until the rew_sub() call closing out that
1168          * sub-block.
1169          */
1170         for (n = m->last; n && n != head; n = n->parent) {
1171                 if (MDOC_BLOCK == n->type && 
1172                                 MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1173                                 ! (MDOC_VALID & n->flags)) {
1174                         n->pending = head;
1175                         return(1);
1176                 }
1177         }
1178
1179         /* Close out scopes to remain in a consistent state. */
1180
1181         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1182                 return(0);
1183         if ( ! mdoc_body_alloc(m, line, ppos, tok))
1184                 return(0);
1185
1186 out:
1187         if ( ! (MDOC_FREECOL & m->flags))
1188                 return(1);
1189
1190         if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
1191                 return(0);
1192         if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
1193                 return(0);
1194
1195         m->flags &= ~MDOC_FREECOL;
1196         return(1);
1197 }
1198
1199
1200 static int
1201 blk_part_imp(MACRO_PROT_ARGS)
1202 {
1203         int               la, nl;
1204         enum mdoct        ntok;
1205         enum margserr     ac;
1206         char             *p;
1207         struct mdoc_node *blk; /* saved block context */
1208         struct mdoc_node *body; /* saved body context */
1209         struct mdoc_node *n;
1210
1211         nl = MDOC_NEWLINE & m->flags;
1212
1213         /*
1214          * A macro that spans to the end of the line.  This is generally
1215          * (but not necessarily) called as the first macro.  The block
1216          * has a head as the immediate child, which is always empty,
1217          * followed by zero or more opening punctuation nodes, then the
1218          * body (which may be empty, depending on the macro), then zero
1219          * or more closing punctuation nodes.
1220          */
1221
1222         if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1223                 return(0);
1224
1225         blk = m->last;
1226
1227         if ( ! mdoc_head_alloc(m, line, ppos, tok))
1228                 return(0);
1229         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1230                 return(0);
1231
1232         /*
1233          * Open the body scope "on-demand", that is, after we've
1234          * processed all our the leading delimiters (open parenthesis,
1235          * etc.).
1236          */
1237
1238         for (body = NULL; ; ) {
1239                 la = *pos;
1240                 ac = mdoc_args(m, line, pos, buf, tok, &p);
1241
1242                 if (ARGS_ERROR == ac)
1243                         return(0);
1244                 if (ARGS_EOLN == ac)
1245                         break;
1246                 if (ARGS_PUNCT == ac)
1247                         break;
1248
1249                 if (NULL == body && ARGS_QWORD != ac &&
1250                                 DELIM_OPEN == mdoc_isdelim(p)) {
1251                         if ( ! dword(m, line, la, p, DELIM_OPEN))
1252                                 return(0);
1253                         continue;
1254                 } 
1255
1256                 if (NULL == body) {
1257                        if ( ! mdoc_body_alloc(m, line, ppos, tok))
1258                                return(0);
1259                         body = m->last;
1260                 }
1261
1262                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1263
1264                 if (MDOC_MAX == ntok) {
1265                         if ( ! dword(m, line, la, p, DELIM_MAX))
1266                                 return(0);
1267                         continue;
1268                 }
1269
1270                 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1271                         return(0);
1272                 break;
1273         }
1274
1275         /* Clean-ups to leave in a consistent state. */
1276
1277         if (NULL == body) {
1278                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1279                         return(0);
1280                 body = m->last;
1281         }
1282
1283         for (n = body->child; n && n->next; n = n->next)
1284                 /* Do nothing. */ ;
1285         
1286         /* 
1287          * End of sentence spacing: if the last node is a text node and
1288          * has a trailing period, then mark it as being end-of-sentence.
1289          */
1290
1291         if (n && MDOC_TEXT == n->type && n->string)
1292                 if (mandoc_eos(n->string, strlen(n->string), 1))
1293                         n->flags |= MDOC_EOS;
1294
1295         /* Up-propogate the end-of-space flag. */
1296
1297         if (n && (MDOC_EOS & n->flags)) {
1298                 body->flags |= MDOC_EOS;
1299                 body->parent->flags |= MDOC_EOS;
1300         }
1301
1302         /*
1303          * If there is an open sub-block requiring explicit close-out,
1304          * postpone closing out the current block
1305          * until the rew_sub() call closing out the sub-block.
1306          */
1307         for (n = m->last; n && n != body && n != blk->parent; n = n->parent) {
1308                 if (MDOC_BLOCK == n->type &&
1309                     MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1310                     ! (MDOC_VALID & n->flags)) {
1311                         make_pending(n, tok, m, line, ppos);
1312                         if ( ! mdoc_endbody_alloc(m, line, ppos,
1313                             tok, body, ENDBODY_NOSPACE))
1314                                 return(0);
1315                         return(1);
1316                 }
1317         }
1318
1319         /* 
1320          * If we can't rewind to our body, then our scope has already
1321          * been closed by another macro (like `Oc' closing `Op').  This
1322          * is ugly behaviour nodding its head to OpenBSD's overwhelming
1323          * crufty use of `Op' breakage.
1324          */
1325         if (n != body)
1326                 mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos, 
1327                                 "%s broken", mdoc_macronames[tok]);
1328
1329         if (n && ! rew_sub(MDOC_BODY, m, tok, line, ppos))
1330                 return(0);
1331
1332         /* Standard appending of delimiters. */
1333
1334         if (nl && ! append_delims(m, line, pos, buf))
1335                 return(0);
1336
1337         /* Rewind scope, if applicable. */
1338
1339         if (n && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
1340                 return(0);
1341
1342         return(1);
1343 }
1344
1345
1346 static int
1347 blk_part_exp(MACRO_PROT_ARGS)
1348 {
1349         int               la, nl;
1350         enum margserr     ac;
1351         struct mdoc_node *head; /* keep track of head */
1352         struct mdoc_node *body; /* keep track of body */
1353         char             *p;
1354         enum mdoct        ntok;
1355
1356         nl = MDOC_NEWLINE & m->flags;
1357
1358         /*
1359          * The opening of an explicit macro having zero or more leading
1360          * punctuation nodes; a head with optional single element (the
1361          * case of `Eo'); and a body that may be empty.
1362          */
1363
1364         if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
1365                 return(0); 
1366
1367         for (head = body = NULL; ; ) {
1368                 la = *pos;
1369                 ac = mdoc_args(m, line, pos, buf, tok, &p);
1370
1371                 if (ARGS_ERROR == ac)
1372                         return(0);
1373                 if (ARGS_PUNCT == ac)
1374                         break;
1375                 if (ARGS_EOLN == ac)
1376                         break;
1377
1378                 /* Flush out leading punctuation. */
1379
1380                 if (NULL == head && ARGS_QWORD != ac &&
1381                                 DELIM_OPEN == mdoc_isdelim(p)) {
1382                         assert(NULL == body);
1383                         if ( ! dword(m, line, la, p, DELIM_OPEN))
1384                                 return(0);
1385                         continue;
1386                 } 
1387
1388                 if (NULL == head) {
1389                         assert(NULL == body);
1390                         if ( ! mdoc_head_alloc(m, line, ppos, tok))
1391                                 return(0);
1392                         head = m->last;
1393                 }
1394
1395                 /*
1396                  * `Eo' gobbles any data into the head, but most other
1397                  * macros just immediately close out and begin the body.
1398                  */
1399
1400                 if (NULL == body) {
1401                         assert(head);
1402                         /* No check whether it's a macro! */
1403                         if (MDOC_Eo == tok)
1404                                 if ( ! dword(m, line, la, p, DELIM_MAX))
1405                                         return(0);
1406
1407                         if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1408                                 return(0);
1409                         if ( ! mdoc_body_alloc(m, line, ppos, tok))
1410                                 return(0);
1411                         body = m->last;
1412
1413                         if (MDOC_Eo == tok)
1414                                 continue;
1415                 }
1416
1417                 assert(NULL != head && NULL != body);
1418
1419                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1420
1421                 if (MDOC_MAX == ntok) {
1422                         if ( ! dword(m, line, la, p, DELIM_MAX))
1423                                 return(0);
1424                         continue;
1425                 }
1426
1427                 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1428                         return(0);
1429                 break;
1430         }
1431
1432         /* Clean-up to leave in a consistent state. */
1433
1434         if (NULL == head) {
1435                 if ( ! mdoc_head_alloc(m, line, ppos, tok))
1436                         return(0);
1437                 head = m->last;
1438         }
1439
1440         if (NULL == body) {
1441                 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
1442                         return(0);
1443                 if ( ! mdoc_body_alloc(m, line, ppos, tok))
1444                         return(0);
1445                 body = m->last;
1446         }
1447
1448         /* Standard appending of delimiters. */
1449
1450         if ( ! nl)
1451                 return(1);
1452         return(append_delims(m, line, pos, buf));
1453 }
1454
1455
1456 /* ARGSUSED */
1457 static int
1458 in_line_argn(MACRO_PROT_ARGS)
1459 {
1460         int              la, flushed, j, maxargs, nl;
1461         enum margserr    ac;
1462         enum margverr    av;
1463         struct mdoc_arg *arg;
1464         char            *p;
1465         enum mdoct       ntok;
1466
1467         nl = MDOC_NEWLINE & m->flags;
1468
1469         /*
1470          * A line macro that has a fixed number of arguments (maxargs).
1471          * Only open the scope once the first non-leading-punctuation is
1472          * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then
1473          * keep it open until the maximum number of arguments are
1474          * exhausted.
1475          */
1476
1477         switch (tok) {
1478         case (MDOC_Ap):
1479                 /* FALLTHROUGH */
1480         case (MDOC_No):
1481                 /* FALLTHROUGH */
1482         case (MDOC_Ns):
1483                 /* FALLTHROUGH */
1484         case (MDOC_Ux):
1485                 maxargs = 0;
1486                 break;
1487         case (MDOC_Bx):
1488                 /* FALLTHROUGH */
1489         case (MDOC_Xr):
1490                 maxargs = 2;
1491                 break;
1492         default:
1493                 maxargs = 1;
1494                 break;
1495         }
1496
1497         for (arg = NULL; ; ) {
1498                 la = *pos;
1499                 av = mdoc_argv(m, line, tok, &arg, pos, buf);
1500
1501                 if (ARGV_WORD == av) {
1502                         *pos = la;
1503                         break;
1504                 } 
1505
1506                 if (ARGV_EOLN == av)
1507                         break;
1508                 if (ARGV_ARG == av)
1509                         continue;
1510
1511                 mdoc_argv_free(arg);
1512                 return(0);
1513         }
1514
1515         for (flushed = j = 0; ; ) {
1516                 la = *pos;
1517                 ac = mdoc_args(m, line, pos, buf, tok, &p);
1518
1519                 if (ARGS_ERROR == ac)
1520                         return(0);
1521                 if (ARGS_PUNCT == ac)
1522                         break;
1523                 if (ARGS_EOLN == ac)
1524                         break;
1525
1526                 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 
1527                                 ARGS_QWORD != ac && 0 == j && 
1528                                 DELIM_OPEN == mdoc_isdelim(p)) {
1529                         if ( ! dword(m, line, la, p, DELIM_OPEN))
1530                                 return(0);
1531                         continue;
1532                 } else if (0 == j)
1533                        if ( ! mdoc_elem_alloc(m, line, la, tok, arg))
1534                                return(0);
1535
1536                 if (j == maxargs && ! flushed) {
1537                         if ( ! rew_elem(m, tok))
1538                                 return(0);
1539                         flushed = 1;
1540                 }
1541
1542                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1543
1544                 if (MDOC_MAX != ntok) {
1545                         if ( ! flushed && ! rew_elem(m, tok))
1546                                 return(0);
1547                         flushed = 1;
1548                         if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1549                                 return(0);
1550                         j++;
1551                         break;
1552                 }
1553
1554                 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1555                                 ARGS_QWORD != ac &&
1556                                 ! flushed &&
1557                                 DELIM_NONE != mdoc_isdelim(p)) {
1558                         if ( ! rew_elem(m, tok))
1559                                 return(0);
1560                         flushed = 1;
1561                 }
1562
1563                 /* 
1564                  * XXX: this is a hack to work around groff's ugliness
1565                  * as regards `Xr' and extraneous arguments.  It should
1566                  * ideally be deprecated behaviour, but because this is
1567                  * code is no here, it's unlikely to be removed.
1568                  */
1569
1570 #ifdef __OpenBSD__
1571                 if (MDOC_Xr == tok && j == maxargs) {
1572                         if ( ! mdoc_elem_alloc(m, line, la, MDOC_Ns, NULL))
1573                                 return(0);
1574                         if ( ! rew_elem(m, MDOC_Ns))
1575                                 return(0);
1576                 }
1577 #endif
1578
1579                 if ( ! dword(m, line, la, p, DELIM_MAX))
1580                         return(0);
1581                 j++;
1582         }
1583
1584         if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg))
1585                return(0);
1586
1587         /* Close out in a consistent state. */
1588
1589         if ( ! flushed && ! rew_elem(m, tok))
1590                 return(0);
1591         if ( ! nl)
1592                 return(1);
1593         return(append_delims(m, line, pos, buf));
1594 }
1595
1596
1597 static int
1598 in_line_eoln(MACRO_PROT_ARGS)
1599 {
1600         int              la;
1601         enum margserr    ac;
1602         enum margverr    av;
1603         struct mdoc_arg *arg;
1604         char            *p;
1605         enum mdoct       ntok;
1606
1607         assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1608
1609         if (tok == MDOC_Pp)
1610                 rew_sub(MDOC_BLOCK, m, MDOC_Nm, line, ppos);
1611
1612         /* Parse macro arguments. */
1613
1614         for (arg = NULL; ; ) {
1615                 la = *pos;
1616                 av = mdoc_argv(m, line, tok, &arg, pos, buf);
1617
1618                 if (ARGV_WORD == av) {
1619                         *pos = la;
1620                         break;
1621                 }
1622                 if (ARGV_EOLN == av) 
1623                         break;
1624                 if (ARGV_ARG == av)
1625                         continue;
1626
1627                 mdoc_argv_free(arg);
1628                 return(0);
1629         }
1630
1631         /* Open element scope. */
1632
1633         if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
1634                 return(0);
1635
1636         /* Parse argument terms. */
1637
1638         for (;;) {
1639                 la = *pos;
1640                 ac = mdoc_args(m, line, pos, buf, tok, &p);
1641
1642                 if (ARGS_ERROR == ac)
1643                         return(0);
1644                 if (ARGS_EOLN == ac)
1645                         break;
1646
1647                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
1648
1649                 if (MDOC_MAX == ntok) {
1650                         if ( ! dword(m, line, la, p, DELIM_MAX))
1651                                 return(0);
1652                         continue;
1653                 }
1654
1655                 if ( ! rew_elem(m, tok))
1656                         return(0);
1657                 return(mdoc_macro(m, ntok, line, la, pos, buf));
1658         }
1659
1660         /* Close out (no delimiters). */
1661
1662         return(rew_elem(m, tok));
1663 }
1664
1665
1666 /* ARGSUSED */
1667 static int
1668 ctx_synopsis(MACRO_PROT_ARGS)
1669 {
1670         int              nl;
1671
1672         nl = MDOC_NEWLINE & m->flags;
1673
1674         /* If we're not in the SYNOPSIS, go straight to in-line. */
1675         if ( ! (MDOC_SYNOPSIS & m->flags))
1676                 return(in_line(m, tok, line, ppos, pos, buf));
1677
1678         /* If we're a nested call, same place. */
1679         if ( ! nl)
1680                 return(in_line(m, tok, line, ppos, pos, buf));
1681
1682         /*
1683          * XXX: this will open a block scope; however, if later we end
1684          * up formatting the block scope, then child nodes will inherit
1685          * the formatting.  Be careful.
1686          */
1687         if (MDOC_Nm == tok)
1688                 return(blk_full(m, tok, line, ppos, pos, buf));
1689         assert(MDOC_Vt == tok);
1690         return(blk_part_imp(m, tok, line, ppos, pos, buf));
1691 }
1692
1693
1694 /* ARGSUSED */
1695 static int
1696 obsolete(MACRO_PROT_ARGS)
1697 {
1698
1699         mdoc_pmsg(m, line, ppos, MANDOCERR_MACROOBS);
1700         return(1);
1701 }
1702
1703
1704 /*
1705  * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1706  * They're unusual because they're basically free-form text until a
1707  * macro is encountered.
1708  */
1709 static int
1710 phrase(struct mdoc *m, int line, int ppos, char *buf)
1711 {
1712         int              la, pos;
1713         enum margserr    ac;
1714         enum mdoct       ntok;
1715         char            *p;
1716
1717         for (pos = ppos; ; ) {
1718                 la = pos;
1719
1720                 ac = mdoc_zargs(m, line, &pos, buf, 0, &p);
1721
1722                 if (ARGS_ERROR == ac)
1723                         return(0);
1724                 if (ARGS_EOLN == ac)
1725                         break;
1726
1727                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
1728
1729                 if (MDOC_MAX == ntok) {
1730                         if ( ! dword(m, line, la, p, DELIM_MAX))
1731                                 return(0);
1732                         continue;
1733                 }
1734
1735                 if ( ! mdoc_macro(m, ntok, line, la, &pos, buf))
1736                         return(0);
1737                 return(append_delims(m, line, &pos, buf));
1738         }
1739
1740         return(1);
1741 }
1742
1743
1744 /* ARGSUSED */
1745 static int
1746 phrase_ta(MACRO_PROT_ARGS)
1747 {
1748         int               la;
1749         enum mdoct        ntok;
1750         enum margserr     ac;
1751         char             *p;
1752
1753         /*
1754          * FIXME: this is overly restrictive: if the `Ta' is unexpected,
1755          * it should simply error out with ARGSLOST.
1756          */
1757
1758         if ( ! rew_sub(MDOC_BODY, m, MDOC_It, line, ppos))
1759                 return(0);
1760         if ( ! mdoc_body_alloc(m, line, ppos, MDOC_It))
1761                 return(0);
1762
1763         for (;;) {
1764                 la = *pos;
1765                 ac = mdoc_zargs(m, line, pos, buf, 0, &p);
1766
1767                 if (ARGS_ERROR == ac)
1768                         return(0);
1769                 if (ARGS_EOLN == ac)
1770                         break;
1771
1772                 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
1773
1774                 if (MDOC_MAX == ntok) {
1775                         if ( ! dword(m, line, la, p, DELIM_MAX))
1776                                 return(0);
1777                         continue;
1778                 }
1779
1780                 if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
1781                         return(0);
1782                 return(append_delims(m, line, pos, buf));
1783         }
1784
1785         return(1);
1786 }