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