]>
git.cameronkatri.com Git - mandoc.git/blob - validate.c
1 /* $Id: validate.c,v 1.49 2009/02/21 15:34:46 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: math symbols. */
38 /* FIXME: valid character-escape checks. */
39 /* FIXME: make sure required sections are included (NAME, ...). */
48 static int pre_check_parent(struct mdoc
*, struct mdoc_node
*,
50 static int pre_check_msecs(struct mdoc
*, struct mdoc_node
*,
51 int, enum mdoc_msec
*);
52 static int pre_check_stdarg(struct mdoc
*, struct mdoc_node
*);
53 static int post_check_children_count(struct mdoc
*);
54 static int post_check_children_lt(struct mdoc
*, const char *, int);
55 static int post_check_children_gt(struct mdoc
*, const char *, int);
56 static int post_check_children_wgt(struct mdoc
*, const char *, int);
57 static int post_check_children_eq(struct mdoc
*, const char *, int);
58 static int post_check_children_weq(struct mdoc
*, const char *, int);
60 /* Specific pre-child-parse routines. */
62 static int pre_display(struct mdoc
*, struct mdoc_node
*);
63 static int pre_sh(struct mdoc
*, struct mdoc_node
*);
64 static int pre_ss(struct mdoc
*, struct mdoc_node
*);
65 static int pre_bd(struct mdoc
*, struct mdoc_node
*);
66 static int pre_bl(struct mdoc
*, struct mdoc_node
*);
67 static int pre_it(struct mdoc
*, struct mdoc_node
*);
68 static int pre_cd(struct mdoc
*, struct mdoc_node
*);
69 static int pre_er(struct mdoc
*, struct mdoc_node
*);
70 static int pre_ex(struct mdoc
*, struct mdoc_node
*);
71 static int pre_rv(struct mdoc
*, struct mdoc_node
*);
72 static int pre_an(struct mdoc
*, struct mdoc_node
*);
73 static int pre_st(struct mdoc
*, struct mdoc_node
*);
74 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
75 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
76 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
78 /* Specific post-child-parse routines. */
80 static int herr_ge1(struct mdoc
*);
81 static int herr_le1(struct mdoc
*);
82 static int herr_eq0(struct mdoc
*);
83 static int eerr_eq0(struct mdoc
*);
84 static int eerr_le1(struct mdoc
*);
85 static int eerr_le2(struct mdoc
*);
86 static int eerr_eq1(struct mdoc
*);
87 static int eerr_ge1(struct mdoc
*);
88 static int ewarn_eq0(struct mdoc
*);
89 static int ewarn_eq1(struct mdoc
*);
90 static int bwarn_ge1(struct mdoc
*);
91 static int ewarn_ge1(struct mdoc
*);
92 static int ebool(struct mdoc
*);
93 static int post_sh(struct mdoc
*);
94 static int post_sh_body(struct mdoc
*);
95 static int post_sh_head(struct mdoc
*);
96 static int post_bl(struct mdoc
*);
97 static int post_it(struct mdoc
*);
98 static int post_ex(struct mdoc
*);
99 static int post_an(struct mdoc
*);
100 static int post_at(struct mdoc
*);
101 static int post_xr(struct mdoc
*);
102 static int post_nm(struct mdoc
*);
103 static int post_bf(struct mdoc
*);
104 static int post_root(struct mdoc
*);
106 /* Collections of pre-child-parse routines. */
108 static v_pre pres_prologue
[] = { pre_prologue
, NULL
};
109 static v_pre pres_d1
[] = { pre_display
, NULL
};
110 static v_pre pres_bd
[] = { pre_display
, pre_bd
, NULL
};
111 static v_pre pres_bl
[] = { pre_bl
, NULL
};
112 static v_pre pres_it
[] = { pre_it
, NULL
};
113 static v_pre pres_ss
[] = { pre_ss
, NULL
};
114 static v_pre pres_sh
[] = { pre_sh
, NULL
};
115 static v_pre pres_cd
[] = { pre_cd
, NULL
};
116 static v_pre pres_er
[] = { pre_er
, NULL
};
117 static v_pre pres_ex
[] = { pre_ex
, NULL
};
118 static v_pre pres_rv
[] = { pre_rv
, NULL
};
119 static v_pre pres_an
[] = { pre_an
, NULL
};
120 static v_pre pres_st
[] = { pre_st
, NULL
};
122 /* Collections of post-child-parse routines. */
124 static v_post posts_bool
[] = { eerr_eq1
, ebool
, NULL
};
125 static v_post posts_bd
[] = { herr_eq0
, bwarn_ge1
, NULL
};
126 static v_post posts_text
[] = { eerr_ge1
, NULL
};
127 static v_post posts_wtext
[] = { ewarn_ge1
, NULL
};
128 static v_post posts_notext
[] = { eerr_eq0
, NULL
};
129 static v_post posts_wline
[] = { bwarn_ge1
, herr_eq0
, NULL
};
130 static v_post posts_sh
[] = { herr_ge1
, bwarn_ge1
, post_sh
, NULL
};
131 static v_post posts_bl
[] = { herr_eq0
, bwarn_ge1
, post_bl
, NULL
};
132 static v_post posts_it
[] = { post_it
, NULL
};
133 static v_post posts_in
[] = { ewarn_eq1
, NULL
};
134 static v_post posts_ss
[] = { herr_ge1
, NULL
};
135 static v_post posts_pp
[] = { ewarn_eq0
, NULL
};
136 static v_post posts_ex
[] = { eerr_le1
, post_ex
, NULL
};
137 static v_post posts_an
[] = { post_an
, NULL
};
138 static v_post posts_at
[] = { post_at
, NULL
};
139 static v_post posts_xr
[] = { eerr_ge1
, eerr_le2
, post_xr
, NULL
};
140 static v_post posts_nm
[] = { post_nm
, NULL
};
141 static v_post posts_bf
[] = { herr_le1
, post_bf
, NULL
};
142 static v_post posts_rs
[] = { herr_eq0
, bwarn_ge1
, NULL
};
143 static v_post posts_fo
[] = { bwarn_ge1
, NULL
};
144 static v_post posts_bk
[] = { herr_eq0
, bwarn_ge1
, NULL
};
146 /* Per-macro pre- and post-child-check routine collections. */
148 const struct valids mdoc_valids
[MDOC_MAX
] = {
149 { NULL
, NULL
}, /* \" */
150 { pres_prologue
, posts_text
}, /* Dd */
151 { pres_prologue
, NULL
}, /* Dt */
152 { pres_prologue
, NULL
}, /* Os */
153 { pres_sh
, posts_sh
}, /* Sh */
154 { pres_ss
, posts_ss
}, /* Ss */
155 { NULL
, posts_pp
}, /* Pp */
156 { pres_d1
, posts_wline
}, /* D1 */
157 { pres_d1
, posts_wline
}, /* Dl */
158 { pres_bd
, posts_bd
}, /* Bd */
159 { NULL
, NULL
}, /* Ed */
160 { pres_bl
, posts_bl
}, /* Bl */
161 { NULL
, NULL
}, /* El */
162 { pres_it
, posts_it
}, /* It */
163 { NULL
, posts_text
}, /* Ad */
164 { pres_an
, posts_an
}, /* An */
165 { NULL
, NULL
}, /* Ar */
166 { pres_cd
, posts_text
}, /* Cd */
167 { NULL
, NULL
}, /* Cm */
168 { NULL
, posts_text
}, /* Dv */
169 { pres_er
, posts_text
}, /* Er */
170 { NULL
, posts_text
}, /* Ev */
171 { pres_ex
, posts_ex
}, /* Ex */
172 { NULL
, posts_text
}, /* Fa */
173 /* FIXME: only in SYNOPSIS section. */
174 { NULL
, posts_wtext
}, /* Fd */
175 { NULL
, NULL
}, /* Fl */
176 { NULL
, posts_text
}, /* Fn */
177 { NULL
, posts_wtext
}, /* Ft */
178 { NULL
, posts_text
}, /* Ic */
179 { NULL
, posts_in
}, /* In */
180 { NULL
, posts_text
}, /* Li */
181 { NULL
, posts_wtext
}, /* Nd */
182 { NULL
, posts_nm
}, /* Nm */
183 { NULL
, posts_wline
}, /* Op */
184 { NULL
, NULL
}, /* Ot */
185 { NULL
, NULL
}, /* Pa */
186 { pres_rv
, posts_notext
}, /* Rv */
187 { pres_st
, posts_notext
}, /* St */
188 { NULL
, posts_text
}, /* Va */
189 { NULL
, posts_text
}, /* Vt */
190 { NULL
, posts_xr
}, /* Xr */
191 { NULL
, posts_text
}, /* %A */
192 { NULL
, posts_text
}, /* %B */
193 { NULL
, posts_text
}, /* %D */
194 { NULL
, posts_text
}, /* %I */
195 { NULL
, posts_text
}, /* %J */
196 { NULL
, posts_text
}, /* %N */
197 { NULL
, posts_text
}, /* %O */
198 { NULL
, posts_text
}, /* %P */
199 { NULL
, posts_text
}, /* %R */
200 { NULL
, posts_text
}, /* %T */
201 { NULL
, posts_text
}, /* %V */
202 { NULL
, NULL
}, /* Ac */
203 { NULL
, NULL
}, /* Ao */
204 { NULL
, posts_wline
}, /* Aq */
205 { NULL
, posts_at
}, /* At */
206 { NULL
, NULL
}, /* Bc */
207 { NULL
, posts_bf
}, /* Bf */
208 { NULL
, NULL
}, /* Bo */
209 { NULL
, posts_wline
}, /* Bq */
210 { NULL
, NULL
}, /* Bsx */
211 { NULL
, NULL
}, /* Bx */
212 { NULL
, posts_bool
}, /* Db */
213 { NULL
, NULL
}, /* Dc */
214 { NULL
, NULL
}, /* Do */
215 { NULL
, posts_wline
}, /* Dq */
216 { NULL
, NULL
}, /* Ec */
217 { NULL
, NULL
}, /* Ef */ /* -symbolic, etc. */
218 { NULL
, posts_text
}, /* Em */
219 { NULL
, NULL
}, /* Eo */
220 { NULL
, NULL
}, /* Fx */
221 { NULL
, posts_text
}, /* Ms */
222 { NULL
, posts_notext
}, /* No */
223 { NULL
, posts_notext
}, /* Ns */
224 { NULL
, NULL
}, /* Nx */
225 { NULL
, NULL
}, /* Ox */
226 { NULL
, NULL
}, /* Pc */
227 { NULL
, NULL
}, /* Pf */
228 { NULL
, NULL
}, /* Po */
229 { NULL
, posts_wline
}, /* Pq */
230 { NULL
, NULL
}, /* Qc */
231 { NULL
, posts_wline
}, /* Ql */
232 { NULL
, NULL
}, /* Qo */
233 { NULL
, posts_wline
}, /* Qq */
234 { NULL
, NULL
}, /* Re */
235 { NULL
, posts_rs
}, /* Rs */
236 { NULL
, NULL
}, /* Sc */
237 { NULL
, NULL
}, /* So */
238 { NULL
, posts_wline
}, /* Sq */
239 { NULL
, posts_bool
}, /* Sm */
240 { NULL
, posts_text
}, /* Sx */
241 { NULL
, posts_text
}, /* Sy */
242 { NULL
, posts_text
}, /* Tn */
243 { NULL
, NULL
}, /* Ux */
244 { NULL
, NULL
}, /* Xc */
245 { NULL
, NULL
}, /* Xo */
246 { NULL
, posts_fo
}, /* Fo */
247 { NULL
, NULL
}, /* Fc */
248 { NULL
, NULL
}, /* Oo */
249 { NULL
, NULL
}, /* Oc */
250 { NULL
, posts_bk
}, /* Bk */
251 { NULL
, NULL
}, /* Ek */
252 { NULL
, posts_notext
}, /* Bt */
253 { NULL
, NULL
}, /* Hf */
254 { NULL
, NULL
}, /* Fr */
255 { NULL
, posts_notext
}, /* Ud */
260 post_check_children_count(struct mdoc
*mdoc
)
265 for (i
= 0, n
= mdoc
->last
->child
; n
; n
= n
->next
, i
++)
272 post_check_children_wgt(struct mdoc
*mdoc
, const char *p
, int sz
)
276 if ((i
= post_check_children_count(mdoc
)) > sz
)
278 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests more "
279 "than %d %s (has %d)", sz
, p
, i
));
284 post_check_children_gt(struct mdoc
*mdoc
, const char *p
, int sz
)
288 if ((i
= post_check_children_count(mdoc
)) > sz
)
290 return(mdoc_err(mdoc
, "macro requires more than %d "
291 "%s (has %d)", sz
, p
, i
));
296 post_check_children_weq(struct mdoc
*mdoc
, const char *p
, int sz
)
300 if ((i
= post_check_children_count(mdoc
)) == sz
)
302 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests %d "
303 "%s (has %d)", sz
, p
, i
));
308 post_check_children_eq(struct mdoc
*mdoc
, const char *p
, int sz
)
312 if ((i
= post_check_children_count(mdoc
)) == sz
)
314 return(mdoc_err(mdoc
, "macro requires %d %s "
315 "(have %d)", sz
, p
, i
));
320 post_check_children_lt(struct mdoc
*mdoc
, const char *p
, int sz
)
324 if ((i
= post_check_children_count(mdoc
)) < sz
)
326 return(mdoc_err(mdoc
, "macro requires less than %d "
327 "%s (have %d)", sz
, p
, i
));
332 pre_check_stdarg(struct mdoc
*mdoc
, struct mdoc_node
*node
)
335 if (1 == node
->data
.elem
.argc
&&
336 MDOC_Std
== node
->data
.elem
.argv
[0].arg
)
338 return(mdoc_nwarn(mdoc
, node
, WARN_COMPAT
,
339 "macro suggests single `%s' argument",
340 mdoc_argnames
[MDOC_Std
]));
345 pre_check_msecs(struct mdoc
*mdoc
, struct mdoc_node
*node
,
346 int sz
, enum mdoc_msec
*msecs
)
350 for (i
= 0; i
< sz
; i
++)
351 if (msecs
[i
] == mdoc
->meta
.msec
)
353 return(mdoc_nwarn(mdoc
, node
, WARN_COMPAT
, "macro not "
354 "appropriate for manual section"));
359 pre_check_parent(struct mdoc
*mdoc
, struct mdoc_node
*node
,
360 int tok
, enum mdoc_type type
)
363 if (type
!= node
->parent
->type
)
364 return(mdoc_nerr(mdoc
, node
, "invalid macro parent class %s, expected %s",
365 mdoc_type2a(node
->parent
->type
),
367 if (MDOC_ROOT
!= type
&& tok
!= node
->parent
->tok
)
368 return(mdoc_nerr(mdoc
, node
, "invalid macro parent `%s', expected `%s'",
369 mdoc_macronames
[node
->parent
->tok
],
370 mdoc_macronames
[tok
]));
376 bwarn_ge1(struct mdoc
*mdoc
)
379 if (MDOC_BODY
!= mdoc
->last
->type
)
381 return(post_check_children_wgt(mdoc
, "body children", 0));
386 ewarn_eq1(struct mdoc
*mdoc
)
389 assert(MDOC_ELEM
== mdoc
->last
->type
);
390 return(post_check_children_weq(mdoc
, "parameters", 1));
395 ewarn_eq0(struct mdoc
*mdoc
)
398 assert(MDOC_ELEM
== mdoc
->last
->type
);
399 return(post_check_children_weq(mdoc
, "parameters", 0));
404 ewarn_ge1(struct mdoc
*mdoc
)
407 assert(MDOC_ELEM
== mdoc
->last
->type
);
408 return(post_check_children_wgt(mdoc
, "parameters", 0));
413 eerr_eq1(struct mdoc
*mdoc
)
416 assert(MDOC_ELEM
== mdoc
->last
->type
);
417 return(post_check_children_eq(mdoc
, "parameters", 1));
422 eerr_le2(struct mdoc
*mdoc
)
425 assert(MDOC_ELEM
== mdoc
->last
->type
);
426 return(post_check_children_lt(mdoc
, "parameters", 3));
431 eerr_le1(struct mdoc
*mdoc
)
434 assert(MDOC_ELEM
== mdoc
->last
->type
);
435 return(post_check_children_lt(mdoc
, "parameters", 2));
440 eerr_eq0(struct mdoc
*mdoc
)
443 assert(MDOC_ELEM
== mdoc
->last
->type
);
444 return(post_check_children_eq(mdoc
, "parameters", 0));
449 eerr_ge1(struct mdoc
*mdoc
)
452 assert(MDOC_ELEM
== mdoc
->last
->type
);
453 return(post_check_children_gt(mdoc
, "parameters", 0));
458 herr_eq0(struct mdoc
*mdoc
)
461 if (MDOC_HEAD
!= mdoc
->last
->type
)
463 return(post_check_children_eq(mdoc
, "parameters", 0));
468 herr_le1(struct mdoc
*mdoc
)
470 if (MDOC_HEAD
!= mdoc
->last
->type
)
472 return(post_check_children_lt(mdoc
, "parameters", 2));
477 herr_ge1(struct mdoc
*mdoc
)
480 if (MDOC_HEAD
!= mdoc
->last
->type
)
482 return(post_check_children_gt(mdoc
, "parameters", 0));
487 pre_display(struct mdoc
*mdoc
, struct mdoc_node
*node
)
491 if (MDOC_BLOCK
!= node
->type
)
496 for (n
= mdoc
->last
->parent
; n
; n
= n
->parent
)
497 if (MDOC_BLOCK
== n
->type
)
498 if (MDOC_Bd
== n
->tok
)
502 return(mdoc_nerr(mdoc
, node
, "displays may not be nested"));
507 pre_bl(struct mdoc
*mdoc
, struct mdoc_node
*node
)
510 struct mdoc_arg
*argv
;
513 if (MDOC_BLOCK
!= node
->type
)
515 assert(MDOC_Bl
== node
->tok
);
518 argc
= node
->data
.block
.argc
;
521 for (i
= type
= err
= 0; i
< argc
; i
++) {
522 argv
= &node
->data
.block
.argv
[(int)i
];
555 return(mdoc_err(mdoc
, "no list type specified"));
559 return(mdoc_perr(mdoc
, argv
->line
,
560 argv
->pos
, "only one list type possible"));
565 pre_bd(struct mdoc
*mdoc
, struct mdoc_node
*node
)
568 struct mdoc_arg
*argv
;
571 if (MDOC_BLOCK
!= node
->type
)
573 assert(MDOC_Bd
== node
->tok
);
576 argc
= node
->data
.block
.argc
;
579 for (err
= i
= type
= 0; 0 == err
&& i
< argc
; i
++) {
580 argv
= &node
->data
.block
.argv
[(int)i
];
585 case (MDOC_Unfilled
):
601 return(mdoc_err(mdoc
, "no display type specified"));
605 return(mdoc_perr(mdoc
, argv
->line
,
606 argv
->pos
, "only one display type possible"));
611 pre_ss(struct mdoc
*mdoc
, struct mdoc_node
*node
)
614 if (MDOC_BLOCK
!= node
->type
)
616 return(pre_check_parent(mdoc
, node
, MDOC_Sh
, MDOC_BODY
));
621 pre_sh(struct mdoc
*mdoc
, struct mdoc_node
*node
)
624 if (MDOC_BLOCK
!= node
->type
)
626 return(pre_check_parent(mdoc
, node
, -1, MDOC_ROOT
));
631 pre_st(struct mdoc
*mdoc
, struct mdoc_node
*node
)
634 assert(MDOC_ELEM
== node
->type
);
635 assert(MDOC_St
== node
->tok
);
636 if (1 == node
->data
.elem
.argc
)
638 return(mdoc_nerr(mdoc
, node
, "macro must have one argument"));
643 pre_an(struct mdoc
*mdoc
, struct mdoc_node
*node
)
646 assert(MDOC_ELEM
== node
->type
);
647 assert(MDOC_An
== node
->tok
);
648 if (1 >= node
->data
.elem
.argc
)
650 return(mdoc_nerr(mdoc
, node
, "macro may only have one argument"));
655 pre_rv(struct mdoc
*mdoc
, struct mdoc_node
*node
)
657 enum mdoc_msec msecs
[2];
659 assert(MDOC_ELEM
== node
->type
);
660 assert(MDOC_Rv
== node
->tok
);
664 if ( ! pre_check_msecs(mdoc
, node
, 2, msecs
))
666 return(pre_check_stdarg(mdoc
, node
));
671 pre_ex(struct mdoc
*mdoc
, struct mdoc_node
*node
)
673 enum mdoc_msec msecs
[3];
675 assert(MDOC_ELEM
== node
->type
);
676 assert(MDOC_Ex
== node
->tok
);
681 if ( ! pre_check_msecs(mdoc
, node
, 3, msecs
))
683 return(pre_check_stdarg(mdoc
, node
));
688 pre_er(struct mdoc
*mdoc
, struct mdoc_node
*node
)
690 enum mdoc_msec msecs
[1];
693 return(pre_check_msecs(mdoc
, node
, 1, msecs
));
698 pre_cd(struct mdoc
*mdoc
, struct mdoc_node
*node
)
700 enum mdoc_msec msecs
[1];
703 return(pre_check_msecs(mdoc
, node
, 1, msecs
));
708 pre_it(struct mdoc
*mdoc
, struct mdoc_node
*node
)
711 /* TODO: -width attribute must be specified for -tag. */
712 /* TODO: children too big for -width? */
714 if (MDOC_BLOCK
!= node
->type
)
716 return(pre_check_parent(mdoc
, node
, MDOC_Bl
, MDOC_BODY
));
721 pre_prologue(struct mdoc
*mdoc
, struct mdoc_node
*node
)
724 if (SEC_PROLOGUE
!= mdoc
->lastnamed
)
725 return(mdoc_nerr(mdoc
, node
, "macro may only be invoked in the prologue"));
726 assert(MDOC_ELEM
== node
->type
);
728 /* Check for ordering. */
732 if (mdoc
->meta
.title
&& mdoc
->meta
.date
)
734 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
736 if (NULL
== mdoc
->meta
.title
&& mdoc
->meta
.date
)
738 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
740 if (NULL
== mdoc
->meta
.title
&& 0 == mdoc
->meta
.date
)
742 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
748 /* Check for repetition. */
752 if (NULL
== mdoc
->meta
.os
)
756 if (0 == mdoc
->meta
.date
)
760 if (NULL
== mdoc
->meta
.title
)
768 return(mdoc_nerr(mdoc
, node
, "prologue macro repeated"));
773 post_bf(struct mdoc
*mdoc
)
776 struct mdoc_node
*head
;
778 if (MDOC_BLOCK
!= mdoc
->last
->type
)
780 assert(MDOC_Bf
== mdoc
->last
->tok
);
781 head
= mdoc
->last
->data
.block
.head
;
784 if (0 == mdoc
->last
->data
.block
.argc
) {
786 assert(MDOC_TEXT
== head
->child
->type
);
787 p
= head
->child
->data
.text
.string
;
788 if (xstrcmp(p
, "Em"))
790 else if (xstrcmp(p
, "Li"))
792 else if (xstrcmp(p
, "Sm"))
794 return(mdoc_nerr(mdoc
, head
->child
, "invalid font mode"));
796 return(mdoc_err(mdoc
, "macro expects an argument or parameter"));
799 return(mdoc_err(mdoc
, "macro expects an argument or parameter"));
800 if (1 == mdoc
->last
->data
.block
.argc
)
802 return(mdoc_err(mdoc
, "macro expects an argument or parameter"));
807 post_nm(struct mdoc
*mdoc
)
810 assert(MDOC_ELEM
== mdoc
->last
->type
);
811 assert(MDOC_Nm
== mdoc
->last
->tok
);
812 if (mdoc
->last
->child
)
816 return(mdoc_err(mdoc
, "macro `%s' has not been invoked with a name",
817 mdoc_macronames
[MDOC_Nm
]));
822 post_xr(struct mdoc
*mdoc
)
826 assert(MDOC_ELEM
== mdoc
->last
->type
);
827 assert(MDOC_Xr
== mdoc
->last
->tok
);
828 assert(mdoc
->last
->child
);
829 assert(MDOC_TEXT
== mdoc
->last
->child
->type
);
831 if (NULL
== (n
= mdoc
->last
->child
->next
))
833 assert(MDOC_TEXT
== n
->type
);
834 if (MSEC_DEFAULT
!= mdoc_atomsec(n
->data
.text
.string
))
836 return(mdoc_nerr(mdoc
, n
, "invalid manual section"));
841 post_at(struct mdoc
*mdoc
)
844 assert(MDOC_ELEM
== mdoc
->last
->type
);
845 assert(MDOC_At
== mdoc
->last
->tok
);
847 if (NULL
== mdoc
->last
->child
)
849 assert(MDOC_TEXT
== mdoc
->last
->child
->type
);
851 if (ATT_DEFAULT
!= mdoc_atoatt(mdoc
->last
->child
->data
.text
.string
))
853 return(mdoc_err(mdoc
, "macro expects a valid AT&T version symbol"));
858 post_an(struct mdoc
*mdoc
)
861 assert(MDOC_ELEM
== mdoc
->last
->type
);
862 assert(MDOC_An
== mdoc
->last
->tok
);
864 if (0 != mdoc
->last
->data
.elem
.argc
) {
865 if (NULL
== mdoc
->last
->child
)
867 return(mdoc_err(mdoc
, "macro expects either argument or parameters"));
870 if (mdoc
->last
->child
)
872 return(mdoc_err(mdoc
, "macro expects either argument or parameters"));
877 post_ex(struct mdoc
*mdoc
)
880 assert(MDOC_ELEM
== mdoc
->last
->type
);
881 assert(MDOC_Ex
== mdoc
->last
->tok
);
883 if (0 == mdoc
->last
->data
.elem
.argc
) {
884 if (mdoc
->last
->child
)
886 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
887 mdoc_argnames
[MDOC_Std
]));
889 if (mdoc
->last
->child
)
890 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
891 mdoc_argnames
[MDOC_Std
]));
892 if (1 != mdoc
->last
->data
.elem
.argc
)
893 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
894 mdoc_argnames
[MDOC_Std
]));
895 if (MDOC_Std
!= mdoc
->last
->data
.elem
.argv
[0].arg
)
896 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
897 mdoc_argnames
[MDOC_Std
]));
902 /* Warn if `Bl' type-specific syntax isn't reflected in items. */
904 post_it(struct mdoc
*mdoc
)
907 #define TYPE_NONE (0)
908 #define TYPE_BODY (1)
909 #define TYPE_HEAD (2)
910 #define TYPE_OHEAD (3)
914 if (MDOC_BLOCK
!= mdoc
->last
->type
)
917 assert(MDOC_It
== mdoc
->last
->tok
);
919 n
= mdoc
->last
->parent
;
921 assert(MDOC_Bl
== n
->tok
);
924 assert(MDOC_BLOCK
== n
->type
);
925 assert(MDOC_Bl
== n
->tok
);
927 argc
= n
->data
.block
.argc
;
931 /* Some types require block-head, some not. */
934 for (i
= 0; TYPE_NONE
== type
&& i
< argc
; i
++)
935 switch (n
->data
.block
.argv
[(int)i
].arg
) {
946 sv
= n
->data
.block
.argv
[(int)i
].arg
;
958 sv
= n
->data
.block
.argv
[(int)i
].arg
;
962 sv
= n
->data
.block
.argv
[(int)i
].arg
;
968 assert(TYPE_NONE
!= type
);
970 n
= mdoc
->last
->data
.block
.head
;
973 if (TYPE_HEAD
== type
) {
974 if (NULL
== n
->child
)
975 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests line parameters"))
978 n
= mdoc
->last
->data
.block
.body
;
980 if (NULL
== n
->child
)
981 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests body children"))
984 } else if (TYPE_BODY
== type
) {
986 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests no line parameters"))
989 n
= mdoc
->last
->data
.block
.body
;
991 if (NULL
== n
->child
)
992 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests body children"))
995 if (NULL
== n
->child
)
996 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests line parameters"))
999 n
= mdoc
->last
->data
.block
.body
;
1002 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests no body children"))
1006 if (MDOC_Column
!= sv
)
1009 /* Make sure the number of columns is sane. */
1011 argc
= mdoc
->last
->parent
->parent
->data
.block
.argv
->sz
;
1012 n
= mdoc
->last
->data
.block
.head
->child
;
1014 for (i
= 0; n
; n
= n
->next
)
1019 return(mdoc_err(mdoc
, "expected %zu list columns, have %zu", argc
, i
));
1028 post_bl(struct mdoc
*mdoc
)
1030 struct mdoc_node
*n
;
1032 if (MDOC_BODY
!= mdoc
->last
->type
)
1034 assert(MDOC_Bl
== mdoc
->last
->tok
);
1037 for (n
= mdoc
->last
->child
; n
; n
= n
->next
) {
1038 if (MDOC_BLOCK
== n
->type
)
1039 if (MDOC_It
== n
->tok
)
1045 return(mdoc_nerr(mdoc
, n
, "invalid child of parent macro `Bl'"));
1050 ebool(struct mdoc
*mdoc
)
1052 struct mdoc_node
*n
;
1054 assert(MDOC_ELEM
== mdoc
->last
->type
);
1056 for (n
= mdoc
->last
->child
; n
; n
= n
->next
) {
1057 if (MDOC_TEXT
!= n
->type
)
1059 if (xstrcmp(n
->data
.text
.string
, "on"))
1061 if (xstrcmp(n
->data
.text
.string
, "off"))
1067 return(mdoc_nerr(mdoc
, n
, "expected boolean value"));
1072 post_root(struct mdoc
*mdoc
)
1075 if (NULL
== mdoc
->first
->child
)
1076 return(mdoc_err(mdoc
, "document has no data"));
1077 if (SEC_PROLOGUE
== mdoc
->lastnamed
)
1078 return(mdoc_err(mdoc
, "document has incomplete prologue"));
1079 if (MDOC_BLOCK
!= mdoc
->first
->child
->type
)
1080 return(mdoc_err(mdoc
, "document expects `%s' macro after prologue", mdoc_macronames
[MDOC_Sh
]));
1081 if (MDOC_Sh
!= mdoc
->first
->child
->tok
)
1082 return(mdoc_err(mdoc
, "document expects `%s' macro after prologue", mdoc_macronames
[MDOC_Sh
]));
1088 post_sh(struct mdoc
*mdoc
)
1091 if (MDOC_HEAD
== mdoc
->last
->type
)
1092 return(post_sh_head(mdoc
));
1093 if (MDOC_BODY
== mdoc
->last
->type
)
1094 return(post_sh_body(mdoc
));
1100 post_sh_body(struct mdoc
*mdoc
)
1102 struct mdoc_node
*n
;
1104 assert(MDOC_Sh
== mdoc
->last
->tok
);
1105 if (SEC_NAME
!= mdoc
->lastnamed
)
1108 if (NULL
== (n
= mdoc
->last
->child
))
1109 return(mdoc_err(mdoc
, "section NAME must contain %s as the first body child", mdoc_macronames
[MDOC_Nm
]));
1110 if (MDOC_ELEM
!= n
->type
|| MDOC_Nm
!= n
->tok
)
1111 return(mdoc_err(mdoc
, "section NAME must contain %s as the first body child", mdoc_macronames
[MDOC_Nm
]));
1112 if (NULL
== (n
= n
->next
))
1113 return(mdoc_err(mdoc
, "section NAME must contain %s as the second body child", mdoc_macronames
[MDOC_Nd
]));
1114 if (MDOC_ELEM
!= n
->type
|| MDOC_Nd
!= n
->tok
)
1115 return(mdoc_err(mdoc
, "section NAME must contain %s as the second body child", mdoc_macronames
[MDOC_Nd
]));
1116 if (NULL
== (n
= n
->next
))
1119 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "section NAME usually limited to %s and %s body children",
1120 mdoc_macronames
[MDOC_Nm
], mdoc_macronames
[MDOC_Nd
]));
1125 post_sh_head(struct mdoc
*mdoc
)
1130 assert(MDOC_Sh
== mdoc
->last
->tok
);
1132 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
1133 return(mdoc_err(mdoc
, "macro parameters too long"));
1135 sec
= mdoc_atosec(buf
);
1137 if (SEC_BODY
== mdoc
->lastnamed
&& SEC_NAME
!= sec
)
1138 return(mdoc_err(mdoc
, "section NAME must be first"));
1139 if (SEC_CUSTOM
== sec
)
1141 if (sec
== mdoc
->lastnamed
)
1142 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "section repeated"));
1143 if (sec
< mdoc
->lastnamed
)
1144 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "section out of conventional order"));
1151 mdoc_valid_pre(struct mdoc
*mdoc
, struct mdoc_node
*node
)
1155 if (MDOC_TEXT
== node
->type
)
1157 assert(MDOC_ROOT
!= node
->type
);
1159 if (NULL
== mdoc_valids
[node
->tok
].pre
)
1161 for (p
= mdoc_valids
[node
->tok
].pre
; *p
; p
++)
1162 if ( ! (*p
)(mdoc
, node
))
1169 mdoc_valid_post(struct mdoc
*mdoc
)
1173 if (MDOC_VALID
& mdoc
->last
->flags
)
1175 mdoc
->last
->flags
|= MDOC_VALID
;
1177 if (MDOC_TEXT
== mdoc
->last
->type
)
1179 if (MDOC_ROOT
== mdoc
->last
->type
)
1180 return(post_root(mdoc
));
1182 if (NULL
== mdoc_valids
[mdoc
->last
->tok
].post
)
1184 for (p
= mdoc_valids
[mdoc
->last
->tok
].post
; *p
; p
++)