1 /* $Id: mdoc_validate.c,v 1.243 2014/08/06 15:09:05 schwarze Exp $ */
3 * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010-2014 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.
24 #include <sys/utsname.h>
27 #include <sys/types.h>
39 #include "mandoc_aux.h"
41 #include "libmandoc.h"
43 /* FIXME: .Bl -diag can't have non-text children in HEAD. */
45 #define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n
46 #define POST_ARGS struct mdoc *mdoc
59 typedef int (*v_pre)(PRE_ARGS);
60 typedef int (*v_post)(POST_ARGS);
67 static int check_count(struct mdoc *, enum mdoc_type,
68 enum check_lvl, enum check_ineq, int);
69 static void check_text(struct mdoc *, int, int, char *);
70 static void check_argv(struct mdoc *,
71 struct mdoc_node *, struct mdoc_argv *);
72 static void check_args(struct mdoc *, struct mdoc_node *);
73 static enum mdoc_sec a2sec(const char *);
74 static size_t macro2len(enum mdoct);
76 static int ebool(POST_ARGS);
77 static int berr_ge1(POST_ARGS);
78 static int bwarn_ge1(POST_ARGS);
79 static int ewarn_eq0(POST_ARGS);
80 static int ewarn_eq1(POST_ARGS);
81 static int ewarn_ge1(POST_ARGS);
82 static int ewarn_le1(POST_ARGS);
83 static int hwarn_eq0(POST_ARGS);
84 static int hwarn_eq1(POST_ARGS);
85 static int hwarn_ge1(POST_ARGS);
87 static int post_an(POST_ARGS);
88 static int post_at(POST_ARGS);
89 static int post_bf(POST_ARGS);
90 static int post_bk(POST_ARGS);
91 static int post_bl(POST_ARGS);
92 static int post_bl_block(POST_ARGS);
93 static int post_bl_block_width(POST_ARGS);
94 static int post_bl_block_tag(POST_ARGS);
95 static int post_bl_head(POST_ARGS);
96 static int post_bx(POST_ARGS);
97 static int post_d1(POST_ARGS);
98 static int post_defaults(POST_ARGS);
99 static int post_dd(POST_ARGS);
100 static int post_dt(POST_ARGS);
101 static int post_en(POST_ARGS);
102 static int post_es(POST_ARGS);
103 static int post_eoln(POST_ARGS);
104 static int post_ex(POST_ARGS);
105 static int post_fo(POST_ARGS);
106 static int post_hyph(POST_ARGS);
107 static int post_hyphtext(POST_ARGS);
108 static int post_ignpar(POST_ARGS);
109 static int post_it(POST_ARGS);
110 static int post_lb(POST_ARGS);
111 static int post_literal(POST_ARGS);
112 static int post_nd(POST_ARGS);
113 static int post_nm(POST_ARGS);
114 static int post_ns(POST_ARGS);
115 static int post_os(POST_ARGS);
116 static int post_par(POST_ARGS);
117 static int post_root(POST_ARGS);
118 static int post_rs(POST_ARGS);
119 static int post_sh(POST_ARGS);
120 static int post_sh_body(POST_ARGS);
121 static int post_sh_head(POST_ARGS);
122 static int post_st(POST_ARGS);
123 static int post_vt(POST_ARGS);
124 static int pre_an(PRE_ARGS);
125 static int pre_bd(PRE_ARGS);
126 static int pre_bl(PRE_ARGS);
127 static int pre_dd(PRE_ARGS);
128 static int pre_display(PRE_ARGS);
129 static int pre_dt(PRE_ARGS);
130 static int pre_literal(PRE_ARGS);
131 static int pre_obsolete(PRE_ARGS);
132 static int pre_os(PRE_ARGS);
133 static int pre_par(PRE_ARGS);
134 static int pre_std(PRE_ARGS);
136 static const struct valids mdoc_valids[MDOC_MAX] = {
137 { NULL, NULL }, /* Ap */
138 { pre_dd, post_dd }, /* Dd */
139 { pre_dt, post_dt }, /* Dt */
140 { pre_os, post_os }, /* Os */
141 { NULL, post_sh }, /* Sh */
142 { NULL, post_ignpar }, /* Ss */
143 { pre_par, post_par }, /* Pp */
144 { pre_display, post_d1 }, /* D1 */
145 { pre_literal, post_literal }, /* Dl */
146 { pre_bd, post_literal }, /* Bd */
147 { NULL, NULL }, /* Ed */
148 { pre_bl, post_bl }, /* Bl */
149 { NULL, NULL }, /* El */
150 { pre_par, post_it }, /* It */
151 { NULL, NULL }, /* Ad */
152 { pre_an, post_an }, /* An */
153 { NULL, post_defaults }, /* Ar */
154 { NULL, NULL }, /* Cd */
155 { NULL, NULL }, /* Cm */
156 { NULL, NULL }, /* Dv */
157 { NULL, NULL }, /* Er */
158 { NULL, NULL }, /* Ev */
159 { pre_std, post_ex }, /* Ex */
160 { NULL, NULL }, /* Fa */
161 { NULL, ewarn_ge1 }, /* Fd */
162 { NULL, NULL }, /* Fl */
163 { NULL, NULL }, /* Fn */
164 { NULL, NULL }, /* Ft */
165 { NULL, NULL }, /* Ic */
166 { NULL, ewarn_eq1 }, /* In */
167 { NULL, post_defaults }, /* Li */
168 { NULL, post_nd }, /* Nd */
169 { NULL, post_nm }, /* Nm */
170 { NULL, NULL }, /* Op */
171 { pre_obsolete, NULL }, /* Ot */
172 { NULL, post_defaults }, /* Pa */
173 { pre_std, NULL }, /* Rv */
174 { NULL, post_st }, /* St */
175 { NULL, NULL }, /* Va */
176 { NULL, post_vt }, /* Vt */
177 { NULL, ewarn_ge1 }, /* Xr */
178 { NULL, ewarn_ge1 }, /* %A */
179 { NULL, post_hyphtext }, /* %B */ /* FIXME: can be used outside Rs/Re. */
180 { NULL, ewarn_ge1 }, /* %D */
181 { NULL, ewarn_ge1 }, /* %I */
182 { NULL, ewarn_ge1 }, /* %J */
183 { NULL, post_hyphtext }, /* %N */
184 { NULL, post_hyphtext }, /* %O */
185 { NULL, ewarn_ge1 }, /* %P */
186 { NULL, post_hyphtext }, /* %R */
187 { NULL, post_hyphtext }, /* %T */ /* FIXME: can be used outside Rs/Re. */
188 { NULL, ewarn_ge1 }, /* %V */
189 { NULL, NULL }, /* Ac */
190 { NULL, NULL }, /* Ao */
191 { NULL, NULL }, /* Aq */
192 { NULL, post_at }, /* At */
193 { NULL, NULL }, /* Bc */
194 { NULL, post_bf }, /* Bf */
195 { NULL, NULL }, /* Bo */
196 { NULL, NULL }, /* Bq */
197 { NULL, NULL }, /* Bsx */
198 { NULL, post_bx }, /* Bx */
199 { NULL, ebool }, /* Db */
200 { NULL, NULL }, /* Dc */
201 { NULL, NULL }, /* Do */
202 { NULL, NULL }, /* Dq */
203 { NULL, NULL }, /* Ec */
204 { NULL, NULL }, /* Ef */
205 { NULL, NULL }, /* Em */
206 { NULL, NULL }, /* Eo */
207 { NULL, NULL }, /* Fx */
208 { NULL, NULL }, /* Ms */
209 { NULL, ewarn_eq0 }, /* No */
210 { NULL, post_ns }, /* Ns */
211 { NULL, NULL }, /* Nx */
212 { NULL, NULL }, /* Ox */
213 { NULL, NULL }, /* Pc */
214 { NULL, ewarn_eq1 }, /* Pf */
215 { NULL, NULL }, /* Po */
216 { NULL, NULL }, /* Pq */
217 { NULL, NULL }, /* Qc */
218 { NULL, NULL }, /* Ql */
219 { NULL, NULL }, /* Qo */
220 { NULL, NULL }, /* Qq */
221 { NULL, NULL }, /* Re */
222 { NULL, post_rs }, /* Rs */
223 { NULL, NULL }, /* Sc */
224 { NULL, NULL }, /* So */
225 { NULL, NULL }, /* Sq */
226 { NULL, ebool }, /* Sm */
227 { NULL, post_hyph }, /* Sx */
228 { NULL, NULL }, /* Sy */
229 { NULL, NULL }, /* Tn */
230 { NULL, NULL }, /* Ux */
231 { NULL, NULL }, /* Xc */
232 { NULL, NULL }, /* Xo */
233 { NULL, post_fo }, /* Fo */
234 { NULL, NULL }, /* Fc */
235 { NULL, NULL }, /* Oo */
236 { NULL, NULL }, /* Oc */
237 { NULL, post_bk }, /* Bk */
238 { NULL, NULL }, /* Ek */
239 { NULL, post_eoln }, /* Bt */
240 { NULL, NULL }, /* Hf */
241 { pre_obsolete, NULL }, /* Fr */
242 { NULL, post_eoln }, /* Ud */
243 { NULL, post_lb }, /* Lb */
244 { pre_par, post_par }, /* Lp */
245 { NULL, NULL }, /* Lk */
246 { NULL, post_defaults }, /* Mt */
247 { NULL, NULL }, /* Brq */
248 { NULL, NULL }, /* Bro */
249 { NULL, NULL }, /* Brc */
250 { NULL, ewarn_ge1 }, /* %C */
251 { pre_obsolete, post_es }, /* Es */
252 { pre_obsolete, post_en }, /* En */
253 { NULL, NULL }, /* Dx */
254 { NULL, ewarn_ge1 }, /* %Q */
255 { NULL, post_par }, /* br */
256 { NULL, post_par }, /* sp */
257 { NULL, ewarn_eq1 }, /* %U */
258 { NULL, NULL }, /* Ta */
259 { NULL, NULL }, /* ll */
262 #define RSORD_MAX 14 /* Number of `Rs' blocks. */
264 static const enum mdoct rsord[RSORD_MAX] = {
281 static const char * const secnames[SEC__MAX] = {
288 "IMPLEMENTATION NOTES",
303 "SECURITY CONSIDERATIONS",
309 mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n)
315 check_text(mdoc, n->line, n->pos, n->string);
328 p = mdoc_valids[n->tok].pre;
329 return(*p ? (*p)(mdoc, n) : 1);
333 mdoc_valid_post(struct mdoc *mdoc)
339 if (n->flags & MDOC_VALID)
341 n->flags |= MDOC_VALID;
351 return(post_root(mdoc));
353 p = mdoc_valids[n->tok].post;
354 return(*p ? (*p)(mdoc) : 1);
359 check_count(struct mdoc *mdoc, enum mdoc_type type,
360 enum check_lvl lvl, enum check_ineq ineq, int val)
365 if (mdoc->last->type != type)
371 if (mdoc->last->nchild < val)
376 if (mdoc->last->nchild > val)
381 if (val == mdoc->last->nchild)
389 t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
390 mandoc_vmsg(t, mdoc->parse, mdoc->last->line,
391 mdoc->last->pos, "want %s%d children (have %d)",
392 p, val, mdoc->last->nchild);
400 return(check_count(mdoc, MDOC_BODY, CHECK_ERROR, CHECK_GT, 0));
406 return(check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0));
412 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0));
418 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1));
424 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0));
430 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2));
436 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0));
442 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 1));
448 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_GT, 0));
452 check_args(struct mdoc *mdoc, struct mdoc_node *n)
459 assert(n->args->argc);
460 for (i = 0; i < (int)n->args->argc; i++)
461 check_argv(mdoc, n, &n->args->argv[i]);
465 check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v)
469 for (i = 0; i < (int)v->sz; i++)
470 check_text(mdoc, v->line, v->pos, v->value[i]);
474 check_text(struct mdoc *mdoc, int ln, int pos, char *p)
478 if (MDOC_LITERAL & mdoc->flags)
481 for (cp = p; NULL != (p = strchr(p, '\t')); p++)
482 mandoc_msg(MANDOCERR_FI_TAB, mdoc->parse,
483 ln, pos + (int)(p - cp), NULL);
487 pre_display(PRE_ARGS)
489 struct mdoc_node *node;
491 if (MDOC_BLOCK != n->type)
494 for (node = mdoc->last->parent; node; node = node->parent)
495 if (MDOC_BLOCK == node->type)
496 if (MDOC_Bd == node->tok)
500 mandoc_vmsg(MANDOCERR_BD_NEST,
501 mdoc->parse, n->line, n->pos,
502 "%s in Bd", mdoc_macronames[n->tok]);
510 struct mdoc_node *np;
511 struct mdoc_argv *argv, *wa;
513 enum mdocargt mdoclt;
516 if (MDOC_BLOCK != n->type) {
517 if (ENDBODY_NOT != n->end) {
519 np = n->pending->parent;
524 assert(MDOC_BLOCK == np->type);
525 assert(MDOC_Bl == np->tok);
530 * First figure out which kind of list to use: bind ourselves to
531 * the first mentioned list type and warn about any remaining
532 * ones. If we find no list type, we default to LIST_item.
536 mdoclt = MDOC_ARG_MAX;
537 for (i = 0; n->args && i < (int)n->args->argc; i++) {
538 argv = n->args->argv + i;
541 /* Set list types. */
575 /* Set list arguments. */
577 if (n->norm->Bl.comp)
578 mandoc_msg(MANDOCERR_ARG_REP,
579 mdoc->parse, argv->line,
580 argv->pos, "Bl -compact");
581 n->norm->Bl.comp = 1;
586 mandoc_msg(MANDOCERR_ARG_EMPTY,
587 mdoc->parse, argv->line,
588 argv->pos, "Bl -width");
589 n->norm->Bl.width = "0n";
592 if (NULL != n->norm->Bl.width)
593 mandoc_vmsg(MANDOCERR_ARG_REP,
594 mdoc->parse, argv->line,
595 argv->pos, "Bl -width %s",
597 n->norm->Bl.width = argv->value[0];
601 mandoc_msg(MANDOCERR_ARG_EMPTY,
602 mdoc->parse, argv->line,
603 argv->pos, "Bl -offset");
606 if (NULL != n->norm->Bl.offs)
607 mandoc_vmsg(MANDOCERR_ARG_REP,
608 mdoc->parse, argv->line,
609 argv->pos, "Bl -offset %s",
611 n->norm->Bl.offs = argv->value[0];
616 if (LIST__NONE == lt)
620 /* Check: multiple list types. */
622 if (LIST__NONE != n->norm->Bl.type) {
623 mandoc_vmsg(MANDOCERR_BL_REP,
624 mdoc->parse, n->line, n->pos,
625 "Bl -%s", mdoc_argnames[argv->arg]);
629 /* The list type should come first. */
631 if (n->norm->Bl.width ||
634 mandoc_vmsg(MANDOCERR_BL_LATETYPE,
635 mdoc->parse, n->line, n->pos, "Bl -%s",
636 mdoc_argnames[n->args->argv[0].arg]);
638 n->norm->Bl.type = lt;
639 if (LIST_column == lt) {
640 n->norm->Bl.ncols = argv->sz;
641 n->norm->Bl.cols = (void *)argv->value;
645 /* Allow lists to default to LIST_item. */
647 if (LIST__NONE == n->norm->Bl.type) {
648 mandoc_msg(MANDOCERR_BL_NOTYPE, mdoc->parse,
649 n->line, n->pos, "Bl");
650 n->norm->Bl.type = LIST_item;
654 * Validate the width field. Some list types don't need width
655 * types and should be warned about them. Others should have it
656 * and must also be warned. Yet others have a default and need
660 switch (n->norm->Bl.type) {
662 if (NULL == n->norm->Bl.width)
663 mandoc_msg(MANDOCERR_BL_NOWIDTH, mdoc->parse,
664 n->line, n->pos, "Bl -tag");
675 if (n->norm->Bl.width)
676 mandoc_vmsg(MANDOCERR_BL_SKIPW, mdoc->parse,
677 wa->line, wa->pos, "Bl -%s",
678 mdoc_argnames[mdoclt]);
685 if (NULL == n->norm->Bl.width)
686 n->norm->Bl.width = "2n";
689 if (NULL == n->norm->Bl.width)
690 n->norm->Bl.width = "3n";
696 return(pre_par(mdoc, n));
702 struct mdoc_node *np;
703 struct mdoc_argv *argv;
707 pre_literal(mdoc, n);
709 if (MDOC_BLOCK != n->type) {
710 if (ENDBODY_NOT != n->end) {
712 np = n->pending->parent;
717 assert(MDOC_BLOCK == np->type);
718 assert(MDOC_Bd == np->tok);
722 for (i = 0; n->args && i < (int)n->args->argc; i++) {
723 argv = n->args->argv + i;
743 mandoc_msg(MANDOCERR_BD_FILE, mdoc->parse,
744 n->line, n->pos, NULL);
748 mandoc_msg(MANDOCERR_ARG_EMPTY,
749 mdoc->parse, argv->line,
750 argv->pos, "Bd -offset");
753 if (NULL != n->norm->Bd.offs)
754 mandoc_vmsg(MANDOCERR_ARG_REP,
755 mdoc->parse, argv->line,
756 argv->pos, "Bd -offset %s",
758 n->norm->Bd.offs = argv->value[0];
761 if (n->norm->Bd.comp)
762 mandoc_msg(MANDOCERR_ARG_REP,
763 mdoc->parse, argv->line,
764 argv->pos, "Bd -compact");
765 n->norm->Bd.comp = 1;
771 if (DISP__NONE == dt)
774 if (DISP__NONE == n->norm->Bd.type)
775 n->norm->Bd.type = dt;
777 mandoc_vmsg(MANDOCERR_BD_REP,
778 mdoc->parse, n->line, n->pos,
779 "Bd -%s", mdoc_argnames[argv->arg]);
782 if (DISP__NONE == n->norm->Bd.type) {
783 mandoc_msg(MANDOCERR_BD_NOTYPE, mdoc->parse,
784 n->line, n->pos, "Bd");
785 n->norm->Bd.type = DISP_ragged;
788 return(pre_par(mdoc, n));
794 struct mdoc_argv *argv;
800 for (i = 1; i < n->args->argc; i++) {
801 argv = n->args->argv + i;
802 mandoc_vmsg(MANDOCERR_AN_REP,
803 mdoc->parse, argv->line, argv->pos,
804 "An -%s", mdoc_argnames[argv->arg]);
807 argv = n->args->argv;
808 if (argv->arg == MDOC_Split)
809 n->norm->An.auth = AUTH_split;
810 else if (argv->arg == MDOC_Nosplit)
811 n->norm->An.auth = AUTH_nosplit;
822 if (n->args && 1 == n->args->argc)
823 if (MDOC_Std == n->args->argv[0].arg)
826 mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse,
827 n->line, n->pos, mdoc_macronames[n->tok]);
832 pre_obsolete(PRE_ARGS)
835 if (MDOC_ELEM == n->type || MDOC_BLOCK == n->type)
836 mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse,
837 n->line, n->pos, mdoc_macronames[n->tok]);
845 if (mdoc->meta.title != NULL)
846 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
847 n->line, n->pos, "Dt");
848 else if (mdoc->meta.os != NULL)
849 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
850 n->line, n->pos, "Dt after Os");
858 if (mdoc->meta.os != NULL)
859 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
860 n->line, n->pos, "Os");
861 else if (mdoc->flags & MDOC_PBODY)
862 mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
863 n->line, n->pos, "Os");
871 if (mdoc->meta.date != NULL)
872 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
873 n->line, n->pos, "Dd");
874 else if (mdoc->flags & MDOC_PBODY)
875 mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
876 n->line, n->pos, "Dd");
877 else if (mdoc->meta.title != NULL)
878 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
879 n->line, n->pos, "Dd after Dt");
880 else if (mdoc->meta.os != NULL)
881 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
882 n->line, n->pos, "Dd after Os");
889 struct mdoc_node *np, *nch;
893 * Unlike other data pointers, these are "housed" by the HEAD
894 * element, which contains the goods.
897 if (MDOC_HEAD != mdoc->last->type) {
898 if (ENDBODY_NOT != mdoc->last->end) {
899 assert(mdoc->last->pending);
900 np = mdoc->last->pending->parent->head;
901 } else if (MDOC_BLOCK != mdoc->last->type) {
902 np = mdoc->last->parent->head;
904 np = mdoc->last->head;
907 assert(MDOC_HEAD == np->type);
908 assert(MDOC_Bf == np->tok);
913 assert(MDOC_BLOCK == np->parent->type);
914 assert(MDOC_Bf == np->parent->tok);
916 /* Check the number of arguments. */
919 if (NULL == np->parent->args) {
921 mandoc_msg(MANDOCERR_BF_NOFONT, mdoc->parse,
922 np->line, np->pos, "Bf");
928 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
929 nch->line, nch->pos, "Bf ... %s", nch->string);
931 /* Extract argument into data. */
933 if (np->parent->args) {
934 arg = np->parent->args->argv[0].arg;
935 if (MDOC_Emphasis == arg)
936 np->norm->Bf.font = FONT_Em;
937 else if (MDOC_Literal == arg)
938 np->norm->Bf.font = FONT_Li;
939 else if (MDOC_Symbolic == arg)
940 np->norm->Bf.font = FONT_Sy;
946 /* Extract parameter into data. */
948 if (0 == strcmp(np->child->string, "Em"))
949 np->norm->Bf.font = FONT_Em;
950 else if (0 == strcmp(np->child->string, "Li"))
951 np->norm->Bf.font = FONT_Li;
952 else if (0 == strcmp(np->child->string, "Sy"))
953 np->norm->Bf.font = FONT_Sy;
955 mandoc_vmsg(MANDOCERR_BF_BADFONT, mdoc->parse,
956 np->child->line, np->child->pos,
957 "Bf %s", np->child->string);
966 const char *stdlibname;
969 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
971 n = mdoc->last->child;
974 assert(MDOC_TEXT == n->type);
976 if (NULL == (stdlibname = mdoc_a2lib(n->string)))
977 mandoc_asprintf(&libname,
978 "library \\(lq%s\\(rq", n->string);
980 libname = mandoc_strdup(stdlibname);
990 const struct mdoc_node *n;
994 mandoc_vmsg(MANDOCERR_ARG_SKIP,
995 mdoc->parse, n->line, n->pos,
996 "%s %s", mdoc_macronames[n->tok],
1013 const struct mdoc_node *n;
1016 * The Vt macro comes in both ELEM and BLOCK form, both of which
1017 * have different syntaxes (yet more context-sensitive
1018 * behaviour). ELEM types must have a child, which is already
1019 * guaranteed by the in_line parsing routine; BLOCK types,
1020 * specifically the BODY, should only have TEXT children.
1023 if (MDOC_BODY != mdoc->last->type)
1026 for (n = mdoc->last->child; n; n = n->next)
1027 if (MDOC_TEXT != n->type)
1028 mandoc_msg(MANDOCERR_VT_CHILD, mdoc->parse,
1029 n->line, n->pos, mdoc_macronames[n->tok]);
1038 if (NULL != mdoc->meta.name)
1041 mdoc_deroff(&mdoc->meta.name, mdoc->last);
1043 if (NULL == mdoc->meta.name)
1044 mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse,
1045 mdoc->last->line, mdoc->last->pos, "Nm");
1054 return(post_hyph(mdoc));
1062 return(post_hyph(mdoc));
1066 post_literal(POST_ARGS)
1069 if (mdoc->last->tok == MDOC_Bd)
1074 * The `Dl' (note "el" not "one") and `Bd' macros unset the
1075 * MDOC_LITERAL flag as they leave. Note that `Bd' only sets
1076 * this in literal mode, but it doesn't hurt to just switch it
1077 * off in general since displays can't be nested.
1080 if (MDOC_BODY == mdoc->last->type)
1081 mdoc->flags &= ~MDOC_LITERAL;
1087 post_defaults(POST_ARGS)
1089 struct mdoc_node *nn;
1092 * The `Ar' defaults to "file ..." if no value is provided as an
1093 * argument; the `Mt' and `Pa' macros use "~"; the `Li' just
1094 * gets an empty string.
1097 if (mdoc->last->child)
1101 mdoc->next = MDOC_NEXT_CHILD;
1105 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "file"))
1107 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "..."))
1111 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, ""))
1117 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "~"))
1132 struct mdoc_node *n;
1133 const char *std_att;
1137 if (n->child == NULL) {
1138 mdoc->next = MDOC_NEXT_CHILD;
1139 if ( ! mdoc_word_alloc(mdoc, n->line, n->pos, "AT&T UNIX"))
1146 * If we have a child, look it up in the standard keys. If a
1147 * key exist, use that instead of the child; if it doesn't,
1148 * prefix "AT&T UNIX " to the existing data.
1152 assert(MDOC_TEXT == n->type);
1153 if (NULL == (std_att = mdoc_a2att(n->string))) {
1154 mandoc_vmsg(MANDOCERR_AT_BAD, mdoc->parse,
1155 n->line, n->pos, "At %s", n->string);
1156 mandoc_asprintf(&att, "AT&T UNIX %s", n->string);
1158 att = mandoc_strdup(std_att);
1168 struct mdoc_node *np;
1171 if (AUTH__NONE == np->norm->An.auth) {
1173 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0);
1174 } else if (np->child)
1175 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0);
1184 if (MDOC_BLOCK == mdoc->last->type)
1185 mdoc->last->norm->Es = mdoc->last_es;
1193 mdoc->last_es = mdoc->last;
1202 struct mdoc_node *nbl, *nit, *nch;
1205 if (MDOC_BLOCK != nit->type)
1208 nbl = nit->parent->parent;
1209 lt = nbl->norm->Bl.type;
1221 if (NULL == nit->head->child)
1222 mandoc_vmsg(MANDOCERR_IT_NOHEAD,
1223 mdoc->parse, nit->line, nit->pos,
1225 mdoc_argnames[nbl->args->argv[0].arg]);
1234 if (NULL == nit->body->child)
1235 mandoc_vmsg(MANDOCERR_IT_NOBODY,
1236 mdoc->parse, nit->line, nit->pos,
1238 mdoc_argnames[nbl->args->argv[0].arg]);
1241 if (NULL != nit->head->child)
1242 mandoc_vmsg(MANDOCERR_ARG_SKIP,
1243 mdoc->parse, nit->line, nit->pos,
1244 "It %s", nit->head->child->string);
1247 cols = (int)nbl->norm->Bl.ncols;
1249 assert(NULL == nit->head->child);
1251 for (i = 0, nch = nit->child; nch; nch = nch->next)
1252 if (MDOC_BODY == nch->type)
1255 if (i < cols || i > cols + 1)
1256 mandoc_vmsg(MANDOCERR_ARGCOUNT,
1257 mdoc->parse, nit->line, nit->pos,
1258 "columns == %d (have %d)", cols, i);
1268 post_bl_block(POST_ARGS)
1270 struct mdoc_node *n, *ni, *nc;
1273 * These are fairly complicated, so we've broken them into two
1274 * functions. post_bl_block_tag() is called when a -tag is
1275 * specified, but no -width (it must be guessed). The second
1276 * when a -width is specified (macro indicators must be
1277 * rewritten into real lengths).
1282 if (LIST_tag == n->norm->Bl.type &&
1283 NULL == n->norm->Bl.width) {
1284 if ( ! post_bl_block_tag(mdoc))
1286 assert(n->norm->Bl.width);
1287 } else if (NULL != n->norm->Bl.width) {
1288 if ( ! post_bl_block_width(mdoc))
1290 assert(n->norm->Bl.width);
1293 for (ni = n->body->child; ni; ni = ni->next) {
1294 if (NULL == ni->body)
1296 nc = ni->body->last;
1297 while (NULL != nc) {
1309 if (NULL == ni->next) {
1310 mandoc_msg(MANDOCERR_PAR_MOVE,
1311 mdoc->parse, nc->line, nc->pos,
1312 mdoc_macronames[nc->tok]);
1313 if ( ! mdoc_node_relink(mdoc, nc))
1315 } else if (0 == n->norm->Bl.comp &&
1316 LIST_column != n->norm->Bl.type) {
1317 mandoc_vmsg(MANDOCERR_PAR_SKIP,
1318 mdoc->parse, nc->line, nc->pos,
1320 mdoc_macronames[nc->tok]);
1321 mdoc_node_delete(mdoc, nc);
1324 nc = ni->body->last;
1331 post_bl_block_width(POST_ARGS)
1336 struct mdoc_node *n;
1342 * Calculate the real width of a list from the -width string,
1343 * which may contain a macro (with a known default width), a
1344 * literal string, or a scaling width.
1346 * If the value to -width is a macro, then we re-write it to be
1347 * the macro's width as set in share/tmac/mdoc/doc-common.
1350 if (0 == strcmp(n->norm->Bl.width, "Ds"))
1352 else if (MDOC_MAX == (tok = mdoc_hash_find(n->norm->Bl.width)))
1355 width = macro2len(tok);
1357 /* The value already exists: free and reallocate it. */
1361 for (i = 0; i < (int)n->args->argc; i++)
1362 if (MDOC_Width == n->args->argv[i].arg)
1365 assert(i < (int)n->args->argc);
1367 (void)snprintf(buf, sizeof(buf), "%un", (unsigned int)width);
1368 free(n->args->argv[i].value[0]);
1369 n->args->argv[i].value[0] = mandoc_strdup(buf);
1371 /* Set our width! */
1372 n->norm->Bl.width = n->args->argv[i].value[0];
1377 post_bl_block_tag(POST_ARGS)
1379 struct mdoc_node *n, *nn;
1385 * Calculate the -width for a `Bl -tag' list if it hasn't been
1386 * provided. Uses the first head macro. NOTE AGAIN: this is
1387 * ONLY if the -width argument has NOT been provided. See
1388 * post_bl_block_width() for converting the -width string.
1394 for (nn = n->body->child; nn; nn = nn->next) {
1395 if (MDOC_It != nn->tok)
1398 assert(MDOC_BLOCK == nn->type);
1399 nn = nn->head->child;
1404 if (MDOC_TEXT == nn->type) {
1405 sz = strlen(nn->string) + 1;
1409 if (0 != (ssz = macro2len(nn->tok)))
1415 /* Defaults to ten ens. */
1417 (void)snprintf(buf, sizeof(buf), "%un", (unsigned int)sz);
1420 * We have to dynamically add this to the macro's argument list.
1421 * We're guaranteed that a MDOC_Width doesn't already exist.
1425 i = (int)(n->args->argc)++;
1427 n->args->argv = mandoc_reallocarray(n->args->argv,
1428 n->args->argc, sizeof(struct mdoc_argv));
1430 n->args->argv[i].arg = MDOC_Width;
1431 n->args->argv[i].line = n->line;
1432 n->args->argv[i].pos = n->pos;
1433 n->args->argv[i].sz = 1;
1434 n->args->argv[i].value = mandoc_malloc(sizeof(char *));
1435 n->args->argv[i].value[0] = mandoc_strdup(buf);
1437 /* Set our width! */
1438 n->norm->Bl.width = n->args->argv[i].value[0];
1443 post_bl_head(POST_ARGS)
1445 struct mdoc_node *np, *nn, *nnp;
1446 struct mdoc_argv *argv;
1449 if (LIST_column != mdoc->last->norm->Bl.type)
1450 /* FIXME: this should be ERROR class... */
1451 return(hwarn_eq0(mdoc));
1454 * Append old-style lists, where the column width specifiers
1455 * trail as macro parameters, to the new-style ("normal-form")
1456 * lists where they're argument values following -column.
1459 if (mdoc->last->child == NULL)
1462 np = mdoc->last->parent;
1465 for (j = 0; j < (int)np->args->argc; j++)
1466 if (MDOC_Column == np->args->argv[j].arg)
1469 assert(j < (int)np->args->argc);
1472 * Accommodate for new-style groff column syntax. Shuffle the
1473 * child nodes, all of which must be TEXT, as arguments for the
1474 * column field. Then, delete the head children.
1477 argv = np->args->argv + j;
1479 argv->sz += mdoc->last->nchild;
1480 argv->value = mandoc_reallocarray(argv->value,
1481 argv->sz, sizeof(char *));
1483 mdoc->last->norm->Bl.ncols = argv->sz;
1484 mdoc->last->norm->Bl.cols = (void *)argv->value;
1486 for (nn = mdoc->last->child; nn; i++) {
1487 argv->value[i] = nn->string;
1491 mdoc_node_delete(NULL, nnp);
1494 mdoc->last->nchild = 0;
1495 mdoc->last->child = NULL;
1503 struct mdoc_node *nparent, *nprev; /* of the Bl block */
1504 struct mdoc_node *nblock, *nbody; /* of the Bl */
1505 struct mdoc_node *nchild, *nnext; /* of the Bl body */
1508 switch (nbody->type) {
1510 return(post_bl_block(mdoc));
1512 return(post_bl_head(mdoc));
1521 nchild = nbody->child;
1522 while (NULL != nchild) {
1523 if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
1524 nchild = nchild->next;
1528 mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse,
1529 nchild->line, nchild->pos,
1530 mdoc_macronames[nchild->tok]);
1533 * Move the node out of the Bl block.
1534 * First, collect all required node pointers.
1537 nblock = nbody->parent;
1538 nprev = nblock->prev;
1539 nparent = nblock->parent;
1540 nnext = nchild->next;
1543 * Unlink this child.
1546 assert(NULL == nchild->prev);
1547 if (0 == --nbody->nchild) {
1548 nbody->child = NULL;
1550 assert(NULL == nnext);
1552 nbody->child = nnext;
1557 * Relink this child.
1560 nchild->parent = nparent;
1561 nchild->prev = nprev;
1562 nchild->next = nblock;
1564 nblock->prev = nchild;
1567 nparent->child = nchild;
1569 nprev->next = nchild;
1587 ebool(struct mdoc *mdoc)
1589 struct mdoc_node *nch;
1592 tok = mdoc->last->tok;
1593 nch = mdoc->last->child;
1597 mdoc->flags ^= MDOC_SMOFF;
1601 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2);
1603 assert(MDOC_TEXT == nch->type);
1605 if (0 == strcmp(nch->string, "on")) {
1607 mdoc->flags &= ~MDOC_SMOFF;
1610 if (0 == strcmp(nch->string, "off")) {
1612 mdoc->flags |= MDOC_SMOFF;
1616 mandoc_vmsg(MANDOCERR_SM_BAD,
1617 mdoc->parse, nch->line, nch->pos,
1618 "%s %s", mdoc_macronames[tok], nch->string);
1619 return(mdoc_node_relink(mdoc, nch));
1623 post_root(POST_ARGS)
1625 struct mdoc_node *n;
1627 /* Add missing prologue data. */
1629 if (mdoc->meta.date == NULL)
1630 mdoc->meta.date = mdoc->quick ?
1632 mandoc_normdate(mdoc->parse, NULL, 0, 0);
1634 if (mdoc->meta.title == NULL) {
1635 mandoc_msg(MANDOCERR_DT_NOTITLE,
1636 mdoc->parse, 0, 0, "EOF");
1637 mdoc->meta.title = mandoc_strdup("UNTITLED");
1640 if (mdoc->meta.vol == NULL)
1641 mdoc->meta.vol = mandoc_strdup("LOCAL");
1643 if (mdoc->meta.os == NULL) {
1644 mandoc_msg(MANDOCERR_OS_MISSING,
1645 mdoc->parse, 0, 0, NULL);
1646 mdoc->meta.os = mandoc_strdup("");
1652 /* Check that we begin with a proper `Sh'. */
1654 if (NULL == n->child)
1655 mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse,
1656 n->line, n->pos, NULL);
1657 else if (MDOC_Sh != n->child->tok)
1658 mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse,
1659 n->child->line, n->child->pos,
1660 mdoc_macronames[n->child->tok]);
1668 struct mdoc_node *n, *nch;
1675 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
1676 n->line, n->pos, mdoc_macronames[n->tok]);
1677 mdoc_node_delete(mdoc, n);
1681 assert(MDOC_TEXT == nch->type);
1683 if (NULL == (p = mdoc_a2st(nch->string))) {
1684 mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse,
1685 nch->line, nch->pos, "St %s", nch->string);
1686 mdoc_node_delete(mdoc, n);
1689 nch->string = mandoc_strdup(p);
1698 struct mdoc_node *nn, *next, *prev;
1701 switch (mdoc->last->type) {
1703 check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0);
1706 if (mdoc->last->child)
1708 check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0);
1715 * The full `Rs' block needs special handling to order the
1716 * sub-elements according to `rsord'. Pick through each element
1717 * and correctly order it. This is an insertion sort.
1721 for (nn = mdoc->last->child->next; nn; nn = next) {
1722 /* Determine order of `nn'. */
1723 for (i = 0; i < RSORD_MAX; i++)
1724 if (rsord[i] == nn->tok)
1727 if (i == RSORD_MAX) {
1728 mandoc_msg(MANDOCERR_RS_BAD,
1729 mdoc->parse, nn->line, nn->pos,
1730 mdoc_macronames[nn->tok]);
1732 } else if (MDOC__J == nn->tok || MDOC__B == nn->tok)
1733 mdoc->last->norm->Rs.quote_T++;
1736 * Remove `nn' from the chain. This somewhat
1737 * repeats mdoc_node_unlink(), but since we're
1738 * just re-ordering, there's no need for the
1739 * full unlink process.
1742 if (NULL != (next = nn->next))
1743 next->prev = nn->prev;
1745 if (NULL != (prev = nn->prev))
1746 prev->next = nn->next;
1748 nn->prev = nn->next = NULL;
1751 * Scan back until we reach a node that's
1752 * ordered before `nn'.
1755 for ( ; prev ; prev = prev->prev) {
1756 /* Determine order of `prev'. */
1757 for (j = 0; j < RSORD_MAX; j++)
1758 if (rsord[j] == prev->tok)
1768 * Set `nn' back into its correct place in front
1769 * of the `prev' node.
1776 prev->next->prev = nn;
1777 nn->next = prev->next;
1780 mdoc->last->child->prev = nn;
1781 nn->next = mdoc->last->child;
1782 mdoc->last->child = nn;
1790 * For some arguments of some macros,
1791 * convert all breakable hyphens into ASCII_HYPH.
1794 post_hyph(POST_ARGS)
1796 struct mdoc_node *n, *nch;
1802 if (MDOC_Sh == n->tok || MDOC_Ss == n->tok)
1806 if (MDOC_D1 == n->tok || MDOC_Nd == n->tok)
1815 for (nch = n->child; nch; nch = nch->next) {
1816 if (MDOC_TEXT != nch->type)
1821 while ('\0' != *(++cp))
1823 isalpha((unsigned char)cp[-1]) &&
1824 isalpha((unsigned char)cp[1]))
1831 post_hyphtext(POST_ARGS)
1835 return(post_hyph(mdoc));
1842 if (MDOC_LINE & mdoc->last->flags)
1843 mandoc_msg(MANDOCERR_NS_SKIP, mdoc->parse,
1844 mdoc->last->line, mdoc->last->pos, NULL);
1854 if (MDOC_HEAD == mdoc->last->type)
1855 return(post_sh_head(mdoc));
1856 if (MDOC_BODY == mdoc->last->type)
1857 return(post_sh_body(mdoc));
1863 post_sh_body(POST_ARGS)
1865 struct mdoc_node *n;
1867 if (SEC_NAME != mdoc->lastsec)
1871 * Warn if the NAME section doesn't contain the `Nm' and `Nd'
1872 * macros (can have multiple `Nm' and one `Nd'). Note that the
1873 * children of the BODY declaration can also be "text".
1876 if (NULL == (n = mdoc->last->child)) {
1877 mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
1878 mdoc->last->line, mdoc->last->pos, "empty");
1882 for ( ; n && n->next; n = n->next) {
1883 if (MDOC_ELEM == n->type && MDOC_Nm == n->tok)
1885 if (MDOC_TEXT == n->type)
1887 mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
1888 n->line, n->pos, mdoc_macronames[n->tok]);
1892 if (MDOC_BLOCK == n->type && MDOC_Nd == n->tok)
1895 mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
1896 n->line, n->pos, mdoc_macronames[n->tok]);
1901 post_sh_head(POST_ARGS)
1903 struct mdoc_node *n;
1904 const char *goodsec;
1909 * Process a new section. Sections are either "named" or
1910 * "custom". Custom sections are user-defined, while named ones
1911 * follow a conventional order and may only appear in certain
1917 mdoc_deroff(&secname, mdoc->last);
1918 sec = NULL == secname ? SEC_CUSTOM : a2sec(secname);
1920 /* The NAME should be first. */
1922 if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
1923 mandoc_vmsg(MANDOCERR_NAMESEC_FIRST, mdoc->parse,
1924 mdoc->last->line, mdoc->last->pos,
1927 /* The SYNOPSIS gets special attention in other areas. */
1929 if (SEC_SYNOPSIS == sec) {
1930 roff_setreg(mdoc->roff, "nS", 1, '=');
1931 mdoc->flags |= MDOC_SYNOPSIS;
1933 roff_setreg(mdoc->roff, "nS", 0, '=');
1934 mdoc->flags &= ~MDOC_SYNOPSIS;
1937 /* Mark our last section. */
1939 mdoc->lastsec = sec;
1942 * Set the section attribute for the current HEAD, for its
1943 * parent BLOCK, and for the HEAD children; the latter can
1944 * only be TEXT nodes, so no recursion is needed.
1945 * For other blocks and elements, including .Sh BODY, this is
1946 * done when allocating the node data structures, but for .Sh
1947 * BLOCK and HEAD, the section is still unknown at that time.
1950 mdoc->last->parent->sec = sec;
1951 mdoc->last->sec = sec;
1952 for (n = mdoc->last->child; n; n = n->next)
1955 /* We don't care about custom sections after this. */
1957 if (SEC_CUSTOM == sec) {
1963 * Check whether our non-custom section is being repeated or is
1967 if (sec == mdoc->lastnamed)
1968 mandoc_vmsg(MANDOCERR_SEC_REP, mdoc->parse,
1969 mdoc->last->line, mdoc->last->pos,
1972 if (sec < mdoc->lastnamed)
1973 mandoc_vmsg(MANDOCERR_SEC_ORDER, mdoc->parse,
1974 mdoc->last->line, mdoc->last->pos,
1977 /* Mark the last named section. */
1979 mdoc->lastnamed = sec;
1981 /* Check particular section/manual conventions. */
1983 if (mdoc->meta.msec == NULL) {
1991 if (*mdoc->meta.msec == '4')
1993 goodsec = "2, 3, 4, 9";
1995 case SEC_RETURN_VALUES:
1998 if (*mdoc->meta.msec == '2')
2000 if (*mdoc->meta.msec == '3')
2002 if (NULL == goodsec)
2003 goodsec = "2, 3, 9";
2006 if (*mdoc->meta.msec == '9')
2008 if (NULL == goodsec)
2010 mandoc_vmsg(MANDOCERR_SEC_MSEC, mdoc->parse,
2011 mdoc->last->line, mdoc->last->pos,
2012 "Sh %s for %s only", secname, goodsec);
2023 post_ignpar(POST_ARGS)
2025 struct mdoc_node *np;
2030 if (MDOC_BODY != mdoc->last->type)
2033 if (NULL != (np = mdoc->last->child))
2034 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
2035 mandoc_vmsg(MANDOCERR_PAR_SKIP,
2036 mdoc->parse, np->line, np->pos,
2037 "%s after %s", mdoc_macronames[np->tok],
2038 mdoc_macronames[mdoc->last->tok]);
2039 mdoc_node_delete(mdoc, np);
2042 if (NULL != (np = mdoc->last->last))
2043 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
2044 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2045 np->line, np->pos, "%s at the end of %s",
2046 mdoc_macronames[np->tok],
2047 mdoc_macronames[mdoc->last->tok]);
2048 mdoc_node_delete(mdoc, np);
2058 if (NULL == mdoc->last)
2060 if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type)
2064 * Don't allow prior `Lp' or `Pp' prior to a paragraph-type
2065 * block: `Lp', `Pp', or non-compact `Bd' or `Bl'.
2068 if (MDOC_Pp != mdoc->last->tok &&
2069 MDOC_Lp != mdoc->last->tok &&
2070 MDOC_br != mdoc->last->tok)
2072 if (MDOC_Bl == n->tok && n->norm->Bl.comp)
2074 if (MDOC_Bd == n->tok && n->norm->Bd.comp)
2076 if (MDOC_It == n->tok && n->parent->norm->Bl.comp)
2079 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2080 mdoc->last->line, mdoc->last->pos,
2081 "%s before %s", mdoc_macronames[mdoc->last->tok],
2082 mdoc_macronames[n->tok]);
2083 mdoc_node_delete(mdoc, mdoc->last);
2090 struct mdoc_node *np;
2092 if (mdoc->last->tok == MDOC_sp)
2097 if (MDOC_ELEM != mdoc->last->type &&
2098 MDOC_BLOCK != mdoc->last->type)
2101 if (NULL == (np = mdoc->last->prev)) {
2102 np = mdoc->last->parent;
2103 if (MDOC_Sh != np->tok && MDOC_Ss != np->tok)
2106 if (MDOC_Pp != np->tok && MDOC_Lp != np->tok &&
2107 (MDOC_br != mdoc->last->tok ||
2108 (MDOC_sp != np->tok && MDOC_br != np->tok)))
2112 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2113 mdoc->last->line, mdoc->last->pos,
2114 "%s after %s", mdoc_macronames[mdoc->last->tok],
2115 mdoc_macronames[np->tok]);
2116 mdoc_node_delete(mdoc, mdoc->last);
2121 pre_literal(PRE_ARGS)
2124 pre_display(mdoc, n);
2126 if (MDOC_BODY != n->type)
2130 * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd
2131 * -unfilled' macros set MDOC_LITERAL on entrance to the body.
2136 mdoc->flags |= MDOC_LITERAL;
2139 if (DISP_literal == n->norm->Bd.type)
2140 mdoc->flags |= MDOC_LITERAL;
2141 if (DISP_unfilled == n->norm->Bd.type)
2142 mdoc->flags |= MDOC_LITERAL;
2155 struct mdoc_node *n;
2158 if (mdoc->meta.date)
2159 free(mdoc->meta.date);
2162 if (NULL == n->child || '\0' == n->child->string[0]) {
2163 mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
2164 mandoc_normdate(mdoc->parse, NULL, n->line, n->pos);
2169 mdoc_deroff(&datestr, n);
2171 mdoc->meta.date = datestr;
2173 mdoc->meta.date = mandoc_normdate(mdoc->parse,
2174 datestr, n->line, n->pos);
2178 mdoc_node_delete(mdoc, n);
2185 struct mdoc_node *nn, *n;
2191 free(mdoc->meta.title);
2192 free(mdoc->meta.msec);
2193 free(mdoc->meta.vol);
2194 free(mdoc->meta.arch);
2196 mdoc->meta.title = NULL;
2197 mdoc->meta.msec = NULL;
2198 mdoc->meta.vol = NULL;
2199 mdoc->meta.arch = NULL;
2201 /* First check that all characters are uppercase. */
2203 if (NULL != (nn = n->child))
2204 for (p = nn->string; *p; p++) {
2205 if (toupper((unsigned char)*p) == *p)
2207 mandoc_vmsg(MANDOCERR_TITLE_CASE,
2208 mdoc->parse, nn->line,
2209 nn->pos + (p - nn->string),
2210 "Dt %s", nn->string);
2214 /* No argument: msec and arch remain NULL. */
2216 if (NULL == (nn = n->child)) {
2217 mandoc_msg(MANDOCERR_DT_NOTITLE,
2218 mdoc->parse, n->line, n->pos, "Dt");
2219 mdoc->meta.title = mandoc_strdup("UNTITLED");
2220 mdoc->meta.vol = mandoc_strdup("LOCAL");
2224 /* One argument: msec and arch remain NULL. */
2226 mdoc->meta.title = mandoc_strdup(
2227 '\0' == nn->string[0] ? "UNTITLED" : nn->string);
2229 if (NULL == (nn = nn->next)) {
2230 mandoc_vmsg(MANDOCERR_MSEC_MISSING,
2231 mdoc->parse, n->line, n->pos,
2232 "Dt %s", mdoc->meta.title);
2233 mdoc->meta.vol = mandoc_strdup("LOCAL");
2237 /* Handles: `.Dt TITLE SEC'
2239 * volume = SEC is msec ? format(msec) : SEC,
2240 * msec = SEC is msec ? atoi(msec) : 0,
2244 cp = mandoc_a2msec(nn->string);
2246 mdoc->meta.vol = mandoc_strdup(cp);
2247 mdoc->meta.msec = mandoc_strdup(nn->string);
2249 mandoc_vmsg(MANDOCERR_MSEC_BAD, mdoc->parse,
2250 nn->line, nn->pos, "Dt ... %s", nn->string);
2251 mdoc->meta.vol = mandoc_strdup(nn->string);
2252 mdoc->meta.msec = mandoc_strdup(nn->string);
2255 if (NULL == (nn = nn->next))
2258 /* Handles: `.Dt TITLE SEC VOL'
2260 * volume = VOL is vol ? format(VOL) :
2261 * VOL is arch ? format(arch) :
2265 cp = mdoc_a2vol(nn->string);
2267 free(mdoc->meta.vol);
2268 mdoc->meta.vol = mandoc_strdup(cp);
2270 cp = mdoc_a2arch(nn->string);
2272 mandoc_vmsg(MANDOCERR_ARCH_BAD, mdoc->parse,
2273 nn->line, nn->pos, "Dt ... %s", nn->string);
2274 free(mdoc->meta.vol);
2275 mdoc->meta.vol = mandoc_strdup(nn->string);
2277 mdoc->meta.arch = mandoc_strdup(cp);
2280 /* Ignore any subsequent parameters... */
2281 /* FIXME: warn about subsequent parameters. */
2283 mdoc_node_delete(mdoc, n);
2290 struct mdoc_node *n;
2293 * Make `Bx's second argument always start with an uppercase
2294 * letter. Groff checks if it's an "accepted" term, but we just
2295 * uppercase blindly.
2298 n = mdoc->last->child;
2299 if (n && NULL != (n = n->next))
2300 *n->string = (char)toupper((unsigned char)*n->string);
2309 struct utsname utsname;
2310 static char *defbuf;
2312 struct mdoc_node *n;
2317 * Set the operating system by way of the `Os' macro.
2318 * The order of precedence is:
2319 * 1. the argument of the `Os' macro, unless empty
2320 * 2. the -Ios=foo command line argument, if provided
2321 * 3. -DOSNAME="\"foo\"", if provided during compilation
2322 * 4. "sysname release" from uname(3)
2325 free(mdoc->meta.os);
2326 mdoc->meta.os = NULL;
2327 mdoc_deroff(&mdoc->meta.os, n);
2332 mdoc->meta.os = mandoc_strdup(mdoc->defos);
2337 mdoc->meta.os = mandoc_strdup(OSNAME);
2339 if (NULL == defbuf) {
2340 if (-1 == uname(&utsname)) {
2341 mandoc_msg(MANDOCERR_OS_UNAME, mdoc->parse,
2342 n->line, n->pos, "Os");
2343 defbuf = mandoc_strdup("UNKNOWN");
2345 mandoc_asprintf(&defbuf, "%s %s",
2346 utsname.sysname, utsname.release);
2348 mdoc->meta.os = mandoc_strdup(defbuf);
2352 mdoc_node_delete(mdoc, n);
2357 * If no argument is provided,
2358 * fill in the name of the current manual page.
2363 struct mdoc_node *n;
2370 if (mdoc->meta.name == NULL) {
2371 mandoc_msg(MANDOCERR_EX_NONAME, mdoc->parse,
2372 n->line, n->pos, "Ex");
2376 mdoc->next = MDOC_NEXT_CHILD;
2378 if ( ! mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name))
2385 static enum mdoc_sec
2386 a2sec(const char *p)
2390 for (i = 0; i < (int)SEC__MAX; i++)
2391 if (secnames[i] && 0 == strcmp(p, secnames[i]))
2392 return((enum mdoc_sec)i);
2398 macro2len(enum mdoct macro)