1 /* $Id: mdoc_validate.c,v 1.124 2014/03/23 15:14:29 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> 4 * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> 5 * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #ifndef OSNAME 20 #include <sys/utsname.h> 21 #endif 22 23 #include <sys/types.h> 24 25 #include <assert.h> 26 #include <ctype.h> 27 #include <limits.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <time.h> 32 33 #include "mdoc.h" 34 #include "mandoc.h" 35 #include "mandoc_aux.h" 36 #include "libmdoc.h" 37 #include "libmandoc.h" 38 39 /* FIXME: .Bl -diag can't have non-text children in HEAD. */ 40 41 #define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n 42 #define POST_ARGS struct mdoc *mdoc 43 44 #define NUMSIZ 32 45 46 enum check_ineq { 47 CHECK_LT, 48 CHECK_GT, 49 CHECK_EQ 50 }; 51 52 enum check_lvl { 53 CHECK_WARN, 54 CHECK_ERROR, 55 }; 56 57 typedef int (*v_pre)(PRE_ARGS); 58 typedef int (*v_post)(POST_ARGS); 59 60 struct valids { 61 v_pre *pre; 62 v_post *post; 63 }; 64 65 static int check_count(struct mdoc *, enum mdoc_type, 66 enum check_lvl, enum check_ineq, int); 67 static int check_parent(PRE_ARGS, enum mdoct, enum mdoc_type); 68 static void check_text(struct mdoc *, int, int, char *); 69 static void check_argv(struct mdoc *, 70 struct mdoc_node *, struct mdoc_argv *); 71 static void check_args(struct mdoc *, struct mdoc_node *); 72 static enum mdoc_sec a2sec(const char *); 73 static size_t macro2len(enum mdoct); 74 75 static int ebool(POST_ARGS); 76 static int berr_ge1(POST_ARGS); 77 static int bwarn_ge1(POST_ARGS); 78 static int ewarn_eq0(POST_ARGS); 79 static int ewarn_eq1(POST_ARGS); 80 static int ewarn_ge1(POST_ARGS); 81 static int ewarn_le1(POST_ARGS); 82 static int hwarn_eq0(POST_ARGS); 83 static int hwarn_eq1(POST_ARGS); 84 static int hwarn_ge1(POST_ARGS); 85 static int hwarn_le1(POST_ARGS); 86 87 static int post_an(POST_ARGS); 88 static int post_at(POST_ARGS); 89 static int post_bf(POST_ARGS); 90 static int post_bl(POST_ARGS); 91 static int post_bl_block(POST_ARGS); 92 static int post_bl_block_width(POST_ARGS); 93 static int post_bl_block_tag(POST_ARGS); 94 static int post_bl_head(POST_ARGS); 95 static int post_bx(POST_ARGS); 96 static int post_defaults(POST_ARGS); 97 static int post_dd(POST_ARGS); 98 static int post_dt(POST_ARGS); 99 static int post_eoln(POST_ARGS); 100 static int post_hyph(POST_ARGS); 101 static int post_ignpar(POST_ARGS); 102 static int post_it(POST_ARGS); 103 static int post_lb(POST_ARGS); 104 static int post_literal(POST_ARGS); 105 static int post_nm(POST_ARGS); 106 static int post_ns(POST_ARGS); 107 static int post_os(POST_ARGS); 108 static int post_par(POST_ARGS); 109 static int post_prol(POST_ARGS); 110 static int post_root(POST_ARGS); 111 static int post_rs(POST_ARGS); 112 static int post_sh(POST_ARGS); 113 static int post_sh_body(POST_ARGS); 114 static int post_sh_head(POST_ARGS); 115 static int post_st(POST_ARGS); 116 static int post_std(POST_ARGS); 117 static int post_vt(POST_ARGS); 118 static int pre_an(PRE_ARGS); 119 static int pre_bd(PRE_ARGS); 120 static int pre_bl(PRE_ARGS); 121 static int pre_dd(PRE_ARGS); 122 static int pre_display(PRE_ARGS); 123 static int pre_dt(PRE_ARGS); 124 static int pre_it(PRE_ARGS); 125 static int pre_literal(PRE_ARGS); 126 static int pre_os(PRE_ARGS); 127 static int pre_par(PRE_ARGS); 128 static int pre_sh(PRE_ARGS); 129 static int pre_ss(PRE_ARGS); 130 static int pre_std(PRE_ARGS); 131 132 static v_post posts_an[] = { post_an, NULL }; 133 static v_post posts_at[] = { post_at, post_defaults, NULL }; 134 static v_post posts_bd[] = { post_literal, hwarn_eq0, bwarn_ge1, NULL }; 135 static v_post posts_bf[] = { hwarn_le1, post_bf, NULL }; 136 static v_post posts_bk[] = { hwarn_eq0, bwarn_ge1, NULL }; 137 static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL }; 138 static v_post posts_bx[] = { post_bx, NULL }; 139 static v_post posts_bool[] = { ebool, NULL }; 140 static v_post posts_eoln[] = { post_eoln, NULL }; 141 static v_post posts_defaults[] = { post_defaults, NULL }; 142 static v_post posts_d1[] = { bwarn_ge1, post_hyph, NULL }; 143 static v_post posts_dd[] = { post_dd, post_prol, NULL }; 144 static v_post posts_dl[] = { post_literal, bwarn_ge1, NULL }; 145 static v_post posts_dt[] = { post_dt, post_prol, NULL }; 146 static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL }; 147 static v_post posts_hyph[] = { post_hyph, NULL }; 148 static v_post posts_hyphtext[] = { ewarn_ge1, post_hyph, NULL }; 149 static v_post posts_it[] = { post_it, NULL }; 150 static v_post posts_lb[] = { post_lb, NULL }; 151 static v_post posts_nd[] = { berr_ge1, post_hyph, NULL }; 152 static v_post posts_nm[] = { post_nm, NULL }; 153 static v_post posts_notext[] = { ewarn_eq0, NULL }; 154 static v_post posts_ns[] = { post_ns, NULL }; 155 static v_post posts_os[] = { post_os, post_prol, NULL }; 156 static v_post posts_pp[] = { post_par, ewarn_eq0, NULL }; 157 static v_post posts_rs[] = { post_rs, NULL }; 158 static v_post posts_sh[] = { post_ignpar,hwarn_ge1,post_sh,post_hyph,NULL }; 159 static v_post posts_sp[] = { post_par, ewarn_le1, NULL }; 160 static v_post posts_ss[] = { post_ignpar, hwarn_ge1, post_hyph, NULL }; 161 static v_post posts_st[] = { post_st, NULL }; 162 static v_post posts_std[] = { post_std, NULL }; 163 static v_post posts_text[] = { ewarn_ge1, NULL }; 164 static v_post posts_text1[] = { ewarn_eq1, NULL }; 165 static v_post posts_vt[] = { post_vt, NULL }; 166 static v_pre pres_an[] = { pre_an, NULL }; 167 static v_pre pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL }; 168 static v_pre pres_bl[] = { pre_bl, pre_par, NULL }; 169 static v_pre pres_d1[] = { pre_display, NULL }; 170 static v_pre pres_dl[] = { pre_literal, pre_display, NULL }; 171 static v_pre pres_dd[] = { pre_dd, NULL }; 172 static v_pre pres_dt[] = { pre_dt, NULL }; 173 static v_pre pres_it[] = { pre_it, pre_par, NULL }; 174 static v_pre pres_os[] = { pre_os, NULL }; 175 static v_pre pres_pp[] = { pre_par, NULL }; 176 static v_pre pres_sh[] = { pre_sh, NULL }; 177 static v_pre pres_ss[] = { pre_ss, NULL }; 178 static v_pre pres_std[] = { pre_std, NULL }; 179 180 static const struct valids mdoc_valids[MDOC_MAX] = { 181 { NULL, NULL }, /* Ap */ 182 { pres_dd, posts_dd }, /* Dd */ 183 { pres_dt, posts_dt }, /* Dt */ 184 { pres_os, posts_os }, /* Os */ 185 { pres_sh, posts_sh }, /* Sh */ 186 { pres_ss, posts_ss }, /* Ss */ 187 { pres_pp, posts_pp }, /* Pp */ 188 { pres_d1, posts_d1 }, /* D1 */ 189 { pres_dl, posts_dl }, /* Dl */ 190 { pres_bd, posts_bd }, /* Bd */ 191 { NULL, NULL }, /* Ed */ 192 { pres_bl, posts_bl }, /* Bl */ 193 { NULL, NULL }, /* El */ 194 { pres_it, posts_it }, /* It */ 195 { NULL, NULL }, /* Ad */ 196 { pres_an, posts_an }, /* An */ 197 { NULL, posts_defaults }, /* Ar */ 198 { NULL, NULL }, /* Cd */ 199 { NULL, NULL }, /* Cm */ 200 { NULL, NULL }, /* Dv */ 201 { NULL, NULL }, /* Er */ 202 { NULL, NULL }, /* Ev */ 203 { pres_std, posts_std }, /* Ex */ 204 { NULL, NULL }, /* Fa */ 205 { NULL, posts_text }, /* Fd */ 206 { NULL, NULL }, /* Fl */ 207 { NULL, NULL }, /* Fn */ 208 { NULL, NULL }, /* Ft */ 209 { NULL, NULL }, /* Ic */ 210 { NULL, posts_text1 }, /* In */ 211 { NULL, posts_defaults }, /* Li */ 212 { NULL, posts_nd }, /* Nd */ 213 { NULL, posts_nm }, /* Nm */ 214 { NULL, NULL }, /* Op */ 215 { NULL, NULL }, /* Ot */ 216 { NULL, posts_defaults }, /* Pa */ 217 { pres_std, posts_std }, /* Rv */ 218 { NULL, posts_st }, /* St */ 219 { NULL, NULL }, /* Va */ 220 { NULL, posts_vt }, /* Vt */ 221 { NULL, posts_text }, /* Xr */ 222 { NULL, posts_text }, /* %A */ 223 { NULL, posts_hyphtext }, /* %B */ /* FIXME: can be used outside Rs/Re. */ 224 { NULL, posts_text }, /* %D */ 225 { NULL, posts_text }, /* %I */ 226 { NULL, posts_text }, /* %J */ 227 { NULL, posts_hyphtext }, /* %N */ 228 { NULL, posts_hyphtext }, /* %O */ 229 { NULL, posts_text }, /* %P */ 230 { NULL, posts_hyphtext }, /* %R */ 231 { NULL, posts_hyphtext }, /* %T */ /* FIXME: can be used outside Rs/Re. */ 232 { NULL, posts_text }, /* %V */ 233 { NULL, NULL }, /* Ac */ 234 { NULL, NULL }, /* Ao */ 235 { NULL, NULL }, /* Aq */ 236 { NULL, posts_at }, /* At */ 237 { NULL, NULL }, /* Bc */ 238 { NULL, posts_bf }, /* Bf */ 239 { NULL, NULL }, /* Bo */ 240 { NULL, NULL }, /* Bq */ 241 { NULL, NULL }, /* Bsx */ 242 { NULL, posts_bx }, /* Bx */ 243 { NULL, posts_bool }, /* Db */ 244 { NULL, NULL }, /* Dc */ 245 { NULL, NULL }, /* Do */ 246 { NULL, NULL }, /* Dq */ 247 { NULL, NULL }, /* Ec */ 248 { NULL, NULL }, /* Ef */ 249 { NULL, NULL }, /* Em */ 250 { NULL, NULL }, /* Eo */ 251 { NULL, NULL }, /* Fx */ 252 { NULL, NULL }, /* Ms */ 253 { NULL, posts_notext }, /* No */ 254 { NULL, posts_ns }, /* Ns */ 255 { NULL, NULL }, /* Nx */ 256 { NULL, NULL }, /* Ox */ 257 { NULL, NULL }, /* Pc */ 258 { NULL, posts_text1 }, /* Pf */ 259 { NULL, NULL }, /* Po */ 260 { NULL, NULL }, /* Pq */ 261 { NULL, NULL }, /* Qc */ 262 { NULL, NULL }, /* Ql */ 263 { NULL, NULL }, /* Qo */ 264 { NULL, NULL }, /* Qq */ 265 { NULL, NULL }, /* Re */ 266 { NULL, posts_rs }, /* Rs */ 267 { NULL, NULL }, /* Sc */ 268 { NULL, NULL }, /* So */ 269 { NULL, NULL }, /* Sq */ 270 { NULL, posts_bool }, /* Sm */ 271 { NULL, posts_hyph }, /* Sx */ 272 { NULL, NULL }, /* Sy */ 273 { NULL, NULL }, /* Tn */ 274 { NULL, NULL }, /* Ux */ 275 { NULL, NULL }, /* Xc */ 276 { NULL, NULL }, /* Xo */ 277 { NULL, posts_fo }, /* Fo */ 278 { NULL, NULL }, /* Fc */ 279 { NULL, NULL }, /* Oo */ 280 { NULL, NULL }, /* Oc */ 281 { NULL, posts_bk }, /* Bk */ 282 { NULL, NULL }, /* Ek */ 283 { NULL, posts_eoln }, /* Bt */ 284 { NULL, NULL }, /* Hf */ 285 { NULL, NULL }, /* Fr */ 286 { NULL, posts_eoln }, /* Ud */ 287 { NULL, posts_lb }, /* Lb */ 288 { pres_pp, posts_pp }, /* Lp */ 289 { NULL, NULL }, /* Lk */ 290 { NULL, posts_defaults }, /* Mt */ 291 { NULL, NULL }, /* Brq */ 292 { NULL, NULL }, /* Bro */ 293 { NULL, NULL }, /* Brc */ 294 { NULL, posts_text }, /* %C */ 295 { NULL, NULL }, /* Es */ 296 { NULL, NULL }, /* En */ 297 { NULL, NULL }, /* Dx */ 298 { NULL, posts_text }, /* %Q */ 299 { NULL, posts_pp }, /* br */ 300 { NULL, posts_sp }, /* sp */ 301 { NULL, posts_text1 }, /* %U */ 302 { NULL, NULL }, /* Ta */ 303 }; 304 305 #define RSORD_MAX 14 /* Number of `Rs' blocks. */ 306 307 static const enum mdoct rsord[RSORD_MAX] = { 308 MDOC__A, 309 MDOC__T, 310 MDOC__B, 311 MDOC__I, 312 MDOC__J, 313 MDOC__R, 314 MDOC__N, 315 MDOC__V, 316 MDOC__U, 317 MDOC__P, 318 MDOC__Q, 319 MDOC__C, 320 MDOC__D, 321 MDOC__O 322 }; 323 324 static const char * const secnames[SEC__MAX] = { 325 NULL, 326 "NAME", 327 "LIBRARY", 328 "SYNOPSIS", 329 "DESCRIPTION", 330 "IMPLEMENTATION NOTES", 331 "RETURN VALUES", 332 "ENVIRONMENT", 333 "FILES", 334 "EXIT STATUS", 335 "EXAMPLES", 336 "DIAGNOSTICS", 337 "COMPATIBILITY", 338 "ERRORS", 339 "SEE ALSO", 340 "STANDARDS", 341 "HISTORY", 342 "AUTHORS", 343 "CAVEATS", 344 "BUGS", 345 "SECURITY CONSIDERATIONS", 346 NULL 347 }; 348 349 int 350 mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n) 351 { 352 v_pre *p; 353 int line, pos; 354 char *tp; 355 356 switch (n->type) { 357 case (MDOC_TEXT): 358 tp = n->string; 359 line = n->line; 360 pos = n->pos; 361 check_text(mdoc, line, pos, tp); 362 /* FALLTHROUGH */ 363 case (MDOC_TBL): 364 /* FALLTHROUGH */ 365 case (MDOC_EQN): 366 /* FALLTHROUGH */ 367 case (MDOC_ROOT): 368 return(1); 369 default: 370 break; 371 } 372 373 check_args(mdoc, n); 374 375 if (NULL == mdoc_valids[n->tok].pre) 376 return(1); 377 for (p = mdoc_valids[n->tok].pre; *p; p++) 378 if ( ! (*p)(mdoc, n)) 379 return(0); 380 return(1); 381 } 382 383 384 int 385 mdoc_valid_post(struct mdoc *mdoc) 386 { 387 v_post *p; 388 389 if (MDOC_VALID & mdoc->last->flags) 390 return(1); 391 mdoc->last->flags |= MDOC_VALID; 392 393 switch (mdoc->last->type) { 394 case (MDOC_TEXT): 395 /* FALLTHROUGH */ 396 case (MDOC_EQN): 397 /* FALLTHROUGH */ 398 case (MDOC_TBL): 399 return(1); 400 case (MDOC_ROOT): 401 return(post_root(mdoc)); 402 default: 403 break; 404 } 405 406 if (NULL == mdoc_valids[mdoc->last->tok].post) 407 return(1); 408 for (p = mdoc_valids[mdoc->last->tok].post; *p; p++) 409 if ( ! (*p)(mdoc)) 410 return(0); 411 412 return(1); 413 } 414 415 static int 416 check_count(struct mdoc *mdoc, enum mdoc_type type, 417 enum check_lvl lvl, enum check_ineq ineq, int val) 418 { 419 const char *p; 420 enum mandocerr t; 421 422 if (mdoc->last->type != type) 423 return(1); 424 425 switch (ineq) { 426 case (CHECK_LT): 427 p = "less than "; 428 if (mdoc->last->nchild < val) 429 return(1); 430 break; 431 case (CHECK_GT): 432 p = "more than "; 433 if (mdoc->last->nchild > val) 434 return(1); 435 break; 436 case (CHECK_EQ): 437 p = ""; 438 if (val == mdoc->last->nchild) 439 return(1); 440 break; 441 default: 442 abort(); 443 /* NOTREACHED */ 444 } 445 446 t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT; 447 mandoc_vmsg(t, mdoc->parse, mdoc->last->line, mdoc->last->pos, 448 "want %s%d children (have %d)", 449 p, val, mdoc->last->nchild); 450 return(1); 451 } 452 453 static int 454 berr_ge1(POST_ARGS) 455 { 456 457 return(check_count(mdoc, MDOC_BODY, CHECK_ERROR, CHECK_GT, 0)); 458 } 459 460 static int 461 bwarn_ge1(POST_ARGS) 462 { 463 return(check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0)); 464 } 465 466 static int 467 ewarn_eq0(POST_ARGS) 468 { 469 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0)); 470 } 471 472 static int 473 ewarn_eq1(POST_ARGS) 474 { 475 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1)); 476 } 477 478 static int 479 ewarn_ge1(POST_ARGS) 480 { 481 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0)); 482 } 483 484 static int 485 ewarn_le1(POST_ARGS) 486 { 487 return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2)); 488 } 489 490 static int 491 hwarn_eq0(POST_ARGS) 492 { 493 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0)); 494 } 495 496 static int 497 hwarn_eq1(POST_ARGS) 498 { 499 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 1)); 500 } 501 502 static int 503 hwarn_ge1(POST_ARGS) 504 { 505 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_GT, 0)); 506 } 507 508 static int 509 hwarn_le1(POST_ARGS) 510 { 511 return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_LT, 2)); 512 } 513 514 static void 515 check_args(struct mdoc *mdoc, struct mdoc_node *n) 516 { 517 int i; 518 519 if (NULL == n->args) 520 return; 521 522 assert(n->args->argc); 523 for (i = 0; i < (int)n->args->argc; i++) 524 check_argv(mdoc, n, &n->args->argv[i]); 525 } 526 527 static void 528 check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v) 529 { 530 int i; 531 532 for (i = 0; i < (int)v->sz; i++) 533 check_text(mdoc, v->line, v->pos, v->value[i]); 534 535 /* FIXME: move to post_std(). */ 536 537 if (MDOC_Std == v->arg) 538 if ( ! (v->sz || mdoc->meta.name)) 539 mdoc_nmsg(mdoc, n, MANDOCERR_NONAME); 540 } 541 542 static void 543 check_text(struct mdoc *mdoc, int ln, int pos, char *p) 544 { 545 char *cp; 546 547 if (MDOC_LITERAL & mdoc->flags) 548 return; 549 550 for (cp = p; NULL != (p = strchr(p, '\t')); p++) 551 mdoc_pmsg(mdoc, ln, pos + (int)(p - cp), MANDOCERR_BADTAB); 552 } 553 554 static int 555 check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t) 556 { 557 558 assert(n->parent); 559 if ((MDOC_ROOT == t || tok == n->parent->tok) && 560 (t == n->parent->type)) 561 return(1); 562 563 mandoc_vmsg(MANDOCERR_SYNTCHILD, mdoc->parse, n->line, 564 n->pos, "want parent %s", MDOC_ROOT == t ? 565 "<root>" : mdoc_macronames[tok]); 566 return(0); 567 } 568 569 570 static int 571 pre_display(PRE_ARGS) 572 { 573 struct mdoc_node *node; 574 575 if (MDOC_BLOCK != n->type) 576 return(1); 577 578 for (node = mdoc->last->parent; node; node = node->parent) 579 if (MDOC_BLOCK == node->type) 580 if (MDOC_Bd == node->tok) 581 break; 582 583 if (node) 584 mdoc_nmsg(mdoc, n, MANDOCERR_NESTEDDISP); 585 586 return(1); 587 } 588 589 590 static int 591 pre_bl(PRE_ARGS) 592 { 593 int i, comp, dup; 594 const char *offs, *width; 595 enum mdoc_list lt; 596 struct mdoc_node *np; 597 598 if (MDOC_BLOCK != n->type) { 599 if (ENDBODY_NOT != n->end) { 600 assert(n->pending); 601 np = n->pending->parent; 602 } else 603 np = n->parent; 604 605 assert(np); 606 assert(MDOC_BLOCK == np->type); 607 assert(MDOC_Bl == np->tok); 608 return(1); 609 } 610 611 /* 612 * First figure out which kind of list to use: bind ourselves to 613 * the first mentioned list type and warn about any remaining 614 * ones. If we find no list type, we default to LIST_item. 615 */ 616 617 /* LINTED */ 618 for (i = 0; n->args && i < (int)n->args->argc; i++) { 619 lt = LIST__NONE; 620 dup = comp = 0; 621 width = offs = NULL; 622 switch (n->args->argv[i].arg) { 623 /* Set list types. */ 624 case (MDOC_Bullet): 625 lt = LIST_bullet; 626 break; 627 case (MDOC_Dash): 628 lt = LIST_dash; 629 break; 630 case (MDOC_Enum): 631 lt = LIST_enum; 632 break; 633 case (MDOC_Hyphen): 634 lt = LIST_hyphen; 635 break; 636 case (MDOC_Item): 637 lt = LIST_item; 638 break; 639 case (MDOC_Tag): 640 lt = LIST_tag; 641 break; 642 case (MDOC_Diag): 643 lt = LIST_diag; 644 break; 645 case (MDOC_Hang): 646 lt = LIST_hang; 647 break; 648 case (MDOC_Ohang): 649 lt = LIST_ohang; 650 break; 651 case (MDOC_Inset): 652 lt = LIST_inset; 653 break; 654 case (MDOC_Column): 655 lt = LIST_column; 656 break; 657 /* Set list arguments. */ 658 case (MDOC_Compact): 659 dup = n->norm->Bl.comp; 660 comp = 1; 661 break; 662 case (MDOC_Width): 663 /* NB: this can be empty! */ 664 if (n->args->argv[i].sz) { 665 width = n->args->argv[i].value[0]; 666 dup = (NULL != n->norm->Bl.width); 667 break; 668 } 669 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 670 break; 671 case (MDOC_Offset): 672 /* NB: this can be empty! */ 673 if (n->args->argv[i].sz) { 674 offs = n->args->argv[i].value[0]; 675 dup = (NULL != n->norm->Bl.offs); 676 break; 677 } 678 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 679 break; 680 default: 681 continue; 682 } 683 684 /* Check: duplicate auxiliary arguments. */ 685 686 if (dup) 687 mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP); 688 689 if (comp && ! dup) 690 n->norm->Bl.comp = comp; 691 if (offs && ! dup) 692 n->norm->Bl.offs = offs; 693 if (width && ! dup) 694 n->norm->Bl.width = width; 695 696 /* Check: multiple list types. */ 697 698 if (LIST__NONE != lt && n->norm->Bl.type != LIST__NONE) 699 mdoc_nmsg(mdoc, n, MANDOCERR_LISTREP); 700 701 /* Assign list type. */ 702 703 if (LIST__NONE != lt && n->norm->Bl.type == LIST__NONE) { 704 n->norm->Bl.type = lt; 705 /* Set column information, too. */ 706 if (LIST_column == lt) { 707 n->norm->Bl.ncols = 708 n->args->argv[i].sz; 709 n->norm->Bl.cols = (void *) 710 n->args->argv[i].value; 711 } 712 } 713 714 /* The list type should come first. */ 715 716 if (n->norm->Bl.type == LIST__NONE) 717 if (n->norm->Bl.width || 718 n->norm->Bl.offs || 719 n->norm->Bl.comp) 720 mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST); 721 722 continue; 723 } 724 725 /* Allow lists to default to LIST_item. */ 726 727 if (LIST__NONE == n->norm->Bl.type) { 728 mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE); 729 n->norm->Bl.type = LIST_item; 730 } 731 732 /* 733 * Validate the width field. Some list types don't need width 734 * types and should be warned about them. Others should have it 735 * and must also be warned. Yet others have a default and need 736 * no warning. 737 */ 738 739 switch (n->norm->Bl.type) { 740 case (LIST_tag): 741 if (NULL == n->norm->Bl.width) 742 mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG); 743 break; 744 case (LIST_column): 745 /* FALLTHROUGH */ 746 case (LIST_diag): 747 /* FALLTHROUGH */ 748 case (LIST_ohang): 749 /* FALLTHROUGH */ 750 case (LIST_inset): 751 /* FALLTHROUGH */ 752 case (LIST_item): 753 if (n->norm->Bl.width) 754 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 755 break; 756 case (LIST_bullet): 757 /* FALLTHROUGH */ 758 case (LIST_dash): 759 /* FALLTHROUGH */ 760 case (LIST_hyphen): 761 if (NULL == n->norm->Bl.width) 762 n->norm->Bl.width = "2n"; 763 break; 764 case (LIST_enum): 765 if (NULL == n->norm->Bl.width) 766 n->norm->Bl.width = "3n"; 767 break; 768 default: 769 break; 770 } 771 772 return(1); 773 } 774 775 776 static int 777 pre_bd(PRE_ARGS) 778 { 779 int i, dup, comp; 780 enum mdoc_disp dt; 781 const char *offs; 782 struct mdoc_node *np; 783 784 if (MDOC_BLOCK != n->type) { 785 if (ENDBODY_NOT != n->end) { 786 assert(n->pending); 787 np = n->pending->parent; 788 } else 789 np = n->parent; 790 791 assert(np); 792 assert(MDOC_BLOCK == np->type); 793 assert(MDOC_Bd == np->tok); 794 return(1); 795 } 796 797 /* LINTED */ 798 for (i = 0; n->args && i < (int)n->args->argc; i++) { 799 dt = DISP__NONE; 800 dup = comp = 0; 801 offs = NULL; 802 803 switch (n->args->argv[i].arg) { 804 case (MDOC_Centred): 805 dt = DISP_centred; 806 break; 807 case (MDOC_Ragged): 808 dt = DISP_ragged; 809 break; 810 case (MDOC_Unfilled): 811 dt = DISP_unfilled; 812 break; 813 case (MDOC_Filled): 814 dt = DISP_filled; 815 break; 816 case (MDOC_Literal): 817 dt = DISP_literal; 818 break; 819 case (MDOC_File): 820 mdoc_nmsg(mdoc, n, MANDOCERR_BADDISP); 821 return(0); 822 case (MDOC_Offset): 823 /* NB: this can be empty! */ 824 if (n->args->argv[i].sz) { 825 offs = n->args->argv[i].value[0]; 826 dup = (NULL != n->norm->Bd.offs); 827 break; 828 } 829 mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 830 break; 831 case (MDOC_Compact): 832 comp = 1; 833 dup = n->norm->Bd.comp; 834 break; 835 default: 836 abort(); 837 /* NOTREACHED */ 838 } 839 840 /* Check whether we have duplicates. */ 841 842 if (dup) 843 mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP); 844 845 /* Make our auxiliary assignments. */ 846 847 if (offs && ! dup) 848 n->norm->Bd.offs = offs; 849 if (comp && ! dup) 850 n->norm->Bd.comp = comp; 851 852 /* Check whether a type has already been assigned. */ 853 854 if (DISP__NONE != dt && n->norm->Bd.type != DISP__NONE) 855 mdoc_nmsg(mdoc, n, MANDOCERR_DISPREP); 856 857 /* Make our type assignment. */ 858 859 if (DISP__NONE != dt && n->norm->Bd.type == DISP__NONE) 860 n->norm->Bd.type = dt; 861 } 862 863 if (DISP__NONE == n->norm->Bd.type) { 864 mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE); 865 n->norm->Bd.type = DISP_ragged; 866 } 867 868 return(1); 869 } 870 871 872 static int 873 pre_ss(PRE_ARGS) 874 { 875 876 if (MDOC_BLOCK != n->type) 877 return(1); 878 return(check_parent(mdoc, n, MDOC_Sh, MDOC_BODY)); 879 } 880 881 882 static int 883 pre_sh(PRE_ARGS) 884 { 885 886 if (MDOC_BLOCK != n->type) 887 return(1); 888 return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT)); 889 } 890 891 892 static int 893 pre_it(PRE_ARGS) 894 { 895 896 if (MDOC_BLOCK != n->type) 897 return(1); 898 899 return(check_parent(mdoc, n, MDOC_Bl, MDOC_BODY)); 900 } 901 902 903 static int 904 pre_an(PRE_ARGS) 905 { 906 int i; 907 908 if (NULL == n->args) 909 return(1); 910 911 for (i = 1; i < (int)n->args->argc; i++) 912 mdoc_pmsg(mdoc, n->args->argv[i].line, 913 n->args->argv[i].pos, MANDOCERR_IGNARGV); 914 915 if (MDOC_Split == n->args->argv[0].arg) 916 n->norm->An.auth = AUTH_split; 917 else if (MDOC_Nosplit == n->args->argv[0].arg) 918 n->norm->An.auth = AUTH_nosplit; 919 else 920 abort(); 921 922 return(1); 923 } 924 925 static int 926 pre_std(PRE_ARGS) 927 { 928 929 if (n->args && 1 == n->args->argc) 930 if (MDOC_Std == n->args->argv[0].arg) 931 return(1); 932 933 mdoc_nmsg(mdoc, n, MANDOCERR_NOARGV); 934 return(1); 935 } 936 937 static int 938 pre_dt(PRE_ARGS) 939 { 940 941 if (NULL == mdoc->meta.date || mdoc->meta.os) 942 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO); 943 944 if (mdoc->meta.title) 945 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP); 946 947 return(1); 948 } 949 950 static int 951 pre_os(PRE_ARGS) 952 { 953 954 if (NULL == mdoc->meta.title || NULL == mdoc->meta.date) 955 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO); 956 957 if (mdoc->meta.os) 958 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP); 959 960 return(1); 961 } 962 963 static int 964 pre_dd(PRE_ARGS) 965 { 966 967 if (mdoc->meta.title || mdoc->meta.os) 968 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO); 969 970 if (mdoc->meta.date) 971 mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP); 972 973 return(1); 974 } 975 976 977 static int 978 post_bf(POST_ARGS) 979 { 980 struct mdoc_node *np; 981 enum mdocargt arg; 982 983 /* 984 * Unlike other data pointers, these are "housed" by the HEAD 985 * element, which contains the goods. 986 */ 987 988 if (MDOC_HEAD != mdoc->last->type) { 989 if (ENDBODY_NOT != mdoc->last->end) { 990 assert(mdoc->last->pending); 991 np = mdoc->last->pending->parent->head; 992 } else if (MDOC_BLOCK != mdoc->last->type) { 993 np = mdoc->last->parent->head; 994 } else 995 np = mdoc->last->head; 996 997 assert(np); 998 assert(MDOC_HEAD == np->type); 999 assert(MDOC_Bf == np->tok); 1000 return(1); 1001 } 1002 1003 np = mdoc->last; 1004 assert(MDOC_BLOCK == np->parent->type); 1005 assert(MDOC_Bf == np->parent->tok); 1006 1007 /* 1008 * Cannot have both argument and parameter. 1009 * If neither is specified, let it through with a warning. 1010 */ 1011 1012 if (np->parent->args && np->child) { 1013 mdoc_nmsg(mdoc, np, MANDOCERR_SYNTARGVCOUNT); 1014 return(0); 1015 } else if (NULL == np->parent->args && NULL == np->child) { 1016 mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE); 1017 return(1); 1018 } 1019 1020 /* Extract argument into data. */ 1021 1022 if (np->parent->args) { 1023 arg = np->parent->args->argv[0].arg; 1024 if (MDOC_Emphasis == arg) 1025 np->norm->Bf.font = FONT_Em; 1026 else if (MDOC_Literal == arg) 1027 np->norm->Bf.font = FONT_Li; 1028 else if (MDOC_Symbolic == arg) 1029 np->norm->Bf.font = FONT_Sy; 1030 else 1031 abort(); 1032 return(1); 1033 } 1034 1035 /* Extract parameter into data. */ 1036 1037 if (0 == strcmp(np->child->string, "Em")) 1038 np->norm->Bf.font = FONT_Em; 1039 else if (0 == strcmp(np->child->string, "Li")) 1040 np->norm->Bf.font = FONT_Li; 1041 else if (0 == strcmp(np->child->string, "Sy")) 1042 np->norm->Bf.font = FONT_Sy; 1043 else 1044 mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE); 1045 1046 return(1); 1047 } 1048 1049 static int 1050 post_lb(POST_ARGS) 1051 { 1052 const char *p; 1053 char *buf; 1054 size_t sz; 1055 1056 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1); 1057 1058 assert(mdoc->last->child); 1059 assert(MDOC_TEXT == mdoc->last->child->type); 1060 1061 p = mdoc_a2lib(mdoc->last->child->string); 1062 1063 /* If lookup ok, replace with table value. */ 1064 1065 if (p) { 1066 free(mdoc->last->child->string); 1067 mdoc->last->child->string = mandoc_strdup(p); 1068 return(1); 1069 } 1070 1071 /* If not, use "library ``xxxx''. */ 1072 1073 sz = strlen(mdoc->last->child->string) + 1074 2 + strlen("\\(lqlibrary\\(rq"); 1075 buf = mandoc_malloc(sz); 1076 snprintf(buf, sz, "library \\(lq%s\\(rq", 1077 mdoc->last->child->string); 1078 free(mdoc->last->child->string); 1079 mdoc->last->child->string = buf; 1080 return(1); 1081 } 1082 1083 static int 1084 post_eoln(POST_ARGS) 1085 { 1086 1087 if (mdoc->last->child) 1088 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST); 1089 return(1); 1090 } 1091 1092 1093 static int 1094 post_vt(POST_ARGS) 1095 { 1096 const struct mdoc_node *n; 1097 1098 /* 1099 * The Vt macro comes in both ELEM and BLOCK form, both of which 1100 * have different syntaxes (yet more context-sensitive 1101 * behaviour). ELEM types must have a child, which is already 1102 * guaranteed by the in_line parsing routine; BLOCK types, 1103 * specifically the BODY, should only have TEXT children. 1104 */ 1105 1106 if (MDOC_BODY != mdoc->last->type) 1107 return(1); 1108 1109 for (n = mdoc->last->child; n; n = n->next) 1110 if (MDOC_TEXT != n->type) 1111 mdoc_nmsg(mdoc, n, MANDOCERR_CHILD); 1112 1113 return(1); 1114 } 1115 1116 1117 static int 1118 post_nm(POST_ARGS) 1119 { 1120 1121 if (NULL != mdoc->meta.name) 1122 return(1); 1123 1124 mdoc_deroff(&mdoc->meta.name, mdoc->last); 1125 1126 if (NULL == mdoc->meta.name) { 1127 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME); 1128 mdoc->meta.name = mandoc_strdup("UNKNOWN"); 1129 } 1130 return(1); 1131 } 1132 1133 static int 1134 post_literal(POST_ARGS) 1135 { 1136 1137 /* 1138 * The `Dl' (note "el" not "one") and `Bd' macros unset the 1139 * MDOC_LITERAL flag as they leave. Note that `Bd' only sets 1140 * this in literal mode, but it doesn't hurt to just switch it 1141 * off in general since displays can't be nested. 1142 */ 1143 1144 if (MDOC_BODY == mdoc->last->type) 1145 mdoc->flags &= ~MDOC_LITERAL; 1146 1147 return(1); 1148 } 1149 1150 static int 1151 post_defaults(POST_ARGS) 1152 { 1153 struct mdoc_node *nn; 1154 1155 /* 1156 * The `Ar' defaults to "file ..." if no value is provided as an 1157 * argument; the `Mt' and `Pa' macros use "~"; the `Li' just 1158 * gets an empty string. 1159 */ 1160 1161 if (mdoc->last->child) 1162 return(1); 1163 1164 nn = mdoc->last; 1165 mdoc->next = MDOC_NEXT_CHILD; 1166 1167 switch (nn->tok) { 1168 case (MDOC_Ar): 1169 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "file")) 1170 return(0); 1171 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "...")) 1172 return(0); 1173 break; 1174 case (MDOC_At): 1175 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "AT&T")) 1176 return(0); 1177 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "UNIX")) 1178 return(0); 1179 break; 1180 case (MDOC_Li): 1181 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "")) 1182 return(0); 1183 break; 1184 case (MDOC_Pa): 1185 /* FALLTHROUGH */ 1186 case (MDOC_Mt): 1187 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "~")) 1188 return(0); 1189 break; 1190 default: 1191 abort(); 1192 /* NOTREACHED */ 1193 } 1194 1195 mdoc->last = nn; 1196 return(1); 1197 } 1198 1199 static int 1200 post_at(POST_ARGS) 1201 { 1202 const char *p, *q; 1203 char *buf; 1204 size_t sz; 1205 1206 /* 1207 * If we have a child, look it up in the standard keys. If a 1208 * key exist, use that instead of the child; if it doesn't, 1209 * prefix "AT&T UNIX " to the existing data. 1210 */ 1211 1212 if (NULL == mdoc->last->child) 1213 return(1); 1214 1215 assert(MDOC_TEXT == mdoc->last->child->type); 1216 p = mdoc_a2att(mdoc->last->child->string); 1217 1218 if (p) { 1219 free(mdoc->last->child->string); 1220 mdoc->last->child->string = mandoc_strdup(p); 1221 } else { 1222 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADATT); 1223 p = "AT&T UNIX "; 1224 q = mdoc->last->child->string; 1225 sz = strlen(p) + strlen(q) + 1; 1226 buf = mandoc_malloc(sz); 1227 strlcpy(buf, p, sz); 1228 strlcat(buf, q, sz); 1229 free(mdoc->last->child->string); 1230 mdoc->last->child->string = buf; 1231 } 1232 1233 return(1); 1234 } 1235 1236 static int 1237 post_an(POST_ARGS) 1238 { 1239 struct mdoc_node *np; 1240 1241 np = mdoc->last; 1242 if (AUTH__NONE == np->norm->An.auth) { 1243 if (0 == np->child) 1244 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0); 1245 } else if (np->child) 1246 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0); 1247 1248 return(1); 1249 } 1250 1251 1252 static int 1253 post_it(POST_ARGS) 1254 { 1255 int i, cols; 1256 enum mdoc_list lt; 1257 struct mdoc_node *n, *c; 1258 enum mandocerr er; 1259 1260 if (MDOC_BLOCK != mdoc->last->type) 1261 return(1); 1262 1263 n = mdoc->last->parent->parent; 1264 lt = n->norm->Bl.type; 1265 1266 if (LIST__NONE == lt) { 1267 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE); 1268 return(1); 1269 } 1270 1271 switch (lt) { 1272 case (LIST_tag): 1273 if (mdoc->last->head->child) 1274 break; 1275 /* FIXME: give this a dummy value. */ 1276 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS); 1277 break; 1278 case (LIST_hang): 1279 /* FALLTHROUGH */ 1280 case (LIST_ohang): 1281 /* FALLTHROUGH */ 1282 case (LIST_inset): 1283 /* FALLTHROUGH */ 1284 case (LIST_diag): 1285 if (NULL == mdoc->last->head->child) 1286 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS); 1287 break; 1288 case (LIST_bullet): 1289 /* FALLTHROUGH */ 1290 case (LIST_dash): 1291 /* FALLTHROUGH */ 1292 case (LIST_enum): 1293 /* FALLTHROUGH */ 1294 case (LIST_hyphen): 1295 if (NULL == mdoc->last->body->child) 1296 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY); 1297 /* FALLTHROUGH */ 1298 case (LIST_item): 1299 if (mdoc->last->head->child) 1300 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST); 1301 break; 1302 case (LIST_column): 1303 cols = (int)n->norm->Bl.ncols; 1304 1305 assert(NULL == mdoc->last->head->child); 1306 1307 if (NULL == mdoc->last->body->child) 1308 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY); 1309 1310 for (i = 0, c = mdoc->last->child; c; c = c->next) 1311 if (MDOC_BODY == c->type) 1312 i++; 1313 1314 if (i < cols) 1315 er = MANDOCERR_ARGCOUNT; 1316 else if (i == cols || i == cols + 1) 1317 break; 1318 else 1319 er = MANDOCERR_SYNTARGCOUNT; 1320 1321 mandoc_vmsg(er, mdoc->parse, mdoc->last->line, 1322 mdoc->last->pos, 1323 "columns == %d (have %d)", cols, i); 1324 return(MANDOCERR_ARGCOUNT == er); 1325 default: 1326 break; 1327 } 1328 1329 return(1); 1330 } 1331 1332 static int 1333 post_bl_block(POST_ARGS) 1334 { 1335 struct mdoc_node *n, *ni, *nc; 1336 1337 /* 1338 * These are fairly complicated, so we've broken them into two 1339 * functions. post_bl_block_tag() is called when a -tag is 1340 * specified, but no -width (it must be guessed). The second 1341 * when a -width is specified (macro indicators must be 1342 * rewritten into real lengths). 1343 */ 1344 1345 n = mdoc->last; 1346 1347 if (LIST_tag == n->norm->Bl.type && 1348 NULL == n->norm->Bl.width) { 1349 if ( ! post_bl_block_tag(mdoc)) 1350 return(0); 1351 assert(n->norm->Bl.width); 1352 } else if (NULL != n->norm->Bl.width) { 1353 if ( ! post_bl_block_width(mdoc)) 1354 return(0); 1355 assert(n->norm->Bl.width); 1356 } 1357 1358 for (ni = n->body->child; ni; ni = ni->next) { 1359 if (NULL == ni->body) 1360 continue; 1361 nc = ni->body->last; 1362 while (NULL != nc) { 1363 switch (nc->tok) { 1364 case (MDOC_Pp): 1365 /* FALLTHROUGH */ 1366 case (MDOC_Lp): 1367 /* FALLTHROUGH */ 1368 case (MDOC_br): 1369 break; 1370 default: 1371 nc = NULL; 1372 continue; 1373 } 1374 if (NULL == ni->next) { 1375 mdoc_nmsg(mdoc, nc, MANDOCERR_MOVEPAR); 1376 if ( ! mdoc_node_relink(mdoc, nc)) 1377 return(0); 1378 } else if (0 == n->norm->Bl.comp && 1379 LIST_column != n->norm->Bl.type) { 1380 mdoc_nmsg(mdoc, nc, MANDOCERR_IGNPAR); 1381 mdoc_node_delete(mdoc, nc); 1382 } else 1383 break; 1384 nc = ni->body->last; 1385 } 1386 } 1387 return(1); 1388 } 1389 1390 static int 1391 post_bl_block_width(POST_ARGS) 1392 { 1393 size_t width; 1394 int i; 1395 enum mdoct tok; 1396 struct mdoc_node *n; 1397 char buf[NUMSIZ]; 1398 1399 n = mdoc->last; 1400 1401 /* 1402 * Calculate the real width of a list from the -width string, 1403 * which may contain a macro (with a known default width), a 1404 * literal string, or a scaling width. 1405 * 1406 * If the value to -width is a macro, then we re-write it to be 1407 * the macro's width as set in share/tmac/mdoc/doc-common. 1408 */ 1409 1410 if (0 == strcmp(n->norm->Bl.width, "Ds")) 1411 width = 6; 1412 else if (MDOC_MAX == (tok = mdoc_hash_find(n->norm->Bl.width))) 1413 return(1); 1414 else if (0 == (width = macro2len(tok))) { 1415 mdoc_nmsg(mdoc, n, MANDOCERR_BADWIDTH); 1416 return(1); 1417 } 1418 1419 /* The value already exists: free and reallocate it. */ 1420 1421 assert(n->args); 1422 1423 for (i = 0; i < (int)n->args->argc; i++) 1424 if (MDOC_Width == n->args->argv[i].arg) 1425 break; 1426 1427 assert(i < (int)n->args->argc); 1428 1429 snprintf(buf, NUMSIZ, "%un", (unsigned int)width); 1430 free(n->args->argv[i].value[0]); 1431 n->args->argv[i].value[0] = mandoc_strdup(buf); 1432 1433 /* Set our width! */ 1434 n->norm->Bl.width = n->args->argv[i].value[0]; 1435 return(1); 1436 } 1437 1438 static int 1439 post_bl_block_tag(POST_ARGS) 1440 { 1441 struct mdoc_node *n, *nn; 1442 size_t sz, ssz; 1443 int i; 1444 char buf[NUMSIZ]; 1445 1446 /* 1447 * Calculate the -width for a `Bl -tag' list if it hasn't been 1448 * provided. Uses the first head macro. NOTE AGAIN: this is 1449 * ONLY if the -width argument has NOT been provided. See 1450 * post_bl_block_width() for converting the -width string. 1451 */ 1452 1453 sz = 10; 1454 n = mdoc->last; 1455 1456 for (nn = n->body->child; nn; nn = nn->next) { 1457 if (MDOC_It != nn->tok) 1458 continue; 1459 1460 assert(MDOC_BLOCK == nn->type); 1461 nn = nn->head->child; 1462 1463 if (nn == NULL) 1464 break; 1465 1466 if (MDOC_TEXT == nn->type) { 1467 sz = strlen(nn->string) + 1; 1468 break; 1469 } 1470 1471 if (0 != (ssz = macro2len(nn->tok))) 1472 sz = ssz; 1473 1474 break; 1475 } 1476 1477 /* Defaults to ten ens. */ 1478 1479 snprintf(buf, NUMSIZ, "%un", (unsigned int)sz); 1480 1481 /* 1482 * We have to dynamically add this to the macro's argument list. 1483 * We're guaranteed that a MDOC_Width doesn't already exist. 1484 */ 1485 1486 assert(n->args); 1487 i = (int)(n->args->argc)++; 1488 1489 n->args->argv = mandoc_realloc(n->args->argv, 1490 n->args->argc * sizeof(struct mdoc_argv)); 1491 1492 n->args->argv[i].arg = MDOC_Width; 1493 n->args->argv[i].line = n->line; 1494 n->args->argv[i].pos = n->pos; 1495 n->args->argv[i].sz = 1; 1496 n->args->argv[i].value = mandoc_malloc(sizeof(char *)); 1497 n->args->argv[i].value[0] = mandoc_strdup(buf); 1498 1499 /* Set our width! */ 1500 n->norm->Bl.width = n->args->argv[i].value[0]; 1501 return(1); 1502 } 1503 1504 1505 static int 1506 post_bl_head(POST_ARGS) 1507 { 1508 struct mdoc_node *np, *nn, *nnp; 1509 int i, j; 1510 1511 if (LIST_column != mdoc->last->norm->Bl.type) 1512 /* FIXME: this should be ERROR class... */ 1513 return(hwarn_eq0(mdoc)); 1514 1515 /* 1516 * Convert old-style lists, where the column width specifiers 1517 * trail as macro parameters, to the new-style ("normal-form") 1518 * lists where they're argument values following -column. 1519 */ 1520 1521 /* First, disallow both types and allow normal-form. */ 1522 1523 /* 1524 * TODO: technically, we can accept both and just merge the two 1525 * lists, but I'll leave that for another day. 1526 */ 1527 1528 if (mdoc->last->norm->Bl.ncols && mdoc->last->nchild) { 1529 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_COLUMNS); 1530 return(0); 1531 } else if (NULL == mdoc->last->child) 1532 return(1); 1533 1534 np = mdoc->last->parent; 1535 assert(np->args); 1536 1537 for (j = 0; j < (int)np->args->argc; j++) 1538 if (MDOC_Column == np->args->argv[j].arg) 1539 break; 1540 1541 assert(j < (int)np->args->argc); 1542 assert(0 == np->args->argv[j].sz); 1543 1544 /* 1545 * Accommodate for new-style groff column syntax. Shuffle the 1546 * child nodes, all of which must be TEXT, as arguments for the 1547 * column field. Then, delete the head children. 1548 */ 1549 1550 np->args->argv[j].sz = (size_t)mdoc->last->nchild; 1551 np->args->argv[j].value = mandoc_malloc 1552 ((size_t)mdoc->last->nchild * sizeof(char *)); 1553 1554 mdoc->last->norm->Bl.ncols = np->args->argv[j].sz; 1555 mdoc->last->norm->Bl.cols = (void *)np->args->argv[j].value; 1556 1557 for (i = 0, nn = mdoc->last->child; nn; i++) { 1558 np->args->argv[j].value[i] = nn->string; 1559 nn->string = NULL; 1560 nnp = nn; 1561 nn = nn->next; 1562 mdoc_node_delete(NULL, nnp); 1563 } 1564 1565 mdoc->last->nchild = 0; 1566 mdoc->last->child = NULL; 1567 1568 return(1); 1569 } 1570 1571 static int 1572 post_bl(POST_ARGS) 1573 { 1574 struct mdoc_node *nparent, *nprev; /* of the Bl block */ 1575 struct mdoc_node *nblock, *nbody; /* of the Bl */ 1576 struct mdoc_node *nchild, *nnext; /* of the Bl body */ 1577 1578 nbody = mdoc->last; 1579 switch (nbody->type) { 1580 case (MDOC_BLOCK): 1581 return(post_bl_block(mdoc)); 1582 case (MDOC_HEAD): 1583 return(post_bl_head(mdoc)); 1584 case (MDOC_BODY): 1585 break; 1586 default: 1587 return(1); 1588 } 1589 1590 nchild = nbody->child; 1591 while (NULL != nchild) { 1592 if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) { 1593 nchild = nchild->next; 1594 continue; 1595 } 1596 1597 mdoc_nmsg(mdoc, nchild, MANDOCERR_CHILD); 1598 1599 /* 1600 * Move the node out of the Bl block. 1601 * First, collect all required node pointers. 1602 */ 1603 1604 nblock = nbody->parent; 1605 nprev = nblock->prev; 1606 nparent = nblock->parent; 1607 nnext = nchild->next; 1608 1609 /* 1610 * Unlink this child. 1611 */ 1612 1613 assert(NULL == nchild->prev); 1614 if (0 == --nbody->nchild) { 1615 nbody->child = NULL; 1616 nbody->last = NULL; 1617 assert(NULL == nnext); 1618 } else { 1619 nbody->child = nnext; 1620 nnext->prev = NULL; 1621 } 1622 1623 /* 1624 * Relink this child. 1625 */ 1626 1627 nchild->parent = nparent; 1628 nchild->prev = nprev; 1629 nchild->next = nblock; 1630 1631 nblock->prev = nchild; 1632 nparent->nchild++; 1633 if (NULL == nprev) 1634 nparent->child = nchild; 1635 else 1636 nprev->next = nchild; 1637 1638 nchild = nnext; 1639 } 1640 1641 return(1); 1642 } 1643 1644 static int 1645 ebool(struct mdoc *mdoc) 1646 { 1647 1648 if (NULL == mdoc->last->child) { 1649 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY); 1650 mdoc_node_delete(mdoc, mdoc->last); 1651 return(1); 1652 } 1653 check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1); 1654 1655 assert(MDOC_TEXT == mdoc->last->child->type); 1656 1657 if (0 == strcmp(mdoc->last->child->string, "on")) { 1658 if (MDOC_Sm == mdoc->last->tok) 1659 mdoc->flags &= ~MDOC_SMOFF; 1660 return(1); 1661 } 1662 if (0 == strcmp(mdoc->last->child->string, "off")) { 1663 if (MDOC_Sm == mdoc->last->tok) 1664 mdoc->flags |= MDOC_SMOFF; 1665 return(1); 1666 } 1667 1668 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL); 1669 return(1); 1670 } 1671 1672 static int 1673 post_root(POST_ARGS) 1674 { 1675 int erc; 1676 struct mdoc_node *n; 1677 1678 erc = 0; 1679 1680 /* Check that we have a finished prologue. */ 1681 1682 if ( ! (MDOC_PBODY & mdoc->flags)) { 1683 erc++; 1684 mdoc_nmsg(mdoc, mdoc->first, MANDOCERR_NODOCPROLOG); 1685 } 1686 1687 n = mdoc->first; 1688 assert(n); 1689 1690 /* Check that we begin with a proper `Sh'. */ 1691 1692 if (NULL == n->child) { 1693 erc++; 1694 mdoc_nmsg(mdoc, n, MANDOCERR_NODOCBODY); 1695 } else if (MDOC_BLOCK != n->child->type || 1696 MDOC_Sh != n->child->tok) { 1697 erc++; 1698 /* Can this be lifted? See rxdebug.1 for example. */ 1699 mdoc_nmsg(mdoc, n, MANDOCERR_NODOCBODY); 1700 } 1701 1702 return(erc ? 0 : 1); 1703 } 1704 1705 static int 1706 post_st(POST_ARGS) 1707 { 1708 struct mdoc_node *ch; 1709 const char *p; 1710 1711 if (NULL == (ch = mdoc->last->child)) { 1712 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY); 1713 mdoc_node_delete(mdoc, mdoc->last); 1714 return(1); 1715 } 1716 1717 assert(MDOC_TEXT == ch->type); 1718 1719 if (NULL == (p = mdoc_a2st(ch->string))) { 1720 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADSTANDARD); 1721 mdoc_node_delete(mdoc, mdoc->last); 1722 } else { 1723 free(ch->string); 1724 ch->string = mandoc_strdup(p); 1725 } 1726 1727 return(1); 1728 } 1729 1730 static int 1731 post_rs(POST_ARGS) 1732 { 1733 struct mdoc_node *nn, *next, *prev; 1734 int i, j; 1735 1736 switch (mdoc->last->type) { 1737 case (MDOC_HEAD): 1738 check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0); 1739 return(1); 1740 case (MDOC_BODY): 1741 if (mdoc->last->child) 1742 break; 1743 check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0); 1744 return(1); 1745 default: 1746 return(1); 1747 } 1748 1749 /* 1750 * Make sure only certain types of nodes are allowed within the 1751 * the `Rs' body. Delete offending nodes and raise a warning. 1752 * Do this before re-ordering for the sake of clarity. 1753 */ 1754 1755 next = NULL; 1756 for (nn = mdoc->last->child; nn; nn = next) { 1757 for (i = 0; i < RSORD_MAX; i++) 1758 if (nn->tok == rsord[i]) 1759 break; 1760 1761 if (i < RSORD_MAX) { 1762 if (MDOC__J == rsord[i] || MDOC__B == rsord[i]) 1763 mdoc->last->norm->Rs.quote_T++; 1764 next = nn->next; 1765 continue; 1766 } 1767 1768 next = nn->next; 1769 mdoc_nmsg(mdoc, nn, MANDOCERR_CHILD); 1770 mdoc_node_delete(mdoc, nn); 1771 } 1772 1773 /* 1774 * Nothing to sort if only invalid nodes were found 1775 * inside the `Rs' body. 1776 */ 1777 1778 if (NULL == mdoc->last->child) 1779 return(1); 1780 1781 /* 1782 * The full `Rs' block needs special handling to order the 1783 * sub-elements according to `rsord'. Pick through each element 1784 * and correctly order it. This is a insertion sort. 1785 */ 1786 1787 next = NULL; 1788 for (nn = mdoc->last->child->next; nn; nn = next) { 1789 /* Determine order of `nn'. */ 1790 for (i = 0; i < RSORD_MAX; i++) 1791 if (rsord[i] == nn->tok) 1792 break; 1793 1794 /* 1795 * Remove `nn' from the chain. This somewhat 1796 * repeats mdoc_node_unlink(), but since we're 1797 * just re-ordering, there's no need for the 1798 * full unlink process. 1799 */ 1800 1801 if (NULL != (next = nn->next)) 1802 next->prev = nn->prev; 1803 1804 if (NULL != (prev = nn->prev)) 1805 prev->next = nn->next; 1806 1807 nn->prev = nn->next = NULL; 1808 1809 /* 1810 * Scan back until we reach a node that's 1811 * ordered before `nn'. 1812 */ 1813 1814 for ( ; prev ; prev = prev->prev) { 1815 /* Determine order of `prev'. */ 1816 for (j = 0; j < RSORD_MAX; j++) 1817 if (rsord[j] == prev->tok) 1818 break; 1819 1820 if (j <= i) 1821 break; 1822 } 1823 1824 /* 1825 * Set `nn' back into its correct place in front 1826 * of the `prev' node. 1827 */ 1828 1829 nn->prev = prev; 1830 1831 if (prev) { 1832 if (prev->next) 1833 prev->next->prev = nn; 1834 nn->next = prev->next; 1835 prev->next = nn; 1836 } else { 1837 mdoc->last->child->prev = nn; 1838 nn->next = mdoc->last->child; 1839 mdoc->last->child = nn; 1840 } 1841 } 1842 1843 return(1); 1844 } 1845 1846 /* 1847 * For some arguments of some macros, 1848 * convert all breakable hyphens into ASCII_HYPH. 1849 */ 1850 static int 1851 post_hyph(POST_ARGS) 1852 { 1853 struct mdoc_node *n, *nch; 1854 char *cp; 1855 1856 n = mdoc->last; 1857 switch (n->type) { 1858 case (MDOC_HEAD): 1859 if (MDOC_Sh == n->tok || MDOC_Ss == n->tok) 1860 break; 1861 return(1); 1862 case (MDOC_BODY): 1863 if (MDOC_D1 == n->tok || MDOC_Nd == n->tok) 1864 break; 1865 return(1); 1866 case (MDOC_ELEM): 1867 break; 1868 default: 1869 return(1); 1870 } 1871 1872 for (nch = n->child; nch; nch = nch->next) { 1873 if (MDOC_TEXT != nch->type) 1874 continue; 1875 cp = nch->string; 1876 if ('\0' == *cp) 1877 continue; 1878 while ('\0' != *(++cp)) 1879 if ('-' == *cp && 1880 isalpha((unsigned char)cp[-1]) && 1881 isalpha((unsigned char)cp[1])) 1882 *cp = ASCII_HYPH; 1883 } 1884 return(1); 1885 } 1886 1887 static int 1888 post_ns(POST_ARGS) 1889 { 1890 1891 if (MDOC_LINE & mdoc->last->flags) 1892 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNNS); 1893 return(1); 1894 } 1895 1896 static int 1897 post_sh(POST_ARGS) 1898 { 1899 1900 if (MDOC_HEAD == mdoc->last->type) 1901 return(post_sh_head(mdoc)); 1902 if (MDOC_BODY == mdoc->last->type) 1903 return(post_sh_body(mdoc)); 1904 1905 return(1); 1906 } 1907 1908 static int 1909 post_sh_body(POST_ARGS) 1910 { 1911 struct mdoc_node *n; 1912 1913 if (SEC_NAME != mdoc->lastsec) 1914 return(1); 1915 1916 /* 1917 * Warn if the NAME section doesn't contain the `Nm' and `Nd' 1918 * macros (can have multiple `Nm' and one `Nd'). Note that the 1919 * children of the BODY declaration can also be "text". 1920 */ 1921 1922 if (NULL == (n = mdoc->last->child)) { 1923 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC); 1924 return(1); 1925 } 1926 1927 for ( ; n && n->next; n = n->next) { 1928 if (MDOC_ELEM == n->type && MDOC_Nm == n->tok) 1929 continue; 1930 if (MDOC_TEXT == n->type) 1931 continue; 1932 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC); 1933 } 1934 1935 assert(n); 1936 if (MDOC_BLOCK == n->type && MDOC_Nd == n->tok) 1937 return(1); 1938 1939 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC); 1940 return(1); 1941 } 1942 1943 static int 1944 post_sh_head(POST_ARGS) 1945 { 1946 struct mdoc_node *n; 1947 const char *secname; 1948 enum mdoc_sec sec; 1949 1950 /* 1951 * Process a new section. Sections are either "named" or 1952 * "custom". Custom sections are user-defined, while named ones 1953 * follow a conventional order and may only appear in certain 1954 * manual sections. 1955 */ 1956 1957 secname = NULL; 1958 sec = SEC_CUSTOM; 1959 n = mdoc->last; 1960 if (n->child) { 1961 assert(1 == n->nchild); 1962 n = n->child; 1963 assert(NULL != n); 1964 assert(MDOC_TEXT == n->type); 1965 secname = n->string; 1966 sec = a2sec(secname); 1967 } 1968 1969 /* The NAME should be first. */ 1970 1971 if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed) 1972 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NAMESECFIRST); 1973 1974 /* The SYNOPSIS gets special attention in other areas. */ 1975 1976 if (SEC_SYNOPSIS == sec) { 1977 roff_setreg(mdoc->roff, "nS", 1, '='); 1978 mdoc->flags |= MDOC_SYNOPSIS; 1979 } else { 1980 roff_setreg(mdoc->roff, "nS", 0, '='); 1981 mdoc->flags &= ~MDOC_SYNOPSIS; 1982 } 1983 1984 /* Mark our last section. */ 1985 1986 mdoc->lastsec = sec; 1987 1988 /* 1989 * Set the section attribute for the current HEAD, for its 1990 * parent BLOCK, and for the HEAD children; the latter can 1991 * only be TEXT nodes, so no recursion is needed. 1992 * For other blocks and elements, including .Sh BODY, this is 1993 * done when allocating the node data structures, but for .Sh 1994 * BLOCK and HEAD, the section is still unknown at that time. 1995 */ 1996 1997 mdoc->last->parent->sec = sec; 1998 mdoc->last->sec = sec; 1999 for (n = mdoc->last->child; n; n = n->next) 2000 n->sec = sec; 2001 2002 /* We don't care about custom sections after this. */ 2003 2004 if (SEC_CUSTOM == sec) 2005 return(1); 2006 2007 /* 2008 * Check whether our non-custom section is being repeated or is 2009 * out of order. 2010 */ 2011 2012 if (sec == mdoc->lastnamed) 2013 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECREP); 2014 2015 if (sec < mdoc->lastnamed) 2016 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECOOO); 2017 2018 /* Mark the last named section. */ 2019 2020 mdoc->lastnamed = sec; 2021 2022 /* Check particular section/manual conventions. */ 2023 2024 assert(mdoc->meta.msec); 2025 2026 switch (sec) { 2027 case (SEC_ERRORS): 2028 if (*mdoc->meta.msec == '4') 2029 break; 2030 /* FALLTHROUGH */ 2031 case (SEC_RETURN_VALUES): 2032 /* FALLTHROUGH */ 2033 case (SEC_LIBRARY): 2034 if (*mdoc->meta.msec == '2') 2035 break; 2036 if (*mdoc->meta.msec == '3') 2037 break; 2038 if (*mdoc->meta.msec == '9') 2039 break; 2040 mandoc_msg(MANDOCERR_SECMSEC, mdoc->parse, 2041 mdoc->last->line, mdoc->last->pos, secname); 2042 break; 2043 default: 2044 break; 2045 } 2046 2047 return(1); 2048 } 2049 2050 static int 2051 post_ignpar(POST_ARGS) 2052 { 2053 struct mdoc_node *np; 2054 2055 if (MDOC_BODY != mdoc->last->type) 2056 return(1); 2057 2058 if (NULL != (np = mdoc->last->child)) 2059 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { 2060 mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR); 2061 mdoc_node_delete(mdoc, np); 2062 } 2063 2064 if (NULL != (np = mdoc->last->last)) 2065 if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { 2066 mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR); 2067 mdoc_node_delete(mdoc, np); 2068 } 2069 2070 return(1); 2071 } 2072 2073 static int 2074 pre_par(PRE_ARGS) 2075 { 2076 2077 if (NULL == mdoc->last) 2078 return(1); 2079 if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type) 2080 return(1); 2081 2082 /* 2083 * Don't allow prior `Lp' or `Pp' prior to a paragraph-type 2084 * block: `Lp', `Pp', or non-compact `Bd' or `Bl'. 2085 */ 2086 2087 if (MDOC_Pp != mdoc->last->tok && 2088 MDOC_Lp != mdoc->last->tok && 2089 MDOC_br != mdoc->last->tok) 2090 return(1); 2091 if (MDOC_Bl == n->tok && n->norm->Bl.comp) 2092 return(1); 2093 if (MDOC_Bd == n->tok && n->norm->Bd.comp) 2094 return(1); 2095 if (MDOC_It == n->tok && n->parent->norm->Bl.comp) 2096 return(1); 2097 2098 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR); 2099 mdoc_node_delete(mdoc, mdoc->last); 2100 return(1); 2101 } 2102 2103 static int 2104 post_par(POST_ARGS) 2105 { 2106 2107 if (MDOC_ELEM != mdoc->last->type && 2108 MDOC_BLOCK != mdoc->last->type) 2109 return(1); 2110 2111 if (NULL == mdoc->last->prev) { 2112 if (MDOC_Sh != mdoc->last->parent->tok && 2113 MDOC_Ss != mdoc->last->parent->tok) 2114 return(1); 2115 } else { 2116 if (MDOC_Pp != mdoc->last->prev->tok && 2117 MDOC_Lp != mdoc->last->prev->tok && 2118 (MDOC_br != mdoc->last->tok || 2119 (MDOC_sp != mdoc->last->prev->tok && 2120 MDOC_br != mdoc->last->prev->tok))) 2121 return(1); 2122 } 2123 2124 mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR); 2125 mdoc_node_delete(mdoc, mdoc->last); 2126 return(1); 2127 } 2128 2129 static int 2130 pre_literal(PRE_ARGS) 2131 { 2132 2133 if (MDOC_BODY != n->type) 2134 return(1); 2135 2136 /* 2137 * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd 2138 * -unfilled' macros set MDOC_LITERAL on entrance to the body. 2139 */ 2140 2141 switch (n->tok) { 2142 case (MDOC_Dl): 2143 mdoc->flags |= MDOC_LITERAL; 2144 break; 2145 case (MDOC_Bd): 2146 if (DISP_literal == n->norm->Bd.type) 2147 mdoc->flags |= MDOC_LITERAL; 2148 if (DISP_unfilled == n->norm->Bd.type) 2149 mdoc->flags |= MDOC_LITERAL; 2150 break; 2151 default: 2152 abort(); 2153 /* NOTREACHED */ 2154 } 2155 2156 return(1); 2157 } 2158 2159 static int 2160 post_dd(POST_ARGS) 2161 { 2162 struct mdoc_node *n; 2163 char *datestr; 2164 2165 if (mdoc->meta.date) 2166 free(mdoc->meta.date); 2167 2168 n = mdoc->last; 2169 if (NULL == n->child || '\0' == n->child->string[0]) { 2170 mdoc->meta.date = mdoc->quick ? mandoc_strdup("") : 2171 mandoc_normdate(mdoc->parse, NULL, n->line, n->pos); 2172 return(1); 2173 } 2174 2175 datestr = NULL; 2176 mdoc_deroff(&datestr, n); 2177 if (mdoc->quick) 2178 mdoc->meta.date = datestr; 2179 else { 2180 mdoc->meta.date = mandoc_normdate(mdoc->parse, 2181 datestr, n->line, n->pos); 2182 free(datestr); 2183 } 2184 return(1); 2185 } 2186 2187 static int 2188 post_dt(POST_ARGS) 2189 { 2190 struct mdoc_node *nn, *n; 2191 const char *cp; 2192 char *p; 2193 2194 n = mdoc->last; 2195 2196 if (mdoc->meta.title) 2197 free(mdoc->meta.title); 2198 if (mdoc->meta.vol) 2199 free(mdoc->meta.vol); 2200 if (mdoc->meta.arch) 2201 free(mdoc->meta.arch); 2202 2203 mdoc->meta.title = mdoc->meta.vol = mdoc->meta.arch = NULL; 2204 2205 /* First make all characters uppercase. */ 2206 2207 if (NULL != (nn = n->child)) 2208 for (p = nn->string; *p; p++) { 2209 if (toupper((unsigned char)*p) == *p) 2210 continue; 2211 2212 /* 2213 * FIXME: don't be lazy: have this make all 2214 * characters be uppercase and just warn once. 2215 */ 2216 mdoc_nmsg(mdoc, nn, MANDOCERR_UPPERCASE); 2217 break; 2218 } 2219 2220 /* Handles: `.Dt' 2221 * --> title = unknown, volume = local, msec = 0, arch = NULL 2222 */ 2223 2224 if (NULL == (nn = n->child)) { 2225 /* XXX: make these macro values. */ 2226 /* FIXME: warn about missing values. */ 2227 mdoc->meta.title = mandoc_strdup("UNKNOWN"); 2228 mdoc->meta.vol = mandoc_strdup("LOCAL"); 2229 mdoc->meta.msec = mandoc_strdup("1"); 2230 return(1); 2231 } 2232 2233 /* Handles: `.Dt TITLE' 2234 * --> title = TITLE, volume = local, msec = 0, arch = NULL 2235 */ 2236 2237 mdoc->meta.title = mandoc_strdup 2238 ('\0' == nn->string[0] ? "UNKNOWN" : nn->string); 2239 2240 if (NULL == (nn = nn->next)) { 2241 /* FIXME: warn about missing msec. */ 2242 /* XXX: make this a macro value. */ 2243 mdoc->meta.vol = mandoc_strdup("LOCAL"); 2244 mdoc->meta.msec = mandoc_strdup("1"); 2245 return(1); 2246 } 2247 2248 /* Handles: `.Dt TITLE SEC' 2249 * --> title = TITLE, volume = SEC is msec ? 2250 * format(msec) : SEC, 2251 * msec = SEC is msec ? atoi(msec) : 0, 2252 * arch = NULL 2253 */ 2254 2255 cp = mandoc_a2msec(nn->string); 2256 if (cp) { 2257 mdoc->meta.vol = mandoc_strdup(cp); 2258 mdoc->meta.msec = mandoc_strdup(nn->string); 2259 } else { 2260 mdoc_nmsg(mdoc, n, MANDOCERR_BADMSEC); 2261 mdoc->meta.vol = mandoc_strdup(nn->string); 2262 mdoc->meta.msec = mandoc_strdup(nn->string); 2263 } 2264 2265 if (NULL == (nn = nn->next)) 2266 return(1); 2267 2268 /* Handles: `.Dt TITLE SEC VOL' 2269 * --> title = TITLE, volume = VOL is vol ? 2270 * format(VOL) : 2271 * VOL is arch ? format(arch) : 2272 * VOL 2273 */ 2274 2275 cp = mdoc_a2vol(nn->string); 2276 if (cp) { 2277 free(mdoc->meta.vol); 2278 mdoc->meta.vol = mandoc_strdup(cp); 2279 } else { 2280 cp = mdoc_a2arch(nn->string); 2281 if (NULL == cp) { 2282 mdoc_nmsg(mdoc, nn, MANDOCERR_BADVOLARCH); 2283 free(mdoc->meta.vol); 2284 mdoc->meta.vol = mandoc_strdup(nn->string); 2285 } else 2286 mdoc->meta.arch = mandoc_strdup(cp); 2287 } 2288 2289 /* Ignore any subsequent parameters... */ 2290 /* FIXME: warn about subsequent parameters. */ 2291 2292 return(1); 2293 } 2294 2295 static int 2296 post_prol(POST_ARGS) 2297 { 2298 /* 2299 * Remove prologue macros from the document after they're 2300 * processed. The final document uses mdoc_meta for these 2301 * values and discards the originals. 2302 */ 2303 2304 mdoc_node_delete(mdoc, mdoc->last); 2305 if (mdoc->meta.title && mdoc->meta.date && mdoc->meta.os) 2306 mdoc->flags |= MDOC_PBODY; 2307 2308 return(1); 2309 } 2310 2311 static int 2312 post_bx(POST_ARGS) 2313 { 2314 struct mdoc_node *n; 2315 2316 /* 2317 * Make `Bx's second argument always start with an uppercase 2318 * letter. Groff checks if it's an "accepted" term, but we just 2319 * uppercase blindly. 2320 */ 2321 2322 n = mdoc->last->child; 2323 if (n && NULL != (n = n->next)) 2324 *n->string = (char)toupper 2325 ((unsigned char)*n->string); 2326 2327 return(1); 2328 } 2329 2330 static int 2331 post_os(POST_ARGS) 2332 { 2333 #ifndef OSNAME 2334 struct utsname utsname; 2335 static char *defbuf; 2336 #endif 2337 struct mdoc_node *n; 2338 2339 n = mdoc->last; 2340 2341 /* 2342 * Set the operating system by way of the `Os' macro. 2343 * The order of precedence is: 2344 * 1. the argument of the `Os' macro, unless empty 2345 * 2. the -Ios=foo command line argument, if provided 2346 * 3. -DOSNAME="\"foo\"", if provided during compilation 2347 * 4. "sysname release" from uname(3) 2348 */ 2349 2350 free(mdoc->meta.os); 2351 mdoc->meta.os = NULL; 2352 mdoc_deroff(&mdoc->meta.os, n); 2353 if (mdoc->meta.os) 2354 return(1); 2355 2356 if (mdoc->defos) { 2357 mdoc->meta.os = mandoc_strdup(mdoc->defos); 2358 return(1); 2359 } 2360 2361 #ifdef OSNAME 2362 mdoc->meta.os = mandoc_strdup(OSNAME); 2363 #else /*!OSNAME */ 2364 if (NULL == defbuf) { 2365 if (-1 == uname(&utsname)) { 2366 mdoc_nmsg(mdoc, n, MANDOCERR_UNAME); 2367 defbuf = mandoc_strdup("UNKNOWN"); 2368 } else 2369 mandoc_asprintf(&defbuf, "%s %s", 2370 utsname.sysname, utsname.release); 2371 } 2372 mdoc->meta.os = mandoc_strdup(defbuf); 2373 #endif /*!OSNAME*/ 2374 return(1); 2375 } 2376 2377 static int 2378 post_std(POST_ARGS) 2379 { 2380 struct mdoc_node *nn, *n; 2381 2382 n = mdoc->last; 2383 2384 /* 2385 * Macros accepting `-std' as an argument have the name of the 2386 * current document (`Nm') filled in as the argument if it's not 2387 * provided. 2388 */ 2389 2390 if (n->child) 2391 return(1); 2392 2393 if (NULL == mdoc->meta.name) 2394 return(1); 2395 2396 nn = n; 2397 mdoc->next = MDOC_NEXT_CHILD; 2398 2399 if ( ! mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name)) 2400 return(0); 2401 2402 mdoc->last = nn; 2403 return(1); 2404 } 2405 2406 static enum mdoc_sec 2407 a2sec(const char *p) 2408 { 2409 int i; 2410 2411 for (i = 0; i < (int)SEC__MAX; i++) 2412 if (secnames[i] && 0 == strcmp(p, secnames[i])) 2413 return((enum mdoc_sec)i); 2414 2415 return(SEC_CUSTOM); 2416 } 2417 2418 static size_t 2419 macro2len(enum mdoct macro) 2420 { 2421 2422 switch (macro) { 2423 case(MDOC_Ad): 2424 return(12); 2425 case(MDOC_Ao): 2426 return(12); 2427 case(MDOC_An): 2428 return(12); 2429 case(MDOC_Aq): 2430 return(12); 2431 case(MDOC_Ar): 2432 return(12); 2433 case(MDOC_Bo): 2434 return(12); 2435 case(MDOC_Bq): 2436 return(12); 2437 case(MDOC_Cd): 2438 return(12); 2439 case(MDOC_Cm): 2440 return(10); 2441 case(MDOC_Do): 2442 return(10); 2443 case(MDOC_Dq): 2444 return(12); 2445 case(MDOC_Dv): 2446 return(12); 2447 case(MDOC_Eo): 2448 return(12); 2449 case(MDOC_Em): 2450 return(10); 2451 case(MDOC_Er): 2452 return(17); 2453 case(MDOC_Ev): 2454 return(15); 2455 case(MDOC_Fa): 2456 return(12); 2457 case(MDOC_Fl): 2458 return(10); 2459 case(MDOC_Fo): 2460 return(16); 2461 case(MDOC_Fn): 2462 return(16); 2463 case(MDOC_Ic): 2464 return(10); 2465 case(MDOC_Li): 2466 return(16); 2467 case(MDOC_Ms): 2468 return(6); 2469 case(MDOC_Nm): 2470 return(10); 2471 case(MDOC_No): 2472 return(12); 2473 case(MDOC_Oo): 2474 return(10); 2475 case(MDOC_Op): 2476 return(14); 2477 case(MDOC_Pa): 2478 return(32); 2479 case(MDOC_Pf): 2480 return(12); 2481 case(MDOC_Po): 2482 return(12); 2483 case(MDOC_Pq): 2484 return(12); 2485 case(MDOC_Ql): 2486 return(16); 2487 case(MDOC_Qo): 2488 return(12); 2489 case(MDOC_So): 2490 return(12); 2491 case(MDOC_Sq): 2492 return(12); 2493 case(MDOC_Sy): 2494 return(6); 2495 case(MDOC_Sx): 2496 return(16); 2497 case(MDOC_Tn): 2498 return(10); 2499 case(MDOC_Va): 2500 return(12); 2501 case(MDOC_Vt): 2502 return(12); 2503 case(MDOC_Xr): 2504 return(10); 2505 default: 2506 break; 2507 }; 2508 return(0); 2509 } 2510