1 /* $Id: mdoc_macro.c,v 1.35 2010/04/07 23:15:05 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 ctx_synopsis(MACRO_PROT_ARGS); 33 static int obsolete(MACRO_PROT_ARGS); 34 static int blk_part_exp(MACRO_PROT_ARGS); 35 static int in_line_eoln(MACRO_PROT_ARGS); 36 static int in_line_argn(MACRO_PROT_ARGS); 37 static int in_line(MACRO_PROT_ARGS); 38 static int blk_full(MACRO_PROT_ARGS); 39 static int blk_exp_close(MACRO_PROT_ARGS); 40 static int blk_part_imp(MACRO_PROT_ARGS); 41 42 static int phrase(struct mdoc *, int, int, char *); 43 static enum rew rew_dohalt(enum mdoct, enum mdoc_type, 44 const struct mdoc_node *); 45 static enum mdoct rew_alt(enum mdoct); 46 static int rew_dobreak(enum mdoct, const struct mdoc_node *); 47 static int rew_elem(struct mdoc *, enum mdoct); 48 static int rew_sub(enum mdoc_type, struct mdoc *, 49 enum mdoct, int, int); 50 static int rew_last(struct mdoc *, 51 const struct mdoc_node *); 52 static int append_delims(struct mdoc *, int, int *, char *); 53 static int lookup(int, const char *); 54 static int lookup_raw(const char *); 55 static int swarn(struct mdoc *, enum mdoc_type, int, int, 56 const struct mdoc_node *); 57 58 /* Central table of library: who gets parsed how. */ 59 60 const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { 61 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */ 62 { in_line_eoln, MDOC_PROLOGUE }, /* Dd */ 63 { in_line_eoln, MDOC_PROLOGUE }, /* Dt */ 64 { in_line_eoln, MDOC_PROLOGUE }, /* Os */ 65 { blk_full, 0 }, /* Sh */ 66 { blk_full, 0 }, /* Ss */ 67 { in_line_eoln, 0 }, /* Pp */ 68 { blk_part_imp, MDOC_PARSED }, /* D1 */ 69 { blk_part_imp, MDOC_PARSED }, /* Dl */ 70 { blk_full, MDOC_EXPLICIT }, /* Bd */ 71 { blk_exp_close, MDOC_EXPLICIT }, /* Ed */ 72 { blk_full, MDOC_EXPLICIT }, /* Bl */ 73 { blk_exp_close, MDOC_EXPLICIT }, /* El */ 74 { blk_full, MDOC_PARSED }, /* It */ 75 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ 76 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */ 77 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ 78 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */ 79 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ 80 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ 81 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ 82 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ 83 { in_line_eoln, 0 }, /* Ex */ 84 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ 85 { in_line_eoln, 0 }, /* Fd */ 86 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */ 87 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ 88 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ 89 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ 90 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */ 91 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */ 92 { blk_full, 0 }, /* Nd */ 93 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ 94 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */ 95 { obsolete, 0 }, /* Ot */ 96 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */ 97 { in_line_eoln, 0 }, /* Rv */ 98 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 99 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ 100 { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ 101 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ 102 { in_line_eoln, 0 }, /* %A */ 103 { in_line_eoln, 0 }, /* %B */ 104 { in_line_eoln, 0 }, /* %D */ 105 { in_line_eoln, 0 }, /* %I */ 106 { in_line_eoln, 0 }, /* %J */ 107 { in_line_eoln, 0 }, /* %N */ 108 { in_line_eoln, 0 }, /* %O */ 109 { in_line_eoln, 0 }, /* %P */ 110 { in_line_eoln, 0 }, /* %R */ 111 { in_line_eoln, 0 }, /* %T */ 112 { in_line_eoln, 0 }, /* %V */ 113 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */ 114 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */ 115 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */ 116 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */ 117 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */ 118 { blk_full, MDOC_EXPLICIT }, /* Bf */ 119 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */ 120 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */ 121 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */ 122 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */ 123 { in_line_eoln, 0 }, /* Db */ 124 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */ 125 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */ 126 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */ 127 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */ 128 { blk_exp_close, MDOC_EXPLICIT }, /* Ef */ 129 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ 130 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ 131 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ 132 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */ 133 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */ 134 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */ 135 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ 136 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ 137 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */ 138 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */ 139 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */ 140 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */ 141 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */ 142 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */ 143 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */ 144 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */ 145 { blk_exp_close, MDOC_EXPLICIT }, /* Re */ 146 { blk_full, MDOC_EXPLICIT }, /* Rs */ 147 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */ 148 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */ 149 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */ 150 { in_line_eoln, 0 }, /* Sm */ 151 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */ 152 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */ 153 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ 154 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */ 155 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */ 156 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */ 157 { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ 158 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ 159 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */ 160 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */ 161 { blk_full, MDOC_EXPLICIT }, /* Bk */ 162 { blk_exp_close, MDOC_EXPLICIT }, /* Ek */ 163 { in_line_eoln, 0 }, /* Bt */ 164 { in_line_eoln, 0 }, /* Hf */ 165 { obsolete, 0 }, /* Fr */ 166 { in_line_eoln, 0 }, /* Ud */ 167 { in_line_eoln, 0 }, /* Lb */ 168 { in_line_eoln, 0 }, /* Lp */ 169 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ 170 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ 171 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */ 172 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */ 173 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */ 174 { in_line_eoln, 0 }, /* %C */ 175 { obsolete, 0 }, /* Es */ 176 { obsolete, 0 }, /* En */ 177 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */ 178 { in_line_eoln, 0 }, /* %Q */ 179 { in_line_eoln, 0 }, /* br */ 180 { in_line_eoln, 0 }, /* sp */ 181 { in_line_eoln, 0 }, /* %U */ 182 { NULL, 0 }, /* eos */ 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 int 267 lookup(int 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 int 281 lookup_raw(const char *p) 282 { 283 int 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 c, lastarg; 620 char *p; 621 622 if (0 == buf[*pos]) 623 return(1); 624 625 for (;;) { 626 lastarg = *pos; 627 c = mdoc_zargs(mdoc, line, pos, buf, ARGS_NOWARN, &p); 628 assert(ARGS_PHRASE != c); 629 630 if (ARGS_ERROR == c) 631 return(0); 632 else if (ARGS_EOLN == c) 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, c, lastarg, maxargs, flushed; 650 char *p; 651 652 switch (tok) { 653 case (MDOC_Ec): 654 maxargs = 1; 655 break; 656 default: 657 maxargs = 0; 658 break; 659 } 660 661 if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) { 662 if (buf[*pos]) 663 if ( ! mdoc_pwarn(m, line, ppos, ENOLINE)) 664 return(0); 665 666 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 667 return(0); 668 return(rew_sub(MDOC_BLOCK, m, tok, line, ppos)); 669 } 670 671 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 672 return(0); 673 674 if (maxargs > 0) 675 if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok))) 676 return(0); 677 678 for (flushed = j = 0; ; j++) { 679 lastarg = *pos; 680 681 if (j == maxargs && ! flushed) { 682 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 683 return(0); 684 flushed = 1; 685 } 686 687 c = mdoc_args(m, line, pos, buf, tok, &p); 688 689 if (ARGS_ERROR == c) 690 return(0); 691 if (ARGS_PUNCT == c) 692 break; 693 if (ARGS_EOLN == c) 694 break; 695 696 if (MDOC_MAX != (c = lookup(tok, p))) { 697 if ( ! flushed) { 698 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 699 return(0); 700 flushed = 1; 701 } 702 if ( ! mdoc_macro(m, c, line, lastarg, pos, buf)) 703 return(0); 704 break; 705 } 706 707 if ( ! mdoc_word_alloc(m, line, lastarg, p)) 708 return(0); 709 } 710 711 if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 712 return(0); 713 714 if (ppos > 1) 715 return(1); 716 return(append_delims(m, line, pos, buf)); 717 } 718 719 720 static int 721 in_line(MACRO_PROT_ARGS) 722 { 723 int la, lastpunct, c, w, cnt, d, nc; 724 struct mdoc_arg *arg; 725 char *p; 726 727 /* 728 * Whether we allow ignored elements (those without content, 729 * usually because of reserved words) to squeak by. 730 */ 731 732 switch (tok) { 733 case (MDOC_An): 734 /* FALLTHROUGH */ 735 case (MDOC_Ar): 736 /* FALLTHROUGH */ 737 case (MDOC_Fl): 738 /* FALLTHROUGH */ 739 case (MDOC_Lk): 740 /* FALLTHROUGH */ 741 case (MDOC_Nm): 742 /* FALLTHROUGH */ 743 case (MDOC_Pa): 744 nc = 1; 745 break; 746 default: 747 nc = 0; 748 break; 749 } 750 751 for (arg = NULL;; ) { 752 la = *pos; 753 c = mdoc_argv(m, line, tok, &arg, pos, buf); 754 755 if (ARGV_WORD == c) { 756 *pos = la; 757 break; 758 } 759 if (ARGV_EOLN == c) 760 break; 761 if (ARGV_ARG == c) 762 continue; 763 764 mdoc_argv_free(arg); 765 return(0); 766 } 767 768 for (cnt = 0, lastpunct = 1;; ) { 769 la = *pos; 770 w = mdoc_args(m, line, pos, buf, tok, &p); 771 772 if (ARGS_ERROR == w) 773 return(0); 774 if (ARGS_EOLN == w) 775 break; 776 if (ARGS_PUNCT == w) 777 break; 778 779 /* Quoted words shouldn't be looked-up. */ 780 781 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p); 782 783 /* 784 * In this case, we've located a submacro and must 785 * execute it. Close out scope, if open. If no 786 * elements have been generated, either create one (nc) 787 * or raise a warning. 788 */ 789 790 if (MDOC_MAX != c) { 791 if (0 == lastpunct && ! rew_elem(m, tok)) 792 return(0); 793 if (nc && 0 == cnt) { 794 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 795 return(0); 796 if ( ! rew_last(m, m->last)) 797 return(0); 798 } else if ( ! nc && 0 == cnt) { 799 mdoc_argv_free(arg); 800 if ( ! mdoc_pwarn(m, line, ppos, EIGNE)) 801 return(0); 802 } 803 c = mdoc_macro(m, c, line, la, pos, buf); 804 if (0 == c) 805 return(0); 806 if (ppos > 1) 807 return(1); 808 return(append_delims(m, line, pos, buf)); 809 } 810 811 /* 812 * Non-quote-enclosed punctuation. Set up our scope, if 813 * a word; rewind the scope, if a delimiter; then append 814 * the word. 815 */ 816 817 d = ARGS_QWORD == w ? 0 : mdoc_isdelim(p); 818 819 if (ARGS_QWORD != w && d) { 820 if (0 == lastpunct && ! rew_elem(m, tok)) 821 return(0); 822 lastpunct = 1; 823 } else if (lastpunct) { 824 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 825 return(0); 826 lastpunct = 0; 827 } 828 829 if ( ! d) 830 cnt++; 831 if ( ! mdoc_word_alloc(m, line, la, p)) 832 return(0); 833 834 /* 835 * `Fl' macros have their scope re-opened with each new 836 * word so that the `-' can be added to each one without 837 * having to parse out spaces. 838 */ 839 if (0 == lastpunct && MDOC_Fl == tok) { 840 if ( ! rew_elem(m, tok)) 841 return(0); 842 lastpunct = 1; 843 } 844 } 845 846 if (0 == lastpunct && ! rew_elem(m, tok)) 847 return(0); 848 849 /* 850 * If no elements have been collected and we're allowed to have 851 * empties (nc), open a scope and close it out. Otherwise, 852 * raise a warning. 853 */ 854 855 if (nc && 0 == cnt) { 856 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 857 return(0); 858 if ( ! rew_last(m, m->last)) 859 return(0); 860 } else if ( ! nc && 0 == cnt) { 861 mdoc_argv_free(arg); 862 if ( ! mdoc_pwarn(m, line, ppos, EIGNE)) 863 return(0); 864 } 865 866 if (ppos > 1) 867 return(1); 868 return(append_delims(m, line, pos, buf)); 869 } 870 871 872 static int 873 blk_full(MACRO_PROT_ARGS) 874 { 875 int c, la; 876 struct mdoc_arg *arg; 877 struct mdoc_node *head; /* save of head macro */ 878 struct mdoc_node *body; /* save of body macro */ 879 struct mdoc_node *n; 880 char *p; 881 882 /* Close out prior implicit scope. */ 883 884 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) { 885 if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos)) 886 return(0); 887 if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos)) 888 return(0); 889 } 890 891 /* 892 * This routine accomodates implicitly- and explicitly-scoped 893 * macro openings. Implicit ones first close out prior scope 894 * (seen above). Delay opening the head until necessary to 895 * allow leading punctuation to print. Special consideration 896 * for `It -column', which has phrase-part syntax instead of 897 * regular child nodes. 898 */ 899 900 for (arg = NULL;; ) { 901 la = *pos; 902 c = mdoc_argv(m, line, tok, &arg, pos, buf); 903 904 if (ARGV_WORD == c) { 905 *pos = la; 906 break; 907 } 908 909 if (ARGV_EOLN == c) 910 break; 911 if (ARGV_ARG == c) 912 continue; 913 914 mdoc_argv_free(arg); 915 return(0); 916 } 917 918 if ( ! mdoc_block_alloc(m, line, ppos, tok, arg)) 919 return(0); 920 921 head = body = NULL; 922 923 /* 924 * The `Nd' macro has all arguments in its body: it's a hybrid 925 * of block partial-explicit and full-implicit. Stupid. 926 */ 927 928 if (MDOC_Nd == tok) { 929 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 930 return(0); 931 head = m->last; 932 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 933 return(0); 934 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 935 return(0); 936 body = m->last; 937 } 938 939 for (;;) { 940 la = *pos; 941 c = mdoc_args(m, line, pos, buf, tok, &p); 942 943 if (ARGS_ERROR == c) 944 return(0); 945 if (ARGS_EOLN == c) 946 break; 947 948 /* 949 * XXX Temporarily disable the handling of leading punctuation. 950 * We must investigate the fallout before enabling this. 951 */ 952 #if 0 953 /* Don't emit leading punct. for phrases. */ 954 955 if (NULL == head && ARGS_PHRASE != c && 956 ARGS_QWORD != c && 957 1 == mdoc_isdelim(p)) { 958 if ( ! mdoc_word_alloc(m, line, la, p)) 959 return(0); 960 continue; 961 } 962 #endif 963 964 /* Always re-open head for phrases. */ 965 966 if (NULL == head || ARGS_PHRASE == c) { 967 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 968 return(0); 969 head = m->last; 970 } 971 972 if (ARGS_PHRASE == c) { 973 if ( ! phrase(m, line, la, buf)) 974 return(0); 975 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 976 return(0); 977 continue; 978 } 979 980 c = lookup(tok, p); 981 if (MDOC_MAX != c) { 982 if ( ! mdoc_macro(m, c, line, la, pos, buf)) 983 return(0); 984 break; 985 } 986 if ( ! mdoc_word_alloc(m, line, la, p)) 987 return(0); 988 989 } 990 991 if (NULL == head) { 992 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 993 return(0); 994 head = m->last; 995 } 996 997 if (1 == ppos && ! append_delims(m, line, pos, buf)) 998 return(0); 999 1000 /* If we've already opened our body, exit now. */ 1001 1002 if (NULL != body) 1003 return(1); 1004 1005 /* 1006 * If there is an open (i.e., unvalidated) sub-block requiring 1007 * explicit close-out, postpone switching the current block from 1008 * head to body until the rew_sub() call closing out that 1009 * sub-block. 1010 */ 1011 for (n = m->last; n && n != head; n = n->parent) { 1012 if (MDOC_BLOCK == n->type && 1013 MDOC_EXPLICIT & mdoc_macros[n->tok].flags && 1014 ! (MDOC_VALID & n->flags)) { 1015 assert( ! (MDOC_ACTED & n->flags)); 1016 n->pending = head; 1017 return(1); 1018 } 1019 } 1020 /* Close out scopes to remain in a consistent state. */ 1021 1022 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1023 return(0); 1024 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1025 return(0); 1026 1027 return(1); 1028 } 1029 1030 1031 static int 1032 blk_part_imp(MACRO_PROT_ARGS) 1033 { 1034 int la, c; 1035 char *p; 1036 struct mdoc_node *blk; /* saved block context */ 1037 struct mdoc_node *body; /* saved body context */ 1038 struct mdoc_node *n; 1039 1040 /* 1041 * A macro that spans to the end of the line. This is generally 1042 * (but not necessarily) called as the first macro. The block 1043 * has a head as the immediate child, which is always empty, 1044 * followed by zero or more opening punctuation nodes, then the 1045 * body (which may be empty, depending on the macro), then zero 1046 * or more closing punctuation nodes. 1047 */ 1048 1049 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL)) 1050 return(0); 1051 1052 blk = m->last; 1053 1054 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1055 return(0); 1056 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1057 return(0); 1058 1059 /* 1060 * Open the body scope "on-demand", that is, after we've 1061 * processed all our the leading delimiters (open parenthesis, 1062 * etc.). 1063 */ 1064 1065 for (body = NULL; ; ) { 1066 la = *pos; 1067 c = mdoc_args(m, line, pos, buf, tok, &p); 1068 1069 assert(ARGS_PHRASE != c); 1070 1071 if (ARGS_ERROR == c) 1072 return(0); 1073 if (ARGS_EOLN == c) 1074 break; 1075 if (ARGS_PUNCT == c) 1076 break; 1077 1078 /* 1079 * XXX Temporarily disable the handling of leading punctuation. 1080 * We must investigate the fallout before enabling this. 1081 */ 1082 #if 0 1083 if (NULL == body && ARGS_QWORD != c && 1084 1 == mdoc_isdelim(p)) { 1085 if ( ! mdoc_word_alloc(m, line, la, p)) 1086 return(0); 1087 continue; 1088 } 1089 #endif 1090 1091 if (NULL == body) { 1092 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1093 return(0); 1094 body = m->last; 1095 } 1096 1097 if (MDOC_MAX != (c = lookup(tok, p))) { 1098 if ( ! mdoc_macro(m, c, line, la, pos, buf)) 1099 return(0); 1100 break; 1101 } 1102 1103 if ( ! mdoc_word_alloc(m, line, la, p)) 1104 return(0); 1105 } 1106 1107 /* Clean-ups to leave in a consistent state. */ 1108 1109 if (NULL == body) { 1110 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1111 return(0); 1112 body = m->last; 1113 } 1114 1115 /* 1116 * If we can't rewind to our body, then our scope has already 1117 * been closed by another macro (like `Oc' closing `Op'). This 1118 * is ugly behaviour nodding its head to OpenBSD's overwhelming 1119 * crufty use of `Op' breakage. 1120 */ 1121 for (n = m->last; n; n = n->parent) 1122 if (body == n) 1123 break; 1124 1125 if (NULL == n && ! mdoc_nwarn(m, body, EIMPBRK)) 1126 return(0); 1127 1128 if (n && ! rew_last(m, body)) 1129 return(0); 1130 1131 /* Standard appending of delimiters. */ 1132 1133 if (1 == ppos && ! append_delims(m, line, pos, buf)) 1134 return(0); 1135 1136 /* Rewind scope, if applicable. */ 1137 1138 if (n && ! rew_last(m, blk)) 1139 return(0); 1140 1141 return(1); 1142 } 1143 1144 1145 static int 1146 blk_part_exp(MACRO_PROT_ARGS) 1147 { 1148 int la, c; 1149 struct mdoc_node *head; /* keep track of head */ 1150 struct mdoc_node *body; /* keep track of body */ 1151 char *p; 1152 1153 /* 1154 * The opening of an explicit macro having zero or more leading 1155 * punctuation nodes; a head with optional single element (the 1156 * case of `Eo'); and a body that may be empty. 1157 */ 1158 1159 if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL)) 1160 return(0); 1161 1162 for (head = body = NULL; ; ) { 1163 la = *pos; 1164 c = mdoc_args(m, line, pos, buf, tok, &p); 1165 1166 if (ARGS_ERROR == c) 1167 return(0); 1168 if (ARGS_PUNCT == c) 1169 break; 1170 if (ARGS_EOLN == c) 1171 break; 1172 1173 assert(ARGS_PHRASE != c); 1174 1175 /* 1176 * XXX Temporarily disable the handling of leading punctuation. 1177 * We must investigate the fallout before enabling this. 1178 */ 1179 #if 0 1180 /* Flush out leading punctuation. */ 1181 1182 if (NULL == head && ARGS_QWORD != c && 1183 1 == mdoc_isdelim(p)) { 1184 assert(NULL == body); 1185 if ( ! mdoc_word_alloc(m, line, la, p)) 1186 return(0); 1187 continue; 1188 } 1189 #endif 1190 1191 if (NULL == head) { 1192 assert(NULL == body); 1193 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1194 return(0); 1195 head = m->last; 1196 } 1197 1198 /* 1199 * `Eo' gobbles any data into the head, but most other 1200 * macros just immediately close out and begin the body. 1201 */ 1202 1203 if (NULL == body) { 1204 assert(head); 1205 /* No check whether it's a macro! */ 1206 if (MDOC_Eo == tok) 1207 if ( ! mdoc_word_alloc(m, line, la, p)) 1208 return(0); 1209 1210 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1211 return(0); 1212 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1213 return(0); 1214 body = m->last; 1215 1216 if (MDOC_Eo == tok) 1217 continue; 1218 } 1219 1220 assert(NULL != head && NULL != body); 1221 1222 if (MDOC_MAX != (c = lookup(tok, p))) { 1223 if ( ! mdoc_macro(m, c, line, la, pos, buf)) 1224 return(0); 1225 break; 1226 } 1227 1228 if ( ! mdoc_word_alloc(m, line, la, p)) 1229 return(0); 1230 } 1231 1232 /* Clean-up to leave in a consistent state. */ 1233 1234 if (NULL == head) { 1235 if ( ! mdoc_head_alloc(m, line, ppos, tok)) 1236 return(0); 1237 head = m->last; 1238 } 1239 1240 if (NULL == body) { 1241 if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) 1242 return(0); 1243 if ( ! mdoc_body_alloc(m, line, ppos, tok)) 1244 return(0); 1245 body = m->last; 1246 } 1247 1248 /* Standard appending of delimiters. */ 1249 1250 if (ppos > 1) 1251 return(1); 1252 1253 return(append_delims(m, line, pos, buf)); 1254 } 1255 1256 1257 static int 1258 in_line_argn(MACRO_PROT_ARGS) 1259 { 1260 int la, flushed, j, c, maxargs; 1261 struct mdoc_arg *arg; 1262 char *p; 1263 1264 /* 1265 * A line macro that has a fixed number of arguments (maxargs). 1266 * Only open the scope once the first non-leading-punctuation is 1267 * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then 1268 * keep it open until the maximum number of arguments are 1269 * exhausted. 1270 */ 1271 1272 switch (tok) { 1273 case (MDOC_Ap): 1274 /* FALLTHROUGH */ 1275 case (MDOC_No): 1276 /* FALLTHROUGH */ 1277 case (MDOC_Ns): 1278 /* FALLTHROUGH */ 1279 case (MDOC_Ux): 1280 maxargs = 0; 1281 break; 1282 case (MDOC_Xr): 1283 maxargs = 2; 1284 break; 1285 default: 1286 maxargs = 1; 1287 break; 1288 } 1289 1290 for (arg = NULL; ; ) { 1291 la = *pos; 1292 c = mdoc_argv(m, line, tok, &arg, pos, buf); 1293 1294 if (ARGV_WORD == c) { 1295 *pos = la; 1296 break; 1297 } 1298 1299 if (ARGV_EOLN == c) 1300 break; 1301 if (ARGV_ARG == c) 1302 continue; 1303 1304 mdoc_argv_free(arg); 1305 return(0); 1306 } 1307 1308 for (flushed = j = 0; ; ) { 1309 la = *pos; 1310 c = mdoc_args(m, line, pos, buf, tok, &p); 1311 1312 if (ARGS_ERROR == c) 1313 return(0); 1314 if (ARGS_PUNCT == c) 1315 break; 1316 if (ARGS_EOLN == c) 1317 break; 1318 1319 /* 1320 * XXX Temporarily disable the handling of leading punctuation. 1321 * We must investigate the fallout before enabling this. 1322 */ 1323 #if 0 1324 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 1325 ARGS_QWORD != c && 1326 0 == j && 1 == mdoc_isdelim(p)) { 1327 if ( ! mdoc_word_alloc(m, line, la, p)) 1328 return(0); 1329 continue; 1330 } else 1331 #endif 1332 if (0 == j) 1333 if ( ! mdoc_elem_alloc(m, line, la, tok, arg)) 1334 return(0); 1335 1336 if (j == maxargs && ! flushed) { 1337 if ( ! rew_elem(m, tok)) 1338 return(0); 1339 flushed = 1; 1340 } 1341 1342 if (MDOC_MAX != (c = lookup(tok, p))) { 1343 if ( ! flushed && ! rew_elem(m, tok)) 1344 return(0); 1345 flushed = 1; 1346 if ( ! mdoc_macro(m, c, line, la, pos, buf)) 1347 return(0); 1348 j++; 1349 break; 1350 } 1351 1352 if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 1353 ARGS_QWORD != c && 1354 ! flushed && mdoc_isdelim(p)) { 1355 if ( ! rew_elem(m, tok)) 1356 return(0); 1357 flushed = 1; 1358 } 1359 1360 /* 1361 * XXX: this is a hack to work around groff's ugliness 1362 * as regards `Xr' and extraneous arguments. It should 1363 * ideally be deprecated behaviour, but because this is 1364 * code is no here, it's unlikely to be removed. 1365 */ 1366 if (MDOC_Xr == tok && j == maxargs) { 1367 if ( ! mdoc_elem_alloc(m, line, la, MDOC_Ns, NULL)) 1368 return(0); 1369 if ( ! rew_elem(m, MDOC_Ns)) 1370 return(0); 1371 } 1372 1373 if ( ! mdoc_word_alloc(m, line, la, p)) 1374 return(0); 1375 j++; 1376 } 1377 1378 if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg)) 1379 return(0); 1380 1381 /* Close out in a consistent state. */ 1382 1383 if ( ! flushed && ! rew_elem(m, tok)) 1384 return(0); 1385 1386 if (ppos > 1) 1387 return(1); 1388 return(append_delims(m, line, pos, buf)); 1389 } 1390 1391 1392 static int 1393 in_line_eoln(MACRO_PROT_ARGS) 1394 { 1395 int c, w, la; 1396 struct mdoc_arg *arg; 1397 char *p; 1398 1399 assert( ! (MDOC_PARSED & mdoc_macros[tok].flags)); 1400 1401 /* Parse macro arguments. */ 1402 1403 for (arg = NULL; ; ) { 1404 la = *pos; 1405 c = mdoc_argv(m, line, tok, &arg, pos, buf); 1406 1407 if (ARGV_WORD == c) { 1408 *pos = la; 1409 break; 1410 } 1411 if (ARGV_EOLN == c) 1412 break; 1413 if (ARGV_ARG == c) 1414 continue; 1415 1416 mdoc_argv_free(arg); 1417 return(0); 1418 } 1419 1420 /* Open element scope. */ 1421 1422 if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) 1423 return(0); 1424 1425 /* Parse argument terms. */ 1426 1427 for (;;) { 1428 la = *pos; 1429 w = mdoc_args(m, line, pos, buf, tok, &p); 1430 1431 if (ARGS_ERROR == w) 1432 return(0); 1433 if (ARGS_EOLN == w) 1434 break; 1435 1436 c = ARGS_QWORD == w ? MDOC_MAX : lookup(tok, p); 1437 1438 if (MDOC_MAX != c) { 1439 if ( ! rew_elem(m, tok)) 1440 return(0); 1441 return(mdoc_macro(m, c, line, la, pos, buf)); 1442 } 1443 1444 if ( ! mdoc_word_alloc(m, line, la, p)) 1445 return(0); 1446 } 1447 1448 /* Close out (no delimiters). */ 1449 1450 return(rew_elem(m, tok)); 1451 } 1452 1453 1454 /* ARGSUSED */ 1455 static int 1456 ctx_synopsis(MACRO_PROT_ARGS) 1457 { 1458 1459 /* If we're not in the SYNOPSIS, go straight to in-line. */ 1460 if (SEC_SYNOPSIS != m->lastsec) 1461 return(in_line(m, tok, line, ppos, pos, buf)); 1462 1463 /* If we're a nested call, same place. */ 1464 if (ppos > 1) 1465 return(in_line(m, tok, line, ppos, pos, buf)); 1466 1467 /* 1468 * XXX: this will open a block scope; however, if later we end 1469 * up formatting the block scope, then child nodes will inherit 1470 * the formatting. Be careful. 1471 */ 1472 1473 return(blk_part_imp(m, tok, line, ppos, pos, buf)); 1474 } 1475 1476 1477 /* ARGSUSED */ 1478 static int 1479 obsolete(MACRO_PROT_ARGS) 1480 { 1481 1482 return(mdoc_pwarn(m, line, ppos, EOBS)); 1483 } 1484 1485 1486 /* 1487 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs. 1488 * They're unusual because they're basically free-form text until a 1489 * macro is encountered. 1490 */ 1491 static int 1492 phrase(struct mdoc *m, int line, int ppos, char *buf) 1493 { 1494 int c, w, la, pos; 1495 char *p; 1496 1497 for (pos = ppos; ; ) { 1498 la = pos; 1499 1500 /* Note: no calling context! */ 1501 w = mdoc_zargs(m, line, &pos, buf, 0, &p); 1502 1503 if (ARGS_ERROR == w) 1504 return(0); 1505 if (ARGS_EOLN == w) 1506 break; 1507 1508 c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(p); 1509 1510 if (MDOC_MAX != c) { 1511 if ( ! mdoc_macro(m, c, line, la, &pos, buf)) 1512 return(0); 1513 return(append_delims(m, line, &pos, buf)); 1514 } 1515 1516 if ( ! mdoc_word_alloc(m, line, la, p)) 1517 return(0); 1518 } 1519 1520 return(1); 1521 } 1522 1523 1524