]> git.cameronkatri.com Git - mandoc.git/blob - validate.c
Lint checks.
[mandoc.git] / validate.c
1 /* $Id: validate.c,v 1.38 2009/01/17 20:10:36 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008 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
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
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.
18 */
19 #include <assert.h>
20 #include <stdlib.h>
21
22 #include "private.h"
23
24 typedef int (*v_pre)(struct mdoc *, struct mdoc_node *);
25 typedef int (*v_post)(struct mdoc *);
26
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. */
32
33 struct valids {
34 v_pre *pre;
35 v_post *post;
36 };
37
38 /* Utility checks. */
39
40 static int pre_check_parent(struct mdoc *, struct mdoc_node *,
41 int, enum mdoc_type);
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);
49
50 /* Specific pre-child-parse routines. */
51
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 *);
67
68 /* Specific post-child-parse routines. */
69
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 *);
92
93 /* Collections of pre-child-parse routines. */
94
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 };
108
109 /* Collections of post-child-parse routines. */
110
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 };
128
129 /* Per-macro pre- and post-child-check routine collections. */
130
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 */
240 };
241
242
243 static int
244 post_check_children_count(struct mdoc *mdoc)
245 {
246 struct mdoc_node *n;
247 int i;
248
249 for (i = 0, n = mdoc->last->child; n; n = n->next, i++)
250 /* Do nothing */ ;
251 return(i);
252 }
253
254
255 static int
256 post_check_children_gt(struct mdoc *mdoc, int sz)
257 {
258 int i;
259
260 if ((i = post_check_children_count(mdoc)) > sz)
261 return(1);
262 return(mdoc_err(mdoc, "macro requires more than %d "
263 "parameters (have %d)", sz, i));
264 }
265
266
267 static int
268 post_check_children_eq(struct mdoc *mdoc, int sz)
269 {
270 int i;
271
272 if ((i = post_check_children_count(mdoc)) == sz)
273 return(1);
274 return(mdoc_err(mdoc, "macro requires %d parameters "
275 "(have %d)", sz, i));
276 }
277
278
279 static int
280 post_check_children_lt(struct mdoc *mdoc, int sz)
281 {
282 int i;
283
284 if ((i = post_check_children_count(mdoc)) < sz)
285 return(1);
286 return(mdoc_err(mdoc, "macro requires less than %d "
287 "parameters (have %d)", sz, i));
288 }
289
290
291 static int
292 pre_check_stdarg(struct mdoc *mdoc, struct mdoc_node *node)
293 {
294
295 if (1 == node->data.elem.argc &&
296 MDOC_Std == node->data.elem.argv[0].arg)
297 return(1);
298 return(mdoc_nwarn(mdoc, node, WARN_COMPAT,
299 "macro suggests single `%s' argument",
300 mdoc_argnames[MDOC_Std]));
301 }
302
303
304 static int
305 pre_check_msecs(struct mdoc *mdoc, struct mdoc_node *node,
306 int sz, enum mdoc_msec *msecs)
307 {
308 int i;
309
310 for (i = 0; i < sz; i++)
311 if (msecs[i] == mdoc->meta.msec)
312 return(1);
313 return(mdoc_nwarn(mdoc, node, WARN_COMPAT, "macro not "
314 "appropriate for manual section"));
315 }
316
317
318 static int
319 pre_check_parent(struct mdoc *mdoc, struct mdoc_node *node,
320 int tok, enum mdoc_type type)
321 {
322
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),
326 mdoc_type2a(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]));
331 return(1);
332 }
333
334
335 static int
336 berr_eq0(struct mdoc *mdoc)
337 {
338
339 if (MDOC_BODY != mdoc->last->type)
340 return(1);
341 if (NULL == mdoc->last->child)
342 return(1);
343 return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests no body children"));
344 }
345
346
347 static int
348 bwarn_ge1(struct mdoc *mdoc)
349 {
350
351 if (MDOC_BODY != mdoc->last->type)
352 return(1);
353 if (mdoc->last->child)
354 return(1);
355 return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests one or more body children"));
356 }
357
358
359 static int
360 ewarn_eq0(struct mdoc *mdoc)
361 {
362
363 assert(MDOC_ELEM == mdoc->last->type);
364 if (NULL == mdoc->last->child)
365 return(1);
366 return(mdoc_pwarn(mdoc, mdoc->last->child->line,
367 mdoc->last->child->pos, WARN_SYNTAX, "macro suggests no parameters"));
368 }
369
370
371 static int
372 ewarn_ge1(struct mdoc *mdoc)
373 {
374
375 assert(MDOC_ELEM == mdoc->last->type);
376 if (mdoc->last->child)
377 return(1);
378 return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests one or more parameters"));
379 }
380
381
382 static int
383 eerr_eq1(struct mdoc *mdoc)
384 {
385
386 assert(MDOC_ELEM == mdoc->last->type);
387 return(post_check_children_eq(mdoc, 1));
388 }
389
390
391 static int
392 eerr_le2(struct mdoc *mdoc)
393 {
394
395 assert(MDOC_ELEM == mdoc->last->type);
396 return(post_check_children_lt(mdoc, 3));
397 }
398
399
400 static int
401 eerr_le1(struct mdoc *mdoc)
402 {
403
404 assert(MDOC_ELEM == mdoc->last->type);
405 return(post_check_children_lt(mdoc, 2));
406 }
407
408
409 static int
410 eerr_eq0(struct mdoc *mdoc)
411 {
412
413 assert(MDOC_ELEM == mdoc->last->type);
414 return(post_check_children_eq(mdoc, 0));
415 }
416
417
418 static int
419 eerr_ge1(struct mdoc *mdoc)
420 {
421
422 assert(MDOC_ELEM == mdoc->last->type);
423 return(post_check_children_gt(mdoc, 0));
424 }
425
426
427 static int
428 herr_eq0(struct mdoc *mdoc)
429 {
430
431 if (MDOC_HEAD != mdoc->last->type)
432 return(1);
433 return(post_check_children_eq(mdoc, 0));
434 }
435
436
437 static int
438 hwarn_ge1(struct mdoc *mdoc)
439 {
440
441 if (MDOC_HEAD != mdoc->last->type)
442 return(1);
443 if (mdoc->last->child)
444 return(1);
445 return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests one or more parameters"));
446 }
447
448
449 static int
450 herr_ge1(struct mdoc *mdoc)
451 {
452
453 if (MDOC_HEAD != mdoc->last->type)
454 return(1);
455 return(post_check_children_gt(mdoc, 0));
456 }
457
458
459 static int
460 pre_display(struct mdoc *mdoc, struct mdoc_node *node)
461 {
462 struct mdoc_node *n;
463
464 if (MDOC_BLOCK != node->type)
465 return(1);
466
467 assert(mdoc->last);
468 /* LINTED */
469 for (n = mdoc->last->parent; n; n = n->parent)
470 if (MDOC_BLOCK == n->type)
471 if (MDOC_Bd == n->tok)
472 break;
473 if (NULL == n)
474 return(1);
475 return(mdoc_nerr(mdoc, node, "displays may not be nested"));
476 }
477
478
479 static int
480 pre_bl(struct mdoc *mdoc, struct mdoc_node *node)
481 {
482 int type, err;
483 struct mdoc_arg *argv;
484 size_t i, argc;
485
486 if (MDOC_BLOCK != node->type)
487 return(1);
488 assert(MDOC_Bl == node->tok);
489
490 argv = NULL;
491 argc = node->data.block.argc;
492
493 /* LINTED */
494 for (i = type = err = 0; i < argc; i++) {
495 argv = &node->data.block.argv[(int)i];
496 assert(argv);
497 switch (argv->arg) {
498 case (MDOC_Bullet):
499 /* FALLTHROUGH */
500 case (MDOC_Dash):
501 /* FALLTHROUGH */
502 case (MDOC_Enum):
503 /* FALLTHROUGH */
504 case (MDOC_Hyphen):
505 /* FALLTHROUGH */
506 case (MDOC_Item):
507 /* FALLTHROUGH */
508 case (MDOC_Tag):
509 /* FALLTHROUGH */
510 case (MDOC_Diag):
511 /* FALLTHROUGH */
512 case (MDOC_Hang):
513 /* FALLTHROUGH */
514 case (MDOC_Ohang):
515 /* FALLTHROUGH */
516 case (MDOC_Inset):
517 /* FALLTHROUGH */
518 case (MDOC_Column):
519 if (type)
520 err++;
521 type++;
522 break;
523 default:
524 break;
525 }
526 }
527 if (0 == type)
528 return(mdoc_err(mdoc, "no list type specified"));
529 if (0 == err)
530 return(1);
531 assert(argv);
532 return(mdoc_perr(mdoc, argv->line,
533 argv->pos, "only one list type possible"));
534 }
535
536
537 static int
538 pre_bd(struct mdoc *mdoc, struct mdoc_node *node)
539 {
540 int type, err;
541 struct mdoc_arg *argv;
542 size_t i, argc;
543
544 if (MDOC_BLOCK != node->type)
545 return(1);
546 assert(MDOC_Bd == node->tok);
547
548 argv = NULL;
549 argc = node->data.block.argc;
550
551 /* LINTED */
552 for (err = i = type = 0; 0 == err && i < argc; i++) {
553 argv = &node->data.block.argv[(int)i];
554 assert(argv);
555 switch (argv->arg) {
556 case (MDOC_Ragged):
557 /* FALLTHROUGH */
558 case (MDOC_Unfilled):
559 /* FALLTHROUGH */
560 case (MDOC_Filled):
561 /* FALLTHROUGH */
562 case (MDOC_Literal):
563 /* FALLTHROUGH */
564 case (MDOC_File):
565 if (type)
566 err++;
567 type++;
568 break;
569 default:
570 break;
571 }
572 }
573 if (0 == type)
574 return(mdoc_err(mdoc, "no display type specified"));
575 if (0 == err)
576 return(1);
577 assert(argv);
578 return(mdoc_perr(mdoc, argv->line,
579 argv->pos, "only one display type possible"));
580 }
581
582
583 static int
584 pre_ss(struct mdoc *mdoc, struct mdoc_node *node)
585 {
586
587 if (MDOC_BLOCK != node->type)
588 return(1);
589 return(pre_check_parent(mdoc, node, MDOC_Sh, MDOC_BODY));
590 }
591
592
593 static int
594 pre_sh(struct mdoc *mdoc, struct mdoc_node *node)
595 {
596
597 if (MDOC_BLOCK != node->type)
598 return(1);
599 return(pre_check_parent(mdoc, node, -1, MDOC_ROOT));
600 }
601
602
603 static int
604 pre_st(struct mdoc *mdoc, struct mdoc_node *node)
605 {
606
607 assert(MDOC_ELEM == node->type);
608 assert(MDOC_St == node->tok);
609 if (1 == node->data.elem.argc)
610 return(1);
611 return(mdoc_nerr(mdoc, node, "macro must have one argument"));
612 }
613
614
615 static int
616 pre_an(struct mdoc *mdoc, struct mdoc_node *node)
617 {
618
619 assert(MDOC_ELEM == node->type);
620 assert(MDOC_An == node->tok);
621 if (1 >= node->data.elem.argc)
622 return(1);
623 return(mdoc_nerr(mdoc, node, "macro may only have one argument"));
624 }
625
626
627 static int
628 pre_rv(struct mdoc *mdoc, struct mdoc_node *node)
629 {
630 enum mdoc_msec msecs[2];
631
632 assert(MDOC_ELEM == node->type);
633 assert(MDOC_Rv == node->tok);
634
635 msecs[0] = MSEC_2;
636 msecs[1] = MSEC_3;
637 if ( ! pre_check_msecs(mdoc, node, 2, msecs))
638 return(0);
639 return(pre_check_stdarg(mdoc, node));
640 }
641
642
643 static int
644 pre_ex(struct mdoc *mdoc, struct mdoc_node *node)
645 {
646 enum mdoc_msec msecs[3];
647
648 assert(MDOC_ELEM == node->type);
649 assert(MDOC_Ex == node->tok);
650
651 msecs[0] = MSEC_1;
652 msecs[1] = MSEC_6;
653 msecs[2] = MSEC_8;
654 if ( ! pre_check_msecs(mdoc, node, 3, msecs))
655 return(0);
656 return(pre_check_stdarg(mdoc, node));
657 }
658
659
660 static int
661 pre_er(struct mdoc *mdoc, struct mdoc_node *node)
662 {
663 enum mdoc_msec msecs[1];
664
665 msecs[0] = MSEC_2;
666 return(pre_check_msecs(mdoc, node, 1, msecs));
667 }
668
669
670 static int
671 pre_cd(struct mdoc *mdoc, struct mdoc_node *node)
672 {
673 enum mdoc_msec msecs[1];
674
675 msecs[0] = MSEC_4;
676 return(pre_check_msecs(mdoc, node, 1, msecs));
677 }
678
679
680 static int
681 pre_it(struct mdoc *mdoc, struct mdoc_node *node)
682 {
683
684 if (MDOC_BLOCK != node->type)
685 return(1);
686 return(pre_check_parent(mdoc, node, MDOC_Bl, MDOC_BODY));
687 }
688
689
690 static int
691 pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
692 {
693
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);
697
698 /* Check for ordering. */
699
700 switch (node->tok) {
701 case (MDOC_Os):
702 if (mdoc->meta.title && mdoc->meta.date)
703 break;
704 return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
705 case (MDOC_Dt):
706 if (NULL == mdoc->meta.title && mdoc->meta.date)
707 break;
708 return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
709 case (MDOC_Dd):
710 if (NULL == mdoc->meta.title && 0 == mdoc->meta.date)
711 break;
712 return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
713 default:
714 abort();
715 /* NOTREACHED */
716 }
717
718 /* Check for repetition. */
719
720 switch (node->tok) {
721 case (MDOC_Os):
722 if (NULL == mdoc->meta.os)
723 return(1);
724 break;
725 case (MDOC_Dd):
726 if (0 == mdoc->meta.date)
727 return(1);
728 break;
729 case (MDOC_Dt):
730 if (NULL == mdoc->meta.title)
731 return(1);
732 break;
733 default:
734 abort();
735 /* NOTREACHED */
736 }
737
738 return(mdoc_nerr(mdoc, node, "prologue macro repeated"));
739 }
740
741
742 static int
743 post_nm(struct mdoc *mdoc)
744 {
745
746 assert(MDOC_ELEM == mdoc->last->type);
747 assert(MDOC_Nm == mdoc->last->tok);
748 if (mdoc->last->child)
749 return(1);
750 if (mdoc->meta.name)
751 return(1);
752 return(mdoc_err(mdoc, "macro `%s' has not been invoked with a name",
753 mdoc_macronames[MDOC_Nm]));
754 }
755
756
757 static int
758 post_xr(struct mdoc *mdoc)
759 {
760 struct mdoc_node *n;
761
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);
766
767 if (NULL == (n = mdoc->last->child->next))
768 return(1);
769 assert(MDOC_TEXT == n->type);
770 if (MSEC_DEFAULT != mdoc_atomsec(n->data.text.string))
771 return(1);
772 return(mdoc_nerr(mdoc, n, "invalid manual section"));
773 }
774
775
776 static int
777 post_at(struct mdoc *mdoc)
778 {
779
780 assert(MDOC_ELEM == mdoc->last->type);
781 assert(MDOC_At == mdoc->last->tok);
782
783 if (NULL == mdoc->last->child)
784 return(1);
785 assert(MDOC_TEXT == mdoc->last->child->type);
786
787 if (ATT_DEFAULT != mdoc_atoatt(mdoc->last->child->data.text.string))
788 return(1);
789 return(mdoc_err(mdoc, "macro expects a valid AT&T version symbol"));
790 }
791
792
793 static int
794 post_an(struct mdoc *mdoc)
795 {
796
797 assert(MDOC_ELEM == mdoc->last->type);
798 assert(MDOC_An == mdoc->last->tok);
799
800 if (0 != mdoc->last->data.elem.argc) {
801 if (NULL == mdoc->last->child)
802 return(1);
803 return(mdoc_err(mdoc, "macro expects either argument or parameters"));
804 }
805
806 if (mdoc->last->child)
807 return(1);
808 return(mdoc_err(mdoc, "macro expects either argument or parameters"));
809 }
810
811
812 static int
813 post_ex(struct mdoc *mdoc)
814 {
815
816 assert(MDOC_ELEM == mdoc->last->type);
817 assert(MDOC_Ex == mdoc->last->tok);
818
819 if (0 == mdoc->last->data.elem.argc) {
820 if (mdoc->last->child)
821 return(1);
822 return(mdoc_err(mdoc, "macro expects `%s' or a single child",
823 mdoc_argnames[MDOC_Std]));
824 }
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]));
834 return(1);
835 }
836
837
838 /* Warn if `Bl' type-specific syntax isn't reflected in items. */
839 static int
840 post_it(struct mdoc *mdoc)
841 {
842 int type, sv;
843 #define TYPE_NONE (0)
844 #define TYPE_BODY (1)
845 #define TYPE_HEAD (2)
846 size_t i, argc;
847 struct mdoc_node *n;
848
849 if (MDOC_BLOCK != mdoc->last->type)
850 return(1);
851
852 assert(MDOC_It == mdoc->last->tok);
853
854 n = mdoc->last->parent;
855 assert(n);
856 assert(MDOC_Bl == n->tok);
857
858 n = n->parent;
859 assert(MDOC_BLOCK == n->type);
860 assert(MDOC_Bl == n->tok);
861
862 argc = n->data.block.argc;
863 type = TYPE_NONE;
864 sv = -1;
865
866 /* Some types require block-head, some not. */
867
868 /* LINTED */
869 for (i = 0; TYPE_NONE == type && i < argc; i++)
870 switch (n->data.block.argv[(int)i].arg) {
871 case (MDOC_Tag):
872 /* FALLTHROUGH */
873 case (MDOC_Diag):
874 /* FALLTHROUGH */
875 case (MDOC_Hang):
876 /* FALLTHROUGH */
877 case (MDOC_Ohang):
878 /* FALLTHROUGH */
879 case (MDOC_Inset):
880 type = TYPE_HEAD;
881 sv = n->data.block.argv[(int)i].arg;
882 break;
883 case (MDOC_Bullet):
884 /* FALLTHROUGH */
885 case (MDOC_Dash):
886 /* FALLTHROUGH */
887 case (MDOC_Enum):
888 /* FALLTHROUGH */
889 case (MDOC_Hyphen):
890 /* FALLTHROUGH */
891 case (MDOC_Item):
892 /* FALLTHROUGH */
893 case (MDOC_Column):
894 type = TYPE_BODY;
895 sv = n->data.block.argv[(int)i].arg;
896 break;
897 default:
898 break;
899 }
900
901 assert(TYPE_NONE != type);
902
903 if (TYPE_HEAD == type) {
904 n = mdoc->last->data.block.head;
905 assert(n);
906 if (NULL == n->child)
907 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests line parameters"))
908 return(0);
909
910 n = mdoc->last->data.block.body;
911 assert(n);
912 if (NULL == n->child)
913 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests body children"))
914 return(0);
915
916 return(1);
917 }
918
919 assert(TYPE_BODY == type);
920 assert(mdoc->last->data.block.head);
921
922 n = mdoc->last->data.block.head;
923 assert(n);
924 if (n->child)
925 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests no line parameters"))
926 return(0);
927
928 n = mdoc->last->data.block.body;
929 assert(n);
930 if (NULL == n->child)
931 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests body children"))
932 return(0);
933
934 assert(-1 != sv);
935 if (MDOC_Column != sv)
936 return(1);
937
938 /* Make sure the number of columns is sane. */
939
940 argc = mdoc->last->parent->parent->data.block.argv->sz;
941 n = mdoc->last->data.block.head->child;
942
943 for (i = 0; n; n = n->next)
944 i++;
945
946 if (i == argc)
947 return(1);
948 return(mdoc_err(mdoc, "expected %zu list columns, have %zu", argc, i));
949 #undef TYPE_NONE
950 #undef TYPE_BODY
951 #undef TYPE_HEAD
952 }
953
954
955 static int
956 post_bl(struct mdoc *mdoc)
957 {
958 struct mdoc_node *n;
959
960 if (MDOC_BODY != mdoc->last->type)
961 return(1);
962 assert(MDOC_Bl == mdoc->last->tok);
963
964 /* LINTED */
965 for (n = mdoc->last->child; n; n = n->next) {
966 if (MDOC_BLOCK == n->type)
967 if (MDOC_It == n->tok)
968 continue;
969 break;
970 }
971 if (NULL == n)
972 return(1);
973 return(mdoc_nerr(mdoc, n, "invalid child of parent macro `Bl'"));
974 }
975
976
977 static int
978 ebool(struct mdoc *mdoc)
979 {
980 struct mdoc_node *n;
981
982 assert(MDOC_ELEM == mdoc->last->type);
983 /* LINTED */
984 for (n = mdoc->last->child; n; n = n->next) {
985 if (MDOC_TEXT != n->type)
986 break;
987 if (xstrcmp(n->data.text.string, "on"))
988 continue;
989 if (xstrcmp(n->data.text.string, "off"))
990 continue;
991 break;
992 }
993 if (NULL == n)
994 return(1);
995 return(mdoc_nerr(mdoc, n, "expected boolean value"));
996 }
997
998
999 static int
1000 post_root(struct mdoc *mdoc)
1001 {
1002
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"));
1011 return(1);
1012 }
1013
1014
1015 /* Warn if conventional sections are out of order. */
1016 static int
1017 post_sh(struct mdoc *mdoc)
1018 {
1019 char buf[64];
1020 enum mdoc_sec sec;
1021
1022 if (MDOC_HEAD != mdoc->last->type)
1023 return(1);
1024 assert(MDOC_Sh == mdoc->last->tok);
1025
1026 if ( ! xstrlcats(buf, mdoc->last->child, 64))
1027 return(mdoc_err(mdoc, "macro parameters too long"));
1028
1029 if (SEC_CUSTOM == (sec = mdoc_atosec(buf)))
1030 return(1);
1031 if (sec > mdoc->sec_lastn)
1032 return(1);
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"));
1036 }
1037
1038
1039 int
1040 mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *node)
1041 {
1042 v_pre *p;
1043
1044 if (MDOC_TEXT == node->type)
1045 return(1);
1046 assert(MDOC_ROOT != node->type);
1047
1048 if (NULL == mdoc_valids[node->tok].pre)
1049 return(1);
1050 for (p = mdoc_valids[node->tok].pre; *p; p++)
1051 if ( ! (*p)(mdoc, node))
1052 return(0);
1053 return(1);
1054 }
1055
1056
1057 int
1058 mdoc_valid_post(struct mdoc *mdoc)
1059 {
1060 v_post *p;
1061
1062 if (MDOC_TEXT == mdoc->last->type)
1063 return(1);
1064 if (MDOC_ROOT == mdoc->last->type)
1065 return(post_root(mdoc));
1066
1067 if (NULL == mdoc_valids[mdoc->last->tok].post)
1068 return(1);
1069 for (p = mdoc_valids[mdoc->last->tok].post; *p; p++)
1070 if ( ! (*p)(mdoc))
1071 return(0);
1072
1073 return(1);
1074 }
1075