1 /* $Id: mdoc_validate.c,v 1.283 2015/02/23 13:55:55 schwarze Exp $ */
3 * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
5 * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include <sys/types.h>
23 #include <sys/utsname.h>
36 #include "mandoc_aux.h"
38 #include "libmandoc.h"
40 /* FIXME: .Bl -diag can't have non-text children in HEAD. */
42 #define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n
43 #define POST_ARGS struct mdoc *mdoc
51 typedef void (*v_pre)(PRE_ARGS);
52 typedef void (*v_post)(POST_ARGS);
59 static void check_text(struct mdoc *, int, int, char *);
60 static void check_argv(struct mdoc *,
61 struct mdoc_node *, struct mdoc_argv *);
62 static void check_args(struct mdoc *, struct mdoc_node *);
63 static int child_an(const struct mdoc_node *);
64 static enum mdoc_sec a2sec(const char *);
65 static size_t macro2len(enum mdoct);
66 static void rewrite_macro2len(char **);
68 static void post_an(POST_ARGS);
69 static void post_at(POST_ARGS);
70 static void post_bf(POST_ARGS);
71 static void post_bk(POST_ARGS);
72 static void post_bl(POST_ARGS);
73 static void post_bl_block(POST_ARGS);
74 static void post_bl_block_tag(POST_ARGS);
75 static void post_bl_head(POST_ARGS);
76 static void post_bx(POST_ARGS);
77 static void post_d1(POST_ARGS);
78 static void post_defaults(POST_ARGS);
79 static void post_dd(POST_ARGS);
80 static void post_dt(POST_ARGS);
81 static void post_en(POST_ARGS);
82 static void post_es(POST_ARGS);
83 static void post_eoln(POST_ARGS);
84 static void post_ex(POST_ARGS);
85 static void post_fa(POST_ARGS);
86 static void post_fn(POST_ARGS);
87 static void post_fname(POST_ARGS);
88 static void post_fo(POST_ARGS);
89 static void post_hyph(POST_ARGS);
90 static void post_ignpar(POST_ARGS);
91 static void post_it(POST_ARGS);
92 static void post_lb(POST_ARGS);
93 static void post_literal(POST_ARGS);
94 static void post_nd(POST_ARGS);
95 static void post_nm(POST_ARGS);
96 static void post_ns(POST_ARGS);
97 static void post_os(POST_ARGS);
98 static void post_par(POST_ARGS);
99 static void post_root(POST_ARGS);
100 static void post_rs(POST_ARGS);
101 static void post_sh(POST_ARGS);
102 static void post_sh_head(POST_ARGS);
103 static void post_sh_name(POST_ARGS);
104 static void post_sh_see_also(POST_ARGS);
105 static void post_sh_authors(POST_ARGS);
106 static void post_sm(POST_ARGS);
107 static void post_st(POST_ARGS);
108 static void post_vt(POST_ARGS);
110 static void pre_an(PRE_ARGS);
111 static void pre_bd(PRE_ARGS);
112 static void pre_bl(PRE_ARGS);
113 static void pre_dd(PRE_ARGS);
114 static void pre_display(PRE_ARGS);
115 static void pre_dt(PRE_ARGS);
116 static void pre_literal(PRE_ARGS);
117 static void pre_obsolete(PRE_ARGS);
118 static void pre_os(PRE_ARGS);
119 static void pre_par(PRE_ARGS);
120 static void pre_std(PRE_ARGS);
122 static const struct valids mdoc_valids[MDOC_MAX] = {
123 { NULL, NULL }, /* Ap */
124 { pre_dd, post_dd }, /* Dd */
125 { pre_dt, post_dt }, /* Dt */
126 { pre_os, post_os }, /* Os */
127 { NULL, post_sh }, /* Sh */
128 { NULL, post_ignpar }, /* Ss */
129 { pre_par, post_par }, /* Pp */
130 { pre_display, post_d1 }, /* D1 */
131 { pre_literal, post_literal }, /* Dl */
132 { pre_bd, post_literal }, /* Bd */
133 { NULL, NULL }, /* Ed */
134 { pre_bl, post_bl }, /* Bl */
135 { NULL, NULL }, /* El */
136 { pre_par, post_it }, /* It */
137 { NULL, NULL }, /* Ad */
138 { pre_an, post_an }, /* An */
139 { NULL, post_defaults }, /* Ar */
140 { NULL, NULL }, /* Cd */
141 { NULL, NULL }, /* Cm */
142 { NULL, NULL }, /* Dv */
143 { NULL, NULL }, /* Er */
144 { NULL, NULL }, /* Ev */
145 { pre_std, post_ex }, /* Ex */
146 { NULL, post_fa }, /* Fa */
147 { NULL, NULL }, /* Fd */
148 { NULL, NULL }, /* Fl */
149 { NULL, post_fn }, /* Fn */
150 { NULL, NULL }, /* Ft */
151 { NULL, NULL }, /* Ic */
152 { NULL, NULL }, /* In */
153 { NULL, post_defaults }, /* Li */
154 { NULL, post_nd }, /* Nd */
155 { NULL, post_nm }, /* Nm */
156 { NULL, NULL }, /* Op */
157 { pre_obsolete, NULL }, /* Ot */
158 { NULL, post_defaults }, /* Pa */
159 { pre_std, NULL }, /* Rv */
160 { NULL, post_st }, /* St */
161 { NULL, NULL }, /* Va */
162 { NULL, post_vt }, /* Vt */
163 { NULL, NULL }, /* Xr */
164 { NULL, NULL }, /* %A */
165 { NULL, post_hyph }, /* %B */ /* FIXME: can be used outside Rs/Re. */
166 { NULL, NULL }, /* %D */
167 { NULL, NULL }, /* %I */
168 { NULL, NULL }, /* %J */
169 { NULL, post_hyph }, /* %N */
170 { NULL, post_hyph }, /* %O */
171 { NULL, NULL }, /* %P */
172 { NULL, post_hyph }, /* %R */
173 { NULL, post_hyph }, /* %T */ /* FIXME: can be used outside Rs/Re. */
174 { NULL, NULL }, /* %V */
175 { NULL, NULL }, /* Ac */
176 { NULL, NULL }, /* Ao */
177 { NULL, NULL }, /* Aq */
178 { NULL, post_at }, /* At */
179 { NULL, NULL }, /* Bc */
180 { NULL, post_bf }, /* Bf */
181 { NULL, NULL }, /* Bo */
182 { NULL, NULL }, /* Bq */
183 { NULL, NULL }, /* Bsx */
184 { NULL, post_bx }, /* Bx */
185 { pre_obsolete, NULL }, /* Db */
186 { NULL, NULL }, /* Dc */
187 { NULL, NULL }, /* Do */
188 { NULL, NULL }, /* Dq */
189 { NULL, NULL }, /* Ec */
190 { NULL, NULL }, /* Ef */
191 { NULL, NULL }, /* Em */
192 { NULL, NULL }, /* Eo */
193 { NULL, NULL }, /* Fx */
194 { NULL, NULL }, /* Ms */
195 { NULL, NULL }, /* No */
196 { NULL, post_ns }, /* Ns */
197 { NULL, NULL }, /* Nx */
198 { NULL, NULL }, /* Ox */
199 { NULL, NULL }, /* Pc */
200 { NULL, NULL }, /* Pf */
201 { NULL, NULL }, /* Po */
202 { NULL, NULL }, /* Pq */
203 { NULL, NULL }, /* Qc */
204 { NULL, NULL }, /* Ql */
205 { NULL, NULL }, /* Qo */
206 { NULL, NULL }, /* Qq */
207 { NULL, NULL }, /* Re */
208 { NULL, post_rs }, /* Rs */
209 { NULL, NULL }, /* Sc */
210 { NULL, NULL }, /* So */
211 { NULL, NULL }, /* Sq */
212 { NULL, post_sm }, /* Sm */
213 { NULL, post_hyph }, /* Sx */
214 { NULL, NULL }, /* Sy */
215 { NULL, NULL }, /* Tn */
216 { NULL, NULL }, /* Ux */
217 { NULL, NULL }, /* Xc */
218 { NULL, NULL }, /* Xo */
219 { NULL, post_fo }, /* Fo */
220 { NULL, NULL }, /* Fc */
221 { NULL, NULL }, /* Oo */
222 { NULL, NULL }, /* Oc */
223 { NULL, post_bk }, /* Bk */
224 { NULL, NULL }, /* Ek */
225 { NULL, post_eoln }, /* Bt */
226 { NULL, NULL }, /* Hf */
227 { pre_obsolete, NULL }, /* Fr */
228 { NULL, post_eoln }, /* Ud */
229 { NULL, post_lb }, /* Lb */
230 { pre_par, post_par }, /* Lp */
231 { NULL, NULL }, /* Lk */
232 { NULL, post_defaults }, /* Mt */
233 { NULL, NULL }, /* Brq */
234 { NULL, NULL }, /* Bro */
235 { NULL, NULL }, /* Brc */
236 { NULL, NULL }, /* %C */
237 { pre_obsolete, post_es }, /* Es */
238 { pre_obsolete, post_en }, /* En */
239 { NULL, NULL }, /* Dx */
240 { NULL, NULL }, /* %Q */
241 { NULL, post_par }, /* br */
242 { NULL, post_par }, /* sp */
243 { NULL, NULL }, /* %U */
244 { NULL, NULL }, /* Ta */
245 { NULL, NULL }, /* ll */
248 #define RSORD_MAX 14 /* Number of `Rs' blocks. */
250 static const enum mdoct rsord[RSORD_MAX] = {
267 static const char * const secnames[SEC__MAX] = {
274 "IMPLEMENTATION NOTES",
289 "SECURITY CONSIDERATIONS",
295 mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n)
301 if (n->sec != SEC_SYNOPSIS || n->parent->tok != MDOC_Fd)
302 check_text(mdoc, n->line, n->pos, n->string);
315 p = mdoc_valids[n->tok].pre;
321 mdoc_valid_post(struct mdoc *mdoc)
327 if (n->flags & MDOC_VALID)
329 n->flags |= MDOC_VALID | MDOC_ENDED;
344 * Closing delimiters are not special at the
345 * beginning of a block, opening delimiters
346 * are not special at the end.
349 if (n->child != NULL)
350 n->child->flags &= ~MDOC_DELIMC;
352 n->last->flags &= ~MDOC_DELIMO;
354 /* Call the macro's postprocessor. */
356 p = mdoc_valids[n->tok].post;
364 check_args(struct mdoc *mdoc, struct mdoc_node *n)
371 assert(n->args->argc);
372 for (i = 0; i < (int)n->args->argc; i++)
373 check_argv(mdoc, n, &n->args->argv[i]);
377 check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v)
381 for (i = 0; i < (int)v->sz; i++)
382 check_text(mdoc, v->line, v->pos, v->value[i]);
386 check_text(struct mdoc *mdoc, int ln, int pos, char *p)
390 if (MDOC_LITERAL & mdoc->flags)
393 for (cp = p; NULL != (p = strchr(p, '\t')); p++)
394 mandoc_msg(MANDOCERR_FI_TAB, mdoc->parse,
395 ln, pos + (int)(p - cp), NULL);
399 pre_display(PRE_ARGS)
401 struct mdoc_node *node;
403 if (MDOC_BLOCK != n->type)
406 for (node = mdoc->last->parent; node; node = node->parent)
407 if (MDOC_BLOCK == node->type)
408 if (MDOC_Bd == node->tok)
412 mandoc_vmsg(MANDOCERR_BD_NEST,
413 mdoc->parse, n->line, n->pos,
414 "%s in Bd", mdoc_macronames[n->tok]);
420 struct mdoc_argv *argv, *wa;
422 enum mdocargt mdoclt;
425 if (n->type != MDOC_BLOCK)
429 * First figure out which kind of list to use: bind ourselves to
430 * the first mentioned list type and warn about any remaining
431 * ones. If we find no list type, we default to LIST_item.
434 wa = (n->args == NULL) ? NULL : n->args->argv;
435 mdoclt = MDOC_ARG_MAX;
436 for (i = 0; n->args && i < (int)n->args->argc; i++) {
437 argv = n->args->argv + i;
440 /* Set list types. */
474 /* Set list arguments. */
476 if (n->norm->Bl.comp)
477 mandoc_msg(MANDOCERR_ARG_REP,
478 mdoc->parse, argv->line,
479 argv->pos, "Bl -compact");
480 n->norm->Bl.comp = 1;
485 mandoc_msg(MANDOCERR_ARG_EMPTY,
486 mdoc->parse, argv->line,
487 argv->pos, "Bl -width");
488 n->norm->Bl.width = "0n";
491 if (NULL != n->norm->Bl.width)
492 mandoc_vmsg(MANDOCERR_ARG_REP,
493 mdoc->parse, argv->line,
494 argv->pos, "Bl -width %s",
496 rewrite_macro2len(argv->value);
497 n->norm->Bl.width = argv->value[0];
501 mandoc_msg(MANDOCERR_ARG_EMPTY,
502 mdoc->parse, argv->line,
503 argv->pos, "Bl -offset");
506 if (NULL != n->norm->Bl.offs)
507 mandoc_vmsg(MANDOCERR_ARG_REP,
508 mdoc->parse, argv->line,
509 argv->pos, "Bl -offset %s",
511 rewrite_macro2len(argv->value);
512 n->norm->Bl.offs = argv->value[0];
517 if (LIST__NONE == lt)
521 /* Check: multiple list types. */
523 if (LIST__NONE != n->norm->Bl.type) {
524 mandoc_vmsg(MANDOCERR_BL_REP,
525 mdoc->parse, n->line, n->pos,
526 "Bl -%s", mdoc_argnames[argv->arg]);
530 /* The list type should come first. */
532 if (n->norm->Bl.width ||
535 mandoc_vmsg(MANDOCERR_BL_LATETYPE,
536 mdoc->parse, n->line, n->pos, "Bl -%s",
537 mdoc_argnames[n->args->argv[0].arg]);
539 n->norm->Bl.type = lt;
540 if (LIST_column == lt) {
541 n->norm->Bl.ncols = argv->sz;
542 n->norm->Bl.cols = (void *)argv->value;
546 /* Allow lists to default to LIST_item. */
548 if (LIST__NONE == n->norm->Bl.type) {
549 mandoc_msg(MANDOCERR_BL_NOTYPE, mdoc->parse,
550 n->line, n->pos, "Bl");
551 n->norm->Bl.type = LIST_item;
555 * Validate the width field. Some list types don't need width
556 * types and should be warned about them. Others should have it
557 * and must also be warned. Yet others have a default and need
561 switch (n->norm->Bl.type) {
563 if (NULL == n->norm->Bl.width)
564 mandoc_msg(MANDOCERR_BL_NOWIDTH, mdoc->parse,
565 n->line, n->pos, "Bl -tag");
576 if (n->norm->Bl.width)
577 mandoc_vmsg(MANDOCERR_BL_SKIPW, mdoc->parse,
578 wa->line, wa->pos, "Bl -%s",
579 mdoc_argnames[mdoclt]);
586 if (NULL == n->norm->Bl.width)
587 n->norm->Bl.width = "2n";
590 if (NULL == n->norm->Bl.width)
591 n->norm->Bl.width = "3n";
602 struct mdoc_argv *argv;
606 pre_literal(mdoc, n);
608 if (n->type != MDOC_BLOCK)
611 for (i = 0; n->args && i < (int)n->args->argc; i++) {
612 argv = n->args->argv + i;
632 mandoc_msg(MANDOCERR_BD_FILE, mdoc->parse,
633 n->line, n->pos, NULL);
637 mandoc_msg(MANDOCERR_ARG_EMPTY,
638 mdoc->parse, argv->line,
639 argv->pos, "Bd -offset");
642 if (NULL != n->norm->Bd.offs)
643 mandoc_vmsg(MANDOCERR_ARG_REP,
644 mdoc->parse, argv->line,
645 argv->pos, "Bd -offset %s",
647 rewrite_macro2len(argv->value);
648 n->norm->Bd.offs = argv->value[0];
651 if (n->norm->Bd.comp)
652 mandoc_msg(MANDOCERR_ARG_REP,
653 mdoc->parse, argv->line,
654 argv->pos, "Bd -compact");
655 n->norm->Bd.comp = 1;
661 if (DISP__NONE == dt)
664 if (DISP__NONE == n->norm->Bd.type)
665 n->norm->Bd.type = dt;
667 mandoc_vmsg(MANDOCERR_BD_REP,
668 mdoc->parse, n->line, n->pos,
669 "Bd -%s", mdoc_argnames[argv->arg]);
672 if (DISP__NONE == n->norm->Bd.type) {
673 mandoc_msg(MANDOCERR_BD_NOTYPE, mdoc->parse,
674 n->line, n->pos, "Bd");
675 n->norm->Bd.type = DISP_ragged;
683 struct mdoc_argv *argv;
689 for (i = 1; i < n->args->argc; i++) {
690 argv = n->args->argv + i;
691 mandoc_vmsg(MANDOCERR_AN_REP,
692 mdoc->parse, argv->line, argv->pos,
693 "An -%s", mdoc_argnames[argv->arg]);
696 argv = n->args->argv;
697 if (argv->arg == MDOC_Split)
698 n->norm->An.auth = AUTH_split;
699 else if (argv->arg == MDOC_Nosplit)
700 n->norm->An.auth = AUTH_nosplit;
709 if (n->args && 1 == n->args->argc)
710 if (MDOC_Std == n->args->argv[0].arg)
713 mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse,
714 n->line, n->pos, mdoc_macronames[n->tok]);
718 pre_obsolete(PRE_ARGS)
721 if (MDOC_ELEM == n->type || MDOC_BLOCK == n->type)
722 mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse,
723 n->line, n->pos, mdoc_macronames[n->tok]);
730 if (mdoc->meta.title != NULL)
731 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
732 n->line, n->pos, "Dt");
733 else if (mdoc->meta.os != NULL)
734 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
735 n->line, n->pos, "Dt after Os");
742 if (mdoc->meta.os != NULL)
743 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
744 n->line, n->pos, "Os");
745 else if (mdoc->flags & MDOC_PBODY)
746 mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
747 n->line, n->pos, "Os");
754 if (mdoc->meta.date != NULL)
755 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
756 n->line, n->pos, "Dd");
757 else if (mdoc->flags & MDOC_PBODY)
758 mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
759 n->line, n->pos, "Dd");
760 else if (mdoc->meta.title != NULL)
761 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
762 n->line, n->pos, "Dd after Dt");
763 else if (mdoc->meta.os != NULL)
764 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
765 n->line, n->pos, "Dd after Os");
771 struct mdoc_node *np, *nch;
775 * Unlike other data pointers, these are "housed" by the HEAD
776 * element, which contains the goods.
780 if (MDOC_HEAD != np->type)
783 assert(MDOC_BLOCK == np->parent->type);
784 assert(MDOC_Bf == np->parent->tok);
786 /* Check the number of arguments. */
789 if (NULL == np->parent->args) {
791 mandoc_msg(MANDOCERR_BF_NOFONT, mdoc->parse,
792 np->line, np->pos, "Bf");
798 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
799 nch->line, nch->pos, "Bf ... %s", nch->string);
801 /* Extract argument into data. */
803 if (np->parent->args) {
804 arg = np->parent->args->argv[0].arg;
805 if (MDOC_Emphasis == arg)
806 np->norm->Bf.font = FONT_Em;
807 else if (MDOC_Literal == arg)
808 np->norm->Bf.font = FONT_Li;
809 else if (MDOC_Symbolic == arg)
810 np->norm->Bf.font = FONT_Sy;
816 /* Extract parameter into data. */
818 if (0 == strcmp(np->child->string, "Em"))
819 np->norm->Bf.font = FONT_Em;
820 else if (0 == strcmp(np->child->string, "Li"))
821 np->norm->Bf.font = FONT_Li;
822 else if (0 == strcmp(np->child->string, "Sy"))
823 np->norm->Bf.font = FONT_Sy;
825 mandoc_vmsg(MANDOCERR_BF_BADFONT, mdoc->parse,
826 np->child->line, np->child->pos,
827 "Bf %s", np->child->string);
834 const char *stdlibname;
837 n = mdoc->last->child;
838 assert(MDOC_TEXT == n->type);
840 if (NULL == (stdlibname = mdoc_a2lib(n->string)))
841 mandoc_asprintf(&libname,
842 "library \\(Lq%s\\(Rq", n->string);
844 libname = mandoc_strdup(stdlibname);
853 const struct mdoc_node *n;
857 mandoc_vmsg(MANDOCERR_ARG_SKIP,
858 mdoc->parse, n->line, n->pos,
859 "%s %s", mdoc_macronames[n->tok],
864 post_fname(POST_ARGS)
866 const struct mdoc_node *n;
870 n = mdoc->last->child;
871 pos = strcspn(n->string, "()");
872 cp = n->string + pos;
873 if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*')))
874 mandoc_msg(MANDOCERR_FN_PAREN, mdoc->parse,
875 n->line, n->pos + pos, n->string);
889 const struct mdoc_node *n;
893 if (n->type != MDOC_HEAD)
896 if (n->child == NULL) {
897 mandoc_msg(MANDOCERR_FO_NOHEAD, mdoc->parse,
898 n->line, n->pos, "Fo");
901 if (n->child != n->last) {
902 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
903 n->child->next->line, n->child->next->pos,
904 "Fo ... %s", n->child->next->string);
905 while (n->child != n->last)
906 mdoc_node_delete(mdoc, n->last);
915 const struct mdoc_node *n;
918 for (n = mdoc->last->child; n != NULL; n = n->next) {
919 for (cp = n->string; *cp != '\0'; cp++) {
920 /* Ignore callbacks and alterations. */
921 if (*cp == '(' || *cp == '{')
925 mandoc_msg(MANDOCERR_FA_COMMA, mdoc->parse,
926 n->line, n->pos + (cp - n->string),
936 const struct mdoc_node *n;
939 * The Vt macro comes in both ELEM and BLOCK form, both of which
940 * have different syntaxes (yet more context-sensitive
941 * behaviour). ELEM types must have a child, which is already
942 * guaranteed by the in_line parsing routine; BLOCK types,
943 * specifically the BODY, should only have TEXT children.
946 if (MDOC_BODY != mdoc->last->type)
949 for (n = mdoc->last->child; n; n = n->next)
950 if (MDOC_TEXT != n->type)
951 mandoc_msg(MANDOCERR_VT_CHILD, mdoc->parse,
952 n->line, n->pos, mdoc_macronames[n->tok]);
962 if (n->last != NULL &&
963 (n->last->tok == MDOC_Pp ||
964 n->last->tok == MDOC_Lp))
965 mdoc_node_relink(mdoc, n->last);
967 if (NULL != mdoc->meta.name)
970 mdoc_deroff(&mdoc->meta.name, n);
972 if (NULL == mdoc->meta.name)
973 mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse,
974 n->line, n->pos, "Nm");
984 if (n->type != MDOC_BODY)
987 if (n->child == NULL)
988 mandoc_msg(MANDOCERR_ND_EMPTY, mdoc->parse,
989 n->line, n->pos, "Nd");
1001 if (n->type != MDOC_BODY)
1004 if (n->child == NULL)
1005 mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
1006 n->line, n->pos, "D1");
1012 post_literal(POST_ARGS)
1014 struct mdoc_node *n;
1018 if (n->type != MDOC_BODY)
1021 if (n->child == NULL)
1022 mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
1023 n->line, n->pos, mdoc_macronames[n->tok]);
1025 if (n->tok == MDOC_Bd &&
1026 n->norm->Bd.type != DISP_literal &&
1027 n->norm->Bd.type != DISP_unfilled)
1030 mdoc->flags &= ~MDOC_LITERAL;
1034 post_defaults(POST_ARGS)
1036 struct mdoc_node *nn;
1039 * The `Ar' defaults to "file ..." if no value is provided as an
1040 * argument; the `Mt' and `Pa' macros use "~"; the `Li' just
1041 * gets an empty string.
1044 if (mdoc->last->child)
1048 mdoc->next = MDOC_NEXT_CHILD;
1052 mdoc_word_alloc(mdoc, nn->line, nn->pos, "file");
1053 mdoc_word_alloc(mdoc, nn->line, nn->pos, "...");
1058 mdoc_word_alloc(mdoc, nn->line, nn->pos, "~");
1070 struct mdoc_node *n;
1071 const char *std_att;
1075 if (n->child == NULL) {
1076 mdoc->next = MDOC_NEXT_CHILD;
1077 mdoc_word_alloc(mdoc, n->line, n->pos, "AT&T UNIX");
1083 * If we have a child, look it up in the standard keys. If a
1084 * key exist, use that instead of the child; if it doesn't,
1085 * prefix "AT&T UNIX " to the existing data.
1089 assert(MDOC_TEXT == n->type);
1090 if (NULL == (std_att = mdoc_a2att(n->string))) {
1091 mandoc_vmsg(MANDOCERR_AT_BAD, mdoc->parse,
1092 n->line, n->pos, "At %s", n->string);
1093 mandoc_asprintf(&att, "AT&T UNIX %s", n->string);
1095 att = mandoc_strdup(std_att);
1104 struct mdoc_node *np, *nch;
1108 if (np->norm->An.auth == AUTH__NONE) {
1110 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
1111 np->line, np->pos, "An");
1112 } else if (nch != NULL)
1113 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
1114 nch->line, nch->pos, "An ... %s", nch->string);
1121 if (MDOC_BLOCK == mdoc->last->type)
1122 mdoc->last->norm->Es = mdoc->last_es;
1129 mdoc->last_es = mdoc->last;
1137 struct mdoc_node *nbl, *nit, *nch;
1140 if (nit->type != MDOC_BLOCK)
1143 nbl = nit->parent->parent;
1144 lt = nbl->norm->Bl.type;
1156 if (nit->head->child == NULL)
1157 mandoc_vmsg(MANDOCERR_IT_NOHEAD,
1158 mdoc->parse, nit->line, nit->pos,
1160 mdoc_argnames[nbl->args->argv[0].arg]);
1169 if (nit->body == NULL || nit->body->child == NULL)
1170 mandoc_vmsg(MANDOCERR_IT_NOBODY,
1171 mdoc->parse, nit->line, nit->pos,
1173 mdoc_argnames[nbl->args->argv[0].arg]);
1176 if (nit->head->child != NULL)
1177 mandoc_vmsg(MANDOCERR_ARG_SKIP,
1178 mdoc->parse, nit->line, nit->pos,
1179 "It %s", nit->head->child->string);
1182 cols = (int)nbl->norm->Bl.ncols;
1184 assert(nit->head->child == NULL);
1186 for (i = 0, nch = nit->child; nch; nch = nch->next)
1187 if (nch->type == MDOC_BODY)
1190 if (i < cols || i > cols + 1)
1191 mandoc_vmsg(MANDOCERR_BL_COL,
1192 mdoc->parse, nit->line, nit->pos,
1193 "%d columns, %d cells", cols, i);
1201 post_bl_block(POST_ARGS)
1203 struct mdoc_node *n, *ni, *nc;
1206 * These are fairly complicated, so we've broken them into two
1207 * functions. post_bl_block_tag() is called when a -tag is
1208 * specified, but no -width (it must be guessed). The second
1209 * when a -width is specified (macro indicators must be
1210 * rewritten into real lengths).
1215 if (LIST_tag == n->norm->Bl.type &&
1216 NULL == n->norm->Bl.width) {
1217 post_bl_block_tag(mdoc);
1218 assert(n->norm->Bl.width);
1221 for (ni = n->body->child; ni; ni = ni->next) {
1222 if (NULL == ni->body)
1224 nc = ni->body->last;
1225 while (NULL != nc) {
1237 if (NULL == ni->next) {
1238 mandoc_msg(MANDOCERR_PAR_MOVE,
1239 mdoc->parse, nc->line, nc->pos,
1240 mdoc_macronames[nc->tok]);
1241 mdoc_node_relink(mdoc, nc);
1242 } else if (0 == n->norm->Bl.comp &&
1243 LIST_column != n->norm->Bl.type) {
1244 mandoc_vmsg(MANDOCERR_PAR_SKIP,
1245 mdoc->parse, nc->line, nc->pos,
1247 mdoc_macronames[nc->tok]);
1248 mdoc_node_delete(mdoc, nc);
1251 nc = ni->body->last;
1257 * If the argument of -offset or -width is a macro,
1258 * replace it with the associated default width.
1261 rewrite_macro2len(char **arg)
1268 else if ( ! strcmp(*arg, "Ds"))
1270 else if ((tok = mdoc_hash_find(*arg)) == MDOC_MAX)
1273 width = macro2len(tok);
1276 mandoc_asprintf(arg, "%zun", width);
1280 post_bl_block_tag(POST_ARGS)
1282 struct mdoc_node *n, *nn;
1288 * Calculate the -width for a `Bl -tag' list if it hasn't been
1289 * provided. Uses the first head macro. NOTE AGAIN: this is
1290 * ONLY if the -width argument has NOT been provided. See
1291 * rewrite_macro2len() for converting the -width string.
1297 for (nn = n->body->child; nn; nn = nn->next) {
1298 if (MDOC_It != nn->tok)
1301 assert(MDOC_BLOCK == nn->type);
1302 nn = nn->head->child;
1307 if (MDOC_TEXT == nn->type) {
1308 sz = strlen(nn->string) + 1;
1312 if (0 != (ssz = macro2len(nn->tok)))
1318 /* Defaults to ten ens. */
1320 (void)snprintf(buf, sizeof(buf), "%un", (unsigned int)sz);
1323 * We have to dynamically add this to the macro's argument list.
1324 * We're guaranteed that a MDOC_Width doesn't already exist.
1328 i = (int)(n->args->argc)++;
1330 n->args->argv = mandoc_reallocarray(n->args->argv,
1331 n->args->argc, sizeof(struct mdoc_argv));
1333 n->args->argv[i].arg = MDOC_Width;
1334 n->args->argv[i].line = n->line;
1335 n->args->argv[i].pos = n->pos;
1336 n->args->argv[i].sz = 1;
1337 n->args->argv[i].value = mandoc_malloc(sizeof(char *));
1338 n->args->argv[i].value[0] = mandoc_strdup(buf);
1340 /* Set our width! */
1341 n->norm->Bl.width = n->args->argv[i].value[0];
1345 post_bl_head(POST_ARGS)
1347 struct mdoc_node *nbl, *nh, *nch, *nnext;
1348 struct mdoc_argv *argv;
1353 if (nh->norm->Bl.type != LIST_column) {
1354 if ((nch = nh->child) == NULL)
1356 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
1357 nch->line, nch->pos, "Bl ... %s", nch->string);
1358 while (nch != NULL) {
1359 mdoc_node_delete(mdoc, nch);
1366 * Append old-style lists, where the column width specifiers
1367 * trail as macro parameters, to the new-style ("normal-form")
1368 * lists where they're argument values following -column.
1371 if (nh->child == NULL)
1375 for (j = 0; j < (int)nbl->args->argc; j++)
1376 if (nbl->args->argv[j].arg == MDOC_Column)
1379 assert(j < (int)nbl->args->argc);
1382 * Accommodate for new-style groff column syntax. Shuffle the
1383 * child nodes, all of which must be TEXT, as arguments for the
1384 * column field. Then, delete the head children.
1387 argv = nbl->args->argv + j;
1389 argv->sz += nh->nchild;
1390 argv->value = mandoc_reallocarray(argv->value,
1391 argv->sz, sizeof(char *));
1393 nh->norm->Bl.ncols = argv->sz;
1394 nh->norm->Bl.cols = (void *)argv->value;
1396 for (nch = nh->child; nch != NULL; nch = nnext) {
1397 argv->value[i++] = nch->string;
1400 mdoc_node_delete(NULL, nch);
1409 struct mdoc_node *nparent, *nprev; /* of the Bl block */
1410 struct mdoc_node *nblock, *nbody; /* of the Bl */
1411 struct mdoc_node *nchild, *nnext; /* of the Bl body */
1414 switch (nbody->type) {
1416 post_bl_block(mdoc);
1427 nchild = nbody->child;
1428 if (nchild == NULL) {
1429 mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
1430 nbody->line, nbody->pos, "Bl");
1433 while (nchild != NULL) {
1434 if (nchild->tok == MDOC_It ||
1435 (nchild->tok == MDOC_Sm &&
1436 nchild->next != NULL &&
1437 nchild->next->tok == MDOC_It)) {
1438 nchild = nchild->next;
1442 mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse,
1443 nchild->line, nchild->pos,
1444 mdoc_macronames[nchild->tok]);
1447 * Move the node out of the Bl block.
1448 * First, collect all required node pointers.
1451 nblock = nbody->parent;
1452 nprev = nblock->prev;
1453 nparent = nblock->parent;
1454 nnext = nchild->next;
1457 * Unlink this child.
1460 assert(NULL == nchild->prev);
1461 if (0 == --nbody->nchild) {
1462 nbody->child = NULL;
1464 assert(NULL == nnext);
1466 nbody->child = nnext;
1471 * Relink this child.
1474 nchild->parent = nparent;
1475 nchild->prev = nprev;
1476 nchild->next = nblock;
1478 nblock->prev = nchild;
1481 nparent->child = nchild;
1483 nprev->next = nchild;
1492 struct mdoc_node *n;
1496 if (n->type == MDOC_BLOCK && n->body->child == NULL) {
1497 mandoc_msg(MANDOCERR_BLK_EMPTY,
1498 mdoc->parse, n->line, n->pos, "Bk");
1499 mdoc_node_delete(mdoc, n);
1504 post_sm(struct mdoc *mdoc)
1506 struct mdoc_node *nch;
1508 nch = mdoc->last->child;
1511 mdoc->flags ^= MDOC_SMOFF;
1515 assert(nch->type == MDOC_TEXT);
1517 if ( ! strcmp(nch->string, "on")) {
1518 mdoc->flags &= ~MDOC_SMOFF;
1521 if ( ! strcmp(nch->string, "off")) {
1522 mdoc->flags |= MDOC_SMOFF;
1526 mandoc_vmsg(MANDOCERR_SM_BAD,
1527 mdoc->parse, nch->line, nch->pos,
1528 "%s %s", mdoc_macronames[mdoc->last->tok], nch->string);
1529 mdoc_node_relink(mdoc, nch);
1534 post_root(POST_ARGS)
1536 struct mdoc_node *n;
1538 /* Add missing prologue data. */
1540 if (mdoc->meta.date == NULL)
1541 mdoc->meta.date = mdoc->quick ?
1543 mandoc_normdate(mdoc->parse, NULL, 0, 0);
1545 if (mdoc->meta.title == NULL) {
1546 mandoc_msg(MANDOCERR_DT_NOTITLE,
1547 mdoc->parse, 0, 0, "EOF");
1548 mdoc->meta.title = mandoc_strdup("UNTITLED");
1551 if (mdoc->meta.vol == NULL)
1552 mdoc->meta.vol = mandoc_strdup("LOCAL");
1554 if (mdoc->meta.os == NULL) {
1555 mandoc_msg(MANDOCERR_OS_MISSING,
1556 mdoc->parse, 0, 0, NULL);
1557 mdoc->meta.os = mandoc_strdup("");
1560 /* Check that we begin with a proper `Sh'. */
1562 n = mdoc->first->child;
1563 while (n != NULL && mdoc_macros[n->tok].flags & MDOC_PROLOGUE)
1567 mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);
1568 else if (n->tok != MDOC_Sh)
1569 mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse,
1570 n->line, n->pos, mdoc_macronames[n->tok]);
1576 struct mdoc_node *n, *nch;
1582 assert(MDOC_TEXT == nch->type);
1584 if (NULL == (p = mdoc_a2st(nch->string))) {
1585 mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse,
1586 nch->line, nch->pos, "St %s", nch->string);
1587 mdoc_node_delete(mdoc, n);
1590 nch->string = mandoc_strdup(p);
1597 struct mdoc_node *np, *nch, *next, *prev;
1602 if (np->type != MDOC_BODY)
1605 if (np->child == NULL) {
1606 mandoc_msg(MANDOCERR_RS_EMPTY, mdoc->parse,
1607 np->line, np->pos, "Rs");
1612 * The full `Rs' block needs special handling to order the
1613 * sub-elements according to `rsord'. Pick through each element
1614 * and correctly order it. This is an insertion sort.
1618 for (nch = np->child->next; nch != NULL; nch = next) {
1619 /* Determine order number of this child. */
1620 for (i = 0; i < RSORD_MAX; i++)
1621 if (rsord[i] == nch->tok)
1624 if (i == RSORD_MAX) {
1625 mandoc_msg(MANDOCERR_RS_BAD,
1626 mdoc->parse, nch->line, nch->pos,
1627 mdoc_macronames[nch->tok]);
1629 } else if (nch->tok == MDOC__J || nch->tok == MDOC__B)
1630 np->norm->Rs.quote_T++;
1633 * Remove this child from the chain. This somewhat
1634 * repeats mdoc_node_unlink(), but since we're
1635 * just re-ordering, there's no need for the
1636 * full unlink process.
1639 if ((next = nch->next) != NULL)
1640 next->prev = nch->prev;
1642 if ((prev = nch->prev) != NULL)
1643 prev->next = nch->next;
1645 nch->prev = nch->next = NULL;
1648 * Scan back until we reach a node that's
1649 * to be ordered before this child.
1652 for ( ; prev ; prev = prev->prev) {
1653 /* Determine order of `prev'. */
1654 for (j = 0; j < RSORD_MAX; j++)
1655 if (rsord[j] == prev->tok)
1665 * Set this child back into its correct place
1666 * in front of the `prev' node.
1672 np->child->prev = nch;
1673 nch->next = np->child;
1677 prev->next->prev = nch;
1678 nch->next = prev->next;
1685 * For some arguments of some macros,
1686 * convert all breakable hyphens into ASCII_HYPH.
1689 post_hyph(POST_ARGS)
1691 struct mdoc_node *nch;
1694 for (nch = mdoc->last->child; nch != NULL; nch = nch->next) {
1695 if (nch->type != MDOC_TEXT)
1700 while (*(++cp) != '\0')
1702 isalpha((unsigned char)cp[-1]) &&
1703 isalpha((unsigned char)cp[1]))
1712 if (MDOC_LINE & mdoc->last->flags)
1713 mandoc_msg(MANDOCERR_NS_SKIP, mdoc->parse,
1714 mdoc->last->line, mdoc->last->pos, NULL);
1723 switch (mdoc->last->type) {
1728 switch (mdoc->lastsec) {
1733 post_sh_see_also(mdoc);
1736 post_sh_authors(mdoc);
1748 post_sh_name(POST_ARGS)
1750 struct mdoc_node *n;
1755 for (n = mdoc->last->child; n != NULL; n = n->next) {
1762 if (n->next != NULL)
1763 mandoc_msg(MANDOCERR_NAMESEC_ND,
1764 mdoc->parse, n->line, n->pos, NULL);
1771 mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
1772 n->line, n->pos, mdoc_macronames[n->tok]);
1778 mandoc_msg(MANDOCERR_NAMESEC_NONM, mdoc->parse,
1779 mdoc->last->line, mdoc->last->pos, NULL);
1781 mandoc_msg(MANDOCERR_NAMESEC_NOND, mdoc->parse,
1782 mdoc->last->line, mdoc->last->pos, NULL);
1786 post_sh_see_also(POST_ARGS)
1788 const struct mdoc_node *n;
1789 const char *name, *sec;
1790 const char *lastname, *lastsec, *lastpunct;
1793 n = mdoc->last->child;
1794 lastname = lastsec = lastpunct = NULL;
1796 if (n->tok != MDOC_Xr || n->nchild < 2)
1799 /* Process one .Xr node. */
1801 name = n->child->string;
1802 sec = n->child->next->string;
1803 if (lastsec != NULL) {
1804 if (lastpunct[0] != ',' || lastpunct[1] != '\0')
1805 mandoc_vmsg(MANDOCERR_XR_PUNCT,
1806 mdoc->parse, n->line, n->pos,
1807 "%s before %s(%s)", lastpunct,
1809 cmp = strcmp(lastsec, sec);
1811 mandoc_vmsg(MANDOCERR_XR_ORDER,
1812 mdoc->parse, n->line, n->pos,
1813 "%s(%s) after %s(%s)", name,
1814 sec, lastname, lastsec);
1815 else if (cmp == 0 &&
1816 strcasecmp(lastname, name) > 0)
1817 mandoc_vmsg(MANDOCERR_XR_ORDER,
1818 mdoc->parse, n->line, n->pos,
1819 "%s after %s", name, lastname);
1824 /* Process the following node. */
1829 if (n->tok == MDOC_Xr) {
1833 if (n->type != MDOC_TEXT)
1835 for (name = n->string; *name != '\0'; name++)
1836 if (isalpha((const unsigned char)*name))
1838 lastpunct = n->string;
1839 if (n->next == NULL)
1840 mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse,
1841 n->line, n->pos, "%s after %s(%s)",
1842 lastpunct, lastname, lastsec);
1848 child_an(const struct mdoc_node *n)
1851 for (n = n->child; n != NULL; n = n->next)
1852 if ((n->tok == MDOC_An && n->nchild) || child_an(n))
1858 post_sh_authors(POST_ARGS)
1861 if ( ! child_an(mdoc->last))
1862 mandoc_msg(MANDOCERR_AN_MISSING, mdoc->parse,
1863 mdoc->last->line, mdoc->last->pos, NULL);
1867 post_sh_head(POST_ARGS)
1869 struct mdoc_node *n;
1870 const char *goodsec;
1875 * Process a new section. Sections are either "named" or
1876 * "custom". Custom sections are user-defined, while named ones
1877 * follow a conventional order and may only appear in certain
1883 mdoc_deroff(&secname, mdoc->last);
1884 sec = NULL == secname ? SEC_CUSTOM : a2sec(secname);
1886 /* The NAME should be first. */
1888 if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
1889 mandoc_vmsg(MANDOCERR_NAMESEC_FIRST, mdoc->parse,
1890 mdoc->last->line, mdoc->last->pos,
1893 /* The SYNOPSIS gets special attention in other areas. */
1895 if (SEC_SYNOPSIS == sec) {
1896 roff_setreg(mdoc->roff, "nS", 1, '=');
1897 mdoc->flags |= MDOC_SYNOPSIS;
1899 roff_setreg(mdoc->roff, "nS", 0, '=');
1900 mdoc->flags &= ~MDOC_SYNOPSIS;
1903 /* Mark our last section. */
1905 mdoc->lastsec = sec;
1908 * Set the section attribute for the current HEAD, for its
1909 * parent BLOCK, and for the HEAD children; the latter can
1910 * only be TEXT nodes, so no recursion is needed.
1911 * For other blocks and elements, including .Sh BODY, this is
1912 * done when allocating the node data structures, but for .Sh
1913 * BLOCK and HEAD, the section is still unknown at that time.
1916 mdoc->last->parent->sec = sec;
1917 mdoc->last->sec = sec;
1918 for (n = mdoc->last->child; n; n = n->next)
1921 /* We don't care about custom sections after this. */
1923 if (SEC_CUSTOM == sec) {
1929 * Check whether our non-custom section is being repeated or is
1933 if (sec == mdoc->lastnamed)
1934 mandoc_vmsg(MANDOCERR_SEC_REP, mdoc->parse,
1935 mdoc->last->line, mdoc->last->pos,
1938 if (sec < mdoc->lastnamed)
1939 mandoc_vmsg(MANDOCERR_SEC_ORDER, mdoc->parse,
1940 mdoc->last->line, mdoc->last->pos,
1943 /* Mark the last named section. */
1945 mdoc->lastnamed = sec;
1947 /* Check particular section/manual conventions. */
1949 if (mdoc->meta.msec == NULL) {
1957 if (*mdoc->meta.msec == '4')
1959 goodsec = "2, 3, 4, 9";
1961 case SEC_RETURN_VALUES:
1964 if (*mdoc->meta.msec == '2')
1966 if (*mdoc->meta.msec == '3')
1968 if (NULL == goodsec)
1969 goodsec = "2, 3, 9";
1972 if (*mdoc->meta.msec == '9')
1974 if (NULL == goodsec)
1976 mandoc_vmsg(MANDOCERR_SEC_MSEC, mdoc->parse,
1977 mdoc->last->line, mdoc->last->pos,
1978 "Sh %s for %s only", secname, goodsec);
1987 post_ignpar(POST_ARGS)
1989 struct mdoc_node *np;
1991 switch (mdoc->last->type) {
2001 if (NULL != (np = mdoc->last->child))
2002 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
2003 mandoc_vmsg(MANDOCERR_PAR_SKIP,
2004 mdoc->parse, np->line, np->pos,
2005 "%s after %s", mdoc_macronames[np->tok],
2006 mdoc_macronames[mdoc->last->tok]);
2007 mdoc_node_delete(mdoc, np);
2010 if (NULL != (np = mdoc->last->last))
2011 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
2012 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2013 np->line, np->pos, "%s at the end of %s",
2014 mdoc_macronames[np->tok],
2015 mdoc_macronames[mdoc->last->tok]);
2016 mdoc_node_delete(mdoc, np);
2024 if (NULL == mdoc->last)
2026 if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type)
2030 * Don't allow prior `Lp' or `Pp' prior to a paragraph-type
2031 * block: `Lp', `Pp', or non-compact `Bd' or `Bl'.
2034 if (MDOC_Pp != mdoc->last->tok &&
2035 MDOC_Lp != mdoc->last->tok &&
2036 MDOC_br != mdoc->last->tok)
2038 if (MDOC_Bl == n->tok && n->norm->Bl.comp)
2040 if (MDOC_Bd == n->tok && n->norm->Bd.comp)
2042 if (MDOC_It == n->tok && n->parent->norm->Bl.comp)
2045 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2046 mdoc->last->line, mdoc->last->pos,
2047 "%s before %s", mdoc_macronames[mdoc->last->tok],
2048 mdoc_macronames[n->tok]);
2049 mdoc_node_delete(mdoc, mdoc->last);
2055 struct mdoc_node *np;
2059 if (np->tok == MDOC_sp) {
2061 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
2062 np->child->next->line, np->child->next->pos,
2063 "sp ... %s", np->child->next->string);
2064 } else if (np->child != NULL)
2065 mandoc_vmsg(MANDOCERR_ARG_SKIP,
2066 mdoc->parse, np->line, np->pos, "%s %s",
2067 mdoc_macronames[np->tok], np->child->string);
2069 if (NULL == (np = mdoc->last->prev)) {
2070 np = mdoc->last->parent;
2071 if (MDOC_Sh != np->tok && MDOC_Ss != np->tok)
2073 } else if (MDOC_Pp != np->tok && MDOC_Lp != np->tok &&
2074 (MDOC_br != mdoc->last->tok ||
2075 (MDOC_sp != np->tok && MDOC_br != np->tok)))
2078 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2079 mdoc->last->line, mdoc->last->pos,
2080 "%s after %s", mdoc_macronames[mdoc->last->tok],
2081 mdoc_macronames[np->tok]);
2082 mdoc_node_delete(mdoc, mdoc->last);
2086 pre_literal(PRE_ARGS)
2089 pre_display(mdoc, n);
2091 if (MDOC_BODY != n->type)
2095 * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd
2096 * -unfilled' macros set MDOC_LITERAL on entrance to the body.
2101 mdoc->flags |= MDOC_LITERAL;
2104 if (DISP_literal == n->norm->Bd.type)
2105 mdoc->flags |= MDOC_LITERAL;
2106 if (DISP_unfilled == n->norm->Bd.type)
2107 mdoc->flags |= MDOC_LITERAL;
2118 struct mdoc_node *n;
2121 if (mdoc->meta.date)
2122 free(mdoc->meta.date);
2125 if (NULL == n->child || '\0' == n->child->string[0]) {
2126 mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
2127 mandoc_normdate(mdoc->parse, NULL, n->line, n->pos);
2132 mdoc_deroff(&datestr, n);
2134 mdoc->meta.date = datestr;
2136 mdoc->meta.date = mandoc_normdate(mdoc->parse,
2137 datestr, n->line, n->pos);
2141 mdoc_node_delete(mdoc, n);
2147 struct mdoc_node *nn, *n;
2153 free(mdoc->meta.title);
2154 free(mdoc->meta.msec);
2155 free(mdoc->meta.vol);
2156 free(mdoc->meta.arch);
2158 mdoc->meta.title = NULL;
2159 mdoc->meta.msec = NULL;
2160 mdoc->meta.vol = NULL;
2161 mdoc->meta.arch = NULL;
2163 /* Mandatory first argument: title. */
2166 if (nn == NULL || *nn->string == '\0') {
2167 mandoc_msg(MANDOCERR_DT_NOTITLE,
2168 mdoc->parse, n->line, n->pos, "Dt");
2169 mdoc->meta.title = mandoc_strdup("UNTITLED");
2171 mdoc->meta.title = mandoc_strdup(nn->string);
2173 /* Check that all characters are uppercase. */
2175 for (p = nn->string; *p != '\0'; p++)
2176 if (islower((unsigned char)*p)) {
2177 mandoc_vmsg(MANDOCERR_TITLE_CASE,
2178 mdoc->parse, nn->line,
2179 nn->pos + (p - nn->string),
2180 "Dt %s", nn->string);
2185 /* Mandatory second argument: section. */
2191 mandoc_vmsg(MANDOCERR_MSEC_MISSING,
2192 mdoc->parse, n->line, n->pos,
2193 "Dt %s", mdoc->meta.title);
2194 mdoc->meta.vol = mandoc_strdup("LOCAL");
2195 goto out; /* msec and arch remain NULL. */
2198 mdoc->meta.msec = mandoc_strdup(nn->string);
2200 /* Infer volume title from section number. */
2202 cp = mandoc_a2msec(nn->string);
2204 mandoc_vmsg(MANDOCERR_MSEC_BAD, mdoc->parse,
2205 nn->line, nn->pos, "Dt ... %s", nn->string);
2206 mdoc->meta.vol = mandoc_strdup(nn->string);
2208 mdoc->meta.vol = mandoc_strdup(cp);
2210 /* Optional third argument: architecture. */
2212 if ((nn = nn->next) == NULL)
2215 for (p = nn->string; *p != '\0'; p++)
2216 *p = tolower((unsigned char)*p);
2217 mdoc->meta.arch = mandoc_strdup(nn->string);
2219 /* Ignore fourth and later arguments. */
2221 if ((nn = nn->next) != NULL)
2222 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
2223 nn->line, nn->pos, "Dt ... %s", nn->string);
2226 mdoc_node_delete(mdoc, n);
2232 struct mdoc_node *n;
2235 * Make `Bx's second argument always start with an uppercase
2236 * letter. Groff checks if it's an "accepted" term, but we just
2237 * uppercase blindly.
2240 n = mdoc->last->child;
2241 if (n && NULL != (n = n->next))
2242 *n->string = (char)toupper((unsigned char)*n->string);
2249 struct utsname utsname;
2250 static char *defbuf;
2252 struct mdoc_node *n;
2257 * Set the operating system by way of the `Os' macro.
2258 * The order of precedence is:
2259 * 1. the argument of the `Os' macro, unless empty
2260 * 2. the -Ios=foo command line argument, if provided
2261 * 3. -DOSNAME="\"foo\"", if provided during compilation
2262 * 4. "sysname release" from uname(3)
2265 free(mdoc->meta.os);
2266 mdoc->meta.os = NULL;
2267 mdoc_deroff(&mdoc->meta.os, n);
2272 mdoc->meta.os = mandoc_strdup(mdoc->defos);
2277 mdoc->meta.os = mandoc_strdup(OSNAME);
2279 if (NULL == defbuf) {
2280 if (-1 == uname(&utsname)) {
2281 mandoc_msg(MANDOCERR_OS_UNAME, mdoc->parse,
2282 n->line, n->pos, "Os");
2283 defbuf = mandoc_strdup("UNKNOWN");
2285 mandoc_asprintf(&defbuf, "%s %s",
2286 utsname.sysname, utsname.release);
2288 mdoc->meta.os = mandoc_strdup(defbuf);
2292 mdoc_node_delete(mdoc, n);
2296 * If no argument is provided,
2297 * fill in the name of the current manual page.
2302 struct mdoc_node *n;
2309 if (mdoc->meta.name == NULL) {
2310 mandoc_msg(MANDOCERR_EX_NONAME, mdoc->parse,
2311 n->line, n->pos, "Ex");
2315 mdoc->next = MDOC_NEXT_CHILD;
2316 mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name);
2320 static enum mdoc_sec
2321 a2sec(const char *p)
2325 for (i = 0; i < (int)SEC__MAX; i++)
2326 if (secnames[i] && 0 == strcmp(p, secnames[i]))
2327 return((enum mdoc_sec)i);
2333 macro2len(enum mdoct macro)