]> git.cameronkatri.com Git - mandoc.git/blob - validate.c
More validation on prologue/first NAME section.
[mandoc.git] / validate.c
1 /* $Id: validate.c,v 1.46 2009/01/21 11:35:26 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 /*
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.
30 */
31
32 typedef int (*v_pre)(struct mdoc *, struct mdoc_node *);
33 typedef int (*v_post)(struct mdoc *);
34
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, ...). */
40
41 struct valids {
42 v_pre *pre;
43 v_post *post;
44 };
45
46 /* Utility checks. */
47
48 static int pre_check_parent(struct mdoc *, struct mdoc_node *,
49 int, enum mdoc_type);
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);
59
60 /* Specific pre-child-parse routines. */
61
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 *);
77
78 /* Specific post-child-parse routines. */
79
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 *);
105
106 /* Collections of pre-child-parse routines. */
107
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 };
121
122 /* Collections of post-child-parse routines. */
123
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 };
145
146 /* Per-macro pre- and post-child-check routine collections. */
147
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 /* FIXME: NAME section internal ordering. */
154 { pres_sh, posts_sh }, /* Sh */
155 { pres_ss, posts_ss }, /* Ss */
156 { NULL, posts_pp }, /* Pp */
157 { pres_d1, posts_wline }, /* D1 */
158 { pres_d1, posts_wline }, /* Dl */
159 { pres_bd, posts_bd }, /* Bd */
160 { NULL, NULL }, /* Ed */
161 { pres_bl, posts_bl }, /* Bl */
162 { NULL, NULL }, /* El */
163 { pres_it, posts_it }, /* It */
164 { NULL, posts_text }, /* Ad */
165 { pres_an, posts_an }, /* An */
166 { NULL, NULL }, /* Ar */
167 { pres_cd, posts_text }, /* Cd */
168 { NULL, NULL }, /* Cm */
169 { NULL, posts_text }, /* Dv */
170 { pres_er, posts_text }, /* Er */
171 { NULL, posts_text }, /* Ev */
172 { pres_ex, posts_ex }, /* Ex */
173 { NULL, posts_text }, /* Fa */
174 /* FIXME: only in SYNOPSIS section. */
175 { NULL, posts_wtext }, /* Fd */
176 { NULL, NULL }, /* Fl */
177 { NULL, posts_text }, /* Fn */
178 { NULL, posts_wtext }, /* Ft */
179 { NULL, posts_text }, /* Ic */
180 { NULL, posts_in }, /* In */
181 { NULL, posts_text }, /* Li */
182 { NULL, posts_wtext }, /* Nd */
183 { NULL, posts_nm }, /* Nm */
184 { NULL, posts_wline }, /* Op */
185 { NULL, NULL }, /* Ot */
186 { NULL, NULL }, /* Pa */
187 { pres_rv, posts_notext }, /* Rv */
188 { pres_st, posts_notext }, /* St */
189 { NULL, posts_text }, /* Va */
190 { NULL, posts_text }, /* Vt */
191 { NULL, posts_xr }, /* Xr */
192 { NULL, posts_text }, /* %A */
193 { NULL, posts_text }, /* %B */
194 { NULL, posts_text }, /* %D */
195 { NULL, posts_text }, /* %I */
196 { NULL, posts_text }, /* %J */
197 { NULL, posts_text }, /* %N */
198 { NULL, posts_text }, /* %O */
199 { NULL, posts_text }, /* %P */
200 { NULL, posts_text }, /* %R */
201 { NULL, posts_text }, /* %T */
202 { NULL, posts_text }, /* %V */
203 { NULL, NULL }, /* Ac */
204 { NULL, NULL }, /* Ao */
205 { NULL, posts_wline }, /* Aq */
206 { NULL, posts_at }, /* At */
207 { NULL, NULL }, /* Bc */
208 { NULL, posts_bf }, /* Bf */
209 { NULL, NULL }, /* Bo */
210 { NULL, posts_wline }, /* Bq */
211 { NULL, NULL }, /* Bsx */
212 { NULL, NULL }, /* Bx */
213 { NULL, posts_bool }, /* Db */
214 { NULL, NULL }, /* Dc */
215 { NULL, NULL }, /* Do */
216 { NULL, posts_wline }, /* Dq */
217 { NULL, NULL }, /* Ec */
218 { NULL, NULL }, /* Ef */ /* -symbolic, etc. */
219 { NULL, posts_text }, /* Em */
220 { NULL, NULL }, /* Eo */
221 { NULL, NULL }, /* Fx */
222 { NULL, posts_text }, /* Ms */
223 { NULL, posts_notext }, /* No */
224 { NULL, posts_notext }, /* Ns */
225 { NULL, NULL }, /* Nx */
226 { NULL, NULL }, /* Ox */
227 { NULL, NULL }, /* Pc */
228 { NULL, NULL }, /* Pf */
229 { NULL, NULL }, /* Po */
230 { NULL, posts_wline }, /* Pq */
231 { NULL, NULL }, /* Qc */
232 { NULL, posts_wline }, /* Ql */
233 { NULL, NULL }, /* Qo */
234 { NULL, posts_wline }, /* Qq */
235 { NULL, NULL }, /* Re */
236 { NULL, posts_rs }, /* Rs */
237 { NULL, NULL }, /* Sc */
238 { NULL, NULL }, /* So */
239 { NULL, posts_wline }, /* Sq */
240 { NULL, posts_bool }, /* Sm */
241 { NULL, posts_text }, /* Sx */
242 { NULL, posts_text }, /* Sy */
243 { NULL, posts_text }, /* Tn */
244 { NULL, NULL }, /* Ux */
245 { NULL, NULL }, /* Xc */
246 { NULL, NULL }, /* Xo */
247 { NULL, posts_fo }, /* Fo */
248 { NULL, NULL }, /* Fc */
249 { NULL, NULL }, /* Oo */
250 { NULL, NULL }, /* Oc */
251 { NULL, posts_bk }, /* Bk */
252 { NULL, NULL }, /* Ek */
253 { NULL, posts_notext }, /* Bt */
254 { NULL, NULL }, /* Hf */
255 { NULL, NULL }, /* Fr */
256 { NULL, posts_notext }, /* Ud */
257 };
258
259
260 static int
261 post_check_children_count(struct mdoc *mdoc)
262 {
263 struct mdoc_node *n;
264 int i;
265
266 for (i = 0, n = mdoc->last->child; n; n = n->next, i++)
267 /* Do nothing */ ;
268 return(i);
269 }
270
271
272 static int
273 post_check_children_wgt(struct mdoc *mdoc, const char *p, int sz)
274 {
275 int i;
276
277 if ((i = post_check_children_count(mdoc)) > sz)
278 return(1);
279 return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests more "
280 "than %d %s (has %d)", sz, p, i));
281 }
282
283
284 static int
285 post_check_children_gt(struct mdoc *mdoc, const char *p, int sz)
286 {
287 int i;
288
289 if ((i = post_check_children_count(mdoc)) > sz)
290 return(1);
291 return(mdoc_err(mdoc, "macro requires more than %d "
292 "%s (has %d)", sz, p, i));
293 }
294
295
296 static int
297 post_check_children_weq(struct mdoc *mdoc, const char *p, int sz)
298 {
299 int i;
300
301 if ((i = post_check_children_count(mdoc)) == sz)
302 return(1);
303 return(mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests %d "
304 "%s (has %d)", sz, p, i));
305 }
306
307
308 static int
309 post_check_children_eq(struct mdoc *mdoc, const char *p, int sz)
310 {
311 int i;
312
313 if ((i = post_check_children_count(mdoc)) == sz)
314 return(1);
315 return(mdoc_err(mdoc, "macro requires %d %s "
316 "(have %d)", sz, p, i));
317 }
318
319
320 static int
321 post_check_children_lt(struct mdoc *mdoc, const char *p, int sz)
322 {
323 int i;
324
325 if ((i = post_check_children_count(mdoc)) < sz)
326 return(1);
327 return(mdoc_err(mdoc, "macro requires less than %d "
328 "%s (have %d)", sz, p, i));
329 }
330
331
332 static int
333 pre_check_stdarg(struct mdoc *mdoc, struct mdoc_node *node)
334 {
335
336 if (1 == node->data.elem.argc &&
337 MDOC_Std == node->data.elem.argv[0].arg)
338 return(1);
339 return(mdoc_nwarn(mdoc, node, WARN_COMPAT,
340 "macro suggests single `%s' argument",
341 mdoc_argnames[MDOC_Std]));
342 }
343
344
345 static int
346 pre_check_msecs(struct mdoc *mdoc, struct mdoc_node *node,
347 int sz, enum mdoc_msec *msecs)
348 {
349 int i;
350
351 for (i = 0; i < sz; i++)
352 if (msecs[i] == mdoc->meta.msec)
353 return(1);
354 return(mdoc_nwarn(mdoc, node, WARN_COMPAT, "macro not "
355 "appropriate for manual section"));
356 }
357
358
359 static int
360 pre_check_parent(struct mdoc *mdoc, struct mdoc_node *node,
361 int tok, enum mdoc_type type)
362 {
363
364 if (type != node->parent->type)
365 return(mdoc_nerr(mdoc, node, "invalid macro parent class %s, expected %s",
366 mdoc_type2a(node->parent->type),
367 mdoc_type2a(type)));
368 if (MDOC_ROOT != type && tok != node->parent->tok)
369 return(mdoc_nerr(mdoc, node, "invalid macro parent `%s', expected `%s'",
370 mdoc_macronames[node->parent->tok],
371 mdoc_macronames[tok]));
372 return(1);
373 }
374
375
376 static int
377 bwarn_ge1(struct mdoc *mdoc)
378 {
379
380 if (MDOC_BODY != mdoc->last->type)
381 return(1);
382 return(post_check_children_wgt(mdoc, "body children", 0));
383 }
384
385
386 static int
387 ewarn_eq1(struct mdoc *mdoc)
388 {
389
390 assert(MDOC_ELEM == mdoc->last->type);
391 return(post_check_children_weq(mdoc, "parameters", 1));
392 }
393
394
395 static int
396 ewarn_eq0(struct mdoc *mdoc)
397 {
398
399 assert(MDOC_ELEM == mdoc->last->type);
400 return(post_check_children_weq(mdoc, "parameters", 0));
401 }
402
403
404 static int
405 ewarn_ge1(struct mdoc *mdoc)
406 {
407
408 assert(MDOC_ELEM == mdoc->last->type);
409 return(post_check_children_wgt(mdoc, "parameters", 0));
410 }
411
412
413 static int
414 eerr_eq1(struct mdoc *mdoc)
415 {
416
417 assert(MDOC_ELEM == mdoc->last->type);
418 return(post_check_children_eq(mdoc, "parameters", 1));
419 }
420
421
422 static int
423 eerr_le2(struct mdoc *mdoc)
424 {
425
426 assert(MDOC_ELEM == mdoc->last->type);
427 return(post_check_children_lt(mdoc, "parameters", 3));
428 }
429
430
431 static int
432 eerr_le1(struct mdoc *mdoc)
433 {
434
435 assert(MDOC_ELEM == mdoc->last->type);
436 return(post_check_children_lt(mdoc, "parameters", 2));
437 }
438
439
440 static int
441 eerr_eq0(struct mdoc *mdoc)
442 {
443
444 assert(MDOC_ELEM == mdoc->last->type);
445 return(post_check_children_eq(mdoc, "parameters", 0));
446 }
447
448
449 static int
450 eerr_ge1(struct mdoc *mdoc)
451 {
452
453 assert(MDOC_ELEM == mdoc->last->type);
454 return(post_check_children_gt(mdoc, "parameters", 0));
455 }
456
457
458 static int
459 herr_eq0(struct mdoc *mdoc)
460 {
461
462 if (MDOC_HEAD != mdoc->last->type)
463 return(1);
464 return(post_check_children_eq(mdoc, "parameters", 0));
465 }
466
467
468 static int
469 herr_le1(struct mdoc *mdoc)
470 {
471 if (MDOC_HEAD != mdoc->last->type)
472 return(1);
473 return(post_check_children_lt(mdoc, "parameters", 2));
474 }
475
476
477 static int
478 herr_ge1(struct mdoc *mdoc)
479 {
480
481 if (MDOC_HEAD != mdoc->last->type)
482 return(1);
483 return(post_check_children_gt(mdoc, "parameters", 0));
484 }
485
486
487 static int
488 pre_display(struct mdoc *mdoc, struct mdoc_node *node)
489 {
490 struct mdoc_node *n;
491
492 if (MDOC_BLOCK != node->type)
493 return(1);
494
495 assert(mdoc->last);
496 /* LINTED */
497 for (n = mdoc->last->parent; n; n = n->parent)
498 if (MDOC_BLOCK == n->type)
499 if (MDOC_Bd == n->tok)
500 break;
501 if (NULL == n)
502 return(1);
503 return(mdoc_nerr(mdoc, node, "displays may not be nested"));
504 }
505
506
507 static int
508 pre_bl(struct mdoc *mdoc, struct mdoc_node *node)
509 {
510 int type, err;
511 struct mdoc_arg *argv;
512 size_t i, argc;
513
514 if (MDOC_BLOCK != node->type)
515 return(1);
516 assert(MDOC_Bl == node->tok);
517
518 argv = NULL;
519 argc = node->data.block.argc;
520
521 /* LINTED */
522 for (i = type = err = 0; i < argc; i++) {
523 argv = &node->data.block.argv[(int)i];
524 assert(argv);
525 switch (argv->arg) {
526 case (MDOC_Bullet):
527 /* FALLTHROUGH */
528 case (MDOC_Dash):
529 /* FALLTHROUGH */
530 case (MDOC_Enum):
531 /* FALLTHROUGH */
532 case (MDOC_Hyphen):
533 /* FALLTHROUGH */
534 case (MDOC_Item):
535 /* FALLTHROUGH */
536 case (MDOC_Tag):
537 /* FALLTHROUGH */
538 case (MDOC_Diag):
539 /* FALLTHROUGH */
540 case (MDOC_Hang):
541 /* FALLTHROUGH */
542 case (MDOC_Ohang):
543 /* FALLTHROUGH */
544 case (MDOC_Inset):
545 /* FALLTHROUGH */
546 case (MDOC_Column):
547 if (type)
548 err++;
549 type++;
550 break;
551 default:
552 break;
553 }
554 }
555 if (0 == type)
556 return(mdoc_err(mdoc, "no list type specified"));
557 if (0 == err)
558 return(1);
559 assert(argv);
560 return(mdoc_perr(mdoc, argv->line,
561 argv->pos, "only one list type possible"));
562 }
563
564
565 static int
566 pre_bd(struct mdoc *mdoc, struct mdoc_node *node)
567 {
568 int type, err;
569 struct mdoc_arg *argv;
570 size_t i, argc;
571
572 if (MDOC_BLOCK != node->type)
573 return(1);
574 assert(MDOC_Bd == node->tok);
575
576 argv = NULL;
577 argc = node->data.block.argc;
578
579 /* LINTED */
580 for (err = i = type = 0; 0 == err && i < argc; i++) {
581 argv = &node->data.block.argv[(int)i];
582 assert(argv);
583 switch (argv->arg) {
584 case (MDOC_Ragged):
585 /* FALLTHROUGH */
586 case (MDOC_Unfilled):
587 /* FALLTHROUGH */
588 case (MDOC_Filled):
589 /* FALLTHROUGH */
590 case (MDOC_Literal):
591 /* FALLTHROUGH */
592 case (MDOC_File):
593 if (type)
594 err++;
595 type++;
596 break;
597 default:
598 break;
599 }
600 }
601 if (0 == type)
602 return(mdoc_err(mdoc, "no display type specified"));
603 if (0 == err)
604 return(1);
605 assert(argv);
606 return(mdoc_perr(mdoc, argv->line,
607 argv->pos, "only one display type possible"));
608 }
609
610
611 static int
612 pre_ss(struct mdoc *mdoc, struct mdoc_node *node)
613 {
614
615 if (MDOC_BLOCK != node->type)
616 return(1);
617 return(pre_check_parent(mdoc, node, MDOC_Sh, MDOC_BODY));
618 }
619
620
621 static int
622 pre_sh(struct mdoc *mdoc, struct mdoc_node *node)
623 {
624
625 if (MDOC_BLOCK != node->type)
626 return(1);
627 return(pre_check_parent(mdoc, node, -1, MDOC_ROOT));
628 }
629
630
631 static int
632 pre_st(struct mdoc *mdoc, struct mdoc_node *node)
633 {
634
635 assert(MDOC_ELEM == node->type);
636 assert(MDOC_St == node->tok);
637 if (1 == node->data.elem.argc)
638 return(1);
639 return(mdoc_nerr(mdoc, node, "macro must have one argument"));
640 }
641
642
643 static int
644 pre_an(struct mdoc *mdoc, struct mdoc_node *node)
645 {
646
647 assert(MDOC_ELEM == node->type);
648 assert(MDOC_An == node->tok);
649 if (1 >= node->data.elem.argc)
650 return(1);
651 return(mdoc_nerr(mdoc, node, "macro may only have one argument"));
652 }
653
654
655 static int
656 pre_rv(struct mdoc *mdoc, struct mdoc_node *node)
657 {
658 enum mdoc_msec msecs[2];
659
660 assert(MDOC_ELEM == node->type);
661 assert(MDOC_Rv == node->tok);
662
663 msecs[0] = MSEC_2;
664 msecs[1] = MSEC_3;
665 if ( ! pre_check_msecs(mdoc, node, 2, msecs))
666 return(0);
667 return(pre_check_stdarg(mdoc, node));
668 }
669
670
671 static int
672 pre_ex(struct mdoc *mdoc, struct mdoc_node *node)
673 {
674 enum mdoc_msec msecs[3];
675
676 assert(MDOC_ELEM == node->type);
677 assert(MDOC_Ex == node->tok);
678
679 msecs[0] = MSEC_1;
680 msecs[1] = MSEC_6;
681 msecs[2] = MSEC_8;
682 if ( ! pre_check_msecs(mdoc, node, 3, msecs))
683 return(0);
684 return(pre_check_stdarg(mdoc, node));
685 }
686
687
688 static int
689 pre_er(struct mdoc *mdoc, struct mdoc_node *node)
690 {
691 enum mdoc_msec msecs[1];
692
693 msecs[0] = MSEC_2;
694 return(pre_check_msecs(mdoc, node, 1, msecs));
695 }
696
697
698 static int
699 pre_cd(struct mdoc *mdoc, struct mdoc_node *node)
700 {
701 enum mdoc_msec msecs[1];
702
703 msecs[0] = MSEC_4;
704 return(pre_check_msecs(mdoc, node, 1, msecs));
705 }
706
707
708 static int
709 pre_it(struct mdoc *mdoc, struct mdoc_node *node)
710 {
711
712 if (MDOC_BLOCK != node->type)
713 return(1);
714 return(pre_check_parent(mdoc, node, MDOC_Bl, MDOC_BODY));
715 }
716
717
718 static int
719 pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
720 {
721
722 if (SEC_PROLOGUE != mdoc->lastnamed)
723 return(mdoc_nerr(mdoc, node, "macro may only be invoked in the prologue"));
724 assert(MDOC_ELEM == node->type);
725
726 /* Check for ordering. */
727
728 switch (node->tok) {
729 case (MDOC_Os):
730 if (mdoc->meta.title && mdoc->meta.date)
731 break;
732 return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
733 case (MDOC_Dt):
734 if (NULL == mdoc->meta.title && mdoc->meta.date)
735 break;
736 return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
737 case (MDOC_Dd):
738 if (NULL == mdoc->meta.title && 0 == mdoc->meta.date)
739 break;
740 return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
741 default:
742 abort();
743 /* NOTREACHED */
744 }
745
746 /* Check for repetition. */
747
748 switch (node->tok) {
749 case (MDOC_Os):
750 if (NULL == mdoc->meta.os)
751 return(1);
752 break;
753 case (MDOC_Dd):
754 if (0 == mdoc->meta.date)
755 return(1);
756 break;
757 case (MDOC_Dt):
758 if (NULL == mdoc->meta.title)
759 return(1);
760 break;
761 default:
762 abort();
763 /* NOTREACHED */
764 }
765
766 return(mdoc_nerr(mdoc, node, "prologue macro repeated"));
767 }
768
769
770 static int
771 post_bf(struct mdoc *mdoc)
772 {
773 char *p;
774 struct mdoc_node *head;
775
776 if (MDOC_BLOCK != mdoc->last->type)
777 return(1);
778 assert(MDOC_Bf == mdoc->last->tok);
779 head = mdoc->last->data.block.head;
780 assert(head);
781
782 if (0 == mdoc->last->data.block.argc) {
783 if (head->child) {
784 assert(MDOC_TEXT == head->child->type);
785 p = head->child->data.text.string;
786 if (xstrcmp(p, "Em"))
787 return(1);
788 else if (xstrcmp(p, "Li"))
789 return(1);
790 else if (xstrcmp(p, "Sm"))
791 return(1);
792 return(mdoc_nerr(mdoc, head->child, "invalid font mode"));
793 }
794 return(mdoc_err(mdoc, "macro expects an argument or parameter"));
795 }
796 if (head->child)
797 return(mdoc_err(mdoc, "macro expects an argument or parameter"));
798 if (1 == mdoc->last->data.block.argc)
799 return(1);
800 return(mdoc_err(mdoc, "macro expects an argument or parameter"));
801 }
802
803
804 static int
805 post_nm(struct mdoc *mdoc)
806 {
807
808 assert(MDOC_ELEM == mdoc->last->type);
809 assert(MDOC_Nm == mdoc->last->tok);
810 if (mdoc->last->child)
811 return(1);
812 if (mdoc->meta.name)
813 return(1);
814 return(mdoc_err(mdoc, "macro `%s' has not been invoked with a name",
815 mdoc_macronames[MDOC_Nm]));
816 }
817
818
819 static int
820 post_xr(struct mdoc *mdoc)
821 {
822 struct mdoc_node *n;
823
824 assert(MDOC_ELEM == mdoc->last->type);
825 assert(MDOC_Xr == mdoc->last->tok);
826 assert(mdoc->last->child);
827 assert(MDOC_TEXT == mdoc->last->child->type);
828
829 if (NULL == (n = mdoc->last->child->next))
830 return(1);
831 assert(MDOC_TEXT == n->type);
832 if (MSEC_DEFAULT != mdoc_atomsec(n->data.text.string))
833 return(1);
834 return(mdoc_nerr(mdoc, n, "invalid manual section"));
835 }
836
837
838 static int
839 post_at(struct mdoc *mdoc)
840 {
841
842 assert(MDOC_ELEM == mdoc->last->type);
843 assert(MDOC_At == mdoc->last->tok);
844
845 if (NULL == mdoc->last->child)
846 return(1);
847 assert(MDOC_TEXT == mdoc->last->child->type);
848
849 if (ATT_DEFAULT != mdoc_atoatt(mdoc->last->child->data.text.string))
850 return(1);
851 return(mdoc_err(mdoc, "macro expects a valid AT&T version symbol"));
852 }
853
854
855 static int
856 post_an(struct mdoc *mdoc)
857 {
858
859 assert(MDOC_ELEM == mdoc->last->type);
860 assert(MDOC_An == mdoc->last->tok);
861
862 if (0 != mdoc->last->data.elem.argc) {
863 if (NULL == mdoc->last->child)
864 return(1);
865 return(mdoc_err(mdoc, "macro expects either argument or parameters"));
866 }
867
868 if (mdoc->last->child)
869 return(1);
870 return(mdoc_err(mdoc, "macro expects either argument or parameters"));
871 }
872
873
874 static int
875 post_ex(struct mdoc *mdoc)
876 {
877
878 assert(MDOC_ELEM == mdoc->last->type);
879 assert(MDOC_Ex == mdoc->last->tok);
880
881 if (0 == mdoc->last->data.elem.argc) {
882 if (mdoc->last->child)
883 return(1);
884 return(mdoc_err(mdoc, "macro expects `%s' or a single child",
885 mdoc_argnames[MDOC_Std]));
886 }
887 if (mdoc->last->child)
888 return(mdoc_err(mdoc, "macro expects `%s' or a single child",
889 mdoc_argnames[MDOC_Std]));
890 if (1 != mdoc->last->data.elem.argc)
891 return(mdoc_err(mdoc, "macro expects `%s' or a single child",
892 mdoc_argnames[MDOC_Std]));
893 if (MDOC_Std != mdoc->last->data.elem.argv[0].arg)
894 return(mdoc_err(mdoc, "macro expects `%s' or a single child",
895 mdoc_argnames[MDOC_Std]));
896 return(1);
897 }
898
899
900 /* Warn if `Bl' type-specific syntax isn't reflected in items. */
901 static int
902 post_it(struct mdoc *mdoc)
903 {
904 int type, sv;
905 #define TYPE_NONE (0)
906 #define TYPE_BODY (1)
907 #define TYPE_HEAD (2)
908 size_t i, argc;
909 struct mdoc_node *n;
910
911 if (MDOC_BLOCK != mdoc->last->type)
912 return(1);
913
914 assert(MDOC_It == mdoc->last->tok);
915
916 n = mdoc->last->parent;
917 assert(n);
918 assert(MDOC_Bl == n->tok);
919
920 n = n->parent;
921 assert(MDOC_BLOCK == n->type);
922 assert(MDOC_Bl == n->tok);
923
924 argc = n->data.block.argc;
925 type = TYPE_NONE;
926 sv = -1;
927
928 /* Some types require block-head, some not. */
929
930 /* LINTED */
931 for (i = 0; TYPE_NONE == type && i < argc; i++)
932 switch (n->data.block.argv[(int)i].arg) {
933 case (MDOC_Tag):
934 /* FALLTHROUGH */
935 case (MDOC_Diag):
936 /* FALLTHROUGH */
937 case (MDOC_Hang):
938 /* FALLTHROUGH */
939 case (MDOC_Ohang):
940 /* FALLTHROUGH */
941 case (MDOC_Inset):
942 type = TYPE_HEAD;
943 sv = n->data.block.argv[(int)i].arg;
944 break;
945 case (MDOC_Bullet):
946 /* FALLTHROUGH */
947 case (MDOC_Dash):
948 /* FALLTHROUGH */
949 case (MDOC_Enum):
950 /* FALLTHROUGH */
951 case (MDOC_Hyphen):
952 /* FALLTHROUGH */
953 case (MDOC_Item):
954 /* FALLTHROUGH */
955 case (MDOC_Column):
956 type = TYPE_BODY;
957 sv = n->data.block.argv[(int)i].arg;
958 break;
959 default:
960 break;
961 }
962
963 assert(TYPE_NONE != type);
964
965 if (TYPE_HEAD == type) {
966 n = mdoc->last->data.block.head;
967 assert(n);
968 if (NULL == n->child)
969 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests line parameters"))
970 return(0);
971
972 n = mdoc->last->data.block.body;
973 assert(n);
974 if (NULL == n->child)
975 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests body children"))
976 return(0);
977
978 return(1);
979 }
980
981 assert(TYPE_BODY == type);
982 assert(mdoc->last->data.block.head);
983
984 n = mdoc->last->data.block.head;
985 assert(n);
986 if (n->child)
987 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests no line parameters"))
988 return(0);
989
990 n = mdoc->last->data.block.body;
991 assert(n);
992 if (NULL == n->child)
993 if ( ! mdoc_warn(mdoc, WARN_SYNTAX, "macro suggests body children"))
994 return(0);
995
996 assert(-1 != sv);
997 if (MDOC_Column != sv)
998 return(1);
999
1000 /* Make sure the number of columns is sane. */
1001
1002 argc = mdoc->last->parent->parent->data.block.argv->sz;
1003 n = mdoc->last->data.block.head->child;
1004
1005 for (i = 0; n; n = n->next)
1006 i++;
1007
1008 if (i == argc)
1009 return(1);
1010 return(mdoc_err(mdoc, "expected %zu list columns, have %zu", argc, i));
1011 #undef TYPE_NONE
1012 #undef TYPE_BODY
1013 #undef TYPE_HEAD
1014 }
1015
1016
1017 static int
1018 post_bl(struct mdoc *mdoc)
1019 {
1020 struct mdoc_node *n;
1021
1022 if (MDOC_BODY != mdoc->last->type)
1023 return(1);
1024 assert(MDOC_Bl == mdoc->last->tok);
1025
1026 /* LINTED */
1027 for (n = mdoc->last->child; n; n = n->next) {
1028 if (MDOC_BLOCK == n->type)
1029 if (MDOC_It == n->tok)
1030 continue;
1031 break;
1032 }
1033 if (NULL == n)
1034 return(1);
1035 return(mdoc_nerr(mdoc, n, "invalid child of parent macro `Bl'"));
1036 }
1037
1038
1039 static int
1040 ebool(struct mdoc *mdoc)
1041 {
1042 struct mdoc_node *n;
1043
1044 assert(MDOC_ELEM == mdoc->last->type);
1045 /* LINTED */
1046 for (n = mdoc->last->child; n; n = n->next) {
1047 if (MDOC_TEXT != n->type)
1048 break;
1049 if (xstrcmp(n->data.text.string, "on"))
1050 continue;
1051 if (xstrcmp(n->data.text.string, "off"))
1052 continue;
1053 break;
1054 }
1055 if (NULL == n)
1056 return(1);
1057 return(mdoc_nerr(mdoc, n, "expected boolean value"));
1058 }
1059
1060
1061 static int
1062 post_root(struct mdoc *mdoc)
1063 {
1064
1065 if (NULL == mdoc->first->child)
1066 return(mdoc_err(mdoc, "document has no data"));
1067 if (SEC_PROLOGUE == mdoc->lastnamed)
1068 return(mdoc_err(mdoc, "document has incomplete prologue"));
1069 if (MDOC_BLOCK != mdoc->first->child->type)
1070 return(mdoc_err(mdoc, "document expects `%s' macro after prologue", mdoc_macronames[MDOC_Sh]));
1071 if (MDOC_Sh != mdoc->first->child->tok)
1072 return(mdoc_err(mdoc, "document expects `%s' macro after prologue", mdoc_macronames[MDOC_Sh]));
1073 return(1);
1074 }
1075
1076
1077 static int
1078 post_sh(struct mdoc *mdoc)
1079 {
1080
1081 if (MDOC_HEAD == mdoc->last->type)
1082 return(post_sh_head(mdoc));
1083 if (MDOC_BODY == mdoc->last->type)
1084 return(post_sh_body(mdoc));
1085 return(1);
1086 }
1087
1088
1089 static int
1090 post_sh_body(struct mdoc *mdoc)
1091 {
1092 struct mdoc_node *n;
1093
1094 assert(MDOC_Sh == mdoc->last->tok);
1095 if (SEC_NAME != mdoc->lastnamed)
1096 return(1);
1097
1098 if (NULL == (n = mdoc->last->child))
1099 return(mdoc_err(mdoc, "section NAME must contain %s as the first body child", mdoc_macronames[MDOC_Nm]));
1100 if (MDOC_ELEM != n->type || MDOC_Nm != n->tok)
1101 return(mdoc_err(mdoc, "section NAME must contain %s as the first body child", mdoc_macronames[MDOC_Nm]));
1102 if (NULL == (n = n->next))
1103 return(mdoc_err(mdoc, "section NAME must contain %s as the second body child", mdoc_macronames[MDOC_Nd]));
1104 if (MDOC_ELEM != n->type || MDOC_Nd != n->tok)
1105 return(mdoc_err(mdoc, "section NAME must contain %s as the second body child", mdoc_macronames[MDOC_Nd]));
1106 if (NULL == (n = n->next))
1107 return(1);
1108
1109 return(mdoc_warn(mdoc, WARN_SYNTAX, "section NAME usually limited to %s and %s body children",
1110 mdoc_macronames[MDOC_Nm], mdoc_macronames[MDOC_Nd]));
1111 }
1112
1113
1114 static int
1115 post_sh_head(struct mdoc *mdoc)
1116 {
1117 char buf[64];
1118 enum mdoc_sec sec;
1119
1120 assert(MDOC_Sh == mdoc->last->tok);
1121
1122 if ( ! xstrlcats(buf, mdoc->last->child, 64))
1123 return(mdoc_err(mdoc, "macro parameters too long"));
1124
1125 sec = mdoc_atosec(buf);
1126
1127 if (SEC_BODY == mdoc->lastnamed && SEC_NAME != sec)
1128 return(mdoc_err(mdoc, "section NAME must be first"));
1129 if (SEC_CUSTOM == sec)
1130 return(1);
1131 if (sec == mdoc->lastnamed)
1132 return(mdoc_warn(mdoc, WARN_SYNTAX, "section repeated"));
1133 if (sec < mdoc->lastnamed)
1134 return(mdoc_warn(mdoc, WARN_SYNTAX, "section out of conventional order"));
1135
1136 return(1);
1137 }
1138
1139
1140 int
1141 mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *node)
1142 {
1143 v_pre *p;
1144
1145 if (MDOC_TEXT == node->type)
1146 return(1);
1147 assert(MDOC_ROOT != node->type);
1148
1149 if (NULL == mdoc_valids[node->tok].pre)
1150 return(1);
1151 for (p = mdoc_valids[node->tok].pre; *p; p++)
1152 if ( ! (*p)(mdoc, node))
1153 return(0);
1154 return(1);
1155 }
1156
1157
1158 int
1159 mdoc_valid_post(struct mdoc *mdoc)
1160 {
1161 v_post *p;
1162
1163 if (MDOC_VALID & mdoc->last->flags)
1164 return(1);
1165 mdoc->last->flags |= MDOC_VALID;
1166
1167 if (MDOC_TEXT == mdoc->last->type)
1168 return(1);
1169 if (MDOC_ROOT == mdoc->last->type)
1170 return(post_root(mdoc));
1171
1172 if (NULL == mdoc_valids[mdoc->last->tok].post)
1173 return(1);
1174 for (p = mdoc_valids[mdoc->last->tok].post; *p; p++)
1175 if ( ! (*p)(mdoc))
1176 return(0);
1177
1178 return(1);
1179 }
1180