1 /* $Id: mdoc_validate.c,v 1.263 2014/11/30 05:29:00 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.
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
56 typedef void (*v_pre)(PRE_ARGS);
57 typedef void (*v_post)(POST_ARGS);
64 static void check_count(struct mdoc *, enum mdoc_type,
65 enum check_lvl, enum check_ineq, int);
66 static void check_text(struct mdoc *, int, int, char *);
67 static void check_argv(struct mdoc *,
68 struct mdoc_node *, struct mdoc_argv *);
69 static void check_args(struct mdoc *, struct mdoc_node *);
70 static int child_an(const struct mdoc_node *);
71 static enum mdoc_sec a2sec(const char *);
72 static size_t macro2len(enum mdoct);
73 static void rewrite_macro2len(char **);
75 static void bwarn_ge1(POST_ARGS);
76 static void ewarn_eq1(POST_ARGS);
77 static void ewarn_ge1(POST_ARGS);
78 static void hwarn_eq0(POST_ARGS);
80 static void post_an(POST_ARGS);
81 static void post_at(POST_ARGS);
82 static void post_bf(POST_ARGS);
83 static void post_bk(POST_ARGS);
84 static void post_bl(POST_ARGS);
85 static void post_bl_block(POST_ARGS);
86 static void post_bl_block_tag(POST_ARGS);
87 static void post_bl_head(POST_ARGS);
88 static void post_bx(POST_ARGS);
89 static void post_d1(POST_ARGS);
90 static void post_defaults(POST_ARGS);
91 static void post_dd(POST_ARGS);
92 static void post_dt(POST_ARGS);
93 static void post_en(POST_ARGS);
94 static void post_es(POST_ARGS);
95 static void post_eoln(POST_ARGS);
96 static void post_ex(POST_ARGS);
97 static void post_fa(POST_ARGS);
98 static void post_fn(POST_ARGS);
99 static void post_fname(POST_ARGS);
100 static void post_fo(POST_ARGS);
101 static void post_hyph(POST_ARGS);
102 static void post_hyphtext(POST_ARGS);
103 static void post_ignpar(POST_ARGS);
104 static void post_it(POST_ARGS);
105 static void post_lb(POST_ARGS);
106 static void post_literal(POST_ARGS);
107 static void post_nd(POST_ARGS);
108 static void post_nm(POST_ARGS);
109 static void post_ns(POST_ARGS);
110 static void post_os(POST_ARGS);
111 static void post_par(POST_ARGS);
112 static void post_root(POST_ARGS);
113 static void post_rs(POST_ARGS);
114 static void post_sh(POST_ARGS);
115 static void post_sh_head(POST_ARGS);
116 static void post_sh_name(POST_ARGS);
117 static void post_sh_see_also(POST_ARGS);
118 static void post_sh_authors(POST_ARGS);
119 static void post_sm(POST_ARGS);
120 static void post_st(POST_ARGS);
121 static void post_vt(POST_ARGS);
123 static void pre_an(PRE_ARGS);
124 static void pre_bd(PRE_ARGS);
125 static void pre_bl(PRE_ARGS);
126 static void pre_dd(PRE_ARGS);
127 static void pre_display(PRE_ARGS);
128 static void pre_dt(PRE_ARGS);
129 static void pre_literal(PRE_ARGS);
130 static void pre_obsolete(PRE_ARGS);
131 static void pre_os(PRE_ARGS);
132 static void pre_par(PRE_ARGS);
133 static void pre_std(PRE_ARGS);
135 static const struct valids mdoc_valids[MDOC_MAX] = {
136 { NULL, NULL }, /* Ap */
137 { pre_dd, post_dd }, /* Dd */
138 { pre_dt, post_dt }, /* Dt */
139 { pre_os, post_os }, /* Os */
140 { NULL, post_sh }, /* Sh */
141 { NULL, post_ignpar }, /* Ss */
142 { pre_par, post_par }, /* Pp */
143 { pre_display, post_d1 }, /* D1 */
144 { pre_literal, post_literal }, /* Dl */
145 { pre_bd, post_literal }, /* Bd */
146 { NULL, NULL }, /* Ed */
147 { pre_bl, post_bl }, /* Bl */
148 { NULL, NULL }, /* El */
149 { pre_par, post_it }, /* It */
150 { NULL, NULL }, /* Ad */
151 { pre_an, post_an }, /* An */
152 { NULL, post_defaults }, /* Ar */
153 { NULL, NULL }, /* Cd */
154 { NULL, NULL }, /* Cm */
155 { NULL, NULL }, /* Dv */
156 { NULL, NULL }, /* Er */
157 { NULL, NULL }, /* Ev */
158 { pre_std, post_ex }, /* Ex */
159 { NULL, post_fa }, /* Fa */
160 { NULL, ewarn_ge1 }, /* Fd */
161 { NULL, NULL }, /* Fl */
162 { NULL, post_fn }, /* Fn */
163 { NULL, NULL }, /* Ft */
164 { NULL, NULL }, /* Ic */
165 { NULL, ewarn_eq1 }, /* In */
166 { NULL, post_defaults }, /* Li */
167 { NULL, post_nd }, /* Nd */
168 { NULL, post_nm }, /* Nm */
169 { NULL, NULL }, /* Op */
170 { pre_obsolete, NULL }, /* Ot */
171 { NULL, post_defaults }, /* Pa */
172 { pre_std, NULL }, /* Rv */
173 { NULL, post_st }, /* St */
174 { NULL, NULL }, /* Va */
175 { NULL, post_vt }, /* Vt */
176 { NULL, ewarn_ge1 }, /* Xr */
177 { NULL, ewarn_ge1 }, /* %A */
178 { NULL, post_hyphtext }, /* %B */ /* FIXME: can be used outside Rs/Re. */
179 { NULL, ewarn_ge1 }, /* %D */
180 { NULL, ewarn_ge1 }, /* %I */
181 { NULL, ewarn_ge1 }, /* %J */
182 { NULL, post_hyphtext }, /* %N */
183 { NULL, post_hyphtext }, /* %O */
184 { NULL, ewarn_ge1 }, /* %P */
185 { NULL, post_hyphtext }, /* %R */
186 { NULL, post_hyphtext }, /* %T */ /* FIXME: can be used outside Rs/Re. */
187 { NULL, ewarn_ge1 }, /* %V */
188 { NULL, NULL }, /* Ac */
189 { NULL, NULL }, /* Ao */
190 { NULL, NULL }, /* Aq */
191 { NULL, post_at }, /* At */
192 { NULL, NULL }, /* Bc */
193 { NULL, post_bf }, /* Bf */
194 { NULL, NULL }, /* Bo */
195 { NULL, NULL }, /* Bq */
196 { NULL, NULL }, /* Bsx */
197 { NULL, post_bx }, /* Bx */
198 { pre_obsolete, NULL }, /* Db */
199 { NULL, NULL }, /* Dc */
200 { NULL, NULL }, /* Do */
201 { NULL, NULL }, /* Dq */
202 { NULL, NULL }, /* Ec */
203 { NULL, NULL }, /* Ef */
204 { NULL, NULL }, /* Em */
205 { NULL, NULL }, /* Eo */
206 { NULL, NULL }, /* Fx */
207 { NULL, NULL }, /* Ms */
208 { NULL, NULL }, /* No */
209 { NULL, post_ns }, /* Ns */
210 { NULL, NULL }, /* Nx */
211 { NULL, NULL }, /* Ox */
212 { NULL, NULL }, /* Pc */
213 { NULL, NULL }, /* Pf */
214 { NULL, NULL }, /* Po */
215 { NULL, NULL }, /* Pq */
216 { NULL, NULL }, /* Qc */
217 { NULL, NULL }, /* Ql */
218 { NULL, NULL }, /* Qo */
219 { NULL, NULL }, /* Qq */
220 { NULL, NULL }, /* Re */
221 { NULL, post_rs }, /* Rs */
222 { NULL, NULL }, /* Sc */
223 { NULL, NULL }, /* So */
224 { NULL, NULL }, /* Sq */
225 { NULL, post_sm }, /* Sm */
226 { NULL, post_hyph }, /* Sx */
227 { NULL, NULL }, /* Sy */
228 { NULL, NULL }, /* Tn */
229 { NULL, NULL }, /* Ux */
230 { NULL, NULL }, /* Xc */
231 { NULL, NULL }, /* Xo */
232 { NULL, post_fo }, /* Fo */
233 { NULL, NULL }, /* Fc */
234 { NULL, NULL }, /* Oo */
235 { NULL, NULL }, /* Oc */
236 { NULL, post_bk }, /* Bk */
237 { NULL, NULL }, /* Ek */
238 { NULL, post_eoln }, /* Bt */
239 { NULL, NULL }, /* Hf */
240 { pre_obsolete, NULL }, /* Fr */
241 { NULL, post_eoln }, /* Ud */
242 { NULL, post_lb }, /* Lb */
243 { pre_par, post_par }, /* Lp */
244 { NULL, NULL }, /* Lk */
245 { NULL, post_defaults }, /* Mt */
246 { NULL, NULL }, /* Brq */
247 { NULL, NULL }, /* Bro */
248 { NULL, NULL }, /* Brc */
249 { NULL, ewarn_ge1 }, /* %C */
250 { pre_obsolete, post_es }, /* Es */
251 { pre_obsolete, post_en }, /* En */
252 { NULL, NULL }, /* Dx */
253 { NULL, ewarn_ge1 }, /* %Q */
254 { NULL, post_par }, /* br */
255 { NULL, post_par }, /* sp */
256 { NULL, ewarn_eq1 }, /* %U */
257 { NULL, NULL }, /* Ta */
258 { NULL, NULL }, /* ll */
261 #define RSORD_MAX 14 /* Number of `Rs' blocks. */
263 static const enum mdoct rsord[RSORD_MAX] = {
280 static const char * const secnames[SEC__MAX] = {
287 "IMPLEMENTATION NOTES",
302 "SECURITY CONSIDERATIONS",
308 mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n)
314 check_text(mdoc, n->line, n->pos, n->string);
327 p = mdoc_valids[n->tok].pre;
333 mdoc_valid_post(struct mdoc *mdoc)
339 if (n->flags & MDOC_VALID)
341 n->flags |= MDOC_VALID;
356 * Closing delimiters are not special at the
357 * beginning of a block, opening delimiters
358 * are not special at the end.
361 if (n->child != NULL)
362 n->child->flags &= ~MDOC_DELIMC;
364 n->last->flags &= ~MDOC_DELIMO;
366 /* Call the macro's postprocessor. */
368 p = mdoc_valids[n->tok].post;
376 check_count(struct mdoc *mdoc, enum mdoc_type type,
377 enum check_lvl lvl, enum check_ineq ineq, int val)
382 if (mdoc->last->type != type)
388 if (mdoc->last->nchild < val)
393 if (mdoc->last->nchild > val)
398 if (val == mdoc->last->nchild)
406 t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
407 mandoc_vmsg(t, mdoc->parse, mdoc->last->line,
408 mdoc->last->pos, "want %s%d children (have %d)",
409 p, val, mdoc->last->nchild);
415 check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0);
421 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
427 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0);
433 check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0);
437 check_args(struct mdoc *mdoc, struct mdoc_node *n)
444 assert(n->args->argc);
445 for (i = 0; i < (int)n->args->argc; i++)
446 check_argv(mdoc, n, &n->args->argv[i]);
450 check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v)
454 for (i = 0; i < (int)v->sz; i++)
455 check_text(mdoc, v->line, v->pos, v->value[i]);
459 check_text(struct mdoc *mdoc, int ln, int pos, char *p)
463 if (MDOC_LITERAL & mdoc->flags)
466 for (cp = p; NULL != (p = strchr(p, '\t')); p++)
467 mandoc_msg(MANDOCERR_FI_TAB, mdoc->parse,
468 ln, pos + (int)(p - cp), NULL);
472 pre_display(PRE_ARGS)
474 struct mdoc_node *node;
476 if (MDOC_BLOCK != n->type)
479 for (node = mdoc->last->parent; node; node = node->parent)
480 if (MDOC_BLOCK == node->type)
481 if (MDOC_Bd == node->tok)
485 mandoc_vmsg(MANDOCERR_BD_NEST,
486 mdoc->parse, n->line, n->pos,
487 "%s in Bd", mdoc_macronames[n->tok]);
493 struct mdoc_node *np;
494 struct mdoc_argv *argv, *wa;
496 enum mdocargt mdoclt;
499 if (MDOC_BLOCK != n->type) {
500 if (ENDBODY_NOT != n->end) {
502 np = n->pending->parent;
507 assert(MDOC_BLOCK == np->type);
508 assert(MDOC_Bl == np->tok);
513 * First figure out which kind of list to use: bind ourselves to
514 * the first mentioned list type and warn about any remaining
515 * ones. If we find no list type, we default to LIST_item.
518 wa = (n->args == NULL) ? NULL : n->args->argv;
519 mdoclt = MDOC_ARG_MAX;
520 for (i = 0; n->args && i < (int)n->args->argc; i++) {
521 argv = n->args->argv + i;
524 /* Set list types. */
558 /* Set list arguments. */
560 if (n->norm->Bl.comp)
561 mandoc_msg(MANDOCERR_ARG_REP,
562 mdoc->parse, argv->line,
563 argv->pos, "Bl -compact");
564 n->norm->Bl.comp = 1;
569 mandoc_msg(MANDOCERR_ARG_EMPTY,
570 mdoc->parse, argv->line,
571 argv->pos, "Bl -width");
572 n->norm->Bl.width = "0n";
575 if (NULL != n->norm->Bl.width)
576 mandoc_vmsg(MANDOCERR_ARG_REP,
577 mdoc->parse, argv->line,
578 argv->pos, "Bl -width %s",
580 rewrite_macro2len(argv->value);
581 n->norm->Bl.width = argv->value[0];
585 mandoc_msg(MANDOCERR_ARG_EMPTY,
586 mdoc->parse, argv->line,
587 argv->pos, "Bl -offset");
590 if (NULL != n->norm->Bl.offs)
591 mandoc_vmsg(MANDOCERR_ARG_REP,
592 mdoc->parse, argv->line,
593 argv->pos, "Bl -offset %s",
595 rewrite_macro2len(argv->value);
596 n->norm->Bl.offs = argv->value[0];
601 if (LIST__NONE == lt)
605 /* Check: multiple list types. */
607 if (LIST__NONE != n->norm->Bl.type) {
608 mandoc_vmsg(MANDOCERR_BL_REP,
609 mdoc->parse, n->line, n->pos,
610 "Bl -%s", mdoc_argnames[argv->arg]);
614 /* The list type should come first. */
616 if (n->norm->Bl.width ||
619 mandoc_vmsg(MANDOCERR_BL_LATETYPE,
620 mdoc->parse, n->line, n->pos, "Bl -%s",
621 mdoc_argnames[n->args->argv[0].arg]);
623 n->norm->Bl.type = lt;
624 if (LIST_column == lt) {
625 n->norm->Bl.ncols = argv->sz;
626 n->norm->Bl.cols = (void *)argv->value;
630 /* Allow lists to default to LIST_item. */
632 if (LIST__NONE == n->norm->Bl.type) {
633 mandoc_msg(MANDOCERR_BL_NOTYPE, mdoc->parse,
634 n->line, n->pos, "Bl");
635 n->norm->Bl.type = LIST_item;
639 * Validate the width field. Some list types don't need width
640 * types and should be warned about them. Others should have it
641 * and must also be warned. Yet others have a default and need
645 switch (n->norm->Bl.type) {
647 if (NULL == n->norm->Bl.width)
648 mandoc_msg(MANDOCERR_BL_NOWIDTH, mdoc->parse,
649 n->line, n->pos, "Bl -tag");
660 if (n->norm->Bl.width)
661 mandoc_vmsg(MANDOCERR_BL_SKIPW, mdoc->parse,
662 wa->line, wa->pos, "Bl -%s",
663 mdoc_argnames[mdoclt]);
670 if (NULL == n->norm->Bl.width)
671 n->norm->Bl.width = "2n";
674 if (NULL == n->norm->Bl.width)
675 n->norm->Bl.width = "3n";
686 struct mdoc_node *np;
687 struct mdoc_argv *argv;
691 pre_literal(mdoc, n);
693 if (MDOC_BLOCK != n->type) {
694 if (ENDBODY_NOT != n->end) {
696 np = n->pending->parent;
701 assert(MDOC_BLOCK == np->type);
702 assert(MDOC_Bd == np->tok);
706 for (i = 0; n->args && i < (int)n->args->argc; i++) {
707 argv = n->args->argv + i;
727 mandoc_msg(MANDOCERR_BD_FILE, mdoc->parse,
728 n->line, n->pos, NULL);
732 mandoc_msg(MANDOCERR_ARG_EMPTY,
733 mdoc->parse, argv->line,
734 argv->pos, "Bd -offset");
737 if (NULL != n->norm->Bd.offs)
738 mandoc_vmsg(MANDOCERR_ARG_REP,
739 mdoc->parse, argv->line,
740 argv->pos, "Bd -offset %s",
742 rewrite_macro2len(argv->value);
743 n->norm->Bd.offs = argv->value[0];
746 if (n->norm->Bd.comp)
747 mandoc_msg(MANDOCERR_ARG_REP,
748 mdoc->parse, argv->line,
749 argv->pos, "Bd -compact");
750 n->norm->Bd.comp = 1;
756 if (DISP__NONE == dt)
759 if (DISP__NONE == n->norm->Bd.type)
760 n->norm->Bd.type = dt;
762 mandoc_vmsg(MANDOCERR_BD_REP,
763 mdoc->parse, n->line, n->pos,
764 "Bd -%s", mdoc_argnames[argv->arg]);
767 if (DISP__NONE == n->norm->Bd.type) {
768 mandoc_msg(MANDOCERR_BD_NOTYPE, mdoc->parse,
769 n->line, n->pos, "Bd");
770 n->norm->Bd.type = DISP_ragged;
778 struct mdoc_argv *argv;
784 for (i = 1; i < n->args->argc; i++) {
785 argv = n->args->argv + i;
786 mandoc_vmsg(MANDOCERR_AN_REP,
787 mdoc->parse, argv->line, argv->pos,
788 "An -%s", mdoc_argnames[argv->arg]);
791 argv = n->args->argv;
792 if (argv->arg == MDOC_Split)
793 n->norm->An.auth = AUTH_split;
794 else if (argv->arg == MDOC_Nosplit)
795 n->norm->An.auth = AUTH_nosplit;
804 if (n->args && 1 == n->args->argc)
805 if (MDOC_Std == n->args->argv[0].arg)
808 mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse,
809 n->line, n->pos, mdoc_macronames[n->tok]);
813 pre_obsolete(PRE_ARGS)
816 if (MDOC_ELEM == n->type || MDOC_BLOCK == n->type)
817 mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse,
818 n->line, n->pos, mdoc_macronames[n->tok]);
825 if (mdoc->meta.title != NULL)
826 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
827 n->line, n->pos, "Dt");
828 else if (mdoc->meta.os != NULL)
829 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
830 n->line, n->pos, "Dt after Os");
837 if (mdoc->meta.os != NULL)
838 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
839 n->line, n->pos, "Os");
840 else if (mdoc->flags & MDOC_PBODY)
841 mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
842 n->line, n->pos, "Os");
849 if (mdoc->meta.date != NULL)
850 mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
851 n->line, n->pos, "Dd");
852 else if (mdoc->flags & MDOC_PBODY)
853 mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
854 n->line, n->pos, "Dd");
855 else if (mdoc->meta.title != NULL)
856 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
857 n->line, n->pos, "Dd after Dt");
858 else if (mdoc->meta.os != NULL)
859 mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
860 n->line, n->pos, "Dd after Os");
866 struct mdoc_node *np, *nch;
870 * Unlike other data pointers, these are "housed" by the HEAD
871 * element, which contains the goods.
874 if (MDOC_HEAD != mdoc->last->type) {
875 if (ENDBODY_NOT != mdoc->last->end) {
876 assert(mdoc->last->pending);
877 np = mdoc->last->pending->parent->head;
878 } else if (MDOC_BLOCK != mdoc->last->type) {
879 np = mdoc->last->parent->head;
881 np = mdoc->last->head;
884 assert(MDOC_HEAD == np->type);
885 assert(MDOC_Bf == np->tok);
890 assert(MDOC_BLOCK == np->parent->type);
891 assert(MDOC_Bf == np->parent->tok);
893 /* Check the number of arguments. */
896 if (NULL == np->parent->args) {
898 mandoc_msg(MANDOCERR_BF_NOFONT, mdoc->parse,
899 np->line, np->pos, "Bf");
905 mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
906 nch->line, nch->pos, "Bf ... %s", nch->string);
908 /* Extract argument into data. */
910 if (np->parent->args) {
911 arg = np->parent->args->argv[0].arg;
912 if (MDOC_Emphasis == arg)
913 np->norm->Bf.font = FONT_Em;
914 else if (MDOC_Literal == arg)
915 np->norm->Bf.font = FONT_Li;
916 else if (MDOC_Symbolic == arg)
917 np->norm->Bf.font = FONT_Sy;
923 /* Extract parameter into data. */
925 if (0 == strcmp(np->child->string, "Em"))
926 np->norm->Bf.font = FONT_Em;
927 else if (0 == strcmp(np->child->string, "Li"))
928 np->norm->Bf.font = FONT_Li;
929 else if (0 == strcmp(np->child->string, "Sy"))
930 np->norm->Bf.font = FONT_Sy;
932 mandoc_vmsg(MANDOCERR_BF_BADFONT, mdoc->parse,
933 np->child->line, np->child->pos,
934 "Bf %s", np->child->string);
941 const char *stdlibname;
944 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
945 n = mdoc->last->child;
946 assert(MDOC_TEXT == n->type);
948 if (NULL == (stdlibname = mdoc_a2lib(n->string)))
949 mandoc_asprintf(&libname,
950 "library \\(lq%s\\(rq", n->string);
952 libname = mandoc_strdup(stdlibname);
961 const struct mdoc_node *n;
965 mandoc_vmsg(MANDOCERR_ARG_SKIP,
966 mdoc->parse, n->line, n->pos,
967 "%s %s", mdoc_macronames[n->tok],
972 post_fname(POST_ARGS)
974 const struct mdoc_node *n;
978 n = mdoc->last->child;
979 pos = strcspn(n->string, "()");
980 cp = n->string + pos;
981 if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*')))
982 mandoc_msg(MANDOCERR_FN_PAREN, mdoc->parse,
983 n->line, n->pos + pos, n->string);
998 check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 1);
1000 if (mdoc->last->type == MDOC_HEAD && mdoc->last->nchild)
1007 const struct mdoc_node *n;
1010 for (n = mdoc->last->child; n != NULL; n = n->next) {
1011 for (cp = n->string; *cp != '\0'; cp++) {
1012 /* Ignore callbacks and alterations. */
1013 if (*cp == '(' || *cp == '{')
1017 mandoc_msg(MANDOCERR_FA_COMMA, mdoc->parse,
1018 n->line, n->pos + (cp - n->string),
1028 const struct mdoc_node *n;
1031 * The Vt macro comes in both ELEM and BLOCK form, both of which
1032 * have different syntaxes (yet more context-sensitive
1033 * behaviour). ELEM types must have a child, which is already
1034 * guaranteed by the in_line parsing routine; BLOCK types,
1035 * specifically the BODY, should only have TEXT children.
1038 if (MDOC_BODY != mdoc->last->type)
1041 for (n = mdoc->last->child; n; n = n->next)
1042 if (MDOC_TEXT != n->type)
1043 mandoc_msg(MANDOCERR_VT_CHILD, mdoc->parse,
1044 n->line, n->pos, mdoc_macronames[n->tok]);
1051 if (NULL != mdoc->meta.name)
1054 mdoc_deroff(&mdoc->meta.name, mdoc->last);
1056 if (NULL == mdoc->meta.name)
1057 mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse,
1058 mdoc->last->line, mdoc->last->pos, "Nm");
1065 check_count(mdoc, MDOC_BODY, CHECK_ERROR, CHECK_GT, 0);
1078 post_literal(POST_ARGS)
1081 if (mdoc->last->tok == MDOC_Bd)
1086 * The `Dl' (note "el" not "one") and `Bd' macros unset the
1087 * MDOC_LITERAL flag as they leave. Note that `Bd' only sets
1088 * this in literal mode, but it doesn't hurt to just switch it
1089 * off in general since displays can't be nested.
1092 if (MDOC_BODY == mdoc->last->type)
1093 mdoc->flags &= ~MDOC_LITERAL;
1097 post_defaults(POST_ARGS)
1099 struct mdoc_node *nn;
1102 * The `Ar' defaults to "file ..." if no value is provided as an
1103 * argument; the `Mt' and `Pa' macros use "~"; the `Li' just
1104 * gets an empty string.
1107 if (mdoc->last->child)
1111 mdoc->next = MDOC_NEXT_CHILD;
1115 mdoc_word_alloc(mdoc, nn->line, nn->pos, "file");
1116 mdoc_word_alloc(mdoc, nn->line, nn->pos, "...");
1121 mdoc_word_alloc(mdoc, nn->line, nn->pos, "~");
1133 struct mdoc_node *n;
1134 const char *std_att;
1138 if (n->child == NULL) {
1139 mdoc->next = MDOC_NEXT_CHILD;
1140 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);
1167 struct mdoc_node *np;
1170 if (AUTH__NONE == np->norm->An.auth) {
1172 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0);
1173 } else if (np->child)
1174 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0);
1181 if (MDOC_BLOCK == mdoc->last->type)
1182 mdoc->last->norm->Es = mdoc->last_es;
1189 mdoc->last_es = mdoc->last;
1197 struct mdoc_node *nbl, *nit, *nch;
1200 if (MDOC_BLOCK != nit->type)
1203 nbl = nit->parent->parent;
1204 lt = nbl->norm->Bl.type;
1216 if (NULL == nit->head->child)
1217 mandoc_vmsg(MANDOCERR_IT_NOHEAD,
1218 mdoc->parse, nit->line, nit->pos,
1220 mdoc_argnames[nbl->args->argv[0].arg]);
1229 if (NULL == nit->body->child)
1230 mandoc_vmsg(MANDOCERR_IT_NOBODY,
1231 mdoc->parse, nit->line, nit->pos,
1233 mdoc_argnames[nbl->args->argv[0].arg]);
1236 if (NULL != nit->head->child)
1237 mandoc_vmsg(MANDOCERR_ARG_SKIP,
1238 mdoc->parse, nit->line, nit->pos,
1239 "It %s", nit->head->child->string);
1242 cols = (int)nbl->norm->Bl.ncols;
1244 assert(NULL == nit->head->child);
1246 for (i = 0, nch = nit->child; nch; nch = nch->next)
1247 if (MDOC_BODY == nch->type)
1250 if (i < cols || i > cols + 1)
1251 mandoc_vmsg(MANDOCERR_ARGCOUNT,
1252 mdoc->parse, nit->line, nit->pos,
1253 "columns == %d (have %d)", cols, i);
1261 post_bl_block(POST_ARGS)
1263 struct mdoc_node *n, *ni, *nc;
1266 * These are fairly complicated, so we've broken them into two
1267 * functions. post_bl_block_tag() is called when a -tag is
1268 * specified, but no -width (it must be guessed). The second
1269 * when a -width is specified (macro indicators must be
1270 * rewritten into real lengths).
1275 if (LIST_tag == n->norm->Bl.type &&
1276 NULL == n->norm->Bl.width) {
1277 post_bl_block_tag(mdoc);
1278 assert(n->norm->Bl.width);
1281 for (ni = n->body->child; ni; ni = ni->next) {
1282 if (NULL == ni->body)
1284 nc = ni->body->last;
1285 while (NULL != nc) {
1297 if (NULL == ni->next) {
1298 mandoc_msg(MANDOCERR_PAR_MOVE,
1299 mdoc->parse, nc->line, nc->pos,
1300 mdoc_macronames[nc->tok]);
1301 mdoc_node_relink(mdoc, nc);
1302 } else if (0 == n->norm->Bl.comp &&
1303 LIST_column != n->norm->Bl.type) {
1304 mandoc_vmsg(MANDOCERR_PAR_SKIP,
1305 mdoc->parse, nc->line, nc->pos,
1307 mdoc_macronames[nc->tok]);
1308 mdoc_node_delete(mdoc, nc);
1311 nc = ni->body->last;
1317 * If the argument of -offset or -width is a macro,
1318 * replace it with the associated default width.
1321 rewrite_macro2len(char **arg)
1328 else if ( ! strcmp(*arg, "Ds"))
1330 else if ((tok = mdoc_hash_find(*arg)) == MDOC_MAX)
1333 width = macro2len(tok);
1336 mandoc_asprintf(arg, "%zun", width);
1340 post_bl_block_tag(POST_ARGS)
1342 struct mdoc_node *n, *nn;
1348 * Calculate the -width for a `Bl -tag' list if it hasn't been
1349 * provided. Uses the first head macro. NOTE AGAIN: this is
1350 * ONLY if the -width argument has NOT been provided. See
1351 * rewrite_macro2len() for converting the -width string.
1357 for (nn = n->body->child; nn; nn = nn->next) {
1358 if (MDOC_It != nn->tok)
1361 assert(MDOC_BLOCK == nn->type);
1362 nn = nn->head->child;
1367 if (MDOC_TEXT == nn->type) {
1368 sz = strlen(nn->string) + 1;
1372 if (0 != (ssz = macro2len(nn->tok)))
1378 /* Defaults to ten ens. */
1380 (void)snprintf(buf, sizeof(buf), "%un", (unsigned int)sz);
1383 * We have to dynamically add this to the macro's argument list.
1384 * We're guaranteed that a MDOC_Width doesn't already exist.
1388 i = (int)(n->args->argc)++;
1390 n->args->argv = mandoc_reallocarray(n->args->argv,
1391 n->args->argc, sizeof(struct mdoc_argv));
1393 n->args->argv[i].arg = MDOC_Width;
1394 n->args->argv[i].line = n->line;
1395 n->args->argv[i].pos = n->pos;
1396 n->args->argv[i].sz = 1;
1397 n->args->argv[i].value = mandoc_malloc(sizeof(char *));
1398 n->args->argv[i].value[0] = mandoc_strdup(buf);
1400 /* Set our width! */
1401 n->norm->Bl.width = n->args->argv[i].value[0];
1405 post_bl_head(POST_ARGS)
1407 struct mdoc_node *np, *nn, *nnp;
1408 struct mdoc_argv *argv;
1411 if (LIST_column != mdoc->last->norm->Bl.type) {
1412 /* FIXME: this should be ERROR class... */
1418 * Append old-style lists, where the column width specifiers
1419 * trail as macro parameters, to the new-style ("normal-form")
1420 * lists where they're argument values following -column.
1423 if (mdoc->last->child == NULL)
1426 np = mdoc->last->parent;
1429 for (j = 0; j < (int)np->args->argc; j++)
1430 if (MDOC_Column == np->args->argv[j].arg)
1433 assert(j < (int)np->args->argc);
1436 * Accommodate for new-style groff column syntax. Shuffle the
1437 * child nodes, all of which must be TEXT, as arguments for the
1438 * column field. Then, delete the head children.
1441 argv = np->args->argv + j;
1443 argv->sz += mdoc->last->nchild;
1444 argv->value = mandoc_reallocarray(argv->value,
1445 argv->sz, sizeof(char *));
1447 mdoc->last->norm->Bl.ncols = argv->sz;
1448 mdoc->last->norm->Bl.cols = (void *)argv->value;
1450 for (nn = mdoc->last->child; nn; i++) {
1451 argv->value[i] = nn->string;
1455 mdoc_node_delete(NULL, nnp);
1458 mdoc->last->nchild = 0;
1459 mdoc->last->child = NULL;
1465 struct mdoc_node *nparent, *nprev; /* of the Bl block */
1466 struct mdoc_node *nblock, *nbody; /* of the Bl */
1467 struct mdoc_node *nchild, *nnext; /* of the Bl body */
1470 switch (nbody->type) {
1472 post_bl_block(mdoc);
1485 nchild = nbody->child;
1486 while (NULL != nchild) {
1487 if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
1488 nchild = nchild->next;
1492 mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse,
1493 nchild->line, nchild->pos,
1494 mdoc_macronames[nchild->tok]);
1497 * Move the node out of the Bl block.
1498 * First, collect all required node pointers.
1501 nblock = nbody->parent;
1502 nprev = nblock->prev;
1503 nparent = nblock->parent;
1504 nnext = nchild->next;
1507 * Unlink this child.
1510 assert(NULL == nchild->prev);
1511 if (0 == --nbody->nchild) {
1512 nbody->child = NULL;
1514 assert(NULL == nnext);
1516 nbody->child = nnext;
1521 * Relink this child.
1524 nchild->parent = nparent;
1525 nchild->prev = nprev;
1526 nchild->next = nblock;
1528 nblock->prev = nchild;
1531 nparent->child = nchild;
1533 nprev->next = nchild;
1548 post_sm(struct mdoc *mdoc)
1550 struct mdoc_node *nch;
1552 nch = mdoc->last->child;
1555 mdoc->flags ^= MDOC_SMOFF;
1559 assert(nch->type == MDOC_TEXT);
1561 if ( ! strcmp(nch->string, "on")) {
1562 mdoc->flags &= ~MDOC_SMOFF;
1565 if ( ! strcmp(nch->string, "off")) {
1566 mdoc->flags |= MDOC_SMOFF;
1570 mandoc_vmsg(MANDOCERR_SM_BAD,
1571 mdoc->parse, nch->line, nch->pos,
1572 "%s %s", mdoc_macronames[mdoc->last->tok], nch->string);
1573 mdoc_node_relink(mdoc, nch);
1578 post_root(POST_ARGS)
1580 struct mdoc_node *n;
1582 /* Add missing prologue data. */
1584 if (mdoc->meta.date == NULL)
1585 mdoc->meta.date = mdoc->quick ?
1587 mandoc_normdate(mdoc->parse, NULL, 0, 0);
1589 if (mdoc->meta.title == NULL) {
1590 mandoc_msg(MANDOCERR_DT_NOTITLE,
1591 mdoc->parse, 0, 0, "EOF");
1592 mdoc->meta.title = mandoc_strdup("UNTITLED");
1595 if (mdoc->meta.vol == NULL)
1596 mdoc->meta.vol = mandoc_strdup("LOCAL");
1598 if (mdoc->meta.os == NULL) {
1599 mandoc_msg(MANDOCERR_OS_MISSING,
1600 mdoc->parse, 0, 0, NULL);
1601 mdoc->meta.os = mandoc_strdup("");
1604 /* Check that we begin with a proper `Sh'. */
1606 n = mdoc->first->child;
1607 while (n != NULL && mdoc_macros[n->tok].flags & MDOC_PROLOGUE)
1611 mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);
1612 else if (n->tok != MDOC_Sh)
1613 mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse,
1614 n->line, n->pos, mdoc_macronames[n->tok]);
1620 struct mdoc_node *n, *nch;
1627 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
1628 n->line, n->pos, mdoc_macronames[n->tok]);
1629 mdoc_node_delete(mdoc, n);
1633 assert(MDOC_TEXT == nch->type);
1635 if (NULL == (p = mdoc_a2st(nch->string))) {
1636 mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse,
1637 nch->line, nch->pos, "St %s", nch->string);
1638 mdoc_node_delete(mdoc, n);
1641 nch->string = mandoc_strdup(p);
1648 struct mdoc_node *nn, *next, *prev;
1651 switch (mdoc->last->type) {
1653 check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0);
1656 if (mdoc->last->child)
1658 check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0);
1665 * The full `Rs' block needs special handling to order the
1666 * sub-elements according to `rsord'. Pick through each element
1667 * and correctly order it. This is an insertion sort.
1671 for (nn = mdoc->last->child->next; nn; nn = next) {
1672 /* Determine order of `nn'. */
1673 for (i = 0; i < RSORD_MAX; i++)
1674 if (rsord[i] == nn->tok)
1677 if (i == RSORD_MAX) {
1678 mandoc_msg(MANDOCERR_RS_BAD,
1679 mdoc->parse, nn->line, nn->pos,
1680 mdoc_macronames[nn->tok]);
1682 } else if (MDOC__J == nn->tok || MDOC__B == nn->tok)
1683 mdoc->last->norm->Rs.quote_T++;
1686 * Remove `nn' from the chain. This somewhat
1687 * repeats mdoc_node_unlink(), but since we're
1688 * just re-ordering, there's no need for the
1689 * full unlink process.
1692 if (NULL != (next = nn->next))
1693 next->prev = nn->prev;
1695 if (NULL != (prev = nn->prev))
1696 prev->next = nn->next;
1698 nn->prev = nn->next = NULL;
1701 * Scan back until we reach a node that's
1702 * ordered before `nn'.
1705 for ( ; prev ; prev = prev->prev) {
1706 /* Determine order of `prev'. */
1707 for (j = 0; j < RSORD_MAX; j++)
1708 if (rsord[j] == prev->tok)
1718 * Set `nn' back into its correct place in front
1719 * of the `prev' node.
1726 prev->next->prev = nn;
1727 nn->next = prev->next;
1730 mdoc->last->child->prev = nn;
1731 nn->next = mdoc->last->child;
1732 mdoc->last->child = nn;
1738 * For some arguments of some macros,
1739 * convert all breakable hyphens into ASCII_HYPH.
1742 post_hyph(POST_ARGS)
1744 struct mdoc_node *n, *nch;
1750 if (MDOC_Sh == n->tok || MDOC_Ss == n->tok)
1754 if (MDOC_D1 == n->tok || MDOC_Nd == n->tok)
1763 for (nch = n->child; nch; nch = nch->next) {
1764 if (MDOC_TEXT != nch->type)
1769 while ('\0' != *(++cp))
1771 isalpha((unsigned char)cp[-1]) &&
1772 isalpha((unsigned char)cp[1]))
1778 post_hyphtext(POST_ARGS)
1789 if (MDOC_LINE & mdoc->last->flags)
1790 mandoc_msg(MANDOCERR_NS_SKIP, mdoc->parse,
1791 mdoc->last->line, mdoc->last->pos, NULL);
1800 switch (mdoc->last->type) {
1805 switch (mdoc->lastsec) {
1810 post_sh_see_also(mdoc);
1813 post_sh_authors(mdoc);
1825 post_sh_name(POST_ARGS)
1827 struct mdoc_node *n;
1830 * Warn if the NAME section doesn't contain the `Nm' and `Nd'
1831 * macros (can have multiple `Nm' and one `Nd'). Note that the
1832 * children of the BODY declaration can also be "text".
1835 if (NULL == (n = mdoc->last->child)) {
1836 mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
1837 mdoc->last->line, mdoc->last->pos, "empty");
1841 for ( ; n && n->next; n = n->next) {
1842 if (MDOC_ELEM == n->type && MDOC_Nm == n->tok)
1844 if (MDOC_TEXT == n->type)
1846 mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
1847 n->line, n->pos, mdoc_macronames[n->tok]);
1851 if (MDOC_BLOCK == n->type && MDOC_Nd == n->tok)
1854 mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
1855 n->line, n->pos, mdoc_macronames[n->tok]);
1859 post_sh_see_also(POST_ARGS)
1861 const struct mdoc_node *n;
1862 const char *name, *sec;
1863 const char *lastname, *lastsec, *lastpunct;
1866 n = mdoc->last->child;
1867 lastname = lastsec = lastpunct = NULL;
1869 if (n->tok != MDOC_Xr || n->nchild < 2)
1872 /* Process one .Xr node. */
1874 name = n->child->string;
1875 sec = n->child->next->string;
1876 if (lastsec != NULL) {
1877 if (lastpunct[0] != ',' || lastpunct[1] != '\0')
1878 mandoc_vmsg(MANDOCERR_XR_PUNCT,
1879 mdoc->parse, n->line, n->pos,
1880 "%s before %s(%s)", lastpunct,
1882 cmp = strcmp(lastsec, sec);
1884 mandoc_vmsg(MANDOCERR_XR_ORDER,
1885 mdoc->parse, n->line, n->pos,
1886 "%s(%s) after %s(%s)", name,
1887 sec, lastname, lastsec);
1888 else if (cmp == 0 &&
1889 strcasecmp(lastname, name) > 0)
1890 mandoc_vmsg(MANDOCERR_XR_ORDER,
1891 mdoc->parse, n->line, n->pos,
1892 "%s after %s", name, lastname);
1897 /* Process the following node. */
1902 if (n->tok == MDOC_Xr) {
1906 if (n->type != MDOC_TEXT)
1908 for (name = n->string; *name != '\0'; name++)
1909 if (isalpha((const unsigned char)*name))
1911 lastpunct = n->string;
1912 if (n->next == NULL)
1913 mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse,
1914 n->line, n->pos, "%s after %s(%s)",
1915 lastpunct, lastname, lastsec);
1921 child_an(const struct mdoc_node *n)
1924 for (n = n->child; n != NULL; n = n->next)
1925 if ((n->tok == MDOC_An && n->nchild) || child_an(n))
1931 post_sh_authors(POST_ARGS)
1934 if ( ! child_an(mdoc->last))
1935 mandoc_msg(MANDOCERR_AN_MISSING, mdoc->parse,
1936 mdoc->last->line, mdoc->last->pos, NULL);
1940 post_sh_head(POST_ARGS)
1942 struct mdoc_node *n;
1943 const char *goodsec;
1948 * Process a new section. Sections are either "named" or
1949 * "custom". Custom sections are user-defined, while named ones
1950 * follow a conventional order and may only appear in certain
1956 mdoc_deroff(&secname, mdoc->last);
1957 sec = NULL == secname ? SEC_CUSTOM : a2sec(secname);
1959 /* The NAME should be first. */
1961 if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
1962 mandoc_vmsg(MANDOCERR_NAMESEC_FIRST, mdoc->parse,
1963 mdoc->last->line, mdoc->last->pos,
1966 /* The SYNOPSIS gets special attention in other areas. */
1968 if (SEC_SYNOPSIS == sec) {
1969 roff_setreg(mdoc->roff, "nS", 1, '=');
1970 mdoc->flags |= MDOC_SYNOPSIS;
1972 roff_setreg(mdoc->roff, "nS", 0, '=');
1973 mdoc->flags &= ~MDOC_SYNOPSIS;
1976 /* Mark our last section. */
1978 mdoc->lastsec = sec;
1981 * Set the section attribute for the current HEAD, for its
1982 * parent BLOCK, and for the HEAD children; the latter can
1983 * only be TEXT nodes, so no recursion is needed.
1984 * For other blocks and elements, including .Sh BODY, this is
1985 * done when allocating the node data structures, but for .Sh
1986 * BLOCK and HEAD, the section is still unknown at that time.
1989 mdoc->last->parent->sec = sec;
1990 mdoc->last->sec = sec;
1991 for (n = mdoc->last->child; n; n = n->next)
1994 /* We don't care about custom sections after this. */
1996 if (SEC_CUSTOM == sec) {
2002 * Check whether our non-custom section is being repeated or is
2006 if (sec == mdoc->lastnamed)
2007 mandoc_vmsg(MANDOCERR_SEC_REP, mdoc->parse,
2008 mdoc->last->line, mdoc->last->pos,
2011 if (sec < mdoc->lastnamed)
2012 mandoc_vmsg(MANDOCERR_SEC_ORDER, mdoc->parse,
2013 mdoc->last->line, mdoc->last->pos,
2016 /* Mark the last named section. */
2018 mdoc->lastnamed = sec;
2020 /* Check particular section/manual conventions. */
2022 if (mdoc->meta.msec == NULL) {
2030 if (*mdoc->meta.msec == '4')
2032 goodsec = "2, 3, 4, 9";
2034 case SEC_RETURN_VALUES:
2037 if (*mdoc->meta.msec == '2')
2039 if (*mdoc->meta.msec == '3')
2041 if (NULL == goodsec)
2042 goodsec = "2, 3, 9";
2045 if (*mdoc->meta.msec == '9')
2047 if (NULL == goodsec)
2049 mandoc_vmsg(MANDOCERR_SEC_MSEC, mdoc->parse,
2050 mdoc->last->line, mdoc->last->pos,
2051 "Sh %s for %s only", secname, goodsec);
2060 post_ignpar(POST_ARGS)
2062 struct mdoc_node *np;
2064 check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_GT, 0);
2067 if (MDOC_BODY != mdoc->last->type)
2070 if (NULL != (np = mdoc->last->child))
2071 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
2072 mandoc_vmsg(MANDOCERR_PAR_SKIP,
2073 mdoc->parse, np->line, np->pos,
2074 "%s after %s", mdoc_macronames[np->tok],
2075 mdoc_macronames[mdoc->last->tok]);
2076 mdoc_node_delete(mdoc, np);
2079 if (NULL != (np = mdoc->last->last))
2080 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) {
2081 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2082 np->line, np->pos, "%s at the end of %s",
2083 mdoc_macronames[np->tok],
2084 mdoc_macronames[mdoc->last->tok]);
2085 mdoc_node_delete(mdoc, np);
2093 if (NULL == mdoc->last)
2095 if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type)
2099 * Don't allow prior `Lp' or `Pp' prior to a paragraph-type
2100 * block: `Lp', `Pp', or non-compact `Bd' or `Bl'.
2103 if (MDOC_Pp != mdoc->last->tok &&
2104 MDOC_Lp != mdoc->last->tok &&
2105 MDOC_br != mdoc->last->tok)
2107 if (MDOC_Bl == n->tok && n->norm->Bl.comp)
2109 if (MDOC_Bd == n->tok && n->norm->Bd.comp)
2111 if (MDOC_It == n->tok && n->parent->norm->Bl.comp)
2114 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2115 mdoc->last->line, mdoc->last->pos,
2116 "%s before %s", mdoc_macronames[mdoc->last->tok],
2117 mdoc_macronames[n->tok]);
2118 mdoc_node_delete(mdoc, mdoc->last);
2124 struct mdoc_node *np;
2126 if (mdoc->last->tok == MDOC_sp)
2127 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2);
2129 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0);
2131 if (MDOC_ELEM != mdoc->last->type &&
2132 MDOC_BLOCK != mdoc->last->type)
2135 if (NULL == (np = mdoc->last->prev)) {
2136 np = mdoc->last->parent;
2137 if (MDOC_Sh != np->tok && MDOC_Ss != np->tok)
2139 } else if (MDOC_Pp != np->tok && MDOC_Lp != np->tok &&
2140 (MDOC_br != mdoc->last->tok ||
2141 (MDOC_sp != np->tok && MDOC_br != np->tok)))
2144 mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
2145 mdoc->last->line, mdoc->last->pos,
2146 "%s after %s", mdoc_macronames[mdoc->last->tok],
2147 mdoc_macronames[np->tok]);
2148 mdoc_node_delete(mdoc, mdoc->last);
2152 pre_literal(PRE_ARGS)
2155 pre_display(mdoc, n);
2157 if (MDOC_BODY != n->type)
2161 * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd
2162 * -unfilled' macros set MDOC_LITERAL on entrance to the body.
2167 mdoc->flags |= MDOC_LITERAL;
2170 if (DISP_literal == n->norm->Bd.type)
2171 mdoc->flags |= MDOC_LITERAL;
2172 if (DISP_unfilled == n->norm->Bd.type)
2173 mdoc->flags |= MDOC_LITERAL;
2184 struct mdoc_node *n;
2187 if (mdoc->meta.date)
2188 free(mdoc->meta.date);
2191 if (NULL == n->child || '\0' == n->child->string[0]) {
2192 mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
2193 mandoc_normdate(mdoc->parse, NULL, n->line, n->pos);
2198 mdoc_deroff(&datestr, n);
2200 mdoc->meta.date = datestr;
2202 mdoc->meta.date = mandoc_normdate(mdoc->parse,
2203 datestr, n->line, n->pos);
2207 mdoc_node_delete(mdoc, n);
2213 struct mdoc_node *nn, *n;
2219 free(mdoc->meta.title);
2220 free(mdoc->meta.msec);
2221 free(mdoc->meta.vol);
2222 free(mdoc->meta.arch);
2224 mdoc->meta.title = NULL;
2225 mdoc->meta.msec = NULL;
2226 mdoc->meta.vol = NULL;
2227 mdoc->meta.arch = NULL;
2229 /* First check that all characters are uppercase. */
2231 if (NULL != (nn = n->child))
2232 for (p = nn->string; *p; p++) {
2233 if (toupper((unsigned char)*p) == *p)
2235 mandoc_vmsg(MANDOCERR_TITLE_CASE,
2236 mdoc->parse, nn->line,
2237 nn->pos + (p - nn->string),
2238 "Dt %s", nn->string);
2242 /* No argument: msec and arch remain NULL. */
2244 if (NULL == (nn = n->child)) {
2245 mandoc_msg(MANDOCERR_DT_NOTITLE,
2246 mdoc->parse, n->line, n->pos, "Dt");
2247 mdoc->meta.title = mandoc_strdup("UNTITLED");
2248 mdoc->meta.vol = mandoc_strdup("LOCAL");
2252 /* One argument: msec and arch remain NULL. */
2254 mdoc->meta.title = mandoc_strdup(
2255 '\0' == nn->string[0] ? "UNTITLED" : nn->string);
2257 if (NULL == (nn = nn->next)) {
2258 mandoc_vmsg(MANDOCERR_MSEC_MISSING,
2259 mdoc->parse, n->line, n->pos,
2260 "Dt %s", mdoc->meta.title);
2261 mdoc->meta.vol = mandoc_strdup("LOCAL");
2265 /* Handles: `.Dt TITLE SEC'
2267 * volume = SEC is msec ? format(msec) : SEC,
2268 * msec = SEC is msec ? atoi(msec) : 0,
2272 cp = mandoc_a2msec(nn->string);
2274 mdoc->meta.vol = mandoc_strdup(cp);
2275 mdoc->meta.msec = mandoc_strdup(nn->string);
2277 mandoc_vmsg(MANDOCERR_MSEC_BAD, mdoc->parse,
2278 nn->line, nn->pos, "Dt ... %s", nn->string);
2279 mdoc->meta.vol = mandoc_strdup(nn->string);
2280 mdoc->meta.msec = mandoc_strdup(nn->string);
2283 /* Handle an optional architecture */
2285 if ((nn = nn->next) != NULL) {
2286 for (p = nn->string; *p; p++)
2287 *p = tolower((unsigned char)*p);
2288 mdoc->meta.arch = mandoc_strdup(nn->string);
2291 /* Ignore any subsequent parameters... */
2292 /* FIXME: warn about subsequent parameters. */
2294 mdoc_node_delete(mdoc, n);
2300 struct mdoc_node *n;
2303 * Make `Bx's second argument always start with an uppercase
2304 * letter. Groff checks if it's an "accepted" term, but we just
2305 * uppercase blindly.
2308 n = mdoc->last->child;
2309 if (n && NULL != (n = n->next))
2310 *n->string = (char)toupper((unsigned char)*n->string);
2317 struct utsname utsname;
2318 static char *defbuf;
2320 struct mdoc_node *n;
2325 * Set the operating system by way of the `Os' macro.
2326 * The order of precedence is:
2327 * 1. the argument of the `Os' macro, unless empty
2328 * 2. the -Ios=foo command line argument, if provided
2329 * 3. -DOSNAME="\"foo\"", if provided during compilation
2330 * 4. "sysname release" from uname(3)
2333 free(mdoc->meta.os);
2334 mdoc->meta.os = NULL;
2335 mdoc_deroff(&mdoc->meta.os, n);
2340 mdoc->meta.os = mandoc_strdup(mdoc->defos);
2345 mdoc->meta.os = mandoc_strdup(OSNAME);
2347 if (NULL == defbuf) {
2348 if (-1 == uname(&utsname)) {
2349 mandoc_msg(MANDOCERR_OS_UNAME, mdoc->parse,
2350 n->line, n->pos, "Os");
2351 defbuf = mandoc_strdup("UNKNOWN");
2353 mandoc_asprintf(&defbuf, "%s %s",
2354 utsname.sysname, utsname.release);
2356 mdoc->meta.os = mandoc_strdup(defbuf);
2360 mdoc_node_delete(mdoc, n);
2364 * If no argument is provided,
2365 * fill in the name of the current manual page.
2370 struct mdoc_node *n;
2377 if (mdoc->meta.name == NULL) {
2378 mandoc_msg(MANDOCERR_EX_NONAME, mdoc->parse,
2379 n->line, n->pos, "Ex");
2383 mdoc->next = MDOC_NEXT_CHILD;
2384 mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name);
2388 static enum mdoc_sec
2389 a2sec(const char *p)
2393 for (i = 0; i < (int)SEC__MAX; i++)
2394 if (secnames[i] && 0 == strcmp(p, secnames[i]))
2395 return((enum mdoc_sec)i);
2401 macro2len(enum mdoct macro)