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