1 /* $Id: mdoc_macro.c,v 1.38 2010/05/14 19:52:43 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 #include <time.h> 23 24 #include "libmdoc.h" 25 26 enum rew { 27 REWIND_REWIND, 28 REWIND_NOHALT, 29 REWIND_HALT 30 }; 31 32 static int blk_full(MACRO_PROT_ARGS); 33 static int blk_exp_close(MACRO_PROT_ARGS); 34 static int blk_part_exp(MACRO_PROT_ARGS); 35 static int blk_part_imp(MACRO_PROT_ARGS); 36 static int ctx_synopsis(MACRO_PROT_ARGS); 37 static int in_line_eoln(MACRO_PROT_ARGS); 38 static int in_line_argn(MACRO_PROT_ARGS); 39 static int in_line(MACRO_PROT_ARGS); 40 static int obsolete(MACRO_PROT_ARGS); 41 42 static int append_delims(struct mdoc *, 43 int, int *, char *); 44 static enum mdoct lookup(enum mdoct, const char *); 45 static enum mdoct lookup_raw(const char *); 46 static int phrase(struct mdoc *, int, int, 47 char *, enum margserr, int); 48 static enum mdoct rew_alt(enum mdoct); 49 static int rew_dobreak(enum mdoct, 50 const struct mdoc_node *); 51 static enum rew rew_dohalt(enum mdoct, enum mdoc_type, 52 const struct mdoc_node *); 53 static int rew_elem(struct mdoc *, enum mdoct); 54 static int rew_last(struct mdoc *, 55 const struct mdoc_node *); 56 static int rew_sub(enum mdoc_type, struct mdoc *, 57 enum mdoct, int, int); 58 static int swarn(struct mdoc *, enum mdoc_type, int, 59 int, const struct mdoc_node *); 60 61 const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { 62 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */ 63 { in_line_eoln, MDOC_PROLOGUE }, /* Dd */ 64 { in_line_eoln, MDOC_PROLOGUE }, /* Dt */ 65 { in_line_eoln, MDOC_PROLOGUE }, /* Os */ 66 { blk_full, 0 }, /* Sh */ 67 { blk_full, 0 }, /* Ss */ 68 { in_line_eoln, 0 }, /* Pp */ 69 { blk_part_imp, MDOC_PARSED }, /* D1 */ 70 { blk_part_imp, MDOC_PARSED }, /* Dl */ 71 { blk_full, MDOC_EXPLICIT }, /* Bd */ 72 { blk_exp_close, MDOC_EXPLICIT }, /* Ed */ 73 { blk_full, MDOC_EXPLICIT }, /* Bl */ 74 { blk_exp_close, MDOC_EXPLICIT }, /* El */ 75 { blk_full, MDOC_PARSED }, /* It */ 76 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ 77 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */ 78 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ 79 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */ 80 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ 81 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ 82 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ 83 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ 84 { in_line_eoln, 0 }, /* Ex */ 85 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ 86 { in_line_eoln, 0 }, /* Fd */ 87 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */ 88 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ 89 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ 90 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ 91 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */ 92 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */ 93 { blk_full, 0 }, /* Nd */ 94 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ 95 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */ 96 { obsolete, 0 }, /* Ot */ 97 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */ 98 { in_line_eoln, 0 }, /* Rv */ 99 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 100 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ 101 { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ 102 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ 103 { in_line_eoln, 0 }, /* %A */ 104 { in_line_eoln, 0 }, /* %B */ 105 { in_line_eoln, 0 }, /* %D */ 106 { in_line_eoln, 0 }, /* %I */ 107 { in_line_eoln, 0 }, /* %J */ 108 { in_line_eoln, 0 }, /* %N */ 109 { in_line_eoln, 0 }, /* %O */ 110 { in_line_eoln, 0 }, /* %P */ 111 { in_line_eoln, 0 }, /* %R */ 112 { in_line_eoln, 0 }, /* %T */ 113 { in_line_eoln, 0 }, /* %V */ 114 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */ 115 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */ 116 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */ 117 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */ 118 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */ 119 { blk_full, MDOC_EXPLICIT }, /* Bf */ 120 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */ 121 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */ 122 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */ 123 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */ 124 { in_line_eoln, 0 }, /* Db */ 125 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */ 126 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */ 127 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */ 128 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */ 129 { blk_exp_close, MDOC_EXPLICIT }, /* Ef */ 130 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ 131 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ 132 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ 133 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */ 134 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */ 135 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */ 136 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ 137 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ 138 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */ 139 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */ 140 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */ 141 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */ 142 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */ 143 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */ 144 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */ 145 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */ 146 { blk_exp_close, MDOC_EXPLICIT }, /* Re */ 147 { blk_full, MDOC_EXPLICIT }, /* Rs */ 148 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */ 149 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */ 150 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */ 151 { in_line_eoln, 0 }, /* Sm */ 152 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */ 153 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */ 154 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ 155 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */ 156 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */ 157 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */ 158 { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ 159 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ 160 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */ 161 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */ 162 { blk_full, MDOC_EXPLICIT }, /* Bk */ 163 { blk_exp_close, MDOC_EXPLICIT }, /* Ek */ 164 { in_line_eoln, 0 }, /* Bt */ 165 { in_line_eoln, 0 }, /* Hf */ 166 { obsolete, 0 }, /* Fr */ 167 { in_line_eoln, 0 }, /* Ud */ 168 { in_line_eoln, 0 }, /* Lb */ 169 { in_line_eoln, 0 }, /* Lp */ 170 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ 171 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ 172 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */ 173 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */ 174 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */ 175 { in_line_eoln, 0 }, /* %C */ 176 { obsolete, 0 }, /* Es */ 177 { obsolete, 0 }, /* En */ 178 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */ 179 { in_line_eoln, 0 }, /* %Q */ 180 { in_line_eoln, 0 }, /* br */ 181 { in_line_eoln, 0 }, /* sp */ 182 { in_line_eoln, 0 }, /* %U */ 183 }; 184 185 const struct mdoc_macro * const mdoc_macros = __mdoc_macros; 186 187 188 static int 189 swarn(struct mdoc *mdoc, enum mdoc_type type, 190 int line, int pos, const struct mdoc_node *p) 191 { 192 const char *n, *t, *tt; 193 194 n = t = "<root>"; 195 tt = "block"; 196 197 switch (type) { 198 case (MDOC_BODY): 199 tt = "multi-line"; 200 break; 201 case (MDOC_HEAD): 202 tt = "line"; 203 break; 204 default: 205 break; 206 } 207 208 switch (p->type) { 209 case (MDOC_BLOCK): 210 n = mdoc_macronames[p->tok]; 211 t = "block"; 212 break; 213 case (MDOC_BODY): 214 n = mdoc_macronames[p->tok]; 215 t = "multi-line"; 216 break; 217 case (MDOC_HEAD): 218 n = mdoc_macronames[p->tok]; 219 t = "line"; 220 break; 221 default: 222 break; 223 } 224 225 if ( ! (MDOC_IGN_SCOPE & mdoc->pflags)) 226 return(mdoc_verr(mdoc, line, pos, 227 "%s scope breaks %s scope of %s", 228 tt, t, n)); 229 return(mdoc_vwarn(mdoc, line, pos, 230 "%s scope breaks %s scope of %s", 231 tt, t, n)); 232 } 233 234 235 /* 236 * This is called at the end of parsing. It must traverse up the tree, 237 * closing out open [implicit] scopes. Obviously, open explicit scopes 238 * are errors. 239 */ 240 int 241 mdoc_macroend(struct mdoc *m) 242 { 243 struct mdoc_node *n; 244 245 /* Scan for open explicit scopes. */ 246 247 n = MDOC_VALID & m->last->flags ? m->last->parent : m->last; 248 249 for ( ; n; n = n->parent) { 250 if (MDOC_BLOCK != n->type) 251 continue; 252 if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags)) 253 continue; 254 return(mdoc_nerr(m, n, EOPEN)); 255 } 256 257 /* Rewind to the first. */ 258 259 return(rew_last(m, m->first)); 260 } 261 262 263 /* 264 * Look up a macro from within a subsequent context. 265 */ 266 static enum mdoct 267 lookup(enum mdoct from, const char *p) 268 { 269 /* FIXME: make -diag lists be un-PARSED. */ 270 271 if ( ! (MDOC_PARSED & mdoc_macros[from].flags)) 272 return(MDOC_MAX); 273 return(lookup_raw(p)); 274 } 275 276 277 /* 278 * Lookup a macro following the initial line macro. 279 */ 280 static enum mdoct 281 lookup_raw(const char *p) 282 { 283 enum mdoct res; 284 285 if (MDOC_MAX == (res = mdoc_hash_find(p))) 286 return(MDOC_MAX); 287 if (MDOC_CALLABLE & mdoc_macros[res].flags) 288 return(res); 289 return(MDOC_MAX); 290 } 291 292 293 static int 294 rew_last(struct mdoc *mdoc, const struct mdoc_node *to) 295 { 296 297 assert(to); 298 mdoc->next = MDOC_NEXT_SIBLING; 299 300 /* LINTED */ 301 while (mdoc->last != to) { 302 if ( ! mdoc_valid_post(mdoc)) 303 return(0); 304 if ( ! mdoc_action_post(mdoc)) 305 return(0); 306 mdoc->last = mdoc->last->parent; 307 assert(mdoc->last); 308 } 309 310 if ( ! mdoc_valid_post(mdoc)) 311 return(0); 312 return(mdoc_action_post(mdoc)); 313 } 314 315 316 /* 317 * Return the opening macro of a closing one, e.g., `Ec' has `Eo' as its 318 * matching pair. 319 */ 320 static enum mdoct 321 rew_alt(enum mdoct tok) 322 { 323 switch (tok) { 324 case (MDOC_Ac): 325 return(MDOC_Ao); 326 case (MDOC_Bc): 327 return(MDOC_Bo); 328 case (MDOC_Brc): 329 return(MDOC_Bro); 330 case (MDOC_Dc): 331 return(MDOC_Do); 332 case (MDOC_Ec): 333 return(MDOC_Eo); 334 case (MDOC_Ed): 335 return(MDOC_Bd); 336 case (MDOC_Ef): 337 return(MDOC_Bf); 338 case (MDOC_Ek): 339 return(MDOC_Bk); 340 case (MDOC_El): 341 return(MDOC_Bl); 342 case (MDOC_Fc): 343 return(MDOC_Fo); 344 case (MDOC_Oc): 345 return(MDOC_Oo); 346 case (MDOC_Pc): 347 return(MDOC_Po); 348 case (MDOC_Qc): 349 return(MDOC_Qo); 350 case (MDOC_Re): 351 return(MDOC_Rs); 352 case (MDOC_Sc): 353 return(MDOC_So); 354 case (MDOC_Xc): 355 return(MDOC_Xo); 356 default: 357 break; 358 } 359 abort(); 360 /* NOTREACHED */ 361 } 362 363 364 /* 365 * Rewind rules. This indicates whether to stop rewinding 366 * (REWIND_HALT) without touching our current scope, stop rewinding and 367 * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT). 368 * The scope-closing and so on occurs in the various rew_* routines. 369 */ 370 static enum rew 371 rew_dohalt(enum mdoct tok, enum mdoc_type type, 372 const struct mdoc_node *p) 373 { 374 375 if (MDOC_ROOT == p->type) 376 return(REWIND_HALT); 377 if (MDOC_VALID & p->flags) 378 return(REWIND_NOHALT); 379 380 switch (tok) { 381 case (MDOC_Aq): 382 /* FALLTHROUGH */ 383 case (MDOC_Bq): 384 /* FALLTHROUGH */ 385 case (MDOC_Brq): 386 /* FALLTHROUGH */ 387 case (MDOC_D1): 388 /* FALLTHROUGH */ 389 case (MDOC_Dl): 390 /* FALLTHROUGH */ 391 case (MDOC_Dq): 392 /* FALLTHROUGH */ 393 case (MDOC_Op): 394 /* FALLTHROUGH */ 395 case (MDOC_Pq): 396 /* FALLTHROUGH */ 397 case (MDOC_Ql): 398 /* FALLTHROUGH */ 399 case (MDOC_Qq): 400 /* FALLTHROUGH */ 401 case (MDOC_Sq): 402 /* FALLTHROUGH */ 403 case (MDOC_Vt): 404 assert(MDOC_TAIL != type); 405 if (type == p->type && tok == p->tok) 406 return(REWIND_REWIND); 407 break; 408 case (MDOC_It): 409 assert(MDOC_TAIL != type); 410 if (type == p->type && tok == p->tok) 411 return(REWIND_REWIND); 412 if (MDOC_BODY == p->type && MDOC_Bl == p->tok) 413 return(REWIND_HALT); 414 break; 415 case (MDOC_Sh): 416 if (type == p->type && tok == p->tok) 417 return(REWIND_REWIND); 418 break; 419 case (MDOC_Nd): 420 /* FALLTHROUGH */ 421 case (MDOC_Ss): 422 assert(MDOC_TAIL != type); 423 if (type == p->type && tok == p->tok) 424 return(REWIND_REWIND); 425 if (MDOC_BODY == p->type && MDOC_Sh == p->tok) 426 return(REWIND_HALT); 427 break; 428 case (MDOC_Ao): 429 /* FALLTHROUGH */ 430 case (MDOC_Bd): 431 /* FALLTHROUGH */ 432 case (MDOC_Bf): 433 /* FALLTHROUGH */ 434 case (MDOC_Bk): 435 /* FALLTHROUGH */ 436 case (MDOC_Bl): 437 /* FALLTHROUGH */ 438 case (MDOC_Bo): 439 /* FALLTHROUGH */ 440 case (MDOC_Bro): 441 /* FALLTHROUGH */ 442 case (MDOC_Do): 443 /* FALLTHROUGH */ 444 case (MDOC_Eo): 445 /* FALLTHROUGH */ 446 case (MDOC_Fo): 447 /* FALLTHROUGH */ 448 case (MDOC_Oo): 449 /* FALLTHROUGH */ 450 case (MDOC_Po): 451 /* FALLTHROUGH */ 452 case (MDOC_Qo): 453 /* FALLTHROUGH */ 454 case (MDOC_Rs): 455 /* FALLTHROUGH */ 456 case (MDOC_So): 457 /* FALLTHROUGH */ 458 case (MDOC_Xo): 459 if (type == p->type && tok == p->tok) 460 return(REWIND_REWIND); 461 break; 462 /* Multi-line explicit scope close. */ 463 case (MDOC_Ac): 464 /* FALLTHROUGH */ 465 case (MDOC_Bc): 466 /* FALLTHROUGH */ 467 case (MDOC_Brc): 468 /* FALLTHROUGH */ 469 case (MDOC_Dc): 470 /* FALLTHROUGH */ 471 case (MDOC_Ec): 472 /* FALLTHROUGH */ 473 case (MDOC_Ed): 474 /* FALLTHROUGH */ 475 case (MDOC_Ek): 476 /* FALLTHROUGH */ 477 case (MDOC_El): 478 /* FALLTHROUGH */ 479 case (MDOC_Fc): 480 /* FALLTHROUGH */ 481 case (MDOC_Ef): 482 /* FALLTHROUGH */ 483 case (MDOC_Oc): 484 /* FALLTHROUGH */ 485 case (MDOC_Pc): 486 /* FALLTHROUGH */ 487 case (MDOC_Qc): 488 /* FALLTHROUGH */ 489 case (MDOC_Re): 490 /* FALLTHROUGH */ 491 case (MDOC_Sc): 492 /* FALLTHROUGH */ 493 case (MDOC_Xc): 494 if (type == p->type && rew_alt(tok) == p->tok) 495 return(REWIND_REWIND); 496 break; 497 default: 498 abort(); 499 /* NOTREACHED */ 500 } 501 502 return(REWIND_NOHALT); 503 } 504 505 506 /* 507 * See if we can break an encountered scope (the rew_dohalt has returned 508 * REWIND_NOHALT). 509 */ 510 static int 511 rew_dobreak(enum mdoct tok, const struct mdoc_node *p) 512 { 513 514 assert(MDOC_ROOT != p->type); 515 if (MDOC_ELEM == p->type) 516 return(1); 517 if (MDOC_TEXT == p->type) 518 return(1); 519 if (MDOC_VALID & p->flags) 520 return(1); 521 522 switch (tok) { 523 case (MDOC_It): 524 return(MDOC_It == p->tok); 525 case (MDOC_Nd): 526 return(MDOC_Nd == p->tok); 527 case (MDOC_Ss): 528 return(MDOC_Ss == p->tok); 529 case (MDOC_Sh): 530 if (MDOC_Nd == p->tok) 531 return(1); 532 if (MDOC_Ss == p->tok) 533 return(1); 534 return(MDOC_Sh == p->tok); 535 case (MDOC_El): 536 if (MDOC_It == p->tok) 537 return(1); 538 break; 539 case (MDOC_Oc): 540 if (MDOC_Op == p->tok) 541 return(1); 542 break; 543 default: 544 break; 545 } 546 547 if (MDOC_EXPLICIT & mdoc_macros[tok].flags) 548 return(p->tok == rew_alt(tok)); 549 else if (MDOC_BLOCK == p->type) 550 return(1); 551 552 return(tok == p->tok); 553 } 554 555 556 static int 557 rew_elem(struct mdoc *mdoc, enum mdoct tok) 558 { 559 struct mdoc_node *n; 560 561 n = mdoc->last; 562 if (MDOC_ELEM != n->type) 563 n = n->parent; 564 assert(MDOC_ELEM == n->type); 565 assert(tok == n->tok); 566 567 return(rew_last(mdoc, n)); 568 } 569 570 571 static int 572 rew_sub(enum mdoc_type t, struct mdoc *m, 573 enum mdoct tok, int line, int ppos) 574 { 575 struct mdoc_node *n; 576 enum rew c; 577 578 /* LINTED */ 579 for (n = m->last; n; n = n->parent) { 580 c = rew_dohalt(tok, t, n); 581 if (REWIND_HALT == c) { 582 if (MDOC_BLOCK != t) 583 return(1); 584 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) 585 return(1); 586 return(mdoc_perr(m, line, ppos, ENOCTX)); 587 } 588 if (REWIND_REWIND == c) 589 break; 590 else if (rew_dobreak(tok, n)) 591 continue; 592 if ( ! swarn(m, t, line, ppos, n)) 593 return(0); 594 } 595 596 assert(n); 597 if ( ! rew_last(m, n)) 598 return(0); 599 600 /* 601 * The current block extends an enclosing block beyond a line 602 * break. Now that the current block ends, close the enclosing 603 * block, too. 604 */ 605 if (NULL != (n = n->pending)) { 606 assert(MDOC_HEAD == n->type); 607 if ( ! rew_last(m, n)) 608 return(0); 609 if ( ! mdoc_body_alloc(m, n->line, n->pos, n->tok)) 610 return(0); 611 } 612 return(1); 613 } 614 615 616 static int 617 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf) 618 { 619 int lastarg; 620 enum margserr ac; 621 char *p; 622 623 if (0 == buf[*pos]) 624 return(1); 625 626 for (;;) { 627 lastarg = *pos; 628 ac = mdoc_zargs(mdoc, line, pos, buf, ARGS_NOWARN, &p); 629 630 if (ARGS_ERROR == ac) 631 return(0); 632 else if (ARGS_EOLN == ac) 633 break; 634 assert(mdoc_isdelim(p)); 635 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p)) 636 return(0); 637 } 638 639 return(1); 640 } 641 642 643 /* 644 * Close out block partial/full explicit. 645 */ 646 static int 647 blk_exp_close(MACRO_PROT_ARGS) 648 { 649 int j, lastarg, maxargs, flushed, nl; 650 enum margserr ac; 651 enum mdoct ntok; 652 char *p; 653 654 nl = MDOC_NEWLINE & m->flags; 655 656 switch (tok) { 657 case (MDOC_Ec): 658 maxargs = 1; 659 break; 660 default: 661 maxargs = 0; 662 break; 663 } 664 665 if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) { 666 if (buf[*pos]) 667 if ( ! mdoc_pwarn(m, line, ppos, ENOLINE)) 668 return(0); 669 670 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 671 return(0); 672 return(rew_sub(MDOC_BLOCK, m, tok, line, ppos)); 673 } 674 675 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 676 return(0); 677 678 if (maxargs > 0) 679 if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok))) 680 return(0); 681 682 for (flushed = j = 0; ; j++) { 683 lastarg = *pos; 684 685 if (j == maxargs && ! flushed) { 686 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 687 return(0); 688 flushed = 1; 689 } 690 691 ac = mdoc_args(m, line, pos, buf, tok, &p); 692 693 if (ARGS_ERROR == ac) 694 return(0); 695 if (ARGS_PUNCT == ac) 696 break; 697 if (ARGS_EOLN == ac) 698 break; 699 700 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); 701 702 if (MDOC_MAX == ntok) { 703 if ( ! mdoc_word_alloc(m, line, lastarg, p)) 704 return(0); 705 continue; 706 } 707 708 if ( ! flushed) { 709 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 710 return(0); 711 flushed = 1; 712 } 713 if ( ! mdoc_macro(m, ntok, line, lastarg, pos, buf)) 714 return(0); 715 break; 716 } 717 718 if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 719 return(0); 720 721 if ( ! nl) 722 return(1); 723 return(append_delims(m, line, pos, buf)); 724 } 725 726 727 static int 728 in_line(MACRO_PROT_ARGS) 729 { 730 int la, lastpunct, cnt, d, nc, nl; 731 enum margverr av; 732 enum mdoct ntok; 733 enum margserr ac; 734 struct mdoc_arg *arg; 735 char *p; 736 737 nl = MDOC_NEWLINE & m->flags; 738 739 /* 740 * Whether we allow ignored elements (those without content, 741 * usually because of reserved words) to squeak by. 742 */ 743 744 switch (tok) { 745 case (MDOC_An): 746 /* FALLTHROUGH */ 747 case (MDOC_Ar): 748 /* FALLTHROUGH */ 749 case (MDOC_Fl): 750 /* FALLTHROUGH */ 751 case (MDOC_Lk): 752 /* FALLTHROUGH */ 753 case (MDOC_Nm): 754 /* FALLTHROUGH */ 755 case (MDOC_Pa): 756 nc = 1; 757 break; 758 default: 759 nc = 0; 760 break; 761 } 762 763 for (arg = NULL;; ) { 764 la = *pos; 765 av = mdoc_argv(m, line, tok, &arg, pos, buf); 766 767 if (ARGV_WORD == av) { 768 *pos = la; 769 break; 770 } 771 if (ARGV_EOLN == av) 772 break; 773 if (ARGV_ARG == av) 774 continue; 775 776 mdoc_argv_free(arg); 777 return(0); 778 } 779 780 for (cnt = 0, lastpunct = 1;; ) { 781 la = *pos; 782 ac = mdoc_args(m, line, pos, buf, tok, &p); 783 784 if (ARGS_ERROR == ac) 785 return(0); 786 if (ARGS_EOLN == ac) 787 break; 788 if (ARGS_PUNCT == ac) 789 break; 790 791 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); 792 793 /* 794 * In this case, we've located a submacro and must 795 * execute it. Close out scope, if open. If no 796 * elements have been generated, either create one (nc) 797 * or raise a warning. 798 */ 799 800 if (MDOC_MAX != ntok) { 801 if (0 == lastpunct && ! rew_elem(m, tok)) 802 return(0); 803 if (nc && 0 == cnt) { 804 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 805 return(0); 806 if ( ! rew_last(m, m->last)) 807 return(0); 808 } else if ( ! nc && 0 == cnt) { 809 mdoc_argv_free(arg); 810 if ( ! mdoc_pwarn(m, line, ppos, EIGNE)) 811 return(0); 812 } 813 if ( ! mdoc_macro(m, ntok, line, la, pos, buf)) 814 return(0); 815 if ( ! nl) 816 return(1); 817 return(append_delims(m, line, pos, buf)); 818 } 819 820 /* 821 * Non-quote-enclosed punctuation. Set up our scope, if 822 * a word; rewind the scope, if a delimiter; then append 823 * the word. 824 */ 825 826 d = ARGS_QWORD == ac ? 0 : mdoc_isdelim(p); 827 828 if (ARGS_QWORD != ac && d) { 829 if (0 == lastpunct && ! rew_elem(m, tok)) 830 return(0); 831 lastpunct = 1; 832 } else if (lastpunct) { 833 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 834 return(0); 835 lastpunct = 0; 836 } 837 838 if ( ! d) 839 cnt++; 840 if ( ! mdoc_word_alloc(m, line, la, p)) 841 return(0); 842 843 /* 844 * `Fl' macros have their scope re-opened with each new 845 * word so that the `-' can be added to each one without 846 * having to parse out spaces. 847 */ 848 if (0 == lastpunct && MDOC_Fl == tok) { 849 if ( ! rew_elem(m, tok)) 850 return(0); 851 lastpunct = 1; 852 } 853 } 854 855 if (0 == lastpunct && ! rew_elem(m, tok)) 856 return(0); 857 858 /* 859 * If no elements have been collected and we're allowed to have 860 * empties (nc), open a scope and close it out. Otherwise, 861 * raise a warning. 862 */ 863 864 if (nc && 0 == cnt) { 865 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 866 return(0); 867 if ( ! rew_last(m, m->last)) 868 return(0); 869 } else if ( ! nc && 0 == cnt) { 870 mdoc_argv_free(arg); 871 if ( ! mdoc_pwarn(m, line, ppos, EIGNE)) 872 return(0); 873 } 874 875 if ( ! nl) 876 return(1); 877 return(append_delims(m, line, pos, buf)); 878 } 879 880 881 static int 882 blk_full(MACRO_PROT_ARGS) 883 { 884 int la, pcnt; 885 struct mdoc_arg *arg; 886 struct mdoc_node *head; /* save of head macro */ 887 struct mdoc_node *body; /* save of body macro */ 888 struct mdoc_node *n; 889 enum mdoct ntok; 890 enum margserr ac, lac; 891 enum margverr av; 892 char *p; 893 894 /* Close out prior implicit scope. */ 895 896 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) { 897 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 898 return(0); 899 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 900 return(0); 901 } 902 903 /* 904 * This routine accomodates implicitly- and explicitly-scoped 905 * macro openings. Implicit ones first close out prior scope 906 * (seen above). Delay opening the head until necessary to 907 * allow leading punctuation to print. Special consideration 908 * for `It -column', which has phrase-part syntax instead of 909 * regular child nodes. 910 */ 911 912 for (arg = NULL;; ) { 913 la = *pos; 914 av = mdoc_argv(m, line, tok, &arg, pos, buf); 915 916 if (ARGV_WORD == av) { 917 *pos = la; 918 break; 919 } 920 921 if (ARGV_EOLN == av) 922 break; 923 if (ARGV_ARG == av) 924 continue; 925 926 mdoc_argv_free(arg); 927 return(0); 928 } 929 930 if ( ! mdoc_block_alloc(m, line, ppos, tok, arg)) 931 return(0); 932 933 head = body = NULL; 934 935 /* 936 * The `Nd' macro has all arguments in its body: it's a hybrid 937 * of block partial-explicit and full-implicit. Stupid. 938 */ 939 940 if (MDOC_Nd == tok) { 941 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 942 return(0); 943 head = m->last; 944 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 945 return(0); 946 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 947 return(0); 948 body = m->last; 949 } 950 951 ac = ARGS_ERROR; 952 953 for (pcnt = 0; ; ) { 954 la = *pos; 955 lac = ac; 956 ac = mdoc_args(m, line, pos, buf, tok, &p); 957 958 if (ARGS_ERROR == ac) 959 return(0); 960 if (ARGS_EOLN == ac) 961 break; 962 963 /* 964 * XXX Temporarily disable the handling of leading punctuation. 965 * We must investigate the fallout before enabling this. 966 */ 967 #if 0 968 /* Don't emit leading punct. for phrases. */ 969 970 if (NULL == head && 971 ARGS_PHRASE != ac && 972 ARGS_PPHRASE != ac && 973 ARGS_PEND != ac && 974 ARGS_QWORD != ac && 975 1 == mdoc_isdelim(p)) { 976 if ( ! mdoc_word_alloc(m, line, la, p)) 977 return(0); 978 continue; 979 } 980 #endif 981 982 /* Always re-open head for phrases. */ 983 984 if (NULL == head || 985 ARGS_PHRASE == ac || 986 ARGS_PEND == ac || 987 ARGS_PPHRASE == ac) { 988 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 989 return(0); 990 head = m->last; 991 } 992 993 if (ARGS_PHRASE == ac || 994 ARGS_PEND == ac || 995 ARGS_PPHRASE == ac) { 996 /* 997 * Special treatment for the last phrase. A 998 * prior ARGS_PHRASE gets is handled as a 999 * regular ARGS_PHRASE, but a prior ARGS_PPHRASE 1000 * has special handling. 1001 */ 1002 if (ARGS_PEND == ac && ARGS_ERROR == lac) 1003 ac = ARGS_PHRASE; 1004 else if (ARGS_PEND == ac && ARGS_PHRASE == lac) 1005 ac = ARGS_PHRASE; 1006 1007 if ( ! phrase(m, line, la, buf, ac, pcnt++)) 1008 return(0); 1009 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1010 return(0); 1011 continue; 1012 } 1013 1014 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); 1015 1016 if (MDOC_MAX == ntok) { 1017 if ( ! mdoc_word_alloc(m, line, la, p)) 1018 return(0); 1019 continue; 1020 } 1021 1022 if ( ! mdoc_macro(m, ntok, line, la, pos, buf)) 1023 return(0); 1024 break; 1025 } 1026 1027 if (NULL == head) { 1028 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1029 return(0); 1030 head = m->last; 1031 } 1032 1033 if (1 == ppos && ! append_delims(m, line, pos, buf)) 1034 return(0); 1035 1036 /* If we've already opened our body, exit now. */ 1037 1038 if (NULL != body) 1039 return(1); 1040 1041 /* 1042 * If there is an open (i.e., unvalidated) sub-block requiring 1043 * explicit close-out, postpone switching the current block from 1044 * head to body until the rew_sub() call closing out that 1045 * sub-block. 1046 */ 1047 for (n = m->last; n && n != head; n = n->parent) { 1048 if (MDOC_BLOCK == n->type && 1049 MDOC_EXPLICIT & mdoc_macros[n->tok].flags && 1050 ! (MDOC_VALID & n->flags)) { 1051 assert( ! (MDOC_ACTED & n->flags)); 1052 n->pending = head; 1053 return(1); 1054 } 1055 } 1056 /* Close out scopes to remain in a consistent state. */ 1057 1058 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1059 return(0); 1060 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1061 return(0); 1062 1063 return(1); 1064 } 1065 1066 1067 static int 1068 blk_part_imp(MACRO_PROT_ARGS) 1069 { 1070 int la; 1071 enum mdoct ntok; 1072 enum margserr ac; 1073 char *p; 1074 struct mdoc_node *blk; /* saved block context */ 1075 struct mdoc_node *body; /* saved body context */ 1076 struct mdoc_node *n; 1077 1078 /* 1079 * A macro that spans to the end of the line. This is generally 1080 * (but not necessarily) called as the first macro. The block 1081 * has a head as the immediate child, which is always empty, 1082 * followed by zero or more opening punctuation nodes, then the 1083 * body (which may be empty, depending on the macro), then zero 1084 * or more closing punctuation nodes. 1085 */ 1086 1087 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL)) 1088 return(0); 1089 1090 blk = m->last; 1091 1092 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1093 return(0); 1094 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1095 return(0); 1096 1097 /* 1098 * Open the body scope "on-demand", that is, after we've 1099 * processed all our the leading delimiters (open parenthesis, 1100 * etc.). 1101 */ 1102 1103 for (body = NULL; ; ) { 1104 la = *pos; 1105 ac = mdoc_args(m, line, pos, buf, tok, &p); 1106 1107 if (ARGS_ERROR == ac) 1108 return(0); 1109 if (ARGS_EOLN == ac) 1110 break; 1111 if (ARGS_PUNCT == ac) 1112 break; 1113 1114 /* 1115 * XXX Temporarily disable the handling of leading punctuation. 1116 * We must investigate the fallout before enabling this. 1117 */ 1118 #if 0 1119 if (NULL == body && ARGS_QWORD != ac && 1120 1 == mdoc_isdelim(p)) { 1121 if ( ! mdoc_word_alloc(m, line, la, p)) 1122 return(0); 1123 continue; 1124 } 1125 #endif 1126 1127 if (NULL == body) { 1128 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1129 return(0); 1130 body = m->last; 1131 } 1132 1133 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); 1134 1135 if (MDOC_MAX == ntok) { 1136 if ( ! mdoc_word_alloc(m, line, la, p)) 1137 return(0); 1138 continue; 1139 } 1140 1141 if ( ! mdoc_macro(m, ntok, line, la, pos, buf)) 1142 return(0); 1143 break; 1144 } 1145 1146 /* Clean-ups to leave in a consistent state. */ 1147 1148 if (NULL == body) { 1149 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1150 return(0); 1151 body = m->last; 1152 } 1153 1154 /* 1155 * If we can't rewind to our body, then our scope has already 1156 * been closed by another macro (like `Oc' closing `Op'). This 1157 * is ugly behaviour nodding its head to OpenBSD's overwhelming 1158 * crufty use of `Op' breakage. 1159 */ 1160 for (n = m->last; n; n = n->parent) 1161 if (body == n) 1162 break; 1163 1164 if (NULL == n && ! mdoc_nwarn(m, body, EIMPBRK)) 1165 return(0); 1166 1167 if (n && ! rew_last(m, body)) 1168 return(0); 1169 1170 /* Standard appending of delimiters. */ 1171 1172 if (1 == ppos && ! append_delims(m, line, pos, buf)) 1173 return(0); 1174 1175 /* Rewind scope, if applicable. */ 1176 1177 if (n && ! rew_last(m, blk)) 1178 return(0); 1179 1180 return(1); 1181 } 1182 1183 1184 static int 1185 blk_part_exp(MACRO_PROT_ARGS) 1186 { 1187 int la, nl; 1188 enum margserr ac; 1189 struct mdoc_node *head; /* keep track of head */ 1190 struct mdoc_node *body; /* keep track of body */ 1191 char *p; 1192 enum mdoct ntok; 1193 1194 nl = MDOC_NEWLINE & m->flags; 1195 1196 /* 1197 * The opening of an explicit macro having zero or more leading 1198 * punctuation nodes; a head with optional single element (the 1199 * case of `Eo'); and a body that may be empty. 1200 */ 1201 1202 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL)) 1203 return(0); 1204 1205 for (head = body = NULL; ; ) { 1206 la = *pos; 1207 ac = mdoc_args(m, line, pos, buf, tok, &p); 1208 1209 if (ARGS_ERROR == ac) 1210 return(0); 1211 if (ARGS_PUNCT == ac) 1212 break; 1213 if (ARGS_EOLN == ac) 1214 break; 1215 1216 /* 1217 * XXX Temporarily disable the handling of leading punctuation. 1218 * We must investigate the fallout before enabling this. 1219 */ 1220 #if 0 1221 /* Flush out leading punctuation. */ 1222 1223 if (NULL == head && ARGS_QWORD != ac && 1224 1 == mdoc_isdelim(p)) { 1225 assert(NULL == body); 1226 if ( ! mdoc_word_alloc(m, line, la, p)) 1227 return(0); 1228 continue; 1229 } 1230 #endif 1231 1232 if (NULL == head) { 1233 assert(NULL == body); 1234 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1235 return(0); 1236 head = m->last; 1237 } 1238 1239 /* 1240 * `Eo' gobbles any data into the head, but most other 1241 * macros just immediately close out and begin the body. 1242 */ 1243 1244 if (NULL == body) { 1245 assert(head); 1246 /* No check whether it's a macro! */ 1247 if (MDOC_Eo == tok) 1248 if ( ! mdoc_word_alloc(m, line, la, p)) 1249 return(0); 1250 1251 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1252 return(0); 1253 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1254 return(0); 1255 body = m->last; 1256 1257 if (MDOC_Eo == tok) 1258 continue; 1259 } 1260 1261 assert(NULL != head && NULL != body); 1262 1263 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); 1264 1265 if (MDOC_MAX == ntok) { 1266 if ( ! mdoc_word_alloc(m, line, la, p)) 1267 return(0); 1268 continue; 1269 } 1270 1271 if ( ! mdoc_macro(m, ntok, line, la, pos, buf)) 1272 return(0); 1273 break; 1274 } 1275 1276 /* Clean-up to leave in a consistent state. */ 1277 1278 if (NULL == head) { 1279 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1280 return(0); 1281 head = m->last; 1282 } 1283 1284 if (NULL == body) { 1285 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1286 return(0); 1287 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1288 return(0); 1289 body = m->last; 1290 } 1291 1292 /* Standard appending of delimiters. */ 1293 1294 if ( ! nl) 1295 return(1); 1296 return(append_delims(m, line, pos, buf)); 1297 } 1298 1299 1300 /* ARGSUSED */ 1301 static int 1302 in_line_argn(MACRO_PROT_ARGS) 1303 { 1304 int la, flushed, j, maxargs, nl; 1305 enum margserr ac; 1306 enum margverr av; 1307 struct mdoc_arg *arg; 1308 char *p; 1309 enum mdoct ntok; 1310 1311 nl = MDOC_NEWLINE & m->flags; 1312 1313 /* 1314 * A line macro that has a fixed number of arguments (maxargs). 1315 * Only open the scope once the first non-leading-punctuation is 1316 * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then 1317 * keep it open until the maximum number of arguments are 1318 * exhausted. 1319 */ 1320 1321 switch (tok) { 1322 case (MDOC_Ap): 1323 /* FALLTHROUGH */ 1324 case (MDOC_No): 1325 /* FALLTHROUGH */ 1326 case (MDOC_Ns): 1327 /* FALLTHROUGH */ 1328 case (MDOC_Ux): 1329 maxargs = 0; 1330 break; 1331 case (MDOC_Xr): 1332 maxargs = 2; 1333 break; 1334 default: 1335 maxargs = 1; 1336 break; 1337 } 1338 1339 for (arg = NULL; ; ) { 1340 la = *pos; 1341 av = mdoc_argv(m, line, tok, &arg, pos, buf); 1342 1343 if (ARGV_WORD == av) { 1344 *pos = la; 1345 break; 1346 } 1347 1348 if (ARGV_EOLN == av) 1349 break; 1350 if (ARGV_ARG == av) 1351 continue; 1352 1353 mdoc_argv_free(arg); 1354 return(0); 1355 } 1356 1357 for (flushed = j = 0; ; ) { 1358 la = *pos; 1359 ac = mdoc_args(m, line, pos, buf, tok, &p); 1360 1361 if (ARGS_ERROR == ac) 1362 return(0); 1363 if (ARGS_PUNCT == ac) 1364 break; 1365 if (ARGS_EOLN == ac) 1366 break; 1367 1368 /* 1369 * XXX Temporarily disable the handling of leading punctuation. 1370 * We must investigate the fallout before enabling this. 1371 */ 1372 #if 0 1373 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 1374 ARGS_QWORD != ac && 1375 0 == j && 1 == mdoc_isdelim(p)) { 1376 if ( ! mdoc_word_alloc(m, line, la, p)) 1377 return(0); 1378 continue; 1379 } else 1380 #endif 1381 if (0 == j) 1382 if ( ! mdoc_elem_alloc(m, line, la, tok, arg)) 1383 return(0); 1384 1385 if (j == maxargs && ! flushed) { 1386 if ( ! rew_elem(m, tok)) 1387 return(0); 1388 flushed = 1; 1389 } 1390 1391 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); 1392 1393 if (MDOC_MAX != ntok) { 1394 if ( ! flushed && ! rew_elem(m, tok)) 1395 return(0); 1396 flushed = 1; 1397 if ( ! mdoc_macro(m, ntok, line, la, pos, buf)) 1398 return(0); 1399 j++; 1400 break; 1401 } 1402 1403 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 1404 ARGS_QWORD != ac && 1405 ! flushed && mdoc_isdelim(p)) { 1406 if ( ! rew_elem(m, tok)) 1407 return(0); 1408 flushed = 1; 1409 } 1410 1411 /* 1412 * XXX: this is a hack to work around groff's ugliness 1413 * as regards `Xr' and extraneous arguments. It should 1414 * ideally be deprecated behaviour, but because this is 1415 * code is no here, it's unlikely to be removed. 1416 */ 1417 if (MDOC_Xr == tok && j == maxargs) { 1418 if ( ! mdoc_elem_alloc(m, line, la, MDOC_Ns, NULL)) 1419 return(0); 1420 if ( ! rew_elem(m, MDOC_Ns)) 1421 return(0); 1422 } 1423 1424 if ( ! mdoc_word_alloc(m, line, la, p)) 1425 return(0); 1426 j++; 1427 } 1428 1429 if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg)) 1430 return(0); 1431 1432 /* Close out in a consistent state. */ 1433 1434 if ( ! flushed && ! rew_elem(m, tok)) 1435 return(0); 1436 if ( ! nl) 1437 return(1); 1438 return(append_delims(m, line, pos, buf)); 1439 } 1440 1441 1442 static int 1443 in_line_eoln(MACRO_PROT_ARGS) 1444 { 1445 int la; 1446 enum margserr ac; 1447 enum margverr av; 1448 struct mdoc_arg *arg; 1449 char *p; 1450 enum mdoct ntok; 1451 1452 assert( ! (MDOC_PARSED & mdoc_macros[tok].flags)); 1453 1454 /* Parse macro arguments. */ 1455 1456 for (arg = NULL; ; ) { 1457 la = *pos; 1458 av = mdoc_argv(m, line, tok, &arg, pos, buf); 1459 1460 if (ARGV_WORD == av) { 1461 *pos = la; 1462 break; 1463 } 1464 if (ARGV_EOLN == av) 1465 break; 1466 if (ARGV_ARG == av) 1467 continue; 1468 1469 mdoc_argv_free(arg); 1470 return(0); 1471 } 1472 1473 /* Open element scope. */ 1474 1475 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 1476 return(0); 1477 1478 /* Parse argument terms. */ 1479 1480 for (;;) { 1481 la = *pos; 1482 ac = mdoc_args(m, line, pos, buf, tok, &p); 1483 1484 if (ARGS_ERROR == ac) 1485 return(0); 1486 if (ARGS_EOLN == ac) 1487 break; 1488 1489 ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p); 1490 1491 if (MDOC_MAX == ntok) { 1492 if ( ! mdoc_word_alloc(m, line, la, p)) 1493 return(0); 1494 continue; 1495 } 1496 1497 if ( ! rew_elem(m, tok)) 1498 return(0); 1499 return(mdoc_macro(m, ntok, line, la, pos, buf)); 1500 } 1501 1502 /* Close out (no delimiters). */ 1503 1504 return(rew_elem(m, tok)); 1505 } 1506 1507 1508 /* ARGSUSED */ 1509 static int 1510 ctx_synopsis(MACRO_PROT_ARGS) 1511 { 1512 int nl; 1513 1514 nl = MDOC_NEWLINE & m->flags; 1515 1516 /* If we're not in the SYNOPSIS, go straight to in-line. */ 1517 if (SEC_SYNOPSIS != m->lastsec) 1518 return(in_line(m, tok, line, ppos, pos, buf)); 1519 1520 /* If we're a nested call, same place. */ 1521 if ( ! nl) 1522 return(in_line(m, tok, line, ppos, pos, buf)); 1523 1524 /* 1525 * XXX: this will open a block scope; however, if later we end 1526 * up formatting the block scope, then child nodes will inherit 1527 * the formatting. Be careful. 1528 */ 1529 1530 return(blk_part_imp(m, tok, line, ppos, pos, buf)); 1531 } 1532 1533 1534 /* ARGSUSED */ 1535 static int 1536 obsolete(MACRO_PROT_ARGS) 1537 { 1538 1539 return(mdoc_pwarn(m, line, ppos, EOBS)); 1540 } 1541 1542 1543 /* 1544 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs. 1545 * They're unusual because they're basically free-form text until a 1546 * macro is encountered. 1547 */ 1548 static int 1549 phrase(struct mdoc *m, int line, int ppos, char *buf, 1550 enum margserr ac, int count) 1551 { 1552 int la, pos; 1553 enum margserr aac; 1554 enum mdoct ntok; 1555 char *p; 1556 1557 assert(ARGS_PHRASE == ac || 1558 ARGS_PEND == ac || 1559 ARGS_PPHRASE == ac); 1560 1561 if (count && ARGS_PPHRASE == ac) 1562 return(mdoc_word_alloc(m, line, ppos, &buf[ppos])); 1563 1564 for (pos = ppos; ; ) { 1565 la = pos; 1566 1567 /* Note: no calling context! */ 1568 aac = mdoc_zargs(m, line, &pos, buf, 0, &p); 1569 1570 if (ARGS_ERROR == aac) 1571 return(0); 1572 if (ARGS_EOLN == aac) 1573 break; 1574 1575 ntok = ARGS_QWORD == aac || ARGS_PEND == ac ? 1576 MDOC_MAX : lookup_raw(p); 1577 1578 if (MDOC_MAX == ntok) { 1579 if ( ! mdoc_word_alloc(m, line, la, p)) 1580 return(0); 1581 continue; 1582 } 1583 1584 if ( ! mdoc_macro(m, ntok, line, la, &pos, buf)) 1585 return(0); 1586 return(append_delims(m, line, &pos, buf)); 1587 } 1588 1589 return(1); 1590 } 1591 1592 1593