1 /* $Id: mdoc_macro.c,v 1.25 2009/10/27 21:40:07 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <assert.h> 18 #include <ctype.h> 19 #include <stdlib.h> 20 #include <stdio.h> 21 #include <string.h> 22 23 #include "libmdoc.h" 24 25 #define REWIND_REWIND (1 << 0) 26 #define REWIND_NOHALT (1 << 1) 27 #define REWIND_HALT (1 << 2) 28 29 static int obsolete(MACRO_PROT_ARGS); 30 static int blk_part_exp(MACRO_PROT_ARGS); 31 static int in_line_eoln(MACRO_PROT_ARGS); 32 static int in_line_argn(MACRO_PROT_ARGS); 33 static int in_line(MACRO_PROT_ARGS); 34 static int blk_full(MACRO_PROT_ARGS); 35 static int blk_exp_close(MACRO_PROT_ARGS); 36 static int blk_part_imp(MACRO_PROT_ARGS); 37 38 static int phrase(struct mdoc *, int, int, char *); 39 static int rew_dohalt(int, enum mdoc_type, 40 const struct mdoc_node *); 41 static int rew_alt(int); 42 static int rew_dobreak(int, const struct mdoc_node *); 43 static int rew_elem(struct mdoc *, int); 44 static int rew_sub(enum mdoc_type, struct mdoc *, 45 int, int, int); 46 static int rew_last(struct mdoc *, 47 const struct mdoc_node *); 48 static int append_delims(struct mdoc *, int, int *, char *); 49 static int lookup(int, const char *); 50 static int lookup_raw(const char *); 51 static int swarn(struct mdoc *, enum mdoc_type, int, int, 52 const struct mdoc_node *); 53 54 /* Central table of library: who gets parsed how. */ 55 56 const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { 57 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */ 58 { in_line_eoln, MDOC_PROLOGUE }, /* Dd */ 59 { in_line_eoln, MDOC_PROLOGUE }, /* Dt */ 60 { in_line_eoln, MDOC_PROLOGUE }, /* Os */ 61 { blk_full, 0 }, /* Sh */ 62 { blk_full, 0 }, /* Ss */ 63 { in_line_eoln, 0 }, /* Pp */ 64 { blk_part_imp, MDOC_PARSED }, /* D1 */ 65 { blk_part_imp, MDOC_PARSED }, /* Dl */ 66 { blk_full, MDOC_EXPLICIT }, /* Bd */ 67 { blk_exp_close, MDOC_EXPLICIT }, /* Ed */ 68 { blk_full, MDOC_EXPLICIT }, /* Bl */ 69 { blk_exp_close, MDOC_EXPLICIT }, /* El */ 70 { blk_full, MDOC_PARSED }, /* It */ 71 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ 72 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */ 73 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ 74 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */ 75 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ 76 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ 77 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ 78 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ 79 { in_line_eoln, 0 }, /* Ex */ 80 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ 81 { in_line_eoln, 0 }, /* Fd */ 82 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */ 83 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ 84 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ 85 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ 86 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */ 87 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */ 88 { blk_full, 0 }, /* Nd */ 89 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ 90 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */ 91 { obsolete, 0 }, /* Ot */ 92 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */ 93 { in_line_eoln, 0 }, /* Rv */ 94 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 95 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ 96 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ 97 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ 98 { in_line_eoln, 0 }, /* %A */ 99 { in_line_eoln, 0 }, /* %B */ 100 { in_line_eoln, 0 }, /* %D */ 101 { in_line_eoln, 0 }, /* %I */ 102 { in_line_eoln, 0 }, /* %J */ 103 { in_line_eoln, 0 }, /* %N */ 104 { in_line_eoln, 0 }, /* %O */ 105 { in_line_eoln, 0 }, /* %P */ 106 { in_line_eoln, 0 }, /* %R */ 107 { in_line_eoln, 0 }, /* %T */ 108 { in_line_eoln, 0 }, /* %V */ 109 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */ 110 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */ 111 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */ 112 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */ 113 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */ 114 { blk_full, MDOC_EXPLICIT }, /* Bf */ 115 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */ 116 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */ 117 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */ 118 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */ 119 { in_line_eoln, 0 }, /* Db */ 120 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */ 121 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */ 122 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */ 123 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */ 124 { blk_exp_close, MDOC_EXPLICIT }, /* Ef */ 125 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ 126 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ 127 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ 128 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */ 129 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */ 130 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */ 131 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ 132 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ 133 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */ 134 { in_line_argn, MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */ 135 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */ 136 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */ 137 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */ 138 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */ 139 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */ 140 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */ 141 { blk_exp_close, MDOC_EXPLICIT }, /* Re */ 142 { blk_full, MDOC_EXPLICIT }, /* Rs */ 143 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */ 144 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */ 145 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */ 146 { in_line_eoln, 0 }, /* Sm */ 147 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */ 148 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */ 149 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ 150 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */ 151 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */ 152 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */ 153 { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ 154 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ 155 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */ 156 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */ 157 { blk_full, MDOC_EXPLICIT }, /* Bk */ 158 { blk_exp_close, MDOC_EXPLICIT }, /* Ek */ 159 { in_line_eoln, 0 }, /* Bt */ 160 { in_line_eoln, 0 }, /* Hf */ 161 { obsolete, 0 }, /* Fr */ 162 { in_line_eoln, 0 }, /* Ud */ 163 { in_line_eoln, 0 }, /* Lb */ 164 { in_line_eoln, 0 }, /* Lp */ 165 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ 166 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ 167 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */ 168 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */ 169 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */ 170 { in_line_eoln, 0 }, /* %C */ 171 { obsolete, 0 }, /* Es */ 172 { obsolete, 0 }, /* En */ 173 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */ 174 { in_line_eoln, 0 }, /* %Q */ 175 { in_line_eoln, 0 }, /* br */ 176 { in_line_eoln, 0 }, /* sp */ 177 { in_line_eoln, 0 }, /* %U */ 178 }; 179 180 const struct mdoc_macro * const mdoc_macros = __mdoc_macros; 181 182 183 static int 184 swarn(struct mdoc *mdoc, enum mdoc_type type, 185 int line, int pos, const struct mdoc_node *p) 186 { 187 const char *n, *t, *tt; 188 189 n = t = "<root>"; 190 tt = "block"; 191 192 switch (type) { 193 case (MDOC_BODY): 194 tt = "multi-line"; 195 break; 196 case (MDOC_HEAD): 197 tt = "line"; 198 break; 199 default: 200 break; 201 } 202 203 switch (p->type) { 204 case (MDOC_BLOCK): 205 n = mdoc_macronames[p->tok]; 206 t = "block"; 207 break; 208 case (MDOC_BODY): 209 n = mdoc_macronames[p->tok]; 210 t = "multi-line"; 211 break; 212 case (MDOC_HEAD): 213 n = mdoc_macronames[p->tok]; 214 t = "line"; 215 break; 216 default: 217 break; 218 } 219 220 if ( ! (MDOC_IGN_SCOPE & mdoc->pflags)) 221 return(mdoc_verr(mdoc, line, pos, 222 "%s scope breaks %s scope of %s", 223 tt, t, n)); 224 return(mdoc_vwarn(mdoc, line, pos, 225 "%s scope breaks %s scope of %s", 226 tt, t, n)); 227 } 228 229 230 /* 231 * This is called at the end of parsing. It must traverse up the tree, 232 * closing out open [implicit] scopes. Obviously, open explicit scopes 233 * are errors. 234 */ 235 int 236 mdoc_macroend(struct mdoc *m) 237 { 238 struct mdoc_node *n; 239 240 /* Scan for open explicit scopes. */ 241 242 n = MDOC_VALID & m->last->flags ? m->last->parent : m->last; 243 244 for ( ; n; n = n->parent) { 245 if (MDOC_BLOCK != n->type) 246 continue; 247 if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags)) 248 continue; 249 return(mdoc_nerr(m, n, EOPEN)); 250 } 251 252 /* Rewind to the first. */ 253 254 return(rew_last(m, m->first)); 255 } 256 257 258 /* 259 * Look up a macro from within a subsequent context. 260 */ 261 static int 262 lookup(int from, const char *p) 263 { 264 /* FIXME: make -diag lists be un-PARSED. */ 265 266 if ( ! (MDOC_PARSED & mdoc_macros[from].flags)) 267 return(MDOC_MAX); 268 return(lookup_raw(p)); 269 } 270 271 272 /* 273 * Lookup a macro following the initial line macro. 274 */ 275 static int 276 lookup_raw(const char *p) 277 { 278 int res; 279 280 if (MDOC_MAX == (res = mdoc_hash_find(p))) 281 return(MDOC_MAX); 282 if (MDOC_CALLABLE & mdoc_macros[res].flags) 283 return(res); 284 return(MDOC_MAX); 285 } 286 287 288 static int 289 rew_last(struct mdoc *mdoc, const struct mdoc_node *to) 290 { 291 292 assert(to); 293 mdoc->next = MDOC_NEXT_SIBLING; 294 295 /* LINTED */ 296 while (mdoc->last != to) { 297 if ( ! mdoc_valid_post(mdoc)) 298 return(0); 299 if ( ! mdoc_action_post(mdoc)) 300 return(0); 301 mdoc->last = mdoc->last->parent; 302 assert(mdoc->last); 303 } 304 305 if ( ! mdoc_valid_post(mdoc)) 306 return(0); 307 return(mdoc_action_post(mdoc)); 308 } 309 310 311 /* 312 * Return the opening macro of a closing one, e.g., `Ec' has `Eo' as its 313 * matching pair. 314 */ 315 static int 316 rew_alt(int tok) 317 { 318 switch (tok) { 319 case (MDOC_Ac): 320 return(MDOC_Ao); 321 case (MDOC_Bc): 322 return(MDOC_Bo); 323 case (MDOC_Brc): 324 return(MDOC_Bro); 325 case (MDOC_Dc): 326 return(MDOC_Do); 327 case (MDOC_Ec): 328 return(MDOC_Eo); 329 case (MDOC_Ed): 330 return(MDOC_Bd); 331 case (MDOC_Ef): 332 return(MDOC_Bf); 333 case (MDOC_Ek): 334 return(MDOC_Bk); 335 case (MDOC_El): 336 return(MDOC_Bl); 337 case (MDOC_Fc): 338 return(MDOC_Fo); 339 case (MDOC_Oc): 340 return(MDOC_Oo); 341 case (MDOC_Pc): 342 return(MDOC_Po); 343 case (MDOC_Qc): 344 return(MDOC_Qo); 345 case (MDOC_Re): 346 return(MDOC_Rs); 347 case (MDOC_Sc): 348 return(MDOC_So); 349 case (MDOC_Xc): 350 return(MDOC_Xo); 351 default: 352 break; 353 } 354 abort(); 355 /* NOTREACHED */ 356 } 357 358 359 /* 360 * Rewind rules. This indicates whether to stop rewinding 361 * (REWIND_HALT) without touching our current scope, stop rewinding and 362 * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT). 363 * The scope-closing and so on occurs in the various rew_* routines. 364 */ 365 static int 366 rew_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p) 367 { 368 369 if (MDOC_ROOT == p->type) 370 return(REWIND_HALT); 371 if (MDOC_VALID & p->flags) 372 return(REWIND_NOHALT); 373 374 switch (tok) { 375 case (MDOC_Aq): 376 /* FALLTHROUGH */ 377 case (MDOC_Bq): 378 /* FALLTHROUGH */ 379 case (MDOC_Brq): 380 /* FALLTHROUGH */ 381 case (MDOC_D1): 382 /* FALLTHROUGH */ 383 case (MDOC_Dl): 384 /* FALLTHROUGH */ 385 case (MDOC_Dq): 386 /* FALLTHROUGH */ 387 case (MDOC_Op): 388 /* FALLTHROUGH */ 389 case (MDOC_Pq): 390 /* FALLTHROUGH */ 391 case (MDOC_Ql): 392 /* FALLTHROUGH */ 393 case (MDOC_Qq): 394 /* FALLTHROUGH */ 395 case (MDOC_Sq): 396 assert(MDOC_TAIL != type); 397 if (type == p->type && tok == p->tok) 398 return(REWIND_REWIND); 399 break; 400 case (MDOC_It): 401 assert(MDOC_TAIL != type); 402 if (type == p->type && tok == p->tok) 403 return(REWIND_REWIND); 404 if (MDOC_BODY == p->type && MDOC_Bl == p->tok) 405 return(REWIND_HALT); 406 break; 407 case (MDOC_Sh): 408 if (type == p->type && tok == p->tok) 409 return(REWIND_REWIND); 410 break; 411 case (MDOC_Nd): 412 /* FALLTHROUGH */ 413 case (MDOC_Ss): 414 assert(MDOC_TAIL != type); 415 if (type == p->type && tok == p->tok) 416 return(REWIND_REWIND); 417 if (MDOC_BODY == p->type && MDOC_Sh == p->tok) 418 return(REWIND_HALT); 419 break; 420 case (MDOC_Ao): 421 /* FALLTHROUGH */ 422 case (MDOC_Bd): 423 /* FALLTHROUGH */ 424 case (MDOC_Bf): 425 /* FALLTHROUGH */ 426 case (MDOC_Bk): 427 /* FALLTHROUGH */ 428 case (MDOC_Bl): 429 /* FALLTHROUGH */ 430 case (MDOC_Bo): 431 /* FALLTHROUGH */ 432 case (MDOC_Bro): 433 /* FALLTHROUGH */ 434 case (MDOC_Do): 435 /* FALLTHROUGH */ 436 case (MDOC_Eo): 437 /* FALLTHROUGH */ 438 case (MDOC_Fo): 439 /* FALLTHROUGH */ 440 case (MDOC_Oo): 441 /* FALLTHROUGH */ 442 case (MDOC_Po): 443 /* FALLTHROUGH */ 444 case (MDOC_Qo): 445 /* FALLTHROUGH */ 446 case (MDOC_Rs): 447 /* FALLTHROUGH */ 448 case (MDOC_So): 449 /* FALLTHROUGH */ 450 case (MDOC_Xo): 451 if (type == p->type && tok == p->tok) 452 return(REWIND_REWIND); 453 break; 454 /* Multi-line explicit scope close. */ 455 case (MDOC_Ac): 456 /* FALLTHROUGH */ 457 case (MDOC_Bc): 458 /* FALLTHROUGH */ 459 case (MDOC_Brc): 460 /* FALLTHROUGH */ 461 case (MDOC_Dc): 462 /* FALLTHROUGH */ 463 case (MDOC_Ec): 464 /* FALLTHROUGH */ 465 case (MDOC_Ed): 466 /* FALLTHROUGH */ 467 case (MDOC_Ek): 468 /* FALLTHROUGH */ 469 case (MDOC_El): 470 /* FALLTHROUGH */ 471 case (MDOC_Fc): 472 /* FALLTHROUGH */ 473 case (MDOC_Ef): 474 /* FALLTHROUGH */ 475 case (MDOC_Oc): 476 /* FALLTHROUGH */ 477 case (MDOC_Pc): 478 /* FALLTHROUGH */ 479 case (MDOC_Qc): 480 /* FALLTHROUGH */ 481 case (MDOC_Re): 482 /* FALLTHROUGH */ 483 case (MDOC_Sc): 484 /* FALLTHROUGH */ 485 case (MDOC_Xc): 486 if (type == p->type && rew_alt(tok) == p->tok) 487 return(REWIND_REWIND); 488 break; 489 default: 490 abort(); 491 /* NOTREACHED */ 492 } 493 494 return(REWIND_NOHALT); 495 } 496 497 498 /* 499 * See if we can break an encountered scope (the rew_dohalt has returned 500 * REWIND_NOHALT). 501 */ 502 static int 503 rew_dobreak(int tok, const struct mdoc_node *p) 504 { 505 506 assert(MDOC_ROOT != p->type); 507 if (MDOC_ELEM == p->type) 508 return(1); 509 if (MDOC_TEXT == p->type) 510 return(1); 511 if (MDOC_VALID & p->flags) 512 return(1); 513 514 switch (tok) { 515 case (MDOC_It): 516 return(MDOC_It == p->tok); 517 case (MDOC_Nd): 518 return(MDOC_Nd == p->tok); 519 case (MDOC_Ss): 520 return(MDOC_Ss == p->tok); 521 case (MDOC_Sh): 522 if (MDOC_Nd == p->tok) 523 return(1); 524 if (MDOC_Ss == p->tok) 525 return(1); 526 return(MDOC_Sh == p->tok); 527 case (MDOC_El): 528 if (MDOC_It == p->tok) 529 return(1); 530 break; 531 case (MDOC_Oc): 532 /* XXX - experimental! */ 533 if (MDOC_Op == p->tok) 534 return(1); 535 break; 536 default: 537 break; 538 } 539 540 if (MDOC_EXPLICIT & mdoc_macros[tok].flags) 541 return(p->tok == rew_alt(tok)); 542 else if (MDOC_BLOCK == p->type) 543 return(1); 544 545 return(tok == p->tok); 546 } 547 548 549 static int 550 rew_elem(struct mdoc *mdoc, int tok) 551 { 552 struct mdoc_node *n; 553 554 n = mdoc->last; 555 if (MDOC_ELEM != n->type) 556 n = n->parent; 557 assert(MDOC_ELEM == n->type); 558 assert(tok == n->tok); 559 560 return(rew_last(mdoc, n)); 561 } 562 563 564 static int 565 rew_sub(enum mdoc_type t, struct mdoc *m, 566 int tok, int line, int ppos) 567 { 568 struct mdoc_node *n; 569 int c; 570 571 /* LINTED */ 572 for (n = m->last; n; n = n->parent) { 573 c = rew_dohalt(tok, t, n); 574 if (REWIND_HALT == c) { 575 if (MDOC_BLOCK != t) 576 return(1); 577 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) 578 return(1); 579 return(mdoc_perr(m, line, ppos, ENOCTX)); 580 } 581 if (REWIND_REWIND == c) 582 break; 583 else if (rew_dobreak(tok, n)) 584 continue; 585 if ( ! swarn(m, t, line, ppos, n)) 586 return(0); 587 } 588 589 assert(n); 590 return(rew_last(m, n)); 591 } 592 593 594 static int 595 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf) 596 { 597 int c, lastarg; 598 char *p; 599 600 if (0 == buf[*pos]) 601 return(1); 602 603 for (;;) { 604 lastarg = *pos; 605 c = mdoc_zargs(mdoc, line, pos, buf, ARGS_NOWARN, &p); 606 assert(ARGS_PHRASE != c); 607 608 if (ARGS_ERROR == c) 609 return(0); 610 else if (ARGS_EOLN == c) 611 break; 612 assert(mdoc_isdelim(p)); 613 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p)) 614 return(0); 615 } 616 617 return(1); 618 } 619 620 621 /* 622 * Close out block partial/full explicit. 623 */ 624 static int 625 blk_exp_close(MACRO_PROT_ARGS) 626 { 627 int j, c, lastarg, maxargs, flushed; 628 char *p; 629 630 switch (tok) { 631 case (MDOC_Ec): 632 maxargs = 1; 633 break; 634 default: 635 maxargs = 0; 636 break; 637 } 638 639 if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) { 640 if (buf[*pos]) 641 if ( ! mdoc_pwarn(m, line, ppos, ENOLINE)) 642 return(0); 643 644 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 645 return(0); 646 return(rew_sub(MDOC_BLOCK, m, tok, line, ppos)); 647 } 648 649 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 650 return(0); 651 652 if (maxargs > 0) 653 if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok))) 654 return(0); 655 656 for (flushed = j = 0; ; j++) { 657 lastarg = *pos; 658 659 if (j == maxargs && ! flushed) { 660 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 661 return(0); 662 flushed = 1; 663 } 664 665 c = mdoc_args(m, line, pos, buf, tok, &p); 666 667 if (ARGS_ERROR == c) 668 return(0); 669 if (ARGS_PUNCT == c) 670 break; 671 if (ARGS_EOLN == c) 672 break; 673 674 if (MDOC_MAX != (c = lookup(tok, p))) { 675 if ( ! flushed) { 676 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 677 return(0); 678 flushed = 1; 679 } 680 if ( ! mdoc_macro(m, c, line, lastarg, pos, buf)) 681 return(0); 682 break; 683 } 684 685 if ( ! mdoc_word_alloc(m, line, lastarg, p)) 686 return(0); 687 } 688 689 if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 690 return(0); 691 692 if (ppos > 1) 693 return(1); 694 return(append_delims(m, line, pos, buf)); 695 } 696 697 698 static int 699 in_line(MACRO_PROT_ARGS) 700 { 701 int la, lastpunct, c, w, cnt, d, nc; 702 struct mdoc_arg *arg; 703 char *p; 704 705 /* 706 * Whether we allow ignored elements (those without content, 707 * usually because of reserved words) to squeak by. 708 */ 709 switch (tok) { 710 case (MDOC_An): 711 /* FALLTHROUGH */ 712 case (MDOC_Ar): 713 /* FALLTHROUGH */ 714 case (MDOC_Fl): 715 /* FALLTHROUGH */ 716 case (MDOC_Lk): 717 /* FALLTHROUGH */ 718 case (MDOC_Nm): 719 /* FALLTHROUGH */ 720 case (MDOC_Pa): 721 nc = 1; 722 break; 723 default: 724 nc = 0; 725 break; 726 } 727 728 for (arg = NULL;; ) { 729 la = *pos; 730 c = mdoc_argv(m, line, tok, &arg, pos, buf); 731 732 if (ARGV_WORD == c) { 733 *pos = la; 734 break; 735 } 736 if (ARGV_EOLN == c) 737 break; 738 if (ARGV_ARG == c) 739 continue; 740 741 mdoc_argv_free(arg); 742 return(0); 743 } 744 745 for (cnt = 0, lastpunct = 1;; ) { 746 la = *pos; 747 w = mdoc_args(m, line, pos, buf, tok, &p); 748 749 if (ARGS_ERROR == w) 750 return(0); 751 if (ARGS_EOLN == w) 752 break; 753 if (ARGS_PUNCT == w) 754 break; 755 756 /* Quoted words shouldn't be looked-up. */ 757 758 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p); 759 760 /* 761 * In this case, we've located a submacro and must 762 * execute it. Close out scope, if open. If no 763 * elements have been generated, either create one (nc) 764 * or raise a warning. 765 */ 766 767 if (MDOC_MAX != c) { 768 if (0 == lastpunct && ! rew_elem(m, tok)) 769 return(0); 770 if (nc && 0 == cnt) { 771 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 772 return(0); 773 if ( ! rew_last(m, m->last)) 774 return(0); 775 } else if ( ! nc && 0 == cnt) { 776 mdoc_argv_free(arg); 777 if ( ! mdoc_pwarn(m, line, ppos, EIGNE)) 778 return(0); 779 } 780 c = mdoc_macro(m, c, line, la, pos, buf); 781 if (0 == c) 782 return(0); 783 if (ppos > 1) 784 return(1); 785 return(append_delims(m, line, pos, buf)); 786 } 787 788 /* 789 * Non-quote-enclosed punctuation. Set up our scope, if 790 * a word; rewind the scope, if a delimiter; then append 791 * the word. 792 */ 793 794 d = mdoc_isdelim(p); 795 796 if (ARGS_QWORD != w && d) { 797 if (0 == lastpunct && ! rew_elem(m, tok)) 798 return(0); 799 lastpunct = 1; 800 } else if (lastpunct) { 801 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 802 return(0); 803 lastpunct = 0; 804 } 805 806 if ( ! d) 807 cnt++; 808 if ( ! mdoc_word_alloc(m, line, la, p)) 809 return(0); 810 } 811 812 if (0 == lastpunct && ! rew_elem(m, tok)) 813 return(0); 814 815 /* 816 * If no elements have been collected and we're allowed to have 817 * empties (nc), open a scope and close it out. Otherwise, 818 * raise a warning. 819 * 820 */ 821 if (nc && 0 == cnt) { 822 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 823 return(0); 824 if ( ! rew_last(m, m->last)) 825 return(0); 826 } else if ( ! nc && 0 == cnt) { 827 mdoc_argv_free(arg); 828 if ( ! mdoc_pwarn(m, line, ppos, EIGNE)) 829 return(0); 830 } 831 832 if (ppos > 1) 833 return(1); 834 return(append_delims(m, line, pos, buf)); 835 } 836 837 838 static int 839 blk_full(MACRO_PROT_ARGS) 840 { 841 int c, lastarg, reopen, dohead; 842 struct mdoc_arg *arg; 843 char *p; 844 845 /* 846 * Whether to process a block-head section. If this is 847 * non-zero, then a head will be opened for all line arguments. 848 * If not, then the head will always be empty and only a body 849 * will be opened, which will stay open at the eoln. 850 */ 851 852 switch (tok) { 853 case (MDOC_Nd): 854 dohead = 0; 855 break; 856 default: 857 dohead = 1; 858 break; 859 } 860 861 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) { 862 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 863 return(0); 864 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 865 return(0); 866 } 867 868 for (arg = NULL;; ) { 869 lastarg = *pos; 870 c = mdoc_argv(m, line, tok, &arg, pos, buf); 871 872 if (ARGV_WORD == c) { 873 *pos = lastarg; 874 break; 875 } 876 877 if (ARGV_EOLN == c) 878 break; 879 if (ARGV_ARG == c) 880 continue; 881 882 mdoc_argv_free(arg); 883 return(0); 884 } 885 886 if ( ! mdoc_block_alloc(m, line, ppos, tok, arg)) 887 return(0); 888 889 if (0 == buf[*pos]) { 890 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 891 return(0); 892 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 893 return(0); 894 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 895 return(0); 896 return(1); 897 } 898 899 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 900 return(0); 901 902 /* Immediately close out head and enter body, if applicable. */ 903 904 if (0 == dohead) { 905 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 906 return(0); 907 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 908 return(0); 909 } 910 911 for (reopen = 0;; ) { 912 lastarg = *pos; 913 c = mdoc_args(m, line, pos, buf, tok, &p); 914 915 if (ARGS_ERROR == c) 916 return(0); 917 if (ARGS_EOLN == c) 918 break; 919 if (ARGS_PHRASE == c) { 920 assert(dohead); 921 if (reopen && ! mdoc_head_alloc(m, line, ppos, tok)) 922 return(0); 923 /* 924 * Phrases are self-contained macro phrases used 925 * in the columnar output of a macro. They need 926 * special handling. 927 */ 928 if ( ! phrase(m, line, lastarg, buf)) 929 return(0); 930 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 931 return(0); 932 933 reopen = 1; 934 continue; 935 } 936 937 if (MDOC_MAX == (c = lookup(tok, p))) { 938 if ( ! mdoc_word_alloc(m, line, lastarg, p)) 939 return(0); 940 continue; 941 } 942 943 if ( ! mdoc_macro(m, c, line, lastarg, pos, buf)) 944 return(0); 945 break; 946 } 947 948 if (1 == ppos && ! append_delims(m, line, pos, buf)) 949 return(0); 950 951 /* If the body's already open, then just return. */ 952 if (0 == dohead) 953 return(1); 954 955 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 956 return(0); 957 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 958 return(0); 959 960 return(1); 961 } 962 963 964 static int 965 blk_part_imp(MACRO_PROT_ARGS) 966 { 967 int la, c; 968 char *p; 969 struct mdoc_node *blk, *body, *n; 970 971 /* If applicable, close out prior scopes. */ 972 973 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL)) 974 return(0); 975 /* Saved for later close-out. */ 976 blk = m->last; 977 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 978 return(0); 979 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 980 return(0); 981 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 982 return(0); 983 /* Saved for later close-out. */ 984 body = m->last; 985 986 /* Body argument processing. */ 987 988 for (;;) { 989 la = *pos; 990 c = mdoc_args(m, line, pos, buf, tok, &p); 991 assert(ARGS_PHRASE != c); 992 993 if (ARGS_ERROR == c) 994 return(0); 995 if (ARGS_PUNCT == c) 996 break; 997 if (ARGS_EOLN == c) 998 break; 999 1000 if (MDOC_MAX == (c = lookup(tok, p))) { 1001 if ( ! mdoc_word_alloc(m, line, la, p)) 1002 return(0); 1003 continue; 1004 } 1005 1006 if ( ! mdoc_macro(m, c, line, la, pos, buf)) 1007 return(0); 1008 break; 1009 } 1010 1011 /* 1012 * If we can't rewind to our body, then our scope has already 1013 * been closed by another macro (like `Oc' closing `Op'). This 1014 * is ugly behaviour nodding its head to OpenBSD's overwhelming 1015 * crufty use of `Op' breakage--XXX, deprecate in time. 1016 */ 1017 for (n = m->last; n; n = n->parent) 1018 if (body == n) 1019 break; 1020 if (NULL == n && ! mdoc_nwarn(m, body, EIMPBRK)) 1021 return(0); 1022 if (n && ! rew_last(m, body)) 1023 return(0); 1024 1025 /* Standard appending of delimiters. */ 1026 1027 if (1 == ppos && ! append_delims(m, line, pos, buf)) 1028 return(0); 1029 1030 /* Rewind scope, if applicable. */ 1031 1032 if (n && ! rew_last(m, blk)) 1033 return(0); 1034 1035 return(1); 1036 } 1037 1038 1039 static int 1040 blk_part_exp(MACRO_PROT_ARGS) 1041 { 1042 int la, flushed, j, c, maxargs; 1043 char *p; 1044 1045 /* Number of head arguments. Only `Eo' has these, */ 1046 1047 switch (tok) { 1048 case (MDOC_Eo): 1049 maxargs = 1; 1050 break; 1051 default: 1052 maxargs = 0; 1053 break; 1054 } 1055 1056 /* Begin the block scope. */ 1057 1058 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL)) 1059 return(0); 1060 1061 /* 1062 * If no head arguments, open and then close out a head, noting 1063 * that we've flushed our terms. `flushed' means that we've 1064 * flushed out the head and the body is open. 1065 */ 1066 1067 if (0 == maxargs) { 1068 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1069 return(0); 1070 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1071 return(0); 1072 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1073 return(0); 1074 flushed = 1; 1075 } else { 1076 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1077 return(0); 1078 flushed = 0; 1079 } 1080 1081 /* Process the head/head+body line arguments. */ 1082 1083 for (j = 0; ; j++) { 1084 la = *pos; 1085 if (j == maxargs && ! flushed) { 1086 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1087 return(0); 1088 flushed = 1; 1089 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1090 return(0); 1091 } 1092 1093 c = mdoc_args(m, line, pos, buf, tok, &p); 1094 assert(ARGS_PHRASE != c); 1095 1096 if (ARGS_ERROR == c) 1097 return(0); 1098 if (ARGS_PUNCT == c) 1099 break; 1100 if (ARGS_EOLN == c) 1101 break; 1102 1103 if (MDOC_MAX != (c = lookup(tok, p))) { 1104 if ( ! flushed) { 1105 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1106 return(0); 1107 flushed = 1; 1108 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1109 return(0); 1110 } 1111 if ( ! mdoc_macro(m, c, line, la, pos, buf)) 1112 return(0); 1113 break; 1114 } 1115 1116 if ( ! flushed && mdoc_isdelim(p)) { 1117 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1118 return(0); 1119 flushed = 1; 1120 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1121 return(0); 1122 } 1123 1124 if ( ! mdoc_word_alloc(m, line, la, p)) 1125 return(0); 1126 } 1127 1128 /* Close the head and open the body, if applicable. */ 1129 1130 if ( ! flushed) { 1131 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1132 return(0); 1133 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1134 return(0); 1135 } 1136 1137 /* Standard appending of delimiters. */ 1138 1139 if (ppos > 1) 1140 return(1); 1141 return(append_delims(m, line, pos, buf)); 1142 } 1143 1144 1145 static int 1146 in_line_argn(MACRO_PROT_ARGS) 1147 { 1148 int la, flushed, j, c, maxargs; 1149 struct mdoc_arg *arg; 1150 char *p; 1151 1152 /* Fixed maximum arguments per macro, if applicable. */ 1153 1154 switch (tok) { 1155 case (MDOC_Ap): 1156 /* FALLTHROUGH */ 1157 case (MDOC_No): 1158 /* FALLTHROUGH */ 1159 case (MDOC_Ns): 1160 /* FALLTHROUGH */ 1161 case (MDOC_Ux): 1162 maxargs = 0; 1163 break; 1164 default: 1165 maxargs = 1; 1166 break; 1167 } 1168 1169 /* Macro argument processing. */ 1170 1171 for (arg = NULL;; ) { 1172 la = *pos; 1173 c = mdoc_argv(m, line, tok, &arg, pos, buf); 1174 1175 if (ARGV_WORD == c) { 1176 *pos = la; 1177 break; 1178 } 1179 1180 if (ARGV_EOLN == c) 1181 break; 1182 if (ARGV_ARG == c) 1183 continue; 1184 1185 mdoc_argv_free(arg); 1186 return(0); 1187 } 1188 1189 /* Open the element scope. */ 1190 1191 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 1192 return(0); 1193 1194 /* Process element arguments. */ 1195 1196 for (flushed = j = 0; ; j++) { 1197 la = *pos; 1198 1199 if (j == maxargs && ! flushed) { 1200 if ( ! rew_elem(m, tok)) 1201 return(0); 1202 flushed = 1; 1203 } 1204 1205 c = mdoc_args(m, line, pos, buf, tok, &p); 1206 1207 if (ARGS_ERROR == c) 1208 return(0); 1209 if (ARGS_PUNCT == c) 1210 break; 1211 if (ARGS_EOLN == c) 1212 break; 1213 1214 if (MDOC_MAX != (c = lookup(tok, p))) { 1215 if ( ! flushed && ! rew_elem(m, tok)) 1216 return(0); 1217 flushed = 1; 1218 if ( ! mdoc_macro(m, c, line, la, pos, buf)) 1219 return(0); 1220 break; 1221 } 1222 1223 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 1224 ! flushed && mdoc_isdelim(p)) { 1225 if ( ! rew_elem(m, tok)) 1226 return(0); 1227 flushed = 1; 1228 } 1229 1230 if ( ! mdoc_word_alloc(m, line, la, p)) 1231 return(0); 1232 } 1233 1234 /* Close out and append delimiters. */ 1235 1236 if ( ! flushed && ! rew_elem(m, tok)) 1237 return(0); 1238 1239 if (ppos > 1) 1240 return(1); 1241 return(append_delims(m, line, pos, buf)); 1242 } 1243 1244 1245 static int 1246 in_line_eoln(MACRO_PROT_ARGS) 1247 { 1248 int c, w, la; 1249 struct mdoc_arg *arg; 1250 char *p; 1251 1252 assert( ! (MDOC_PARSED & mdoc_macros[tok].flags)); 1253 1254 /* Parse macro arguments. */ 1255 1256 for (arg = NULL; ; ) { 1257 la = *pos; 1258 c = mdoc_argv(m, line, tok, &arg, pos, buf); 1259 1260 if (ARGV_WORD == c) { 1261 *pos = la; 1262 break; 1263 } 1264 if (ARGV_EOLN == c) 1265 break; 1266 if (ARGV_ARG == c) 1267 continue; 1268 1269 mdoc_argv_free(arg); 1270 return(0); 1271 } 1272 1273 /* Open element scope. */ 1274 1275 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 1276 return(0); 1277 1278 /* Parse argument terms. */ 1279 1280 for (;;) { 1281 la = *pos; 1282 w = mdoc_args(m, line, pos, buf, tok, &p); 1283 1284 if (ARGS_ERROR == w) 1285 return(0); 1286 if (ARGS_EOLN == w) 1287 break; 1288 1289 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p); 1290 1291 if (MDOC_MAX != c) { 1292 if ( ! rew_elem(m, tok)) 1293 return(0); 1294 return(mdoc_macro(m, c, line, la, pos, buf)); 1295 } 1296 1297 if ( ! mdoc_word_alloc(m, line, la, p)) 1298 return(0); 1299 } 1300 1301 /* Close out (no delimiters). */ 1302 1303 return(rew_elem(m, tok)); 1304 } 1305 1306 1307 /* ARGSUSED */ 1308 static int 1309 obsolete(MACRO_PROT_ARGS) 1310 { 1311 1312 return(mdoc_pwarn(m, line, ppos, EOBS)); 1313 } 1314 1315 1316 /* 1317 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs. 1318 * They're unusual because they're basically free-form text until a 1319 * macro is encountered. 1320 */ 1321 static int 1322 phrase(struct mdoc *m, int line, int ppos, char *buf) 1323 { 1324 int c, w, la, pos; 1325 char *p; 1326 1327 for (pos = ppos; ; ) { 1328 la = pos; 1329 1330 /* Note: no calling context! */ 1331 w = mdoc_zargs(m, line, &pos, buf, 0, &p); 1332 1333 if (ARGS_ERROR == w) 1334 return(0); 1335 if (ARGS_EOLN == w) 1336 break; 1337 1338 c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(p); 1339 1340 if (MDOC_MAX != c) { 1341 if ( ! mdoc_macro(m, c, line, la, &pos, buf)) 1342 return(0); 1343 return(append_delims(m, line, &pos, buf)); 1344 } 1345 1346 if ( ! mdoc_word_alloc(m, line, la, p)) 1347 return(0); 1348 } 1349 1350 return(1); 1351 } 1352 1353 1354