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