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