]>
git.cameronkatri.com Git - mandoc.git/blob - validate.c
1 /* $Id: validate.c,v 1.38 2009/01/17 20:10:36 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.
24 typedef int (*v_pre
)(struct mdoc
*, struct mdoc_node
*);
25 typedef int (*v_post
)(struct mdoc
*);
27 /* FIXME: some sections should only occur in specific msecs. */
28 /* FIXME: ignoring Pp. */
29 /* FIXME: math symbols. */
30 /* FIXME: make sure prologue is complete. */
31 /* FIXME: valid character-escape checks. */
40 static int pre_check_parent(struct mdoc
*, struct mdoc_node
*,
42 static int pre_check_msecs(struct mdoc
*, struct mdoc_node
*,
43 int, enum mdoc_msec
*);
44 static int pre_check_stdarg(struct mdoc
*, struct mdoc_node
*);
45 static int post_check_children_count(struct mdoc
*);
46 static int post_check_children_lt(struct mdoc
*, int);
47 static int post_check_children_gt(struct mdoc
*, int);
48 static int post_check_children_eq(struct mdoc
*, int);
50 /* Specific pre-child-parse routines. */
52 static int pre_display(struct mdoc
*, struct mdoc_node
*);
53 static int pre_sh(struct mdoc
*, struct mdoc_node
*);
54 static int pre_ss(struct mdoc
*, struct mdoc_node
*);
55 static int pre_bd(struct mdoc
*, struct mdoc_node
*);
56 static int pre_bl(struct mdoc
*, struct mdoc_node
*);
57 static int pre_it(struct mdoc
*, struct mdoc_node
*);
58 static int pre_cd(struct mdoc
*, struct mdoc_node
*);
59 static int pre_er(struct mdoc
*, struct mdoc_node
*);
60 static int pre_ex(struct mdoc
*, struct mdoc_node
*);
61 static int pre_rv(struct mdoc
*, struct mdoc_node
*);
62 static int pre_an(struct mdoc
*, struct mdoc_node
*);
63 static int pre_st(struct mdoc
*, struct mdoc_node
*);
64 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
65 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
66 static int pre_prologue(struct mdoc
*, struct mdoc_node
*);
68 /* Specific post-child-parse routines. */
70 static int herr_ge1(struct mdoc
*);
71 static int hwarn_ge1(struct mdoc
*);
72 static int herr_eq0(struct mdoc
*);
73 static int eerr_eq0(struct mdoc
*);
74 static int eerr_le1(struct mdoc
*);
75 static int eerr_le2(struct mdoc
*);
76 static int eerr_eq1(struct mdoc
*);
77 static int eerr_ge1(struct mdoc
*);
78 static int ewarn_eq0(struct mdoc
*);
79 static int bwarn_ge1(struct mdoc
*);
80 static int berr_eq0(struct mdoc
*);
81 static int ewarn_ge1(struct mdoc
*);
82 static int ebool(struct mdoc
*);
83 static int post_sh(struct mdoc
*);
84 static int post_bl(struct mdoc
*);
85 static int post_it(struct mdoc
*);
86 static int post_ex(struct mdoc
*);
87 static int post_an(struct mdoc
*);
88 static int post_at(struct mdoc
*);
89 static int post_xr(struct mdoc
*);
90 static int post_nm(struct mdoc
*);
91 static int post_root(struct mdoc
*);
93 /* Collections of pre-child-parse routines. */
95 static v_pre pres_prologue
[] = { pre_prologue
, NULL
};
96 static v_pre pres_d1
[] = { pre_display
, NULL
};
97 static v_pre pres_bd
[] = { pre_display
, pre_bd
, NULL
};
98 static v_pre pres_bl
[] = { pre_bl
, NULL
};
99 static v_pre pres_it
[] = { pre_it
, NULL
};
100 static v_pre pres_ss
[] = { pre_ss
, NULL
};
101 static v_pre pres_sh
[] = { pre_sh
, NULL
};
102 static v_pre pres_cd
[] = { pre_cd
, NULL
};
103 static v_pre pres_er
[] = { pre_er
, NULL
};
104 static v_pre pres_ex
[] = { pre_ex
, NULL
};
105 static v_pre pres_rv
[] = { pre_rv
, NULL
};
106 static v_pre pres_an
[] = { pre_an
, NULL
};
107 static v_pre pres_st
[] = { pre_st
, NULL
};
109 /* Collections of post-child-parse routines. */
111 static v_post posts_bool
[] = { eerr_eq1
, ebool
, NULL
};
112 static v_post posts_bd
[] = { herr_eq0
, bwarn_ge1
, NULL
};
113 static v_post posts_text
[] = { eerr_ge1
, NULL
};
114 static v_post posts_wtext
[] = { ewarn_ge1
, NULL
};
115 static v_post posts_notext
[] = { eerr_eq0
, NULL
};
116 static v_post posts_wline
[] = { hwarn_ge1
, berr_eq0
, NULL
};
117 static v_post posts_sh
[] = { herr_ge1
, bwarn_ge1
, post_sh
, NULL
};
118 static v_post posts_bl
[] = { herr_eq0
, bwarn_ge1
, post_bl
, NULL
};
119 static v_post posts_it
[] = { post_it
, NULL
};
120 static v_post posts_ss
[] = { herr_ge1
, NULL
};
121 static v_post posts_pp
[] = { ewarn_eq0
, NULL
};
122 static v_post posts_d1
[] = { herr_ge1
, NULL
};
123 static v_post posts_ex
[] = { eerr_le1
, post_ex
, NULL
};
124 static v_post posts_an
[] = { post_an
, NULL
};
125 static v_post posts_at
[] = { post_at
, NULL
};
126 static v_post posts_xr
[] = { eerr_ge1
, eerr_le2
, post_xr
, NULL
};
127 static v_post posts_nm
[] = { post_nm
, NULL
};
129 /* Per-macro pre- and post-child-check routine collections. */
131 const struct valids mdoc_valids
[MDOC_MAX
] = {
132 { NULL
, NULL
}, /* \" */
133 { pres_prologue
, posts_text
}, /* Dd */
134 { pres_prologue
, NULL
}, /* Dt */
135 { pres_prologue
, NULL
}, /* Os */
136 /* FIXME: NAME section internal ordering. */
137 { pres_sh
, posts_sh
}, /* Sh */
138 { pres_ss
, posts_ss
}, /* Ss */
139 { NULL
, posts_pp
}, /* Pp */
140 { pres_d1
, posts_d1
}, /* D1 */
141 { pres_d1
, posts_d1
}, /* Dl */
142 { pres_bd
, posts_bd
}, /* Bd */
143 { NULL
, NULL
}, /* Ed */
144 { pres_bl
, posts_bl
}, /* Bl */
145 { NULL
, NULL
}, /* El */
146 { pres_it
, posts_it
}, /* It */
147 { NULL
, posts_text
}, /* Ad */
148 { pres_an
, posts_an
}, /* An */
149 { NULL
, NULL
}, /* Ar */
150 { pres_cd
, posts_text
}, /* Cd */
151 { NULL
, NULL
}, /* Cm */
152 { NULL
, posts_text
}, /* Dv */
153 { pres_er
, posts_text
}, /* Er */
154 { NULL
, posts_text
}, /* Ev */
155 { pres_ex
, posts_ex
}, /* Ex */
156 { NULL
, posts_text
}, /* Fa */
157 /* FIXME: only in SYNOPSIS section. */
158 { NULL
, NULL
}, /* Fd */
159 { NULL
, NULL
}, /* Fl */
160 { NULL
, posts_text
}, /* Fn */
161 { NULL
, NULL
}, /* Ft */
162 { NULL
, posts_text
}, /* Ic */
163 { NULL
, posts_wtext
}, /* In */
164 { NULL
, posts_text
}, /* Li */
165 { NULL
, posts_wtext
}, /* Nd */
166 { NULL
, posts_nm
}, /* Nm */
167 { NULL
, posts_wline
}, /* Op */
168 { NULL
, NULL
}, /* Ot */
169 { NULL
, NULL
}, /* Pa */
170 { pres_rv
, posts_notext
}, /* Rv */
171 { pres_st
, posts_notext
}, /* St */
172 { NULL
, posts_text
}, /* Va */
173 { NULL
, posts_text
}, /* Vt */
174 { NULL
, posts_xr
}, /* Xr */
175 { NULL
, posts_text
}, /* %A */
176 { NULL
, posts_text
}, /* %B */
177 { NULL
, posts_text
}, /* %D */
178 { NULL
, posts_text
}, /* %I */
179 { NULL
, posts_text
}, /* %J */
180 { NULL
, posts_text
}, /* %N */
181 { NULL
, posts_text
}, /* %O */
182 { NULL
, posts_text
}, /* %P */
183 { NULL
, posts_text
}, /* %R */
184 { NULL
, posts_text
}, /* %T */
185 { NULL
, posts_text
}, /* %V */
186 { NULL
, NULL
}, /* Ac */
187 { NULL
, NULL
}, /* Ao */
188 { NULL
, posts_wline
}, /* Aq */
189 { NULL
, posts_at
}, /* At */
190 { NULL
, NULL
}, /* Bc */
191 { NULL
, NULL
}, /* Bf */
192 { NULL
, NULL
}, /* Bo */
193 { NULL
, posts_wline
}, /* Bq */
194 { NULL
, NULL
}, /* Bsx */
195 { NULL
, NULL
}, /* Bx */
196 { NULL
, posts_bool
}, /* Db */
197 { NULL
, NULL
}, /* Dc */
198 { NULL
, NULL
}, /* Do */
199 { NULL
, posts_wline
}, /* Dq */
200 { NULL
, NULL
}, /* Ec */
201 { NULL
, NULL
}, /* Ef */ /* -symbolic, etc. */
202 { NULL
, posts_text
}, /* Em */
203 { NULL
, NULL
}, /* Eo */
204 { NULL
, NULL
}, /* Fx */
205 { NULL
, posts_text
}, /* Ms */
206 { NULL
, posts_notext
}, /* No */
207 { NULL
, posts_notext
}, /* Ns */
208 { NULL
, NULL
}, /* Nx */
209 { NULL
, NULL
}, /* Ox */
210 { NULL
, NULL
}, /* Pc */
211 { NULL
, NULL
}, /* Pf */
212 { NULL
, NULL
}, /* Po */
213 { NULL
, posts_wline
}, /* Pq */
214 { NULL
, NULL
}, /* Qc */
215 { NULL
, posts_wline
}, /* Ql */
216 { NULL
, NULL
}, /* Qo */
217 { NULL
, posts_wline
}, /* Qq */
218 { NULL
, NULL
}, /* Re */
219 { NULL
, NULL
}, /* Rs */
220 { NULL
, NULL
}, /* Sc */
221 { NULL
, NULL
}, /* So */
222 { NULL
, posts_wline
}, /* Sq */
223 { NULL
, posts_bool
}, /* Sm */
224 { NULL
, posts_text
}, /* Sx */
225 { NULL
, posts_text
}, /* Sy */
226 { NULL
, posts_text
}, /* Tn */
227 { NULL
, NULL
}, /* Ux */
228 { NULL
, NULL
}, /* Xc */
229 { NULL
, NULL
}, /* Xo */
230 { NULL
, NULL
}, /* Fo */
231 { NULL
, NULL
}, /* Fc */
232 { NULL
, NULL
}, /* Oo */
233 { NULL
, NULL
}, /* Oc */
234 { NULL
, NULL
}, /* Bk */
235 { NULL
, NULL
}, /* Ek */
236 { NULL
, posts_notext
}, /* Bt */
237 { NULL
, NULL
}, /* Hf */
238 { NULL
, NULL
}, /* Fr */
239 { NULL
, posts_notext
}, /* Ud */
244 post_check_children_count(struct mdoc
*mdoc
)
249 for (i
= 0, n
= mdoc
->last
->child
; n
; n
= n
->next
, i
++)
256 post_check_children_gt(struct mdoc
*mdoc
, int sz
)
260 if ((i
= post_check_children_count(mdoc
)) > sz
)
262 return(mdoc_err(mdoc
, "macro requires more than %d "
263 "parameters (have %d)", sz
, i
));
268 post_check_children_eq(struct mdoc
*mdoc
, int sz
)
272 if ((i
= post_check_children_count(mdoc
)) == sz
)
274 return(mdoc_err(mdoc
, "macro requires %d parameters "
275 "(have %d)", sz
, i
));
280 post_check_children_lt(struct mdoc
*mdoc
, int sz
)
284 if ((i
= post_check_children_count(mdoc
)) < sz
)
286 return(mdoc_err(mdoc
, "macro requires less than %d "
287 "parameters (have %d)", sz
, i
));
292 pre_check_stdarg(struct mdoc
*mdoc
, struct mdoc_node
*node
)
295 if (1 == node
->data
.elem
.argc
&&
296 MDOC_Std
== node
->data
.elem
.argv
[0].arg
)
298 return(mdoc_nwarn(mdoc
, node
, WARN_COMPAT
,
299 "macro suggests single `%s' argument",
300 mdoc_argnames
[MDOC_Std
]));
305 pre_check_msecs(struct mdoc
*mdoc
, struct mdoc_node
*node
,
306 int sz
, enum mdoc_msec
*msecs
)
310 for (i
= 0; i
< sz
; i
++)
311 if (msecs
[i
] == mdoc
->meta
.msec
)
313 return(mdoc_nwarn(mdoc
, node
, WARN_COMPAT
, "macro not "
314 "appropriate for manual section"));
319 pre_check_parent(struct mdoc
*mdoc
, struct mdoc_node
*node
,
320 int tok
, enum mdoc_type type
)
323 if (type
!= node
->parent
->type
)
324 return(mdoc_nerr(mdoc
, node
, "invalid macro parent class %s, expected %s",
325 mdoc_type2a(node
->parent
->type
),
327 if (MDOC_ROOT
!= type
&& tok
!= node
->parent
->tok
)
328 return(mdoc_nerr(mdoc
, node
, "invalid macro parent `%s', expected `%s'",
329 mdoc_macronames
[node
->parent
->tok
],
330 mdoc_macronames
[tok
]));
336 berr_eq0(struct mdoc
*mdoc
)
339 if (MDOC_BODY
!= mdoc
->last
->type
)
341 if (NULL
== mdoc
->last
->child
)
343 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests no body children"));
348 bwarn_ge1(struct mdoc
*mdoc
)
351 if (MDOC_BODY
!= mdoc
->last
->type
)
353 if (mdoc
->last
->child
)
355 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests one or more body children"));
360 ewarn_eq0(struct mdoc
*mdoc
)
363 assert(MDOC_ELEM
== mdoc
->last
->type
);
364 if (NULL
== mdoc
->last
->child
)
366 return(mdoc_pwarn(mdoc
, mdoc
->last
->child
->line
,
367 mdoc
->last
->child
->pos
, WARN_SYNTAX
, "macro suggests no parameters"));
372 ewarn_ge1(struct mdoc
*mdoc
)
375 assert(MDOC_ELEM
== mdoc
->last
->type
);
376 if (mdoc
->last
->child
)
378 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests one or more parameters"));
383 eerr_eq1(struct mdoc
*mdoc
)
386 assert(MDOC_ELEM
== mdoc
->last
->type
);
387 return(post_check_children_eq(mdoc
, 1));
392 eerr_le2(struct mdoc
*mdoc
)
395 assert(MDOC_ELEM
== mdoc
->last
->type
);
396 return(post_check_children_lt(mdoc
, 3));
401 eerr_le1(struct mdoc
*mdoc
)
404 assert(MDOC_ELEM
== mdoc
->last
->type
);
405 return(post_check_children_lt(mdoc
, 2));
410 eerr_eq0(struct mdoc
*mdoc
)
413 assert(MDOC_ELEM
== mdoc
->last
->type
);
414 return(post_check_children_eq(mdoc
, 0));
419 eerr_ge1(struct mdoc
*mdoc
)
422 assert(MDOC_ELEM
== mdoc
->last
->type
);
423 return(post_check_children_gt(mdoc
, 0));
428 herr_eq0(struct mdoc
*mdoc
)
431 if (MDOC_HEAD
!= mdoc
->last
->type
)
433 return(post_check_children_eq(mdoc
, 0));
438 hwarn_ge1(struct mdoc
*mdoc
)
441 if (MDOC_HEAD
!= mdoc
->last
->type
)
443 if (mdoc
->last
->child
)
445 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests one or more parameters"));
450 herr_ge1(struct mdoc
*mdoc
)
453 if (MDOC_HEAD
!= mdoc
->last
->type
)
455 return(post_check_children_gt(mdoc
, 0));
460 pre_display(struct mdoc
*mdoc
, struct mdoc_node
*node
)
464 if (MDOC_BLOCK
!= node
->type
)
469 for (n
= mdoc
->last
->parent
; n
; n
= n
->parent
)
470 if (MDOC_BLOCK
== n
->type
)
471 if (MDOC_Bd
== n
->tok
)
475 return(mdoc_nerr(mdoc
, node
, "displays may not be nested"));
480 pre_bl(struct mdoc
*mdoc
, struct mdoc_node
*node
)
483 struct mdoc_arg
*argv
;
486 if (MDOC_BLOCK
!= node
->type
)
488 assert(MDOC_Bl
== node
->tok
);
491 argc
= node
->data
.block
.argc
;
494 for (i
= type
= err
= 0; i
< argc
; i
++) {
495 argv
= &node
->data
.block
.argv
[(int)i
];
528 return(mdoc_err(mdoc
, "no list type specified"));
532 return(mdoc_perr(mdoc
, argv
->line
,
533 argv
->pos
, "only one list type possible"));
538 pre_bd(struct mdoc
*mdoc
, struct mdoc_node
*node
)
541 struct mdoc_arg
*argv
;
544 if (MDOC_BLOCK
!= node
->type
)
546 assert(MDOC_Bd
== node
->tok
);
549 argc
= node
->data
.block
.argc
;
552 for (err
= i
= type
= 0; 0 == err
&& i
< argc
; i
++) {
553 argv
= &node
->data
.block
.argv
[(int)i
];
558 case (MDOC_Unfilled
):
574 return(mdoc_err(mdoc
, "no display type specified"));
578 return(mdoc_perr(mdoc
, argv
->line
,
579 argv
->pos
, "only one display type possible"));
584 pre_ss(struct mdoc
*mdoc
, struct mdoc_node
*node
)
587 if (MDOC_BLOCK
!= node
->type
)
589 return(pre_check_parent(mdoc
, node
, MDOC_Sh
, MDOC_BODY
));
594 pre_sh(struct mdoc
*mdoc
, struct mdoc_node
*node
)
597 if (MDOC_BLOCK
!= node
->type
)
599 return(pre_check_parent(mdoc
, node
, -1, MDOC_ROOT
));
604 pre_st(struct mdoc
*mdoc
, struct mdoc_node
*node
)
607 assert(MDOC_ELEM
== node
->type
);
608 assert(MDOC_St
== node
->tok
);
609 if (1 == node
->data
.elem
.argc
)
611 return(mdoc_nerr(mdoc
, node
, "macro must have one argument"));
616 pre_an(struct mdoc
*mdoc
, struct mdoc_node
*node
)
619 assert(MDOC_ELEM
== node
->type
);
620 assert(MDOC_An
== node
->tok
);
621 if (1 >= node
->data
.elem
.argc
)
623 return(mdoc_nerr(mdoc
, node
, "macro may only have one argument"));
628 pre_rv(struct mdoc
*mdoc
, struct mdoc_node
*node
)
630 enum mdoc_msec msecs
[2];
632 assert(MDOC_ELEM
== node
->type
);
633 assert(MDOC_Rv
== node
->tok
);
637 if ( ! pre_check_msecs(mdoc
, node
, 2, msecs
))
639 return(pre_check_stdarg(mdoc
, node
));
644 pre_ex(struct mdoc
*mdoc
, struct mdoc_node
*node
)
646 enum mdoc_msec msecs
[3];
648 assert(MDOC_ELEM
== node
->type
);
649 assert(MDOC_Ex
== node
->tok
);
654 if ( ! pre_check_msecs(mdoc
, node
, 3, msecs
))
656 return(pre_check_stdarg(mdoc
, node
));
661 pre_er(struct mdoc
*mdoc
, struct mdoc_node
*node
)
663 enum mdoc_msec msecs
[1];
666 return(pre_check_msecs(mdoc
, node
, 1, msecs
));
671 pre_cd(struct mdoc
*mdoc
, struct mdoc_node
*node
)
673 enum mdoc_msec msecs
[1];
676 return(pre_check_msecs(mdoc
, node
, 1, msecs
));
681 pre_it(struct mdoc
*mdoc
, struct mdoc_node
*node
)
684 if (MDOC_BLOCK
!= node
->type
)
686 return(pre_check_parent(mdoc
, node
, MDOC_Bl
, MDOC_BODY
));
691 pre_prologue(struct mdoc
*mdoc
, struct mdoc_node
*node
)
694 if (SEC_PROLOGUE
!= mdoc
->sec_lastn
)
695 return(mdoc_nerr(mdoc
, node
, "macro may only be invoked in the prologue"));
696 assert(MDOC_ELEM
== node
->type
);
698 /* Check for ordering. */
702 if (mdoc
->meta
.title
&& mdoc
->meta
.date
)
704 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
706 if (NULL
== mdoc
->meta
.title
&& mdoc
->meta
.date
)
708 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
710 if (NULL
== mdoc
->meta
.title
&& 0 == mdoc
->meta
.date
)
712 return(mdoc_nerr(mdoc
, node
, "prologue macro out-of-order"));
718 /* Check for repetition. */
722 if (NULL
== mdoc
->meta
.os
)
726 if (0 == mdoc
->meta
.date
)
730 if (NULL
== mdoc
->meta
.title
)
738 return(mdoc_nerr(mdoc
, node
, "prologue macro repeated"));
743 post_nm(struct mdoc
*mdoc
)
746 assert(MDOC_ELEM
== mdoc
->last
->type
);
747 assert(MDOC_Nm
== mdoc
->last
->tok
);
748 if (mdoc
->last
->child
)
752 return(mdoc_err(mdoc
, "macro `%s' has not been invoked with a name",
753 mdoc_macronames
[MDOC_Nm
]));
758 post_xr(struct mdoc
*mdoc
)
762 assert(MDOC_ELEM
== mdoc
->last
->type
);
763 assert(MDOC_Xr
== mdoc
->last
->tok
);
764 assert(mdoc
->last
->child
);
765 assert(MDOC_TEXT
== mdoc
->last
->child
->type
);
767 if (NULL
== (n
= mdoc
->last
->child
->next
))
769 assert(MDOC_TEXT
== n
->type
);
770 if (MSEC_DEFAULT
!= mdoc_atomsec(n
->data
.text
.string
))
772 return(mdoc_nerr(mdoc
, n
, "invalid manual section"));
777 post_at(struct mdoc
*mdoc
)
780 assert(MDOC_ELEM
== mdoc
->last
->type
);
781 assert(MDOC_At
== mdoc
->last
->tok
);
783 if (NULL
== mdoc
->last
->child
)
785 assert(MDOC_TEXT
== mdoc
->last
->child
->type
);
787 if (ATT_DEFAULT
!= mdoc_atoatt(mdoc
->last
->child
->data
.text
.string
))
789 return(mdoc_err(mdoc
, "macro expects a valid AT&T version symbol"));
794 post_an(struct mdoc
*mdoc
)
797 assert(MDOC_ELEM
== mdoc
->last
->type
);
798 assert(MDOC_An
== mdoc
->last
->tok
);
800 if (0 != mdoc
->last
->data
.elem
.argc
) {
801 if (NULL
== mdoc
->last
->child
)
803 return(mdoc_err(mdoc
, "macro expects either argument or parameters"));
806 if (mdoc
->last
->child
)
808 return(mdoc_err(mdoc
, "macro expects either argument or parameters"));
813 post_ex(struct mdoc
*mdoc
)
816 assert(MDOC_ELEM
== mdoc
->last
->type
);
817 assert(MDOC_Ex
== mdoc
->last
->tok
);
819 if (0 == mdoc
->last
->data
.elem
.argc
) {
820 if (mdoc
->last
->child
)
822 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
823 mdoc_argnames
[MDOC_Std
]));
825 if (mdoc
->last
->child
)
826 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
827 mdoc_argnames
[MDOC_Std
]));
828 if (1 != mdoc
->last
->data
.elem
.argc
)
829 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
830 mdoc_argnames
[MDOC_Std
]));
831 if (MDOC_Std
!= mdoc
->last
->data
.elem
.argv
[0].arg
)
832 return(mdoc_err(mdoc
, "macro expects `%s' or a single child",
833 mdoc_argnames
[MDOC_Std
]));
838 /* Warn if `Bl' type-specific syntax isn't reflected in items. */
840 post_it(struct mdoc
*mdoc
)
843 #define TYPE_NONE (0)
844 #define TYPE_BODY (1)
845 #define TYPE_HEAD (2)
849 if (MDOC_BLOCK
!= mdoc
->last
->type
)
852 assert(MDOC_It
== mdoc
->last
->tok
);
854 n
= mdoc
->last
->parent
;
856 assert(MDOC_Bl
== n
->tok
);
859 assert(MDOC_BLOCK
== n
->type
);
860 assert(MDOC_Bl
== n
->tok
);
862 argc
= n
->data
.block
.argc
;
866 /* Some types require block-head, some not. */
869 for (i
= 0; TYPE_NONE
== type
&& i
< argc
; i
++)
870 switch (n
->data
.block
.argv
[(int)i
].arg
) {
881 sv
= n
->data
.block
.argv
[(int)i
].arg
;
895 sv
= n
->data
.block
.argv
[(int)i
].arg
;
901 assert(TYPE_NONE
!= type
);
903 if (TYPE_HEAD
== type
) {
904 n
= mdoc
->last
->data
.block
.head
;
906 if (NULL
== n
->child
)
907 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests line parameters"))
910 n
= mdoc
->last
->data
.block
.body
;
912 if (NULL
== n
->child
)
913 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests body children"))
919 assert(TYPE_BODY
== type
);
920 assert(mdoc
->last
->data
.block
.head
);
922 n
= mdoc
->last
->data
.block
.head
;
925 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests no line parameters"))
928 n
= mdoc
->last
->data
.block
.body
;
930 if (NULL
== n
->child
)
931 if ( ! mdoc_warn(mdoc
, WARN_SYNTAX
, "macro suggests body children"))
935 if (MDOC_Column
!= sv
)
938 /* Make sure the number of columns is sane. */
940 argc
= mdoc
->last
->parent
->parent
->data
.block
.argv
->sz
;
941 n
= mdoc
->last
->data
.block
.head
->child
;
943 for (i
= 0; n
; n
= n
->next
)
948 return(mdoc_err(mdoc
, "expected %zu list columns, have %zu", argc
, i
));
956 post_bl(struct mdoc
*mdoc
)
960 if (MDOC_BODY
!= mdoc
->last
->type
)
962 assert(MDOC_Bl
== mdoc
->last
->tok
);
965 for (n
= mdoc
->last
->child
; n
; n
= n
->next
) {
966 if (MDOC_BLOCK
== n
->type
)
967 if (MDOC_It
== n
->tok
)
973 return(mdoc_nerr(mdoc
, n
, "invalid child of parent macro `Bl'"));
978 ebool(struct mdoc
*mdoc
)
982 assert(MDOC_ELEM
== mdoc
->last
->type
);
984 for (n
= mdoc
->last
->child
; n
; n
= n
->next
) {
985 if (MDOC_TEXT
!= n
->type
)
987 if (xstrcmp(n
->data
.text
.string
, "on"))
989 if (xstrcmp(n
->data
.text
.string
, "off"))
995 return(mdoc_nerr(mdoc
, n
, "expected boolean value"));
1000 post_root(struct mdoc
*mdoc
)
1003 if (NULL
== mdoc
->last
->child
)
1004 return(mdoc_err(mdoc
, "document has no data"));
1005 if (NULL
== mdoc
->meta
.title
)
1006 return(mdoc_err(mdoc
, "document has no incomplete prologue"));
1007 if (NULL
== mdoc
->meta
.os
)
1008 return(mdoc_err(mdoc
, "document has no incomplete prologue"));
1009 if (0 == mdoc
->meta
.date
)
1010 return(mdoc_err(mdoc
, "document has no incomplete prologue"));
1015 /* Warn if conventional sections are out of order. */
1017 post_sh(struct mdoc
*mdoc
)
1022 if (MDOC_HEAD
!= mdoc
->last
->type
)
1024 assert(MDOC_Sh
== mdoc
->last
->tok
);
1026 if ( ! xstrlcats(buf
, mdoc
->last
->child
, 64))
1027 return(mdoc_err(mdoc
, "macro parameters too long"));
1029 if (SEC_CUSTOM
== (sec
= mdoc_atosec(buf
)))
1031 if (sec
> mdoc
->sec_lastn
)
1033 if (sec
== mdoc
->sec_lastn
)
1034 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "section repeated"));
1035 return(mdoc_warn(mdoc
, WARN_SYNTAX
, "section out of conventional order"));
1040 mdoc_valid_pre(struct mdoc
*mdoc
, struct mdoc_node
*node
)
1044 if (MDOC_TEXT
== node
->type
)
1046 assert(MDOC_ROOT
!= node
->type
);
1048 if (NULL
== mdoc_valids
[node
->tok
].pre
)
1050 for (p
= mdoc_valids
[node
->tok
].pre
; *p
; p
++)
1051 if ( ! (*p
)(mdoc
, node
))
1058 mdoc_valid_post(struct mdoc
*mdoc
)
1062 if (MDOC_TEXT
== mdoc
->last
->type
)
1064 if (MDOC_ROOT
== mdoc
->last
->type
)
1065 return(post_root(mdoc
));
1067 if (NULL
== mdoc_valids
[mdoc
->last
->tok
].post
)
1069 for (p
= mdoc_valids
[mdoc
->last
->tok
].post
; *p
; p
++)