mandoc(1): Update to 1.9.15.
[dragonfly.git] / usr.bin / mandoc / mdoc_action.c
1 /*      $Id: mdoc_action.c,v 1.50 2010/01/01 17:14:29 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 #ifndef OSNAME
18 #include <sys/utsname.h>
19 #endif
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26
27 #include "libmdoc.h"
28 #include "libmandoc.h"
29
30 #define POST_ARGS struct mdoc *m, struct mdoc_node *n
31 #define PRE_ARGS  struct mdoc *m, const struct mdoc_node *n
32
33 #define NUMSIZ    32
34 #define DATESIZ   32
35
36 struct  actions {
37         int     (*pre)(PRE_ARGS);
38         int     (*post)(POST_ARGS);
39 };
40
41 static  int       concat(struct mdoc *, char *,
42                         const struct mdoc_node *, size_t);
43 static  inline int order_rs(int);
44
45 static  int       post_ar(POST_ARGS);
46 static  int       post_at(POST_ARGS);
47 static  int       post_bl(POST_ARGS);
48 static  int       post_bl_head(POST_ARGS);
49 static  int       post_bl_tagwidth(POST_ARGS);
50 static  int       post_bl_width(POST_ARGS);
51 static  int       post_dd(POST_ARGS);
52 static  int       post_display(POST_ARGS);
53 static  int       post_dt(POST_ARGS);
54 static  int       post_lb(POST_ARGS);
55 static  int       post_nm(POST_ARGS);
56 static  int       post_os(POST_ARGS);
57 static  int       post_pa(POST_ARGS);
58 static  int       post_prol(POST_ARGS);
59 static  int       post_rs(POST_ARGS);
60 static  int       post_sh(POST_ARGS);
61 static  int       post_st(POST_ARGS);
62 static  int       post_std(POST_ARGS);
63
64 static  int       pre_bd(PRE_ARGS);
65 static  int       pre_bl(PRE_ARGS);
66 static  int       pre_dl(PRE_ARGS);
67 static  int       pre_offset(PRE_ARGS);
68
69 static  const struct actions mdoc_actions[MDOC_MAX] = {
70         { NULL, NULL }, /* Ap */
71         { NULL, post_dd }, /* Dd */
72         { NULL, post_dt }, /* Dt */
73         { NULL, post_os }, /* Os */
74         { NULL, post_sh }, /* Sh */
75         { NULL, NULL }, /* Ss */
76         { NULL, NULL }, /* Pp */
77         { NULL, NULL }, /* D1 */
78         { pre_dl, post_display }, /* Dl */
79         { pre_bd, post_display }, /* Bd */
80         { NULL, NULL }, /* Ed */
81         { pre_bl, post_bl }, /* Bl */
82         { NULL, NULL }, /* El */
83         { NULL, NULL }, /* It */
84         { NULL, NULL }, /* Ad */
85         { NULL, NULL }, /* An */
86         { NULL, post_ar }, /* Ar */
87         { NULL, NULL }, /* Cd */
88         { NULL, NULL }, /* Cm */
89         { NULL, NULL }, /* Dv */
90         { NULL, NULL }, /* Er */
91         { NULL, NULL }, /* Ev */
92         { NULL, post_std }, /* Ex */
93         { NULL, NULL }, /* Fa */
94         { NULL, NULL }, /* Fd */
95         { NULL, NULL }, /* Fl */
96         { NULL, NULL }, /* Fn */
97         { NULL, NULL }, /* Ft */
98         { NULL, NULL }, /* Ic */
99         { NULL, NULL }, /* In */
100         { NULL, NULL }, /* Li */
101         { NULL, NULL }, /* Nd */
102         { NULL, post_nm }, /* Nm */
103         { NULL, NULL }, /* Op */
104         { NULL, NULL }, /* Ot */
105         { NULL, post_pa }, /* Pa */
106         { NULL, post_std }, /* Rv */
107         { NULL, post_st }, /* St */
108         { NULL, NULL }, /* Va */
109         { NULL, NULL }, /* Vt */
110         { NULL, NULL }, /* Xr */
111         { NULL, NULL }, /* %A */
112         { NULL, NULL }, /* %B */
113         { NULL, NULL }, /* %D */
114         { NULL, NULL }, /* %I */
115         { NULL, NULL }, /* %J */
116         { NULL, NULL }, /* %N */
117         { NULL, NULL }, /* %O */
118         { NULL, NULL }, /* %P */
119         { NULL, NULL }, /* %R */
120         { NULL, NULL }, /* %T */
121         { NULL, NULL }, /* %V */
122         { NULL, NULL }, /* Ac */
123         { NULL, NULL }, /* Ao */
124         { NULL, NULL }, /* Aq */
125         { NULL, post_at }, /* At */
126         { NULL, NULL }, /* Bc */
127         { NULL, NULL }, /* Bf */
128         { NULL, NULL }, /* Bo */
129         { NULL, NULL }, /* Bq */
130         { NULL, NULL }, /* Bsx */
131         { NULL, NULL }, /* Bx */
132         { NULL, NULL }, /* Db */
133         { NULL, NULL }, /* Dc */
134         { NULL, NULL }, /* Do */
135         { NULL, NULL }, /* Dq */
136         { NULL, NULL }, /* Ec */
137         { NULL, NULL }, /* Ef */
138         { NULL, NULL }, /* Em */
139         { NULL, NULL }, /* Eo */
140         { NULL, NULL }, /* Fx */
141         { NULL, NULL }, /* Ms */
142         { NULL, NULL }, /* No */
143         { NULL, NULL }, /* Ns */
144         { NULL, NULL }, /* Nx */
145         { NULL, NULL }, /* Ox */
146         { NULL, NULL }, /* Pc */
147         { NULL, NULL }, /* Pf */
148         { NULL, NULL }, /* Po */
149         { NULL, NULL }, /* Pq */
150         { NULL, NULL }, /* Qc */
151         { NULL, NULL }, /* Ql */
152         { NULL, NULL }, /* Qo */
153         { NULL, NULL }, /* Qq */
154         { NULL, NULL }, /* Re */
155         { NULL, post_rs }, /* Rs */
156         { NULL, NULL }, /* Sc */
157         { NULL, NULL }, /* So */
158         { NULL, NULL }, /* Sq */
159         { NULL, NULL }, /* Sm */
160         { NULL, NULL }, /* Sx */
161         { NULL, NULL }, /* Sy */
162         { NULL, NULL }, /* Tn */
163         { NULL, NULL }, /* Ux */
164         { NULL, NULL }, /* Xc */
165         { NULL, NULL }, /* Xo */
166         { NULL, NULL }, /* Fo */
167         { NULL, NULL }, /* Fc */
168         { NULL, NULL }, /* Oo */
169         { NULL, NULL }, /* Oc */
170         { NULL, NULL }, /* Bk */
171         { NULL, NULL }, /* Ek */
172         { NULL, NULL }, /* Bt */
173         { NULL, NULL }, /* Hf */
174         { NULL, NULL }, /* Fr */
175         { NULL, NULL }, /* Ud */
176         { NULL, post_lb }, /* Lb */
177         { NULL, NULL }, /* Lp */
178         { NULL, NULL }, /* Lk */
179         { NULL, NULL }, /* Mt */
180         { NULL, NULL }, /* Brq */
181         { NULL, NULL }, /* Bro */
182         { NULL, NULL }, /* Brc */
183         { NULL, NULL }, /* %C */
184         { NULL, NULL }, /* Es */
185         { NULL, NULL }, /* En */
186         { NULL, NULL }, /* Dx */
187         { NULL, NULL }, /* %Q */
188         { NULL, NULL }, /* br */
189         { NULL, NULL }, /* sp */
190         { NULL, NULL }, /* %U */
191 };
192
193 #define RSORD_MAX 14
194
195 static  const int rsord[RSORD_MAX] = {
196         MDOC__A,
197         MDOC__T,
198         MDOC__B,
199         MDOC__I,
200         MDOC__J,
201         MDOC__R,
202         MDOC__N,
203         MDOC__V,
204         MDOC__P,
205         MDOC__Q,
206         MDOC__D,
207         MDOC__O,
208         MDOC__C,
209         MDOC__U
210 };
211
212
213 int
214 mdoc_action_pre(struct mdoc *m, const struct mdoc_node *n)
215 {
216
217         switch (n->type) {
218         case (MDOC_ROOT):
219                 /* FALLTHROUGH */
220         case (MDOC_TEXT):
221                 return(1);
222         default:
223                 break;
224         }
225
226         if (NULL == mdoc_actions[n->tok].pre)
227                 return(1);
228         return((*mdoc_actions[n->tok].pre)(m, n));
229 }
230
231
232 int
233 mdoc_action_post(struct mdoc *m)
234 {
235
236         if (MDOC_ACTED & m->last->flags)
237                 return(1);
238         m->last->flags |= MDOC_ACTED;
239
240         switch (m->last->type) {
241         case (MDOC_TEXT):
242                 /* FALLTHROUGH */
243         case (MDOC_ROOT):
244                 return(1);
245         default:
246                 break;
247         }
248
249         if (NULL == mdoc_actions[m->last->tok].post)
250                 return(1);
251         return((*mdoc_actions[m->last->tok].post)(m, m->last));
252 }
253
254
255 /*
256  * Concatenate sibling nodes together.  All siblings must be of type
257  * MDOC_TEXT or an assertion is raised.  Concatenation is separated by a
258  * single whitespace.
259  */
260 static int
261 concat(struct mdoc *m, char *p, const struct mdoc_node *n, size_t sz)
262 {
263
264         assert(sz);
265         p[0] = '\0';
266         for ( ; n; n = n->next) {
267                 assert(MDOC_TEXT == n->type);
268                 if (strlcat(p, n->string, sz) >= sz)
269                         return(mdoc_nerr(m, n, ETOOLONG));
270                 if (NULL == n->next)
271                         continue;
272                 if (strlcat(p, " ", sz) >= sz)
273                         return(mdoc_nerr(m, n, ETOOLONG));
274         }
275
276         return(1);
277 }
278
279
280 /*
281  * Macros accepting `-std' as an argument have the name of the current
282  * document (`Nm') filled in as the argument if it's not provided.
283  */
284 static int
285 post_std(POST_ARGS)
286 {
287         struct mdoc_node        *nn;
288
289         if (n->child)
290                 return(1);
291
292         nn = n;
293         m->next = MDOC_NEXT_CHILD;
294         assert(m->meta.name);
295         if ( ! mdoc_word_alloc(m, n->line, n->pos, m->meta.name))
296                 return(0);
297         m->last = nn;
298         return(1);
299 }
300
301
302 /*
303  * The `Nm' macro's first use sets the name of the document.  See also
304  * post_std(), etc.
305  */
306 static int
307 post_nm(POST_ARGS)
308 {
309         char             buf[BUFSIZ];
310
311         if (m->meta.name)
312                 return(1);
313         if ( ! concat(m, buf, n->child, BUFSIZ))
314                 return(0);
315         m->meta.name = mandoc_strdup(buf);
316         return(1);
317 }
318
319
320 /*
321  * Look up the value of `Lb' for matching predefined strings.  If it has
322  * one, then substitute the current value for the formatted value.  Note
323  * that the lookup may fail (we can provide arbitrary strings).
324  */
325 /* ARGSUSED */
326 static int
327 post_lb(POST_ARGS)
328 {
329         const char      *p;
330         char            *buf;
331         size_t           sz;
332
333         assert(MDOC_TEXT == n->child->type);
334         p = mdoc_a2lib(n->child->string);
335
336         if (p) {
337                 free(n->child->string);
338                 n->child->string = mandoc_strdup(p);
339                 return(1);
340         }
341
342         sz = strlen(n->child->string) +
343                 2 + strlen("\\(lqlibrary\\(rq");
344         buf = mandoc_malloc(sz);
345         snprintf(buf, sz, "library \\(lq%s\\(rq", n->child->string);
346         free(n->child->string);
347         n->child->string = buf;
348         return(1);
349 }
350
351
352 /*
353  * Substitute the value of `St' for the corresponding formatted string.
354  * We're guaranteed that this exists (it's been verified during the
355  * validation phase).
356  */
357 /* ARGSUSED */
358 static int
359 post_st(POST_ARGS)
360 {
361         const char      *p;
362
363         assert(MDOC_TEXT == n->child->type);
364         p = mdoc_a2st(n->child->string);
365         assert(p);
366         free(n->child->string);
367         n->child->string = mandoc_strdup(p);
368         return(1);
369 }
370
371
372 /*
373  * Look up the standard string in a table.  We know that it exists from
374  * the validation phase, so assert on failure.  If a standard key wasn't
375  * supplied, supply the default ``AT&T UNIX''.
376  */
377 static int
378 post_at(POST_ARGS)
379 {
380         struct mdoc_node        *nn;
381         const char              *p;
382
383         if (n->child) {
384                 assert(MDOC_TEXT == n->child->type);
385                 p = mdoc_a2att(n->child->string);
386                 assert(p);
387                 free(n->child->string);
388                 n->child->string = mandoc_strdup(p);
389                 return(1);
390         }
391
392         nn = n;
393         m->next = MDOC_NEXT_CHILD;
394         if ( ! mdoc_word_alloc(m, nn->line, nn->pos, "AT&T UNIX"))
395                 return(0);
396         m->last = nn;
397         return(1);
398 }
399
400
401 /*
402  * Mark the current section.  The ``named'' section (lastnamed) is set
403  * whenever the current section isn't a custom section--we use this to
404  * keep track of section ordering.  Also check that the section is
405  * allowed within the document's manual section.
406  */
407 static int
408 post_sh(POST_ARGS)
409 {
410         enum mdoc_sec    sec;
411         char             buf[BUFSIZ];
412
413         if (MDOC_HEAD != n->type)
414                 return(1);
415
416         if ( ! concat(m, buf, n->child, BUFSIZ))
417                 return(0);
418         sec = mdoc_atosec(buf);
419         if (SEC_CUSTOM != sec)
420                 m->lastnamed = sec;
421
422         /* Some sections only live in certain manual sections. */
423
424         switch ((m->lastsec = sec)) {
425         case (SEC_RETURN_VALUES):
426                 /* FALLTHROUGH */
427         case (SEC_ERRORS):
428                 switch (m->meta.msec) {
429                 case (2):
430                         /* FALLTHROUGH */
431                 case (3):
432                         /* FALLTHROUGH */
433                 case (9):
434                         break;
435                 default:
436                         return(mdoc_nwarn(m, n, EBADSEC));
437                 }
438                 break;
439         default:
440                 break;
441         }
442         return(1);
443 }
444
445
446 /*
447  * Parse out the contents of `Dt'.  See in-line documentation for how we
448  * handle the various fields of this macro.
449  */
450 static int
451 post_dt(POST_ARGS)
452 {
453         struct mdoc_node *nn;
454         const char       *cp;
455         char             *ep;
456         long              lval;
457
458         if (m->meta.title)
459                 free(m->meta.title);
460         if (m->meta.vol)
461                 free(m->meta.vol);
462         if (m->meta.arch)
463                 free(m->meta.arch);
464
465         m->meta.title = m->meta.vol = m->meta.arch = NULL;
466         m->meta.msec = 0;
467
468         /* Handles: `.Dt'
469          *   --> title = unknown, volume = local, msec = 0, arch = NULL
470          */
471
472         if (NULL == (nn = n->child)) {
473                 /* XXX: make these macro values. */
474                 m->meta.title = mandoc_strdup("unknown");
475                 m->meta.vol = mandoc_strdup("local");
476                 return(post_prol(m, n));
477         }
478
479         /* Handles: `.Dt TITLE'
480          *   --> title = TITLE, volume = local, msec = 0, arch = NULL
481          */
482
483         m->meta.title = mandoc_strdup(nn->string);
484
485         if (NULL == (nn = nn->next)) {
486                 /* XXX: make this a macro value. */
487                 m->meta.vol = mandoc_strdup("local");
488                 return(post_prol(m, n));
489         }
490
491         /* Handles: `.Dt TITLE SEC'
492          *   --> title = TITLE, volume = SEC is msec ?
493          *           format(msec) : SEC,
494          *       msec = SEC is msec ? atoi(msec) : 0,
495          *       arch = NULL
496          */
497
498         cp = mdoc_a2msec(nn->string);
499         if (cp) {
500                 /* FIXME: where is strtonum!? */
501                 m->meta.vol = mandoc_strdup(cp);
502                 lval = strtol(nn->string, &ep, 10);
503                 if (nn->string[0] != '\0' && *ep == '\0')
504                         m->meta.msec = (int)lval;
505         } else
506                 m->meta.vol = mandoc_strdup(nn->string);
507
508         if (NULL == (nn = nn->next))
509                 return(post_prol(m, n));
510
511         /* Handles: `.Dt TITLE SEC VOL'
512          *   --> title = TITLE, volume = VOL is vol ?
513          *       format(VOL) :
514          *           VOL is arch ? format(arch) :
515          *               VOL
516          */
517
518         cp = mdoc_a2vol(nn->string);
519         if (cp) {
520                 free(m->meta.vol);
521                 m->meta.vol = mandoc_strdup(cp);
522         } else {
523                 cp = mdoc_a2arch(nn->string);
524                 if (NULL == cp) {
525                         free(m->meta.vol);
526                         m->meta.vol = mandoc_strdup(nn->string);
527                 } else
528                         m->meta.arch = mandoc_strdup(cp);
529         }
530
531         /* Ignore any subsequent parameters... */
532         /* FIXME: warn about subsequent parameters. */
533
534         return(post_prol(m, n));
535 }
536
537
538 /*
539  * Set the operating system by way of the `Os' macro.  Note that if an
540  * argument isn't provided and -DOSNAME="\"foo\"" is provided during
541  * compilation, this value will be used instead of filling in "sysname
542  * release" from uname().
543  */
544 static int
545 post_os(POST_ARGS)
546 {
547         char              buf[BUFSIZ];
548 #ifndef OSNAME
549         struct utsname    utsname;
550 #endif
551
552         if (m->meta.os)
553                 free(m->meta.os);
554
555         if ( ! concat(m, buf, n->child, BUFSIZ))
556                 return(0);
557
558         if ('\0' == buf[0]) {
559 #ifdef OSNAME
560                 if (strlcat(buf, OSNAME, BUFSIZ) >= BUFSIZ)
561                         return(mdoc_nerr(m, n, EUTSNAME));
562 #else /*!OSNAME */
563                 if (-1 == uname(&utsname))
564                         return(mdoc_nerr(m, n, EUTSNAME));
565                 if (strlcat(buf, utsname.sysname, BUFSIZ) >= BUFSIZ)
566                         return(mdoc_nerr(m, n, ETOOLONG));
567                 if (strlcat(buf, " ", 64) >= BUFSIZ)
568                         return(mdoc_nerr(m, n, ETOOLONG));
569                 if (strlcat(buf, utsname.release, BUFSIZ) >= BUFSIZ)
570                         return(mdoc_nerr(m, n, ETOOLONG));
571 #endif /*!OSNAME*/
572         }
573
574         m->meta.os = mandoc_strdup(buf);
575         return(post_prol(m, n));
576 }
577
578
579 /*
580  * Calculate the -width for a `Bl -tag' list if it hasn't been provided.
581  * Uses the first head macro.  NOTE AGAIN: this is ONLY if the -width
582  * argument has NOT been provided.  See post_bl_width() for converting
583  * the -width string.
584  */
585 static int
586 post_bl_tagwidth(POST_ARGS)
587 {
588         struct mdoc_node *nn;
589         size_t            sz;
590         int               i;
591         char              buf[NUMSIZ];
592
593         /* Defaults to ten ens. */
594
595         sz = 10; /* XXX: make this a macro value. */
596         nn = n->body->child;
597
598         if (nn) {
599                 assert(MDOC_BLOCK == nn->type);
600                 assert(MDOC_It == nn->tok);
601                 nn = nn->head->child;
602                 if (MDOC_TEXT != nn->type) {
603                         sz = mdoc_macro2len(nn->tok);
604                         if (sz == 0) {
605                                 if ( ! mdoc_nwarn(m, n, ENOWIDTH))
606                                         return(0);
607                                 sz = 10;
608                         }
609                 } else
610                         sz = strlen(nn->string) + 1;
611         }
612
613         snprintf(buf, NUMSIZ, "%zun", sz);
614
615         /*
616          * We have to dynamically add this to the macro's argument list.
617          * We're guaranteed that a MDOC_Width doesn't already exist.
618          */
619
620         nn = n;
621         assert(nn->args);
622         i = (int)(nn->args->argc)++;
623
624         nn->args->argv = mandoc_realloc(nn->args->argv,
625                         nn->args->argc * sizeof(struct mdoc_argv));
626
627         nn->args->argv[i].arg = MDOC_Width;
628         nn->args->argv[i].line = n->line;
629         nn->args->argv[i].pos = n->pos;
630         nn->args->argv[i].sz = 1;
631         nn->args->argv[i].value = mandoc_malloc(sizeof(char *));
632         nn->args->argv[i].value[0] = mandoc_strdup(buf);
633         return(1);
634 }
635
636
637 /*
638  * Calculate the real width of a list from the -width string, which may
639  * contain a macro (with a known default width), a literal string, or a
640  * scaling width.
641  */
642 static int
643 post_bl_width(POST_ARGS)
644 {
645         size_t            width;
646         int               i, tok;
647         char              buf[NUMSIZ];
648         char             *p;
649
650         if (NULL == n->args)
651                 return(1);
652
653         for (i = 0; i < (int)n->args->argc; i++)
654                 if (MDOC_Width == n->args->argv[i].arg)
655                         break;
656
657         if (i == (int)n->args->argc)
658                 return(1);
659         p = n->args->argv[i].value[0];
660
661         /*
662          * If the value to -width is a macro, then we re-write it to be
663          * the macro's width as set in share/tmac/mdoc/doc-common.
664          */
665
666         if (0 == strcmp(p, "Ds"))
667                 /* XXX: make into a macro. */
668                 width = 6;
669         else if (MDOC_MAX == (tok = mdoc_hash_find(p)))
670                 return(1);
671         else if (0 == (width = mdoc_macro2len(tok)))
672                 return(mdoc_nwarn(m, n, ENOWIDTH));
673
674         /* The value already exists: free and reallocate it. */
675
676         snprintf(buf, NUMSIZ, "%zun", width);
677         free(n->args->argv[i].value[0]);
678         n->args->argv[i].value[0] = mandoc_strdup(buf);
679         return(1);
680 }
681
682
683 /*
684  * Do processing for -column lists, which can have two distinct styles
685  * of invocation.  Merge this two styles into a consistent form.
686  */
687 /* ARGSUSED */
688 static int
689 post_bl_head(POST_ARGS)
690 {
691         int                      i, c;
692         struct mdoc_node        *np, *nn, *nnp;
693
694         if (NULL == n->child)
695                 return(1);
696
697         np = n->parent;
698         assert(np->args);
699
700         for (c = 0; c < (int)np->args->argc; c++)
701                 if (MDOC_Column == np->args->argv[c].arg)
702                         break;
703
704         if (c == (int)np->args->argc)
705                 return(1);
706         assert(0 == np->args->argv[c].sz);
707
708         /*
709          * Accomodate for new-style groff column syntax.  Shuffle the
710          * child nodes, all of which must be TEXT, as arguments for the
711          * column field.  Then, delete the head children.
712          */
713
714         np->args->argv[c].sz = (size_t)n->nchild;
715         np->args->argv[c].value = mandoc_malloc
716                 ((size_t)n->nchild * sizeof(char *));
717
718         for (i = 0, nn = n->child; nn; i++) {
719                 np->args->argv[c].value[i] = nn->string;
720                 nn->string = NULL;
721                 nnp = nn;
722                 nn = nn->next;
723                 mdoc_node_free(nnp);
724         }
725
726         n->nchild = 0;
727         n->child = NULL;
728         return(1);
729 }
730
731
732 static int
733 post_bl(POST_ARGS)
734 {
735         int               i, r, len;
736
737         if (MDOC_HEAD == n->type)
738                 return(post_bl_head(m, n));
739         if (MDOC_BLOCK != n->type)
740                 return(1);
741
742         /*
743          * These are fairly complicated, so we've broken them into two
744          * functions.  post_bl_tagwidth() is called when a -tag is
745          * specified, but no -width (it must be guessed).  The second
746          * when a -width is specified (macro indicators must be
747          * rewritten into real lengths).
748          */
749
750         len = (int)(n->args ? n->args->argc : 0);
751
752         for (r = i = 0; i < len; i++) {
753                 if (MDOC_Tag == n->args->argv[i].arg)
754                         r |= 1 << 0;
755                 if (MDOC_Width == n->args->argv[i].arg)
756                         r |= 1 << 1;
757         }
758
759         if (r & (1 << 0) && ! (r & (1 << 1))) {
760                 if ( ! post_bl_tagwidth(m, n))
761                         return(0);
762         } else if (r & (1 << 1))
763                 if ( ! post_bl_width(m, n))
764                         return(0);
765
766         return(1);
767 }
768
769
770 /*
771  * The `Pa' macro defaults to a tilde if no value is provided as an
772  * argument.
773  */
774 static int
775 post_pa(POST_ARGS)
776 {
777         struct mdoc_node *np;
778
779         if (n->child)
780                 return(1);
781
782         np = n;
783         m->next = MDOC_NEXT_CHILD;
784         /* XXX: make into macro value. */
785         if ( ! mdoc_word_alloc(m, n->line, n->pos, "~"))
786                 return(0);
787         m->last = np;
788         return(1);
789 }
790
791
792 /*
793  * The `Ar' macro defaults to two strings "file ..." if no value is
794  * provided as an argument.
795  */
796 static int
797 post_ar(POST_ARGS)
798 {
799         struct mdoc_node *np;
800
801         if (n->child)
802                 return(1);
803
804         np = n;
805         m->next = MDOC_NEXT_CHILD;
806         /* XXX: make into macro values. */
807         if ( ! mdoc_word_alloc(m, n->line, n->pos, "file"))
808                 return(0);
809         if ( ! mdoc_word_alloc(m, n->line, n->pos, "..."))
810                 return(0);
811         m->last = np;
812         return(1);
813 }
814
815
816 /*
817  * Parse the date field in `Dd'.
818  */
819 static int
820 post_dd(POST_ARGS)
821 {
822         char            buf[DATESIZ];
823
824         if ( ! concat(m, buf, n->child, DATESIZ))
825                 return(0);
826
827         m->meta.date = mandoc_a2time
828                 (MTIME_MDOCDATE | MTIME_CANONICAL, buf);
829
830         if (0 == m->meta.date) {
831                 if ( ! mdoc_nwarn(m, n, EBADDATE))
832                         return(0);
833                 m->meta.date = time(NULL);
834         }
835
836         return(post_prol(m, n));
837 }
838
839
840 /*
841  * Remove prologue macros from the document after they're processed.
842  * The final document uses mdoc_meta for these values and discards the
843  * originals.
844  */
845 static int
846 post_prol(POST_ARGS)
847 {
848         struct mdoc_node *np;
849
850         if (n->parent->child == n)
851                 n->parent->child = n->prev;
852         if (n->prev)
853                 n->prev->next = NULL;
854
855         np = n;
856         assert(NULL == n->next);
857
858         if (n->prev) {
859                 m->last = n->prev;
860                 m->next = MDOC_NEXT_SIBLING;
861         } else {
862                 m->last = n->parent;
863                 m->next = MDOC_NEXT_CHILD;
864         }
865
866         mdoc_node_freelist(np);
867
868         if (m->meta.title && m->meta.date && m->meta.os)
869                 m->flags |= MDOC_PBODY;
870
871         return(1);
872 }
873
874
875 /*
876  * Trigger a literal context.
877  */
878 static int
879 pre_dl(PRE_ARGS)
880 {
881
882         if (MDOC_BODY == n->type)
883                 m->flags |= MDOC_LITERAL;
884         return(1);
885 }
886
887
888 /* ARGSUSED */
889 static int
890 pre_offset(PRE_ARGS)
891 {
892         int              i;
893
894         /*
895          * Make sure that an empty offset produces an 8n length space as
896          * stipulated by mdoc.samples.
897          */
898
899         assert(n->args);
900         for (i = 0; i < (int)n->args->argc; i++) {
901                 if (MDOC_Offset != n->args->argv[i].arg)
902                         continue;
903                 if (n->args->argv[i].sz)
904                         break;
905                 assert(1 == n->args->refcnt);
906                 /* If no value set, length of <string>. */
907                 n->args->argv[i].sz++;
908                 n->args->argv[i].value = mandoc_malloc(sizeof(char *));
909                 n->args->argv[i].value[0] = mandoc_strdup("8n");
910                 break;
911         }
912
913         return(1);
914 }
915
916
917 static int
918 pre_bl(PRE_ARGS)
919 {
920
921         return(MDOC_BLOCK == n->type ? pre_offset(m, n) : 1);
922 }
923
924
925 static int
926 pre_bd(PRE_ARGS)
927 {
928         int              i;
929
930         if (MDOC_BLOCK == n->type)
931                 return(pre_offset(m, n));
932         if (MDOC_BODY != n->type)
933                 return(1);
934
935         /* Enter literal context if `Bd -literal' or `-unfilled'. */
936
937         for (n = n->parent, i = 0; i < (int)n->args->argc; i++)
938                 if (MDOC_Literal == n->args->argv[i].arg)
939                         m->flags |= MDOC_LITERAL;
940                 else if (MDOC_Unfilled == n->args->argv[i].arg)
941                         m->flags |= MDOC_LITERAL;
942
943         return(1);
944 }
945
946
947 static int
948 post_display(POST_ARGS)
949 {
950
951         if (MDOC_BODY == n->type)
952                 m->flags &= ~MDOC_LITERAL;
953         return(1);
954 }
955
956
957 static inline int
958 order_rs(int t)
959 {
960         int             i;
961
962         for (i = 0; i < RSORD_MAX; i++)
963                 if (rsord[i] == t)
964                         return(i);
965
966         abort();
967         /* NOTREACHED */
968 }
969
970
971 /* ARGSUSED */
972 static int
973 post_rs(POST_ARGS)
974 {
975         struct mdoc_node        *nn, *next, *prev;
976         int                      o;
977
978         if (MDOC_BLOCK != n->type)
979                 return(1);
980
981         assert(n->body->child);
982         for (next = NULL, nn = n->body->child->next; nn; nn = next) {
983                 o = order_rs(nn->tok);
984
985                 /* Remove `nn' from the chain. */
986                 next = nn->next;
987                 if (next)
988                         next->prev = nn->prev;
989
990                 prev = nn->prev;
991                 if (prev)
992                         prev->next = nn->next;
993
994                 nn->prev = nn->next = NULL;
995
996                 /*
997                  * Scan back until we reach a node that's ordered before
998                  * us, then set ourselves as being the next.
999                  */
1000                 for ( ; prev; prev = prev->prev)
1001                         if (order_rs(prev->tok) <= o)
1002                                 break;
1003
1004                 nn->prev = prev;
1005                 if (prev) {
1006                         if (prev->next)
1007                                 prev->next->prev = nn;
1008                         nn->next = prev->next;
1009                         prev->next = nn;
1010                         continue;
1011                 }
1012
1013                 n->body->child->prev = nn;
1014                 nn->next = n->body->child;
1015                 n->body->child = nn;
1016         }
1017         return(1);
1018 }