]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_validate.c
b442293ca44a08a684d47900f036f6963d4d162a
[mandoc.git] / mdoc_validate.c
1 /* $Id: mdoc_validate.c,v 1.70 2010/05/08 07:30:19 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <sys/types.h>
22
23 #include <assert.h>
24 #include <ctype.h>
25 #include <limits.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "libmdoc.h"
31 #include "libmandoc.h"
32
33 /* FIXME: .Bl -diag can't have non-text children in HEAD. */
34 /* TODO: ignoring Pp (it's superfluous in some invocations). */
35
36 #define PRE_ARGS struct mdoc *mdoc, const struct mdoc_node *n
37 #define POST_ARGS struct mdoc *mdoc
38
39 typedef int (*v_pre)(PRE_ARGS);
40 typedef int (*v_post)(POST_ARGS);
41
42 struct valids {
43 v_pre *pre;
44 v_post *post;
45 };
46
47 static int check_parent(PRE_ARGS, enum mdoct, enum mdoc_type);
48 static int check_msec(PRE_ARGS, ...);
49 static int check_sec(PRE_ARGS, ...);
50 static int check_stdarg(PRE_ARGS);
51 static int check_text(struct mdoc *, int, int, const char *);
52 static int check_argv(struct mdoc *,
53 const struct mdoc_node *,
54 const struct mdoc_argv *);
55 static int check_args(struct mdoc *,
56 const struct mdoc_node *);
57 static int err_child_lt(struct mdoc *, const char *, int);
58 static int warn_child_lt(struct mdoc *, const char *, int);
59 static int err_child_gt(struct mdoc *, const char *, int);
60 static int warn_child_gt(struct mdoc *, const char *, int);
61 static int err_child_eq(struct mdoc *, const char *, int);
62 static int warn_child_eq(struct mdoc *, const char *, int);
63 static int warn_print(struct mdoc *, int, int);
64 static int warn_count(struct mdoc *, const char *,
65 int, const char *, int);
66 static int err_count(struct mdoc *, const char *,
67 int, const char *, int);
68
69 static int berr_ge1(POST_ARGS);
70 static int bwarn_ge1(POST_ARGS);
71 static int ebool(POST_ARGS);
72 static int eerr_eq0(POST_ARGS);
73 static int eerr_eq1(POST_ARGS);
74 static int eerr_ge1(POST_ARGS);
75 static int eerr_le1(POST_ARGS);
76 static int ewarn_ge1(POST_ARGS);
77 static int herr_eq0(POST_ARGS);
78 static int herr_ge1(POST_ARGS);
79 static int hwarn_eq1(POST_ARGS);
80 static int hwarn_eq0(POST_ARGS);
81 static int hwarn_le1(POST_ARGS);
82
83 static int post_an(POST_ARGS);
84 static int post_at(POST_ARGS);
85 static int post_bf(POST_ARGS);
86 static int post_bl(POST_ARGS);
87 static int post_bl_head(POST_ARGS);
88 static int post_it(POST_ARGS);
89 static int post_lb(POST_ARGS);
90 static int post_nm(POST_ARGS);
91 static int post_root(POST_ARGS);
92 static int post_rs(POST_ARGS);
93 static int post_sh(POST_ARGS);
94 static int post_sh_body(POST_ARGS);
95 static int post_sh_head(POST_ARGS);
96 static int post_st(POST_ARGS);
97 static int post_vt(POST_ARGS);
98 static int pre_an(PRE_ARGS);
99 static int pre_bd(PRE_ARGS);
100 static int pre_bl(PRE_ARGS);
101 static int pre_dd(PRE_ARGS);
102 static int pre_display(PRE_ARGS);
103 static int pre_dt(PRE_ARGS);
104 static int pre_ex(PRE_ARGS);
105 static int pre_fd(PRE_ARGS);
106 static int pre_it(PRE_ARGS);
107 static int pre_lb(PRE_ARGS);
108 static int pre_os(PRE_ARGS);
109 static int pre_rv(PRE_ARGS);
110 static int pre_sh(PRE_ARGS);
111 static int pre_ss(PRE_ARGS);
112
113 static v_post posts_an[] = { post_an, NULL };
114 static v_post posts_at[] = { post_at, NULL };
115 static v_post posts_bd[] = { hwarn_eq0, bwarn_ge1, NULL };
116 static v_post posts_bf[] = { hwarn_le1, post_bf, NULL };
117 static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL };
118 static v_post posts_bool[] = { eerr_eq1, ebool, NULL };
119 static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
120 static v_post posts_it[] = { post_it, NULL };
121 static v_post posts_lb[] = { eerr_eq1, post_lb, NULL };
122 static v_post posts_nd[] = { berr_ge1, NULL };
123 static v_post posts_nm[] = { post_nm, NULL };
124 static v_post posts_notext[] = { eerr_eq0, NULL };
125 static v_post posts_rs[] = { berr_ge1, herr_eq0, post_rs, NULL };
126 static v_post posts_sh[] = { herr_ge1, bwarn_ge1, post_sh, NULL };
127 static v_post posts_sp[] = { eerr_le1, NULL };
128 static v_post posts_ss[] = { herr_ge1, NULL };
129 static v_post posts_st[] = { eerr_eq1, post_st, NULL };
130 static v_post posts_text[] = { eerr_ge1, NULL };
131 static v_post posts_text1[] = { eerr_eq1, NULL };
132 static v_post posts_vt[] = { post_vt, NULL };
133 static v_post posts_wline[] = { bwarn_ge1, herr_eq0, NULL };
134 static v_post posts_wtext[] = { ewarn_ge1, NULL };
135 static v_post posts_xr[] = { ewarn_ge1, NULL };
136 static v_pre pres_an[] = { pre_an, NULL };
137 static v_pre pres_bd[] = { pre_display, pre_bd, NULL };
138 static v_pre pres_bl[] = { pre_bl, NULL };
139 static v_pre pres_d1[] = { pre_display, NULL };
140 static v_pre pres_dd[] = { pre_dd, NULL };
141 static v_pre pres_dt[] = { pre_dt, NULL };
142 static v_pre pres_er[] = { NULL, NULL };
143 static v_pre pres_ex[] = { pre_ex, NULL };
144 static v_pre pres_fd[] = { pre_fd, NULL };
145 static v_pre pres_it[] = { pre_it, NULL };
146 static v_pre pres_lb[] = { pre_lb, NULL };
147 static v_pre pres_os[] = { pre_os, NULL };
148 static v_pre pres_rv[] = { pre_rv, NULL };
149 static v_pre pres_sh[] = { pre_sh, NULL };
150 static v_pre pres_ss[] = { pre_ss, NULL };
151
152 const struct valids mdoc_valids[MDOC_MAX] = {
153 { NULL, NULL }, /* Ap */
154 { pres_dd, posts_text }, /* Dd */
155 { pres_dt, NULL }, /* Dt */
156 { pres_os, NULL }, /* Os */
157 { pres_sh, posts_sh }, /* Sh */
158 { pres_ss, posts_ss }, /* Ss */
159 { NULL, posts_notext }, /* Pp */
160 { pres_d1, posts_wline }, /* D1 */
161 { pres_d1, posts_wline }, /* Dl */
162 { pres_bd, posts_bd }, /* Bd */
163 { NULL, NULL }, /* Ed */
164 { pres_bl, posts_bl }, /* Bl */
165 { NULL, NULL }, /* El */
166 { pres_it, posts_it }, /* It */
167 { NULL, posts_text }, /* Ad */
168 { pres_an, posts_an }, /* An */
169 { NULL, NULL }, /* Ar */
170 { NULL, posts_text }, /* Cd */
171 { NULL, NULL }, /* Cm */
172 { NULL, NULL }, /* Dv */
173 { pres_er, posts_text }, /* Er */
174 { NULL, NULL }, /* Ev */
175 { pres_ex, NULL }, /* Ex */
176 { NULL, NULL }, /* Fa */
177 { pres_fd, posts_wtext }, /* Fd */
178 { NULL, NULL }, /* Fl */
179 { NULL, posts_text }, /* Fn */
180 { NULL, posts_wtext }, /* Ft */
181 { NULL, posts_text }, /* Ic */
182 { NULL, posts_text1 }, /* In */
183 { NULL, NULL }, /* Li */
184 { NULL, posts_nd }, /* Nd */
185 { NULL, posts_nm }, /* Nm */
186 { NULL, posts_wline }, /* Op */
187 { NULL, NULL }, /* Ot */
188 { NULL, NULL }, /* Pa */
189 { pres_rv, NULL }, /* Rv */
190 { NULL, posts_st }, /* St */
191 { NULL, NULL }, /* Va */
192 { NULL, posts_vt }, /* Vt */
193 { NULL, posts_xr }, /* Xr */
194 { NULL, posts_text }, /* %A */
195 { NULL, posts_text }, /* %B */ /* FIXME: can be used outside Rs/Re. */
196 { NULL, posts_text }, /* %D */ /* FIXME: check date with mandoc_a2time(). */
197 { NULL, posts_text }, /* %I */
198 { NULL, posts_text }, /* %J */
199 { NULL, posts_text }, /* %N */
200 { NULL, posts_text }, /* %O */
201 { NULL, posts_text }, /* %P */
202 { NULL, posts_text }, /* %R */
203 { NULL, posts_text }, /* %T */ /* FIXME: can be used outside Rs/Re. */
204 { NULL, posts_text }, /* %V */
205 { NULL, NULL }, /* Ac */
206 { NULL, NULL }, /* Ao */
207 { NULL, posts_wline }, /* Aq */
208 { NULL, posts_at }, /* At */
209 { NULL, NULL }, /* Bc */
210 { NULL, posts_bf }, /* Bf */
211 { NULL, NULL }, /* Bo */
212 { NULL, posts_wline }, /* Bq */
213 { NULL, NULL }, /* Bsx */
214 { NULL, NULL }, /* Bx */
215 { NULL, posts_bool }, /* Db */
216 { NULL, NULL }, /* Dc */
217 { NULL, NULL }, /* Do */
218 { NULL, posts_wline }, /* Dq */
219 { NULL, NULL }, /* Ec */
220 { NULL, NULL }, /* Ef */
221 { NULL, NULL }, /* Em */
222 { NULL, NULL }, /* Eo */
223 { NULL, NULL }, /* Fx */
224 { NULL, posts_text }, /* Ms */
225 { NULL, posts_notext }, /* No */
226 { NULL, posts_notext }, /* Ns */
227 { NULL, NULL }, /* Nx */
228 { NULL, NULL }, /* Ox */
229 { NULL, NULL }, /* Pc */
230 { NULL, posts_text1 }, /* Pf */
231 { NULL, NULL }, /* Po */
232 { NULL, posts_wline }, /* Pq */
233 { NULL, NULL }, /* Qc */
234 { NULL, posts_wline }, /* Ql */
235 { NULL, NULL }, /* Qo */
236 { NULL, posts_wline }, /* Qq */
237 { NULL, NULL }, /* Re */
238 { NULL, posts_rs }, /* Rs */
239 { NULL, NULL }, /* Sc */
240 { NULL, NULL }, /* So */
241 { NULL, posts_wline }, /* Sq */
242 { NULL, posts_bool }, /* Sm */
243 { NULL, posts_text }, /* Sx */
244 { NULL, posts_text }, /* Sy */
245 { NULL, posts_text }, /* Tn */
246 { NULL, NULL }, /* Ux */
247 { NULL, NULL }, /* Xc */
248 { NULL, NULL }, /* Xo */
249 { NULL, posts_fo }, /* Fo */
250 { NULL, NULL }, /* Fc */
251 { NULL, NULL }, /* Oo */
252 { NULL, NULL }, /* Oc */
253 { NULL, posts_wline }, /* Bk */
254 { NULL, NULL }, /* Ek */
255 { NULL, posts_notext }, /* Bt */
256 { NULL, NULL }, /* Hf */
257 { NULL, NULL }, /* Fr */
258 { NULL, posts_notext }, /* Ud */
259 { pres_lb, posts_lb }, /* Lb */
260 { NULL, posts_notext }, /* Lp */
261 { NULL, posts_text }, /* Lk */
262 { NULL, posts_text }, /* Mt */
263 { NULL, posts_wline }, /* Brq */
264 { NULL, NULL }, /* Bro */
265 { NULL, NULL }, /* Brc */
266 { NULL, posts_text }, /* %C */
267 { NULL, NULL }, /* Es */
268 { NULL, NULL }, /* En */
269 { NULL, NULL }, /* Dx */
270 { NULL, posts_text }, /* %Q */
271 { NULL, posts_notext }, /* br */
272 { NULL, posts_sp }, /* sp */
273 { NULL, posts_text1 }, /* %U */
274 };
275
276
277 int
278 mdoc_valid_pre(struct mdoc *mdoc, const struct mdoc_node *n)
279 {
280 v_pre *p;
281 int line, pos;
282 const char *tp;
283
284 if (MDOC_TEXT == n->type) {
285 tp = n->string;
286 line = n->line;
287 pos = n->pos;
288 return(check_text(mdoc, line, pos, tp));
289 }
290
291 if ( ! check_args(mdoc, n))
292 return(0);
293 if (NULL == mdoc_valids[n->tok].pre)
294 return(1);
295 for (p = mdoc_valids[n->tok].pre; *p; p++)
296 if ( ! (*p)(mdoc, n))
297 return(0);
298 return(1);
299 }
300
301
302 int
303 mdoc_valid_post(struct mdoc *mdoc)
304 {
305 v_post *p;
306
307 if (MDOC_VALID & mdoc->last->flags)
308 return(1);
309 mdoc->last->flags |= MDOC_VALID;
310
311 if (MDOC_TEXT == mdoc->last->type)
312 return(1);
313 if (MDOC_ROOT == mdoc->last->type)
314 return(post_root(mdoc));
315
316 if (NULL == mdoc_valids[mdoc->last->tok].post)
317 return(1);
318 for (p = mdoc_valids[mdoc->last->tok].post; *p; p++)
319 if ( ! (*p)(mdoc))
320 return(0);
321
322 return(1);
323 }
324
325
326 static int
327 warn_print(struct mdoc *m, int ln, int pos)
328 {
329
330 if (MDOC_IGN_CHARS & m->pflags)
331 return(mdoc_pwarn(m, ln, pos, EPRINT));
332 return(mdoc_perr(m, ln, pos, EPRINT));
333 }
334
335
336 static inline int
337 warn_count(struct mdoc *m, const char *k,
338 int want, const char *v, int has)
339 {
340
341 return(mdoc_vwarn(m, m->last->line, m->last->pos,
342 "suggests %s %s %d (has %d)", v, k, want, has));
343 }
344
345
346 static inline int
347 err_count(struct mdoc *m, const char *k,
348 int want, const char *v, int has)
349 {
350
351 return(mdoc_verr(m, m->last->line, m->last->pos,
352 "requires %s %s %d (has %d)", v, k, want, has));
353 }
354
355
356 /*
357 * Build these up with macros because they're basically the same check
358 * for different inequalities. Yes, this could be done with functions,
359 * but this is reasonable for now.
360 */
361
362 #define CHECK_CHILD_DEFN(lvl, name, ineq) \
363 static int \
364 lvl##_child_##name(struct mdoc *mdoc, const char *p, int sz) \
365 { \
366 if (mdoc->last->nchild ineq sz) \
367 return(1); \
368 return(lvl##_count(mdoc, #ineq, sz, p, mdoc->last->nchild)); \
369 }
370
371 #define CHECK_BODY_DEFN(name, lvl, func, num) \
372 static int \
373 b##lvl##_##name(POST_ARGS) \
374 { \
375 if (MDOC_BODY != mdoc->last->type) \
376 return(1); \
377 return(func(mdoc, "multi-line arguments", (num))); \
378 }
379
380 #define CHECK_ELEM_DEFN(name, lvl, func, num) \
381 static int \
382 e##lvl##_##name(POST_ARGS) \
383 { \
384 assert(MDOC_ELEM == mdoc->last->type); \
385 return(func(mdoc, "line arguments", (num))); \
386 }
387
388 #define CHECK_HEAD_DEFN(name, lvl, func, num) \
389 static int \
390 h##lvl##_##name(POST_ARGS) \
391 { \
392 if (MDOC_HEAD != mdoc->last->type) \
393 return(1); \
394 return(func(mdoc, "line arguments", (num))); \
395 }
396
397
398 CHECK_CHILD_DEFN(warn, gt, >) /* warn_child_gt() */
399 CHECK_CHILD_DEFN(err, gt, >) /* err_child_gt() */
400 CHECK_CHILD_DEFN(warn, eq, ==) /* warn_child_eq() */
401 CHECK_CHILD_DEFN(err, eq, ==) /* err_child_eq() */
402 CHECK_CHILD_DEFN(err, lt, <) /* err_child_lt() */
403 CHECK_CHILD_DEFN(warn, lt, <) /* warn_child_lt() */
404 CHECK_BODY_DEFN(ge1, warn, warn_child_gt, 0) /* bwarn_ge1() */
405 CHECK_BODY_DEFN(ge1, err, err_child_gt, 0) /* berr_ge1() */
406 CHECK_ELEM_DEFN(ge1, warn, warn_child_gt, 0) /* ewarn_gt1() */
407 CHECK_ELEM_DEFN(eq1, err, err_child_eq, 1) /* eerr_eq1() */
408 CHECK_ELEM_DEFN(le1, err, err_child_lt, 2) /* eerr_le1() */
409 CHECK_ELEM_DEFN(eq0, err, err_child_eq, 0) /* eerr_eq0() */
410 CHECK_ELEM_DEFN(ge1, err, err_child_gt, 0) /* eerr_ge1() */
411 CHECK_HEAD_DEFN(eq0, err, err_child_eq, 0) /* herr_eq0() */
412 CHECK_HEAD_DEFN(le1, warn, warn_child_lt, 2) /* hwarn_le1() */
413 CHECK_HEAD_DEFN(ge1, err, err_child_gt, 0) /* herr_ge1() */
414 CHECK_HEAD_DEFN(eq1, warn, warn_child_eq, 1) /* hwarn_eq1() */
415 CHECK_HEAD_DEFN(eq0, warn, warn_child_eq, 0) /* hwarn_eq0() */
416
417
418 static int
419 check_stdarg(PRE_ARGS)
420 {
421
422 if (n->args && 1 == n->args->argc)
423 if (MDOC_Std == n->args->argv[0].arg)
424 return(1);
425 return(mdoc_nwarn(mdoc, n, EARGVAL));
426 }
427
428
429 static int
430 check_sec(PRE_ARGS, ...)
431 {
432 enum mdoc_sec sec;
433 va_list ap;
434
435 va_start(ap, n);
436
437 for (;;) {
438 /* LINTED */
439 sec = (enum mdoc_sec)va_arg(ap, int);
440 if (SEC_CUSTOM == sec)
441 break;
442 if (sec != mdoc->lastsec)
443 continue;
444 va_end(ap);
445 return(1);
446 }
447
448 va_end(ap);
449 return(mdoc_nwarn(mdoc, n, EBADSEC));
450 }
451
452
453 static int
454 check_msec(PRE_ARGS, ...)
455 {
456 va_list ap;
457 int msec;
458
459 va_start(ap, n);
460 for (;;) {
461 /* LINTED */
462 if (0 == (msec = va_arg(ap, int)))
463 break;
464 if (msec != mdoc->meta.msec)
465 continue;
466 va_end(ap);
467 return(1);
468 }
469
470 va_end(ap);
471 return(mdoc_nwarn(mdoc, n, EBADMSEC));
472 }
473
474
475 static int
476 check_args(struct mdoc *m, const struct mdoc_node *n)
477 {
478 int i;
479
480 if (NULL == n->args)
481 return(1);
482
483 assert(n->args->argc);
484 for (i = 0; i < (int)n->args->argc; i++)
485 if ( ! check_argv(m, n, &n->args->argv[i]))
486 return(0);
487
488 return(1);
489 }
490
491
492 static int
493 check_argv(struct mdoc *m, const struct mdoc_node *n,
494 const struct mdoc_argv *v)
495 {
496 int i;
497
498 for (i = 0; i < (int)v->sz; i++)
499 if ( ! check_text(m, v->line, v->pos, v->value[i]))
500 return(0);
501
502 if (MDOC_Std == v->arg) {
503 /* `Nm' name must be set. */
504 if (v->sz || m->meta.name)
505 return(1);
506 return(mdoc_nerr(m, n, ENAME));
507 }
508
509 return(1);
510 }
511
512
513 static int
514 check_text(struct mdoc *mdoc, int line, int pos, const char *p)
515 {
516 int c;
517
518 for ( ; *p; p++, pos++) {
519 if ('\t' == *p) {
520 if ( ! (MDOC_LITERAL & mdoc->flags))
521 if ( ! warn_print(mdoc, line, pos))
522 return(0);
523 } else if ( ! isprint((u_char)*p))
524 if ( ! warn_print(mdoc, line, pos))
525 return(0);
526
527 if ('\\' != *p)
528 continue;
529
530 c = mandoc_special(p);
531 if (c) {
532 p += c - 1;
533 pos += c - 1;
534 continue;
535 }
536 if ( ! (MDOC_IGN_ESCAPE & mdoc->pflags))
537 return(mdoc_perr(mdoc, line, pos, EESCAPE));
538 if ( ! mdoc_pwarn(mdoc, line, pos, EESCAPE))
539 return(0);
540 }
541
542 return(1);
543 }
544
545
546
547
548 static int
549 check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t)
550 {
551
552 assert(n->parent);
553 if ((MDOC_ROOT == t || tok == n->parent->tok) &&
554 (t == n->parent->type))
555 return(1);
556
557 return(mdoc_verr(mdoc, n->line, n->pos, "require parent %s",
558 MDOC_ROOT == t ? "<root>" : mdoc_macronames[tok]));
559 }
560
561
562
563 static int
564 pre_display(PRE_ARGS)
565 {
566 struct mdoc_node *node;
567
568 /* Display elements (`Bd', `D1'...) cannot be nested. */
569
570 if (MDOC_BLOCK != n->type)
571 return(1);
572
573 /* LINTED */
574 for (node = mdoc->last->parent; node; node = node->parent)
575 if (MDOC_BLOCK == node->type)
576 if (MDOC_Bd == node->tok)
577 break;
578 if (NULL == node)
579 return(1);
580
581 return(mdoc_nerr(mdoc, n, ENESTDISP));
582 }
583
584
585 static int
586 pre_bl(PRE_ARGS)
587 {
588 int pos, type, width, offset;
589
590 if (MDOC_BLOCK != n->type)
591 return(1);
592 if (NULL == n->args)
593 return(mdoc_nerr(mdoc, n, ELISTTYPE));
594
595 /* Make sure that only one type of list is specified. */
596
597 type = offset = width = -1;
598
599 /* LINTED */
600 for (pos = 0; pos < (int)n->args->argc; pos++)
601 switch (n->args->argv[pos].arg) {
602 case (MDOC_Bullet):
603 /* FALLTHROUGH */
604 case (MDOC_Dash):
605 /* FALLTHROUGH */
606 case (MDOC_Enum):
607 /* FALLTHROUGH */
608 case (MDOC_Hyphen):
609 /* FALLTHROUGH */
610 case (MDOC_Item):
611 /* FALLTHROUGH */
612 case (MDOC_Tag):
613 /* FALLTHROUGH */
614 case (MDOC_Diag):
615 /* FALLTHROUGH */
616 case (MDOC_Hang):
617 /* FALLTHROUGH */
618 case (MDOC_Ohang):
619 /* FALLTHROUGH */
620 case (MDOC_Inset):
621 /* FALLTHROUGH */
622 case (MDOC_Column):
623 /*
624 * Note that if a duplicate is detected, we
625 * remove the duplicate instead of passing it
626 * over. If we don't do this, mdoc_action will
627 * become confused when it scans over multiple
628 * types whilst setting its bitmasks.
629 *
630 * FIXME: this should occur in mdoc_action.c.
631 */
632 if (type >= 0) {
633 if ( ! mdoc_nwarn(mdoc, n, EMULTILIST))
634 return(0);
635 mdoc_argn_free(n->args, pos);
636 break;
637 }
638 type = n->args->argv[pos].arg;
639 break;
640 case (MDOC_Compact):
641 if (type < 0 && ! mdoc_nwarn(mdoc, n, ENOTYPE))
642 return(0);
643 break;
644 case (MDOC_Width):
645 if (width >= 0)
646 return(mdoc_nerr(mdoc, n, EARGREP));
647 if (type < 0 && ! mdoc_nwarn(mdoc, n, ENOTYPE))
648 return(0);
649 width = n->args->argv[pos].arg;
650 break;
651 case (MDOC_Offset):
652 if (offset >= 0)
653 return(mdoc_nerr(mdoc, n, EARGREP));
654 if (type < 0 && ! mdoc_nwarn(mdoc, n, ENOTYPE))
655 return(0);
656 offset = n->args->argv[pos].arg;
657 break;
658 default:
659 break;
660 }
661
662 if (type < 0)
663 return(mdoc_nerr(mdoc, n, ELISTTYPE));
664
665 /*
666 * Validate the width field. Some list types don't need width
667 * types and should be warned about them. Others should have it
668 * and must also be warned.
669 */
670
671 switch (type) {
672 case (MDOC_Tag):
673 if (width < 0 && ! mdoc_nwarn(mdoc, n, EMISSWIDTH))
674 return(0);
675 break;
676 case (MDOC_Column):
677 /* FALLTHROUGH */
678 case (MDOC_Diag):
679 /* FALLTHROUGH */
680 case (MDOC_Ohang):
681 /* FALLTHROUGH */
682 case (MDOC_Inset):
683 /* FALLTHROUGH */
684 case (MDOC_Item):
685 if (width >= 0 && ! mdoc_nwarn(mdoc, n, ENOWIDTH))
686 return(0);
687 break;
688 default:
689 break;
690 }
691
692 return(1);
693 }
694
695
696 static int
697 pre_bd(PRE_ARGS)
698 {
699 int i, type, err;
700
701 if (MDOC_BLOCK != n->type)
702 return(1);
703 if (NULL == n->args)
704 return(mdoc_nerr(mdoc, n, EDISPTYPE));
705
706 /* Make sure that only one type of display is specified. */
707
708 /* LINTED */
709 for (i = 0, err = type = 0; ! err &&
710 i < (int)n->args->argc; i++)
711 switch (n->args->argv[i].arg) {
712 case (MDOC_Centred):
713 /* FALLTHROUGH */
714 case (MDOC_Ragged):
715 /* FALLTHROUGH */
716 case (MDOC_Unfilled):
717 /* FALLTHROUGH */
718 case (MDOC_Filled):
719 /* FALLTHROUGH */
720 case (MDOC_Literal):
721 if (0 == type++)
722 break;
723 return(mdoc_nerr(mdoc, n, EMULTIDISP));
724 default:
725 break;
726 }
727
728 if (type)
729 return(1);
730 return(mdoc_nerr(mdoc, n, EDISPTYPE));
731 }
732
733
734 static int
735 pre_ss(PRE_ARGS)
736 {
737
738 if (MDOC_BLOCK != n->type)
739 return(1);
740 return(check_parent(mdoc, n, MDOC_Sh, MDOC_BODY));
741 }
742
743
744 static int
745 pre_sh(PRE_ARGS)
746 {
747
748 if (MDOC_BLOCK != n->type)
749 return(1);
750 return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
751 }
752
753
754 static int
755 pre_it(PRE_ARGS)
756 {
757
758 if (MDOC_BLOCK != n->type)
759 return(1);
760 return(check_parent(mdoc, n, MDOC_Bl, MDOC_BODY));
761 }
762
763
764 static int
765 pre_an(PRE_ARGS)
766 {
767
768 if (NULL == n->args || 1 == n->args->argc)
769 return(1);
770 return(mdoc_verr(mdoc, n->line, n->pos,
771 "only one argument allowed"));
772 }
773
774
775 static int
776 pre_lb(PRE_ARGS)
777 {
778
779 return(check_sec(mdoc, n, SEC_LIBRARY, SEC_CUSTOM));
780 }
781
782
783 static int
784 pre_rv(PRE_ARGS)
785 {
786
787 return(check_stdarg(mdoc, n));
788 }
789
790
791 static int
792 pre_ex(PRE_ARGS)
793 {
794
795 if ( ! check_msec(mdoc, n, 1, 6, 8, 0))
796 return(0);
797 return(check_stdarg(mdoc, n));
798 }
799
800
801 static int
802 pre_dt(PRE_ARGS)
803 {
804
805 /* FIXME: make sure is capitalised. */
806
807 if (0 == mdoc->meta.date || mdoc->meta.os)
808 if ( ! mdoc_nwarn(mdoc, n, EPROLOOO))
809 return(0);
810 if (mdoc->meta.title)
811 if ( ! mdoc_nwarn(mdoc, n, EPROLREP))
812 return(0);
813 return(1);
814 }
815
816
817 static int
818 pre_os(PRE_ARGS)
819 {
820
821 if (NULL == mdoc->meta.title || 0 == mdoc->meta.date)
822 if ( ! mdoc_nwarn(mdoc, n, EPROLOOO))
823 return(0);
824 if (mdoc->meta.os)
825 if ( ! mdoc_nwarn(mdoc, n, EPROLREP))
826 return(0);
827 return(1);
828 }
829
830
831 static int
832 pre_dd(PRE_ARGS)
833 {
834
835 if (mdoc->meta.title || mdoc->meta.os)
836 if ( ! mdoc_nwarn(mdoc, n, EPROLOOO))
837 return(0);
838 if (mdoc->meta.date)
839 if ( ! mdoc_nwarn(mdoc, n, EPROLREP))
840 return(0);
841 return(1);
842 }
843
844
845 static int
846 post_bf(POST_ARGS)
847 {
848 char *p;
849 struct mdoc_node *head;
850
851 if (MDOC_BLOCK != mdoc->last->type)
852 return(1);
853
854 head = mdoc->last->head;
855
856 if (mdoc->last->args && head->child)
857 return(mdoc_nerr(mdoc, mdoc->last, ELINE));
858 else if (mdoc->last->args)
859 return(1);
860
861 if (NULL == head->child || MDOC_TEXT != head->child->type)
862 return(mdoc_nerr(mdoc, mdoc->last, ELINE));
863
864 p = head->child->string;
865
866 if (0 == strcmp(p, "Em"))
867 return(1);
868 else if (0 == strcmp(p, "Li"))
869 return(1);
870 else if (0 == strcmp(p, "Sy"))
871 return(1);
872
873 return(mdoc_nerr(mdoc, head, EFONT));
874 }
875
876
877 static int
878 post_lb(POST_ARGS)
879 {
880
881 if (mdoc_a2lib(mdoc->last->child->string))
882 return(1);
883 return(mdoc_nwarn(mdoc, mdoc->last, ELIB));
884 }
885
886
887 static int
888 post_vt(POST_ARGS)
889 {
890 const struct mdoc_node *n;
891
892 /*
893 * The Vt macro comes in both ELEM and BLOCK form, both of which
894 * have different syntaxes (yet more context-sensitive
895 * behaviour). ELEM types must have a child; BLOCK types,
896 * specifically the BODY, should only have TEXT children.
897 */
898
899 if (MDOC_ELEM == mdoc->last->type)
900 return(eerr_ge1(mdoc));
901 if (MDOC_BODY != mdoc->last->type)
902 return(1);
903
904 for (n = mdoc->last->child; n; n = n->next)
905 if (MDOC_TEXT != n->type)
906 if ( ! mdoc_nwarn(mdoc, n, EBADCHILD))
907 return(0);
908
909 return(1);
910 }
911
912
913 static int
914 post_nm(POST_ARGS)
915 {
916
917 if (mdoc->last->child)
918 return(1);
919 if (mdoc->meta.name)
920 return(1);
921 return(mdoc_nerr(mdoc, mdoc->last, ENAME));
922 }
923
924
925 static int
926 post_at(POST_ARGS)
927 {
928
929 if (NULL == mdoc->last->child)
930 return(1);
931 if (MDOC_TEXT != mdoc->last->child->type)
932 return(mdoc_nerr(mdoc, mdoc->last, EATT));
933 if (mdoc_a2att(mdoc->last->child->string))
934 return(1);
935 return(mdoc_nerr(mdoc, mdoc->last, EATT));
936 }
937
938
939 static int
940 post_an(POST_ARGS)
941 {
942
943 if (mdoc->last->args) {
944 if (NULL == mdoc->last->child)
945 return(1);
946 return(mdoc_nerr(mdoc, mdoc->last, ENOLINE));
947 }
948
949 if (mdoc->last->child)
950 return(1);
951 return(mdoc_nerr(mdoc, mdoc->last, ELINE));
952 }
953
954
955 static int
956 post_it(POST_ARGS)
957 {
958 int type, i, cols;
959 struct mdoc_node *n, *c;
960
961 if (MDOC_BLOCK != mdoc->last->type)
962 return(1);
963
964 n = mdoc->last->parent->parent;
965 if (NULL == n->args)
966 return(mdoc_nerr(mdoc, mdoc->last, ELISTTYPE));
967
968 /* Some types require block-head, some not. */
969
970 /* LINTED */
971 for (cols = type = -1, i = 0; -1 == type &&
972 i < (int)n->args->argc; i++)
973 switch (n->args->argv[i].arg) {
974 case (MDOC_Tag):
975 /* FALLTHROUGH */
976 case (MDOC_Diag):
977 /* FALLTHROUGH */
978 case (MDOC_Hang):
979 /* FALLTHROUGH */
980 case (MDOC_Ohang):
981 /* FALLTHROUGH */
982 case (MDOC_Inset):
983 /* FALLTHROUGH */
984 case (MDOC_Bullet):
985 /* FALLTHROUGH */
986 case (MDOC_Dash):
987 /* FALLTHROUGH */
988 case (MDOC_Enum):
989 /* FALLTHROUGH */
990 case (MDOC_Hyphen):
991 /* FALLTHROUGH */
992 case (MDOC_Item):
993 type = n->args->argv[i].arg;
994 break;
995 case (MDOC_Column):
996 type = n->args->argv[i].arg;
997 cols = (int)n->args->argv[i].sz;
998 break;
999 default:
1000 break;
1001 }
1002
1003 if (-1 == type)
1004 return(mdoc_nerr(mdoc, mdoc->last, ELISTTYPE));
1005
1006 switch (type) {
1007 case (MDOC_Tag):
1008 if (NULL == mdoc->last->head->child)
1009 if ( ! mdoc_nwarn(mdoc, mdoc->last, ELINE))
1010 return(0);
1011 break;
1012 case (MDOC_Hang):
1013 /* FALLTHROUGH */
1014 case (MDOC_Ohang):
1015 /* FALLTHROUGH */
1016 case (MDOC_Inset):
1017 /* FALLTHROUGH */
1018 case (MDOC_Diag):
1019 if (NULL == mdoc->last->head->child)
1020 if ( ! mdoc_nwarn(mdoc, mdoc->last, ELINE))
1021 return(0);
1022 if (NULL == mdoc->last->body->child)
1023 if ( ! mdoc_nwarn(mdoc, mdoc->last, EMULTILINE))
1024 return(0);
1025 break;
1026 case (MDOC_Bullet):
1027 /* FALLTHROUGH */
1028 case (MDOC_Dash):
1029 /* FALLTHROUGH */
1030 case (MDOC_Enum):
1031 /* FALLTHROUGH */
1032 case (MDOC_Hyphen):
1033 /* FALLTHROUGH */
1034 case (MDOC_Item):
1035 if (mdoc->last->head->child)
1036 if ( ! mdoc_nwarn(mdoc, mdoc->last, ENOLINE))
1037 return(0);
1038 if (NULL == mdoc->last->body->child)
1039 if ( ! mdoc_nwarn(mdoc, mdoc->last, EMULTILINE))
1040 return(0);
1041 break;
1042 case (MDOC_Column):
1043 if (NULL == mdoc->last->head->child)
1044 if ( ! mdoc_nwarn(mdoc, mdoc->last, ELINE))
1045 return(0);
1046 if (mdoc->last->body->child)
1047 if ( ! mdoc_nwarn(mdoc, mdoc->last, ENOMULTILINE))
1048 return(0);
1049 c = mdoc->last->child;
1050 for (i = 0; c && MDOC_HEAD == c->type; c = c->next)
1051 i++;
1052
1053 if (i < cols || i == (cols + 1)) {
1054 if ( ! mdoc_vwarn(mdoc, mdoc->last->line,
1055 mdoc->last->pos, "column "
1056 "mismatch: have %d, want %d",
1057 i, cols))
1058 return(0);
1059 break;
1060 } else if (i == cols)
1061 break;
1062
1063 return(mdoc_verr(mdoc, mdoc->last->line,
1064 mdoc->last->pos, "column mismatch: "
1065 "have %d, want %d", i, cols));
1066 default:
1067 break;
1068 }
1069
1070 return(1);
1071 }
1072
1073
1074 static int
1075 post_bl_head(POST_ARGS)
1076 {
1077 int i;
1078 const struct mdoc_node *n;
1079 const struct mdoc_argv *a;
1080
1081 n = mdoc->last->parent;
1082 assert(n->args);
1083
1084 for (i = 0; i < (int)n->args->argc; i++) {
1085 a = &n->args->argv[i];
1086 if (a->arg == MDOC_Column) {
1087 if (a->sz && mdoc->last->nchild)
1088 return(mdoc_nerr(mdoc, n, ECOLMIS));
1089 return(1);
1090 }
1091 }
1092
1093 if (0 == (i = mdoc->last->nchild))
1094 return(1);
1095 return(warn_count(mdoc, "==", 0, "line arguments", i));
1096 }
1097
1098
1099 static int
1100 post_bl(POST_ARGS)
1101 {
1102 struct mdoc_node *n;
1103
1104 if (MDOC_HEAD == mdoc->last->type)
1105 return(post_bl_head(mdoc));
1106 if (MDOC_BODY != mdoc->last->type)
1107 return(1);
1108 if (NULL == mdoc->last->child)
1109 return(1);
1110
1111 /*
1112 * We only allow certain children of `Bl'. This is usually on
1113 * `It', but apparently `Sm' occurs here and there, so we let
1114 * that one through, too.
1115 */
1116
1117 /* LINTED */
1118 for (n = mdoc->last->child; n; n = n->next) {
1119 if (MDOC_BLOCK == n->type && MDOC_It == n->tok)
1120 continue;
1121 if (MDOC_Sm == n->tok)
1122 continue;
1123 return(mdoc_nerr(mdoc, n, EBADCHILD));
1124 }
1125
1126 return(1);
1127 }
1128
1129
1130 static int
1131 ebool(struct mdoc *mdoc)
1132 {
1133 struct mdoc_node *n;
1134
1135 /* LINTED */
1136 for (n = mdoc->last->child; n; n = n->next) {
1137 if (MDOC_TEXT != n->type)
1138 break;
1139 if (0 == strcmp(n->string, "on"))
1140 continue;
1141 if (0 == strcmp(n->string, "off"))
1142 continue;
1143 break;
1144 }
1145
1146 if (NULL == n)
1147 return(1);
1148 return(mdoc_nerr(mdoc, n, EBOOL));
1149 }
1150
1151
1152 static int
1153 post_root(POST_ARGS)
1154 {
1155
1156 if (NULL == mdoc->first->child)
1157 return(mdoc_nerr(mdoc, mdoc->first, ENODAT));
1158 if ( ! (MDOC_PBODY & mdoc->flags))
1159 return(mdoc_nerr(mdoc, mdoc->first, ENOPROLOGUE));
1160
1161 if (MDOC_BLOCK != mdoc->first->child->type)
1162 return(mdoc_nerr(mdoc, mdoc->first, ENODAT));
1163 if (MDOC_Sh != mdoc->first->child->tok)
1164 return(mdoc_nerr(mdoc, mdoc->first, ENODAT));
1165
1166 return(1);
1167 }
1168
1169
1170 static int
1171 post_st(POST_ARGS)
1172 {
1173
1174 if (mdoc_a2st(mdoc->last->child->string))
1175 return(1);
1176 return(mdoc_nerr(mdoc, mdoc->last, EBADSTAND));
1177 }
1178
1179
1180 static int
1181 post_rs(POST_ARGS)
1182 {
1183 struct mdoc_node *nn;
1184
1185 if (MDOC_BODY != mdoc->last->type)
1186 return(1);
1187
1188 for (nn = mdoc->last->child; nn; nn = nn->next)
1189 switch (nn->tok) {
1190 case(MDOC__U):
1191 /* FALLTHROUGH */
1192 case(MDOC__Q):
1193 /* FALLTHROUGH */
1194 case(MDOC__C):
1195 /* FALLTHROUGH */
1196 case(MDOC__A):
1197 /* FALLTHROUGH */
1198 case(MDOC__B):
1199 /* FALLTHROUGH */
1200 case(MDOC__D):
1201 /* FALLTHROUGH */
1202 case(MDOC__I):
1203 /* FALLTHROUGH */
1204 case(MDOC__J):
1205 /* FALLTHROUGH */
1206 case(MDOC__N):
1207 /* FALLTHROUGH */
1208 case(MDOC__O):
1209 /* FALLTHROUGH */
1210 case(MDOC__P):
1211 /* FALLTHROUGH */
1212 case(MDOC__R):
1213 /* FALLTHROUGH */
1214 case(MDOC__T):
1215 /* FALLTHROUGH */
1216 case(MDOC__V):
1217 break;
1218 default:
1219 return(mdoc_nerr(mdoc, nn, EBADCHILD));
1220 }
1221
1222 return(1);
1223 }
1224
1225
1226 static int
1227 post_sh(POST_ARGS)
1228 {
1229
1230 if (MDOC_HEAD == mdoc->last->type)
1231 return(post_sh_head(mdoc));
1232 if (MDOC_BODY == mdoc->last->type)
1233 return(post_sh_body(mdoc));
1234
1235 return(1);
1236 }
1237
1238
1239 static int
1240 post_sh_body(POST_ARGS)
1241 {
1242 struct mdoc_node *n;
1243
1244 if (SEC_NAME != mdoc->lastsec)
1245 return(1);
1246
1247 /*
1248 * Warn if the NAME section doesn't contain the `Nm' and `Nd'
1249 * macros (can have multiple `Nm' and one `Nd'). Note that the
1250 * children of the BODY declaration can also be "text".
1251 */
1252
1253 if (NULL == (n = mdoc->last->child))
1254 return(mdoc_nwarn(mdoc, mdoc->last, ENAMESECINC));
1255
1256 for ( ; n && n->next; n = n->next) {
1257 if (MDOC_ELEM == n->type && MDOC_Nm == n->tok)
1258 continue;
1259 if (MDOC_TEXT == n->type)
1260 continue;
1261 if ( ! mdoc_nwarn(mdoc, mdoc->last, ENAMESECINC))
1262 return(0);
1263 }
1264
1265 assert(n);
1266 if (MDOC_BLOCK == n->type && MDOC_Nd == n->tok)
1267 return(1);
1268 return(mdoc_nwarn(mdoc, mdoc->last, ENAMESECINC));
1269 }
1270
1271
1272 static int
1273 post_sh_head(POST_ARGS)
1274 {
1275 char buf[64];
1276 enum mdoc_sec sec;
1277 const struct mdoc_node *n;
1278
1279 /*
1280 * Process a new section. Sections are either "named" or
1281 * "custom"; custom sections are user-defined, while named ones
1282 * usually follow a conventional order and may only appear in
1283 * certain manual sections.
1284 */
1285
1286 buf[0] = 0;
1287
1288 for (n = mdoc->last->child; n; n = n->next) {
1289 /* XXX - copied from compact(). */
1290 assert(MDOC_TEXT == n->type);
1291
1292 if (strlcat(buf, n->string, 64) >= 64)
1293 return(mdoc_nerr(mdoc, n, ETOOLONG));
1294 if (NULL == n->next)
1295 continue;
1296 if (strlcat(buf, " ", 64) >= 64)
1297 return(mdoc_nerr(mdoc, n, ETOOLONG));
1298 }
1299
1300 sec = mdoc_atosec(buf);
1301
1302 /*
1303 * Check: NAME should always be first, CUSTOM has no roles,
1304 * non-CUSTOM has a conventional order to be followed.
1305 */
1306
1307 if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed &&
1308 ! mdoc_nwarn(mdoc, mdoc->last, ESECNAME))
1309 return(0);
1310 if (SEC_CUSTOM == sec)
1311 return(1);
1312 if (sec == mdoc->lastnamed)
1313 if ( ! mdoc_nwarn(mdoc, mdoc->last, ESECREP))
1314 return(0);
1315 if (sec < mdoc->lastnamed)
1316 if ( ! mdoc_nwarn(mdoc, mdoc->last, ESECOOO))
1317 return(0);
1318
1319 /*
1320 * Check particular section/manual conventions. LIBRARY can
1321 * only occur in msec 2, 3 (TODO: are there more of these?).
1322 */
1323
1324 switch (sec) {
1325 case (SEC_LIBRARY):
1326 switch (mdoc->meta.msec) {
1327 case (2):
1328 /* FALLTHROUGH */
1329 case (3):
1330 break;
1331 default:
1332 return(mdoc_nwarn(mdoc, mdoc->last, EWRONGMSEC));
1333 }
1334 break;
1335 default:
1336 break;
1337 }
1338
1339 return(1);
1340 }
1341
1342
1343 static int
1344 pre_fd(PRE_ARGS)
1345 {
1346
1347 return(check_sec(mdoc, n, SEC_SYNOPSIS, SEC_CUSTOM));
1348 }