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