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