]>
git.cameronkatri.com Git - mandoc.git/blob - validate.c
1 /* $Id: validate.c,v 1.52 2009/02/22 19:23:48 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
25 * Pre- and post-validate macros as they're parsed. Pre-validation
26 * occurs when the macro has been detected and its arguments parsed.
27 * Post-validation occurs when all child macros have also been parsed.
28 * In the ELEMENT case, this is simply the parameters of the macro; in
29 * the BLOCK case, this is the HEAD, BODY, TAIL and so on.
32 typedef int (*v_pre
)(struct mdoc
*, struct mdoc_node
*);
33 typedef int (*v_post
)(struct mdoc
*);
35 /* FIXME: some sections should only occur in specific msecs. */
36 /* FIXME: ignoring Pp. */
37 /* FIXME: .Ef arguments */
38 /* FIXME: math symbols. */
39 /* FIXME: valid character-escape checks. */
40 /* FIXME: .Fd only in synopsis section. */
49 static int check_parent(struct mdoc
*, struct mdoc_node
*,
51 static int check_msec(struct mdoc
*, struct mdoc_node
*,
52 int, enum mdoc_msec
*);
53 static int check_stdarg(struct mdoc
*, struct mdoc_node
*);
54 static int err_child_lt(struct mdoc
*, const char *, int);
55 static int err_child_gt(struct mdoc
*, const char *, int);
56 static int warn_child_gt(struct mdoc
*, const char *, int);
57 static int err_child_eq(struct mdoc
*, const char *, int);
58 static int warn_child_eq(struct mdoc
*, const char *, int);
60 /* Utility auxiliaries. */
62 static inline int count_child(struct mdoc
*);
63 static inline int warn_count(struct mdoc
*, const char *,
64 int, const char *, int);
65 static inline int err_count(struct mdoc
*, const char *,
66 int, const char *, int);
68 /* Specific pre-child-parse routines. */
70 static int pre_display(struct mdoc
*, struct mdoc_node
*);
71 static int pre_sh(struct mdoc
*, struct mdoc_node
*);
72 static int pre_ss(struct mdoc
*, struct mdoc_node
*);
73 static int pre_bd(struct mdoc
*, struct mdoc_node
*);
74 static int pre_bl(struct mdoc
*, struct mdoc_node
*);
75 static int pre_it(struct mdoc
*, struct mdoc_node
*);
76 static int pre_cd(struct mdoc
*, struct mdoc_node
*);
77 static int pre_er(struct mdoc
*, struct mdoc_node
*);
78 static int pre_ex(struct mdoc
*, struct mdoc_node
*);
79 static int pre_rv(struct mdoc
*, struct mdoc_node
*);
80 static int pre_an(struct mdoc
*, struct mdoc_node
*);
81 static int pre_st(struct mdoc
*, struct mdoc_node
*);
82 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
83 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
84 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
86 /* Specific post-child-parse routines. */
88 static int herr_ge1(struct mdoc
*);
89 static int herr_le1(struct mdoc
*);
90 static int herr_eq0(struct mdoc
*);
91 static int eerr_eq0(struct mdoc
*);
92 static int eerr_le1(struct mdoc
*);
93 static int eerr_le2(struct mdoc
*);
94 static int eerr_eq1(struct mdoc
*);
95 static int eerr_ge1(struct mdoc
*);
96 static int ewarn_eq0(struct mdoc
*);
97 static int ewarn_eq1(struct mdoc
*);
98 static int bwarn_ge1(struct mdoc
*);
99 static int ewarn_ge1(struct mdoc
*);
100 static int ebool(struct mdoc
*);
101 static int post_sh(struct mdoc
*);
102 static int post_sh_body(struct mdoc
*);
103 static int post_sh_head(struct mdoc
*);
104 static int post_bl(struct mdoc
*);
105 static int post_it(struct mdoc
*);
106 static int post_ex(struct mdoc
*);
107 static int post_an(struct mdoc
*);
108 static int post_at(struct mdoc
*);
109 static int post_xr(struct mdoc
*);
110 static int post_nm(struct mdoc
*);
111 static int post_bf(struct mdoc
*);
112 static int post_root(struct mdoc
*);
114 /* Collections of pre-child-parse routines. */
116 static v_pre pres_prologue
[] = { pre_prologue
, NULL
};
117 static v_pre pres_d1
[] = { pre_display
, NULL
};
118 static v_pre pres_bd
[] = { pre_display
, pre_bd
, NULL
};
119 static v_pre pres_bl
[] = { pre_bl
, NULL
};
120 static v_pre pres_it
[] = { pre_it
, NULL
};
121 static v_pre pres_ss
[] = { pre_ss
, NULL
};
122 static v_pre pres_sh
[] = { pre_sh
, NULL
};
123 static v_pre pres_cd
[] = { pre_cd
, NULL
};
124 static v_pre pres_er
[] = { pre_er
, NULL
};
125 static v_pre pres_ex
[] = { pre_ex
, NULL
};
126 static v_pre pres_rv
[] = { pre_rv
, NULL
};
127 static v_pre pres_an
[] = { pre_an
, NULL
};
128 static v_pre pres_st
[] = { pre_st
, NULL
};
130 /* Collections of post-child-parse routines. */
132 static v_post posts_bool
[] = { eerr_eq1
, ebool
, NULL
};
133 static v_post posts_bd
[] = { herr_eq0
, bwarn_ge1
, NULL
};
134 static v_post posts_text
[] = { eerr_ge1
, NULL
};
135 static v_post posts_wtext
[] = { ewarn_ge1
, NULL
};
136 static v_post posts_notext
[] = { eerr_eq0
, NULL
};
137 static v_post posts_wline
[] = { bwarn_ge1
, herr_eq0
, NULL
};
138 static v_post posts_sh
[] = { herr_ge1
, bwarn_ge1
, post_sh
, NULL
};
139 static v_post posts_bl
[] = { herr_eq0
, bwarn_ge1
, post_bl
, NULL
};
140 static v_post posts_it
[] = { post_it
, NULL
};
141 static v_post posts_in
[] = { ewarn_eq1
, NULL
};
142 static v_post posts_ss
[] = { herr_ge1
, NULL
};
143 static v_post posts_pf
[] = { eerr_eq1
, NULL
};
144 static v_post posts_pp
[] = { ewarn_eq0
, NULL
};
145 static v_post posts_ex
[] = { eerr_le1
, post_ex
, NULL
};
146 static v_post posts_an
[] = { post_an
, NULL
};
147 static v_post posts_at
[] = { post_at
, NULL
};
148 static v_post posts_xr
[] = { eerr_ge1
, eerr_le2
, post_xr
, NULL
};
149 static v_post posts_nm
[] = { post_nm
, NULL
};
150 static v_post posts_bf
[] = { herr_le1
, post_bf
, NULL
};
151 static v_post posts_rs
[] = { herr_eq0
, bwarn_ge1
, NULL
};
152 static v_post posts_fo
[] = { bwarn_ge1
, NULL
};
153 static v_post posts_bk
[] = { herr_eq0
, bwarn_ge1
, NULL
};
155 /* Per-macro pre- and post-child-check routine collections. */
157 const struct valids mdoc_valids
[MDOC_MAX
] = {
158 { NULL
, NULL
}, /* \" */
159 { pres_prologue
, posts_text
}, /* Dd */
160 { pres_prologue
, NULL
}, /* Dt */
161 { pres_prologue
, NULL
}, /* Os */
162 { pres_sh
, posts_sh
}, /* Sh */
163 { pres_ss
, posts_ss
}, /* Ss */
164 { NULL
, posts_pp
}, /* Pp */
165 { pres_d1
, posts_wline
}, /* D1 */
166 { pres_d1
, posts_wline
}, /* Dl */
167 { pres_bd
, posts_bd
}, /* Bd */
168 { NULL
, NULL
}, /* Ed */
169 { pres_bl
, posts_bl
}, /* Bl */
170 { NULL
, NULL
}, /* El */
171 { pres_it
, posts_it
}, /* It */
172 { NULL
, posts_text
}, /* Ad */
173 { pres_an
, posts_an
}, /* An */
174 { NULL
, NULL
}, /* Ar */
175 { pres_cd
, posts_text
}, /* Cd */
176 { NULL
, NULL
}, /* Cm */
177 { NULL
, posts_text
}, /* Dv */
178 { pres_er
, posts_text
}, /* Er */
179 { NULL
, posts_text
}, /* Ev */
180 { pres_ex
, posts_ex
}, /* Ex */
181 { NULL
, posts_text
}, /* Fa */
182 { NULL
, posts_wtext
}, /* Fd */
183 { NULL
, NULL
}, /* Fl */
184 { NULL
, posts_text
}, /* Fn */
185 { NULL
, posts_wtext
}, /* Ft */
186 { NULL
, posts_text
}, /* Ic */
187 { NULL
, posts_in
}, /* In */
188 { NULL
, posts_text
}, /* Li */
189 { NULL
, posts_wtext
}, /* Nd */
190 { NULL
, posts_nm
}, /* Nm */
191 { NULL
, posts_wline
}, /* Op */
192 { NULL
, NULL
}, /* Ot */
193 { NULL
, NULL
}, /* Pa */
194 { pres_rv
, posts_notext
}, /* Rv */
195 { pres_st
, posts_notext
}, /* St */
196 { NULL
, posts_text
}, /* Va */
197 { NULL
, posts_text
}, /* Vt */
198 { NULL
, posts_xr
}, /* Xr */
199 { NULL
, posts_text
}, /* %A */
200 { NULL
, posts_text
}, /* %B */
201 { NULL
, posts_text
}, /* %D */
202 { NULL
, posts_text
}, /* %I */
203 { NULL
, posts_text
}, /* %J */
204 { NULL
, posts_text
}, /* %N */
205 { NULL
, posts_text
}, /* %O */
206 { NULL
, posts_text
}, /* %P */
207 { NULL
, posts_text
}, /* %R */
208 { NULL
, posts_text
}, /* %T */
209 { NULL
, posts_text
}, /* %V */
210 { NULL
, NULL
}, /* Ac */
211 { NULL
, NULL
}, /* Ao */
212 { NULL
, posts_wline
}, /* Aq */
213 { NULL
, posts_at
}, /* At */
214 { NULL
, NULL
}, /* Bc */
215 { NULL
, posts_bf
}, /* Bf */
216 { NULL
, NULL
}, /* Bo */
217 { NULL
, posts_wline
}, /* Bq */
218 { NULL
, NULL
}, /* Bsx */
219 { NULL
, NULL
}, /* Bx */
220 { NULL
, posts_bool
}, /* Db */
221 { NULL
, NULL
}, /* Dc */
222 { NULL
, NULL
}, /* Do */
223 { NULL
, posts_wline
}, /* Dq */
224 { NULL
, NULL
}, /* Ec */
225 { NULL
, NULL
}, /* Ef */
226 { NULL
, posts_text
}, /* Em */
227 { NULL
, NULL
}, /* Eo */
228 { NULL
, NULL
}, /* Fx */
229 { NULL
, posts_text
}, /* Ms */
230 { NULL
, posts_notext
}, /* No */
231 { NULL
, posts_notext
}, /* Ns */
232 { NULL
, NULL
}, /* Nx */
233 { NULL
, NULL
}, /* Ox */
234 { NULL
, NULL
}, /* Pc */
235 { NULL
, posts_pf
}, /* Pf */
236 { NULL
, NULL
}, /* Po */
237 { NULL
, posts_wline
}, /* Pq */
238 { NULL
, NULL
}, /* Qc */
239 { NULL
, posts_wline
}, /* Ql */
240 { NULL
, NULL
}, /* Qo */
241 { NULL
, posts_wline
}, /* Qq */
242 { NULL
, NULL
}, /* Re */
243 { NULL
, posts_rs
}, /* Rs */
244 { NULL
, NULL
}, /* Sc */
245 { NULL
, NULL
}, /* So */
246 { NULL
, posts_wline
}, /* Sq */
247 { NULL
, posts_bool
}, /* Sm */
248 { NULL
, posts_text
}, /* Sx */
249 { NULL
, posts_text
}, /* Sy */
250 { NULL
, posts_text
}, /* Tn */
251 { NULL
, NULL
}, /* Ux */
252 { NULL
, NULL
}, /* Xc */
253 { NULL
, NULL
}, /* Xo */
254 { NULL
, posts_fo
}, /* Fo */
255 { NULL
, NULL
}, /* Fc */
256 { NULL
, NULL
}, /* Oo */
257 { NULL
, NULL
}, /* Oc */
258 { NULL
, posts_bk
}, /* Bk */
259 { NULL
, NULL
}, /* Ek */
260 { NULL
, posts_notext
}, /* Bt */
261 { NULL
, NULL
}, /* Hf */
262 { NULL
, NULL
}, /* Fr */
263 { NULL
, posts_notext
}, /* Ud */
268 warn_count(struct mdoc
*m
, const char *k
,
269 int want
, const char *v
, int has
)
272 return(mdoc_warn(m
, WARN_SYNTAX
, "suggests %s %d %s "
273 "(has %d)", v
, want
, k
, has
));
278 err_count(struct mdoc
*m
, const char *k
,
279 int want
, const char *v
, int has
)
282 return(mdoc_err(m
, "requires %s %d %s (has %d)",
288 count_child(struct mdoc
*mdoc
)
293 for (i
= 0, n
= mdoc
->last
->child
; n
; n
= n
->next
, i
++)
300 warn_child_gt(struct mdoc
*mdoc
, const char *p
, int sz
)
304 if ((i
= count_child(mdoc
)) > sz
)
306 return(warn_count(mdoc
, ">", sz
, p
, i
));
311 err_child_gt(struct mdoc
*mdoc
, const char *p
, int sz
)
315 if ((i
= count_child(mdoc
)) > sz
)
317 return(err_count(mdoc
, ">", sz
, p
, i
));
322 warn_child_eq(struct mdoc
*mdoc
, const char *p
, int sz
)
326 if ((i
= count_child(mdoc
)) == sz
)
328 return(warn_count(mdoc
, "==", sz
, p
, i
));
333 err_child_eq(struct mdoc
*mdoc
, const char *p
, int sz
)
337 if ((i
= count_child(mdoc
)) == sz
)
339 return(err_count(mdoc
, "==", sz
, p
, i
));
344 err_child_lt(struct mdoc
*mdoc
, const char *p
, int sz
)
348 if ((i
= count_child(mdoc
)) < sz
)
350 return(err_count(mdoc
, "<", sz
, p
, i
));
355 check_stdarg(struct mdoc
*mdoc
, struct mdoc_node
*node
)
358 if (MDOC_Std
== node
->data
.elem
.argv
[0].arg
&&
359 1 == node
->data
.elem
.argc
)
362 return(mdoc_nwarn(mdoc
, node
, WARN_COMPAT
,
363 "macro suggests single `%s' argument",
364 mdoc_argnames
[MDOC_Std
]));
369 check_msec(struct mdoc
*mdoc
, struct mdoc_node
*node
,
370 int sz
, enum mdoc_msec
*msecs
)
374 for (i
= 0; i
< sz
; i
++)
375 if (msecs
[i
] == mdoc
->meta
.msec
)
377 return(mdoc_nwarn(mdoc
, node
, WARN_COMPAT
, "macro not "
378 "appropriate for manual section"));
383 check_parent(struct mdoc
*mdoc
, struct mdoc_node
*n
,
384 int tok
, enum mdoc_type t
)
388 if ((MDOC_ROOT
== t
|| tok
== n
->parent
->tok
) &&
389 (t
== n
->parent
->type
))
392 return(mdoc_nerr(mdoc
, n
, "require parent %s (have %s)",
393 MDOC_ROOT
== t
? "<root>" :
394 mdoc_macronames
[tok
],
395 MDOC_ROOT
== n
->parent
->type
? "<root>" :
396 mdoc_macronames
[n
->parent
->type
]));
401 bwarn_ge1(struct mdoc
*mdoc
)
404 if (MDOC_BODY
!= mdoc
->last
->type
)
406 return(warn_child_gt(mdoc
, "multi-line parameters", 0));
411 ewarn_eq1(struct mdoc
*mdoc
)
414 assert(MDOC_ELEM
== mdoc
->last
->type
);
415 return(warn_child_eq(mdoc
, "line parameters", 1));
420 ewarn_eq0(struct mdoc
*mdoc
)
423 assert(MDOC_ELEM
== mdoc
->last
->type
);
424 return(warn_child_eq(mdoc
, "line parameters", 0));
429 ewarn_ge1(struct mdoc
*mdoc
)
432 assert(MDOC_ELEM
== mdoc
->last
->type
);
433 return(warn_child_gt(mdoc
, "line parameters", 0));
438 eerr_eq1(struct mdoc
*mdoc
)
441 assert(MDOC_ELEM
== mdoc
->last
->type
);
442 return(err_child_eq(mdoc
, "line parameters", 1));
447 eerr_le2(struct mdoc
*mdoc
)
450 assert(MDOC_ELEM
== mdoc
->last
->type
);
451 return(err_child_lt(mdoc
, "line parameters", 3));
456 eerr_le1(struct mdoc
*mdoc
)
459 assert(MDOC_ELEM
== mdoc
->last
->type
);
460 return(err_child_lt(mdoc
, "line parameters", 2));
465 eerr_eq0(struct mdoc
*mdoc
)
468 assert(MDOC_ELEM
== mdoc
->last
->type
);
469 return(err_child_eq(mdoc
, "line parameters", 0));
474 eerr_ge1(struct mdoc
*mdoc
)
477 assert(MDOC_ELEM
== mdoc
->last
->type
);
478 return(err_child_gt(mdoc
, "line parameters", 0));
483 herr_eq0(struct mdoc
*mdoc
)
486 if (MDOC_HEAD
!= mdoc
->last
->type
)
488 return(err_child_eq(mdoc
, "line parameters", 0));
493 herr_le1(struct mdoc
*mdoc
)
495 if (MDOC_HEAD
!= mdoc
->last
->type
)
497 return(err_child_lt(mdoc
, "line parameters", 2));
502 herr_ge1(struct mdoc
*mdoc
)
505 if (MDOC_HEAD
!= mdoc
->last
->type
)
507 return(err_child_gt(mdoc
, "line parameters", 0));
512 pre_display(struct mdoc
*mdoc
, struct mdoc_node
*node
)
516 if (MDOC_BLOCK
!= node
->type
)
521 for (n
= mdoc
->last
->parent
; n
; n
= n
->parent
)
522 if (MDOC_BLOCK
== n
->type
)
523 if (MDOC_Bd
== n
->tok
)
527 return(mdoc_nerr(mdoc
, node
, "displays may not be nested"));
532 pre_bl(struct mdoc
*mdoc
, struct mdoc_node
*node
)
535 struct mdoc_arg
*argv
;
538 if (MDOC_BLOCK
!= node
->type
)
540 assert(MDOC_Bl
== node
->tok
);
543 argc
= node
->data
.block
.argc
;
546 for (i
= type
= err
= 0; i
< argc
; i
++) {
547 argv
= &node
->data
.block
.argv
[(int)i
];
580 return(mdoc_err(mdoc
, "no list type specified"));
584 return(mdoc_perr(mdoc
, argv
->line
,
585 argv
->pos
, "only one list type possible"));
590 pre_bd(struct mdoc
*mdoc
, struct mdoc_node
*node
)
593 struct mdoc_arg
*argv
;
596 if (MDOC_BLOCK
!= node
->type
)
598 assert(MDOC_Bd
== node
->tok
);
601 argc
= node
->data
.block
.argc
;
604 for (err
= i
= type
= 0; 0 == err
&& i
< argc
; i
++) {
605 argv
= &node
->data
.block
.argv
[(int)i
];
610 case (MDOC_Unfilled
):
626 return(mdoc_err(mdoc
, "no display type specified"));
630 return(mdoc_perr(mdoc
, argv
->line
,
631 argv
->pos
, "only one display type possible"));
636 pre_ss(struct mdoc
*mdoc
, struct mdoc_node
*node
)
639 if (MDOC_BLOCK
!= node
->type
)
641 return(check_parent(mdoc
, node
, MDOC_Sh
, MDOC_BODY
));
646 pre_sh(struct mdoc
*mdoc
, struct mdoc_node
*node
)
649 if (MDOC_BLOCK
!= node
->type
)
651 return(check_parent(mdoc
, node
, -1, MDOC_ROOT
));
656 pre_st(struct mdoc
*mdoc
, struct mdoc_node
*node
)
659 assert(MDOC_ELEM
== node
->type
);
660 assert(MDOC_St
== node
->tok
);
661 if (1 == node
->data
.elem
.argc
)
663 return(mdoc_nerr(mdoc
, node
, "macro must have one argument"));
668 pre_an(struct mdoc
*mdoc
, struct mdoc_node
*node
)
671 assert(MDOC_ELEM
== node
->type
);
672 assert(MDOC_An
== node
->tok
);
673 if (1 >= node
->data
.elem
.argc
)
675 return(mdoc_nerr(mdoc
, node
, "macro may only have one argument"));
680 pre_rv(struct mdoc
*mdoc
, struct mdoc_node
*node
)
682 enum mdoc_msec msecs
[2];
684 assert(MDOC_ELEM
== node
->type
);
685 assert(MDOC_Rv
== node
->tok
);
689 if ( ! check_msec(mdoc
, node
, 2, msecs
))
691 return(check_stdarg(mdoc
, node
));
696 pre_ex(struct mdoc
*mdoc
, struct mdoc_node
*node
)
698 enum mdoc_msec msecs
[3];
700 assert(MDOC_ELEM
== node
->type
);
701 assert(MDOC_Ex
== node
->tok
);
706 if ( ! check_msec(mdoc
, node
, 3, msecs
))
708 return(check_stdarg(mdoc
, node
));
713 pre_er(struct mdoc
*mdoc
, struct mdoc_node
*node
)
715 enum mdoc_msec msecs
[1];
718 return(check_msec(mdoc
, node
, 1, msecs
));
723 pre_cd(struct mdoc
*mdoc
, struct mdoc_node
*node
)
725 enum mdoc_msec msecs
[1];
728 return(check_msec(mdoc
, node
, 1, msecs
));
733 pre_it(struct mdoc
*mdoc
, struct mdoc_node
*node
)
736 /* TODO: -width attribute must be specified for -tag. */
737 /* TODO: children too big for -width? */
739 if (MDOC_BLOCK
!= node
->type
)
741 return(check_parent(mdoc
, node
, MDOC_Bl
, MDOC_BODY
));
746 pre_prologue(struct mdoc
*mdoc
, struct mdoc_node
*node
)
749 if (SEC_PROLOGUE
!= mdoc
->lastnamed
)
750 return(mdoc_nerr(mdoc
, node
, "macro may only be invoked in the prologue"));
751 assert(MDOC_ELEM
== node
->type
);
753 /* Check for ordering. */
757 if (mdoc
->meta
.title
&& mdoc
->meta
.date
)
759 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
761 if (NULL
== mdoc
->meta
.title
&& mdoc
->meta
.date
)
763 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
765 if (NULL
== mdoc
->meta
.title
&& 0 == mdoc
->meta
.date
)
767 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
773 /* Check for repetition. */
777 if (NULL
== mdoc
->meta
.os
)
781 if (0 == mdoc
->meta
.date
)
785 if (NULL
== mdoc
->meta
.title
)
793 return(mdoc_nerr(mdoc
, node
, "prologue macro repeated"));
798 post_bf(struct mdoc
*mdoc
)
801 struct mdoc_node
*head
;
803 if (MDOC_BLOCK
!= mdoc
->last
->type
)
805 assert(MDOC_Bf
== mdoc
->last
->tok
);
806 head
= mdoc
->last
->data
.block
.head
;
809 if (0 == mdoc
->last
->data
.block
.argc
) {
811 assert(MDOC_TEXT
== head
->child
->type
);
812 p
= head
->child
->data
.text
.string
;
813 if (xstrcmp(p
, "Em"))
815 else if (xstrcmp(p
, "Li"))
817 else if (xstrcmp(p
, "Sm"))
819 return(mdoc_nerr(mdoc
, head
->child
, "invalid font mode"));
821 return(mdoc_err(mdoc
, "macro expects an argument or parameter"));
824 return(mdoc_err(mdoc
, "macro expects an argument or parameter"));
825 if (1 == mdoc
->last
->data
.block
.argc
)
827 return(mdoc_err(mdoc
, "macro expects an argument or parameter"));
832 post_nm(struct mdoc
*mdoc
)
835 assert(MDOC_ELEM
== mdoc
->last
->type
);
836 assert(MDOC_Nm
== mdoc
->last
->tok
);
837 if (mdoc
->last
->child
)
841 return(mdoc_err(mdoc
, "macro `%s' has not been invoked with a name",
842 mdoc_macronames
[MDOC_Nm
]));
847 post_xr(struct mdoc
*mdoc
)
851 assert(MDOC_ELEM
== mdoc
->last
->type
);
852 assert(MDOC_Xr
== mdoc
->last
->tok
);
853 assert(mdoc
->last
->child
);
854 assert(MDOC_TEXT
== mdoc
->last
->child
->type
);
856 if (NULL
== (n
= mdoc
->last
->child
->next
))
858 assert(MDOC_TEXT
== n
->type
);
859 if (MSEC_DEFAULT
!= mdoc_atomsec(n
->data
.text
.string
))
861 return(mdoc_nerr(mdoc
, n
, "invalid manual section"));
866 post_at(struct mdoc
*mdoc
)
869 assert(MDOC_ELEM
== mdoc
->last
->type
);
870 assert(MDOC_At
== mdoc
->last
->tok
);
872 if (NULL
== mdoc
->last
->child
)
874 assert(MDOC_TEXT
== mdoc
->last
->child
->type
);
876 if (ATT_DEFAULT
!= mdoc_atoatt(mdoc
->last
->child
->data
.text
.string
))
878 return(mdoc_err(mdoc
, "macro expects a valid AT&T version symbol"));
883 post_an(struct mdoc
*mdoc
)
886 assert(MDOC_ELEM
== mdoc
->last
->type
);
887 assert(MDOC_An
== mdoc
->last
->tok
);
889 if (0 != mdoc
->last
->data
.elem
.argc
) {
890 if (NULL
== mdoc
->last
->child
)
892 return(mdoc_err(mdoc
, "macro expects either argument or parameters"));
895 if (mdoc
->last
->child
)
897 return(mdoc_err(mdoc
, "macro expects either argument or parameters"));
902 post_ex(struct mdoc
*mdoc
)
905 assert(MDOC_ELEM
== mdoc
->last
->type
);
906 assert(MDOC_Ex
== mdoc
->last
->tok
);
908 if (0 == mdoc
->last
->data
.elem
.argc
) {
909 if (mdoc
->last
->child
)
911 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
912 mdoc_argnames
[MDOC_Std
]));
914 if (mdoc
->last
->child
)
915 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
916 mdoc_argnames
[MDOC_Std
]));
917 if (1 != mdoc
->last
->data
.elem
.argc
)
918 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
919 mdoc_argnames
[MDOC_Std
]));
920 if (MDOC_Std
!= mdoc
->last
->data
.elem
.argv
[0].arg
)
921 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
922 mdoc_argnames
[MDOC_Std
]));
927 /* Warn if `Bl' type-specific syntax isn't reflected in items. */
929 post_it(struct mdoc
*mdoc
)
932 #define TYPE_NONE (0)
933 #define TYPE_BODY (1)
934 #define TYPE_HEAD (2)
935 #define TYPE_OHEAD (3)
939 if (MDOC_BLOCK
!= mdoc
->last
->type
)
942 assert(MDOC_It
== mdoc
->last
->tok
);
944 n
= mdoc
->last
->parent
;
946 assert(MDOC_Bl
== n
->tok
);
949 assert(MDOC_BLOCK
== n
->type
);
950 assert(MDOC_Bl
== n
->tok
);
952 argc
= n
->data
.block
.argc
;
956 /* Some types require block-head, some not. */
959 for (i
= 0; TYPE_NONE
== type
&& i
< argc
; i
++)
960 switch (n
->data
.block
.argv
[(int)i
].arg
) {
971 sv
= n
->data
.block
.argv
[(int)i
].arg
;
983 sv
= n
->data
.block
.argv
[(int)i
].arg
;
987 sv
= n
->data
.block
.argv
[(int)i
].arg
;
993 assert(TYPE_NONE
!= type
);
995 n
= mdoc
->last
->data
.block
.head
;
998 if (TYPE_HEAD
== type
) {
999 if (NULL
== n
->child
)
1000 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests line parameters"))
1003 n
= mdoc
->last
->data
.block
.body
;
1005 if (NULL
== n
->child
)
1006 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests body children"))
1009 } else if (TYPE_BODY
== type
) {
1011 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests no line parameters"))
1014 n
= mdoc
->last
->data
.block
.body
;
1016 if (NULL
== n
->child
)
1017 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests body children"))
1020 if (NULL
== n
->child
)
1021 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests line parameters"))
1024 n
= mdoc
->last
->data
.block
.body
;
1027 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests no body children"))
1031 if (MDOC_Column
!= sv
)
1034 /* Make sure the number of columns is sane. */
1036 argc
= mdoc
->last
->parent
->parent
->data
.block
.argv
->sz
;
1037 n
= mdoc
->last
->data
.block
.head
->child
;
1039 for (i
= 0; n
; n
= n
->next
)
1044 return(mdoc_err(mdoc
, "expected %zu list columns, have %zu", argc
, i
));
1053 post_bl(struct mdoc
*mdoc
)
1055 struct mdoc_node
*n
;
1057 if (MDOC_BODY
!= mdoc
->last
->type
)
1059 assert(MDOC_Bl
== mdoc
->last
->tok
);
1062 for (n
= mdoc
->last
->child
; n
; n
= n
->next
) {
1063 if (MDOC_BLOCK
== n
->type
)
1064 if (MDOC_It
== n
->tok
)
1070 return(mdoc_nerr(mdoc
, n
, "invalid child of parent macro `Bl'"));
1075 ebool(struct mdoc
*mdoc
)
1077 struct mdoc_node
*n
;
1079 assert(MDOC_ELEM
== mdoc
->last
->type
);
1081 for (n
= mdoc
->last
->child
; n
; n
= n
->next
) {
1082 if (MDOC_TEXT
!= n
->type
)
1084 if (xstrcmp(n
->data
.text
.string
, "on"))
1086 if (xstrcmp(n
->data
.text
.string
, "off"))
1092 return(mdoc_nerr(mdoc
, n
, "expected boolean value"));
1097 post_root(struct mdoc
*mdoc
)
1100 if (NULL
== mdoc
->first
->child
)
1101 return(mdoc_err(mdoc
, "document has no data"));
1102 if (SEC_PROLOGUE
== mdoc
->lastnamed
)
1103 return(mdoc_err(mdoc
, "document has incomplete prologue"));
1104 if (MDOC_BLOCK
!= mdoc
->first
->child
->type
)
1105 return(mdoc_err(mdoc
, "document expects `%s' macro after prologue", mdoc_macronames
[MDOC_Sh
]));
1106 if (MDOC_Sh
!= mdoc
->first
->child
->tok
)
1107 return(mdoc_err(mdoc
, "document expects `%s' macro after prologue", mdoc_macronames
[MDOC_Sh
]));
1113 post_sh(struct mdoc
*mdoc
)
1116 if (MDOC_HEAD
== mdoc
->last
->type
)
1117 return(post_sh_head(mdoc
));
1118 if (MDOC_BODY
== mdoc
->last
->type
)
1119 return(post_sh_body(mdoc
));
1125 post_sh_body(struct mdoc
*mdoc
)
1127 struct mdoc_node
*n
;
1129 assert(MDOC_Sh
== mdoc
->last
->tok
);
1130 assert(MDOC_BODY
== mdoc
->last
->type
);
1131 if (SEC_NAME
!= mdoc
->lastnamed
)
1135 * Warn if the NAME section doesn't contain the `Nm' and `Nd'
1136 * macros (can have multiple `Nm' and one `Nd'). Note that the
1137 * children of the BODY declaration can also be "text".
1140 if (NULL
== (n
= mdoc
->last
->child
))
1141 return(mdoc_warn(mdoc
, WARN_COMPAT
, "section NAME "
1142 "should contain %s and %s",
1143 mdoc_macronames
[MDOC_Nm
],
1144 mdoc_macronames
[MDOC_Nd
]));
1146 for ( ; n
&& n
->next
; n
= n
->next
) {
1147 if (MDOC_ELEM
== n
->type
&& MDOC_Nm
== n
->tok
)
1149 if (MDOC_TEXT
== n
->type
)
1151 if ( ! (mdoc_nwarn(mdoc
, n
, WARN_COMPAT
, "section "
1152 "NAME should contain %s as "
1153 "initial body child",
1154 mdoc_macronames
[MDOC_Nm
])))
1158 if (MDOC_ELEM
== n
->type
&& MDOC_Nd
== n
->tok
)
1161 return(mdoc_warn(mdoc
, WARN_COMPAT
, "section NAME should "
1162 "contain %s as the last child",
1163 mdoc_macronames
[MDOC_Nd
]));
1168 post_sh_head(struct mdoc
*mdoc
)
1173 assert(MDOC_Sh
== mdoc
->last
->tok
);
1175 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
1176 return(mdoc_err(mdoc
, "macro parameters too long"));
1178 sec
= mdoc_atosec(buf
);
1180 if (SEC_BODY
== mdoc
->lastnamed
&& SEC_NAME
!= sec
)
1181 return(mdoc_err(mdoc
, "section NAME must be first"));
1182 if (SEC_CUSTOM
== sec
)
1184 if (sec
== mdoc
->lastnamed
)
1185 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "section repeated"));
1186 if (sec
< mdoc
->lastnamed
)
1187 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "section out of conventional order"));
1194 mdoc_valid_pre(struct mdoc
*mdoc
, struct mdoc_node
*node
)
1198 if (MDOC_TEXT
== node
->type
)
1200 assert(MDOC_ROOT
!= node
->type
);
1202 if (NULL
== mdoc_valids
[node
->tok
].pre
)
1204 for (p
= mdoc_valids
[node
->tok
].pre
; *p
; p
++)
1205 if ( ! (*p
)(mdoc
, node
))
1212 mdoc_valid_post(struct mdoc
*mdoc
)
1216 if (MDOC_VALID
& mdoc
->last
->flags
)
1218 mdoc
->last
->flags
|= MDOC_VALID
;
1220 if (MDOC_TEXT
== mdoc
->last
->type
)
1222 if (MDOC_ROOT
== mdoc
->last
->type
)
1223 return(post_root(mdoc
));
1225 if (NULL
== mdoc_valids
[mdoc
->last
->tok
].post
)
1227 for (p
= mdoc_valids
[mdoc
->last
->tok
].post
; *p
; p
++)