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