1 /* $OpenBSD: mdoc_macro.c,v 1.112 2014/11/30 05:28:00 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> 4 * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include <sys/types.h> 19 20 #include <assert.h> 21 #include <ctype.h> 22 #include <stdlib.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include <time.h> 26 27 #include "mdoc.h" 28 #include "mandoc.h" 29 #include "libmdoc.h" 30 #include "libmandoc.h" 31 32 enum rew { /* see rew_dohalt() */ 33 REWIND_NONE, 34 REWIND_THIS, 35 REWIND_MORE, 36 REWIND_FORCE, 37 REWIND_LATER, 38 REWIND_ERROR 39 }; 40 41 static void blk_full(MACRO_PROT_ARGS); 42 static void blk_exp_close(MACRO_PROT_ARGS); 43 static void blk_part_exp(MACRO_PROT_ARGS); 44 static void blk_part_imp(MACRO_PROT_ARGS); 45 static void ctx_synopsis(MACRO_PROT_ARGS); 46 static void in_line_eoln(MACRO_PROT_ARGS); 47 static void in_line_argn(MACRO_PROT_ARGS); 48 static void in_line(MACRO_PROT_ARGS); 49 static void phrase_ta(MACRO_PROT_ARGS); 50 51 static void dword(struct mdoc *, int, int, const char *, 52 enum mdelim, int); 53 static void append_delims(struct mdoc *, int, int *, char *); 54 static enum mdoct lookup(struct mdoc *, enum mdoct, 55 int, int, const char *); 56 static int macro_or_word(MACRO_PROT_ARGS, int); 57 static int make_pending(struct mdoc_node *, enum mdoct, 58 struct mdoc *, int, int); 59 static int parse_rest(struct mdoc *, enum mdoct, 60 int, int *, char *); 61 static enum mdoct rew_alt(enum mdoct); 62 static enum rew rew_dohalt(enum mdoct, enum mdoc_type, 63 const struct mdoc_node *); 64 static void rew_elem(struct mdoc *, enum mdoct); 65 static void rew_last(struct mdoc *, const struct mdoc_node *); 66 static void rew_sub(enum mdoc_type, struct mdoc *, 67 enum mdoct, int, int); 68 69 const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { 70 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */ 71 { in_line_eoln, MDOC_PROLOGUE }, /* Dd */ 72 { in_line_eoln, MDOC_PROLOGUE }, /* Dt */ 73 { in_line_eoln, MDOC_PROLOGUE }, /* Os */ 74 { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */ 75 { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Ss */ 76 { in_line_eoln, 0 }, /* Pp */ 77 { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* D1 */ 78 { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* Dl */ 79 { blk_full, MDOC_EXPLICIT }, /* Bd */ 80 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */ 81 { blk_full, MDOC_EXPLICIT }, /* Bl */ 82 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* El */ 83 { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */ 84 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ 85 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */ 86 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ 87 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */ 88 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ 89 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ 90 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ 91 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ 92 { in_line_eoln, 0 }, /* Ex */ 93 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ 94 { in_line_eoln, 0 }, /* Fd */ 95 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */ 96 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ 97 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ 98 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ic */ 99 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */ 100 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Li */ 101 { blk_full, MDOC_JOIN }, /* Nd */ 102 { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ 103 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */ 104 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ot */ 105 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */ 106 { in_line_eoln, 0 }, /* Rv */ 107 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 108 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ 109 { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ 110 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ 111 { in_line_eoln, MDOC_JOIN }, /* %A */ 112 { in_line_eoln, MDOC_JOIN }, /* %B */ 113 { in_line_eoln, MDOC_JOIN }, /* %D */ 114 { in_line_eoln, MDOC_JOIN }, /* %I */ 115 { in_line_eoln, MDOC_JOIN }, /* %J */ 116 { in_line_eoln, 0 }, /* %N */ 117 { in_line_eoln, MDOC_JOIN }, /* %O */ 118 { in_line_eoln, 0 }, /* %P */ 119 { in_line_eoln, MDOC_JOIN }, /* %R */ 120 { in_line_eoln, MDOC_JOIN }, /* %T */ 121 { in_line_eoln, 0 }, /* %V */ 122 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 123 MDOC_EXPLICIT | MDOC_JOIN }, /* Ac */ 124 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 125 MDOC_EXPLICIT | MDOC_JOIN }, /* Ao */ 126 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Aq */ 127 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */ 128 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 129 MDOC_EXPLICIT | MDOC_JOIN }, /* Bc */ 130 { blk_full, MDOC_EXPLICIT }, /* Bf */ 131 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 132 MDOC_EXPLICIT | MDOC_JOIN }, /* Bo */ 133 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Bq */ 134 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */ 135 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */ 136 { in_line_eoln, 0 }, /* Db */ 137 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 138 MDOC_EXPLICIT | MDOC_JOIN }, /* Dc */ 139 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 140 MDOC_EXPLICIT | MDOC_JOIN }, /* Do */ 141 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Dq */ 142 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ec */ 143 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ef */ 144 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Em */ 145 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ 146 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ 147 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */ 148 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* No */ 149 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | 150 MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */ 151 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ 152 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ 153 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 154 MDOC_EXPLICIT | MDOC_JOIN }, /* Pc */ 155 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */ 156 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 157 MDOC_EXPLICIT | MDOC_JOIN }, /* Po */ 158 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Pq */ 159 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 160 MDOC_EXPLICIT | MDOC_JOIN }, /* Qc */ 161 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ql */ 162 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 163 MDOC_EXPLICIT | MDOC_JOIN }, /* Qo */ 164 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Qq */ 165 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Re */ 166 { blk_full, MDOC_EXPLICIT }, /* Rs */ 167 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 168 MDOC_EXPLICIT | MDOC_JOIN }, /* Sc */ 169 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 170 MDOC_EXPLICIT | MDOC_JOIN }, /* So */ 171 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */ 172 { in_line_argn, 0 }, /* Sm */ 173 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */ 174 { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */ 175 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ 176 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ux */ 177 { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */ 178 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */ 179 { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ 180 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 181 MDOC_EXPLICIT | MDOC_JOIN }, /* Fc */ 182 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 183 MDOC_EXPLICIT | MDOC_JOIN }, /* Oo */ 184 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 185 MDOC_EXPLICIT | MDOC_JOIN }, /* Oc */ 186 { blk_full, MDOC_EXPLICIT }, /* Bk */ 187 { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ek */ 188 { in_line_eoln, 0 }, /* Bt */ 189 { in_line_eoln, 0 }, /* Hf */ 190 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fr */ 191 { in_line_eoln, 0 }, /* Ud */ 192 { in_line, 0 }, /* Lb */ 193 { in_line_eoln, 0 }, /* Lp */ 194 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ 195 { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ 196 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */ 197 { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | 198 MDOC_EXPLICIT | MDOC_JOIN }, /* Bro */ 199 { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | 200 MDOC_EXPLICIT | MDOC_JOIN }, /* Brc */ 201 { in_line_eoln, MDOC_JOIN }, /* %C */ 202 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Es */ 203 { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* En */ 204 { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */ 205 { in_line_eoln, MDOC_JOIN }, /* %Q */ 206 { in_line_eoln, 0 }, /* br */ 207 { in_line_eoln, 0 }, /* sp */ 208 { in_line_eoln, 0 }, /* %U */ 209 { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */ 210 { in_line_eoln, MDOC_PROLOGUE }, /* ll */ 211 }; 212 213 const struct mdoc_macro * const mdoc_macros = __mdoc_macros; 214 215 216 /* 217 * This is called at the end of parsing. It must traverse up the tree, 218 * closing out open [implicit] scopes. Obviously, open explicit scopes 219 * are errors. 220 */ 221 void 222 mdoc_macroend(struct mdoc *mdoc) 223 { 224 struct mdoc_node *n; 225 226 /* Scan for open explicit scopes. */ 227 228 n = mdoc->last->flags & MDOC_VALID ? 229 mdoc->last->parent : mdoc->last; 230 231 for ( ; n; n = n->parent) 232 if (n->type == MDOC_BLOCK && 233 mdoc_macros[n->tok].flags & MDOC_EXPLICIT) 234 mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse, 235 n->line, n->pos, mdoc_macronames[n->tok]); 236 237 /* Rewind to the first. */ 238 239 rew_last(mdoc, mdoc->first); 240 } 241 242 /* 243 * Look up the macro at *p called by "from", 244 * or as a line macro if from == MDOC_MAX. 245 */ 246 static enum mdoct 247 lookup(struct mdoc *mdoc, enum mdoct from, int line, int ppos, const char *p) 248 { 249 enum mdoct res; 250 251 if (from == MDOC_MAX || mdoc_macros[from].flags & MDOC_PARSED) { 252 res = mdoc_hash_find(p); 253 if (res != MDOC_MAX) { 254 if (mdoc_macros[res].flags & MDOC_CALLABLE) 255 return(res); 256 if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll) 257 mandoc_msg(MANDOCERR_MACRO_CALL, 258 mdoc->parse, line, ppos, p); 259 } 260 } 261 return(MDOC_MAX); 262 } 263 264 static void 265 rew_last(struct mdoc *mdoc, const struct mdoc_node *to) 266 { 267 struct mdoc_node *n, *np; 268 269 assert(to); 270 mdoc->next = MDOC_NEXT_SIBLING; 271 while (mdoc->last != to) { 272 /* 273 * Save the parent here, because we may delete the 274 * mdoc->last node in the post-validation phase and reset 275 * it to mdoc->last->parent, causing a step in the closing 276 * out to be lost. 277 */ 278 np = mdoc->last->parent; 279 mdoc_valid_post(mdoc); 280 n = mdoc->last; 281 mdoc->last = np; 282 assert(mdoc->last); 283 mdoc->last->last = n; 284 } 285 mdoc_valid_post(mdoc); 286 } 287 288 /* 289 * For a block closing macro, return the corresponding opening one. 290 * Otherwise, return the macro itself. 291 */ 292 static enum mdoct 293 rew_alt(enum mdoct tok) 294 { 295 switch (tok) { 296 case MDOC_Ac: 297 return(MDOC_Ao); 298 case MDOC_Bc: 299 return(MDOC_Bo); 300 case MDOC_Brc: 301 return(MDOC_Bro); 302 case MDOC_Dc: 303 return(MDOC_Do); 304 case MDOC_Ec: 305 return(MDOC_Eo); 306 case MDOC_Ed: 307 return(MDOC_Bd); 308 case MDOC_Ef: 309 return(MDOC_Bf); 310 case MDOC_Ek: 311 return(MDOC_Bk); 312 case MDOC_El: 313 return(MDOC_Bl); 314 case MDOC_Fc: 315 return(MDOC_Fo); 316 case MDOC_Oc: 317 return(MDOC_Oo); 318 case MDOC_Pc: 319 return(MDOC_Po); 320 case MDOC_Qc: 321 return(MDOC_Qo); 322 case MDOC_Re: 323 return(MDOC_Rs); 324 case MDOC_Sc: 325 return(MDOC_So); 326 case MDOC_Xc: 327 return(MDOC_Xo); 328 default: 329 return(tok); 330 } 331 /* NOTREACHED */ 332 } 333 334 /* 335 * Rewinding to tok, how do we have to handle *p? 336 * REWIND_NONE: *p would delimit tok, but no tok scope is open 337 * inside *p, so there is no need to rewind anything at all. 338 * REWIND_THIS: *p matches tok, so rewind *p and nothing else. 339 * REWIND_MORE: *p is implicit, rewind it and keep searching for tok. 340 * REWIND_FORCE: *p is explicit, but tok is full, force rewinding *p. 341 * REWIND_LATER: *p is explicit and still open, postpone rewinding. 342 * REWIND_ERROR: No tok block is open at all. 343 */ 344 static enum rew 345 rew_dohalt(enum mdoct tok, enum mdoc_type type, 346 const struct mdoc_node *p) 347 { 348 349 /* 350 * No matching token, no delimiting block, no broken block. 351 * This can happen when full implicit macros are called for 352 * the first time but try to rewind their previous 353 * instance anyway. 354 */ 355 if (MDOC_ROOT == p->type) 356 return(MDOC_BLOCK == type && 357 MDOC_EXPLICIT & mdoc_macros[tok].flags ? 358 REWIND_ERROR : REWIND_NONE); 359 360 /* 361 * When starting to rewind, skip plain text 362 * and nodes that have already been rewound. 363 */ 364 if (MDOC_TEXT == p->type || MDOC_VALID & p->flags) 365 return(REWIND_MORE); 366 367 /* 368 * The easiest case: Found a matching token. 369 * This applies to both blocks and elements. 370 */ 371 tok = rew_alt(tok); 372 if (tok == p->tok) 373 return(p->end ? REWIND_NONE : 374 type == p->type ? REWIND_THIS : REWIND_MORE); 375 376 /* 377 * While elements do require rewinding for themselves, 378 * they never affect rewinding of other nodes. 379 */ 380 if (MDOC_ELEM == p->type) 381 return(REWIND_MORE); 382 383 /* 384 * Blocks delimited by our target token get REWIND_MORE. 385 * Blocks delimiting our target token get REWIND_NONE. 386 */ 387 switch (tok) { 388 case MDOC_Bl: 389 if (MDOC_It == p->tok) 390 return(REWIND_MORE); 391 break; 392 case MDOC_It: 393 if (MDOC_BODY == p->type && MDOC_Bl == p->tok) 394 return(REWIND_NONE); 395 break; 396 /* 397 * XXX Badly nested block handling still fails badly 398 * when one block is breaking two blocks of the same type. 399 * This is an incomplete and extremely ugly workaround, 400 * required to let the OpenBSD tree build. 401 */ 402 case MDOC_Oo: 403 if (MDOC_Op == p->tok) 404 return(REWIND_MORE); 405 break; 406 case MDOC_Nm: 407 return(REWIND_NONE); 408 case MDOC_Nd: 409 /* FALLTHROUGH */ 410 case MDOC_Ss: 411 if (MDOC_BODY == p->type && MDOC_Sh == p->tok) 412 return(REWIND_NONE); 413 /* FALLTHROUGH */ 414 case MDOC_Sh: 415 if (MDOC_ROOT == p->parent->type) 416 return(REWIND_THIS); 417 if (MDOC_Nd == p->tok || MDOC_Ss == p->tok || 418 MDOC_Sh == p->tok) 419 return(REWIND_MORE); 420 break; 421 default: 422 break; 423 } 424 425 /* 426 * Default block rewinding rules. 427 * In particular, always skip block end markers, 428 * and let all blocks rewind Nm children. 429 * Do not warn again when closing a block, 430 * since closing the body already warned. 431 */ 432 if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok || 433 MDOC_BLOCK == type || (MDOC_BLOCK == p->type && 434 ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))) 435 return(REWIND_MORE); 436 437 /* 438 * By default, closing out full blocks 439 * forces closing of broken explicit blocks, 440 * while closing out partial blocks 441 * allows delayed rewinding by default. 442 */ 443 return (&blk_full == mdoc_macros[tok].fp ? 444 REWIND_FORCE : REWIND_LATER); 445 } 446 447 static void 448 rew_elem(struct mdoc *mdoc, enum mdoct tok) 449 { 450 struct mdoc_node *n; 451 452 n = mdoc->last; 453 if (MDOC_ELEM != n->type) 454 n = n->parent; 455 assert(MDOC_ELEM == n->type); 456 assert(tok == n->tok); 457 rew_last(mdoc, n); 458 } 459 460 /* 461 * We are trying to close a block identified by tok, 462 * but the child block *broken is still open. 463 * Thus, postpone closing the tok block 464 * until the rew_sub call closing *broken. 465 */ 466 static int 467 make_pending(struct mdoc_node *broken, enum mdoct tok, 468 struct mdoc *mdoc, int line, int ppos) 469 { 470 struct mdoc_node *breaker; 471 472 /* 473 * Iterate backwards, searching for the block matching tok, 474 * that is, the block breaking the *broken block. 475 */ 476 for (breaker = broken->parent; breaker; breaker = breaker->parent) { 477 478 /* 479 * If the *broken block had already been broken before 480 * and we encounter its breaker, make the tok block 481 * pending on the inner breaker. 482 * Graphically, "[A breaker=[B broken=[C->B B] tok=A] C]" 483 * becomes "[A broken=[B [C->B B] tok=A] C]" 484 * and finally "[A [B->A [C->B B] A] C]". 485 */ 486 if (breaker == broken->pending) { 487 broken = breaker; 488 continue; 489 } 490 491 if (REWIND_THIS != rew_dohalt(tok, MDOC_BLOCK, breaker)) 492 continue; 493 if (MDOC_BODY == broken->type) 494 broken = broken->parent; 495 496 /* 497 * Found the breaker. 498 * If another, outer breaker is already pending on 499 * the *broken block, we must not clobber the link 500 * to the outer breaker, but make it pending on the 501 * new, now inner breaker. 502 * Graphically, "[A breaker=[B broken=[C->A A] tok=B] C]" 503 * becomes "[A breaker=[B->A broken=[C A] tok=B] C]" 504 * and finally "[A [B->A [C->B A] B] C]". 505 */ 506 if (broken->pending) { 507 struct mdoc_node *taker; 508 509 /* 510 * If the breaker had also been broken before, 511 * it cannot take on the outer breaker itself, 512 * but must hand it on to its own breakers. 513 * Graphically, this is the following situation: 514 * "[A [B breaker=[C->B B] broken=[D->A A] tok=C] D]" 515 * "[A taker=[B->A breaker=[C->B B] [D->C A] C] D]" 516 */ 517 taker = breaker; 518 while (taker->pending) 519 taker = taker->pending; 520 taker->pending = broken->pending; 521 } 522 broken->pending = breaker; 523 mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, 524 "%s breaks %s", mdoc_macronames[tok], 525 mdoc_macronames[broken->tok]); 526 return(1); 527 } 528 529 /* 530 * Found no matching block for tok. 531 * Are you trying to close a block that is not open? 532 */ 533 return(0); 534 } 535 536 static void 537 rew_sub(enum mdoc_type t, struct mdoc *mdoc, 538 enum mdoct tok, int line, int ppos) 539 { 540 struct mdoc_node *n; 541 542 n = mdoc->last; 543 while (n) { 544 switch (rew_dohalt(tok, t, n)) { 545 case REWIND_NONE: 546 return; 547 case REWIND_THIS: 548 n->lastline = line - 549 (mdoc->flags & MDOC_NEWLINE && 550 ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)); 551 break; 552 case REWIND_FORCE: 553 mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, 554 line, ppos, "%s breaks %s", 555 mdoc_macronames[tok], 556 mdoc_macronames[n->tok]); 557 /* FALLTHROUGH */ 558 case REWIND_MORE: 559 n->lastline = line - 560 (mdoc->flags & MDOC_NEWLINE ? 1 : 0); 561 n = n->parent; 562 continue; 563 case REWIND_LATER: 564 if (make_pending(n, tok, mdoc, line, ppos) || 565 t != MDOC_BLOCK) 566 return; 567 /* FALLTHROUGH */ 568 case REWIND_ERROR: 569 mandoc_msg(MANDOCERR_BLK_NOTOPEN, 570 mdoc->parse, line, ppos, 571 mdoc_macronames[tok]); 572 return; 573 } 574 break; 575 } 576 assert(n); 577 rew_last(mdoc, n); 578 579 /* 580 * The current block extends an enclosing block. 581 * Now that the current block ends, close the enclosing block, too. 582 */ 583 while ((n = n->pending) != NULL) { 584 rew_last(mdoc, n); 585 if (n->type == MDOC_HEAD) 586 mdoc_body_alloc(mdoc, n->line, n->pos, n->tok); 587 } 588 } 589 590 /* 591 * Allocate a word and check whether it's punctuation or not. 592 * Punctuation consists of those tokens found in mdoc_isdelim(). 593 */ 594 static void 595 dword(struct mdoc *mdoc, int line, int col, const char *p, 596 enum mdelim d, int may_append) 597 { 598 599 if (d == DELIM_MAX) 600 d = mdoc_isdelim(p); 601 602 if (may_append && 603 ! (mdoc->flags & (MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF)) && 604 d == DELIM_NONE && mdoc->last->type == MDOC_TEXT && 605 mdoc_isdelim(mdoc->last->string) == DELIM_NONE) { 606 mdoc_word_append(mdoc, p); 607 return; 608 } 609 610 mdoc_word_alloc(mdoc, line, col, p); 611 612 /* 613 * If the word consists of a bare delimiter, 614 * flag the new node accordingly, 615 * unless doing so was vetoed by the invoking macro. 616 * Always clear the veto, it is only valid for one word. 617 */ 618 619 if (d == DELIM_OPEN) 620 mdoc->last->flags |= MDOC_DELIMO; 621 else if (d == DELIM_CLOSE && 622 ! (mdoc->flags & MDOC_NODELIMC) && 623 mdoc->last->parent->tok != MDOC_Fd) 624 mdoc->last->flags |= MDOC_DELIMC; 625 mdoc->flags &= ~MDOC_NODELIMC; 626 } 627 628 static void 629 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf) 630 { 631 char *p; 632 int la; 633 634 if (buf[*pos] == '\0') 635 return; 636 637 for (;;) { 638 la = *pos; 639 if (mdoc_args(mdoc, line, pos, buf, MDOC_MAX, &p) == ARGS_EOLN) 640 break; 641 dword(mdoc, line, la, p, DELIM_MAX, 1); 642 643 /* 644 * If we encounter end-of-sentence symbols, then trigger 645 * the double-space. 646 * 647 * XXX: it's easy to allow this to propagate outward to 648 * the last symbol, such that `. )' will cause the 649 * correct double-spacing. However, (1) groff isn't 650 * smart enough to do this and (2) it would require 651 * knowing which symbols break this behaviour, for 652 * example, `. ;' shouldn't propagate the double-space. 653 */ 654 655 if (mandoc_eos(p, strlen(p))) 656 mdoc->last->flags |= MDOC_EOS; 657 } 658 } 659 660 /* 661 * Parse one word. 662 * If it is a macro, call it and return 1. 663 * Otherwise, allocate it and return 0. 664 */ 665 static int 666 macro_or_word(MACRO_PROT_ARGS, int parsed) 667 { 668 char *p; 669 enum mdoct ntok; 670 671 p = buf + ppos; 672 ntok = MDOC_MAX; 673 if (mdoc->flags & MDOC_PHRASELIT) 674 /* nothing */; 675 else if (*p == '"') 676 p++; 677 else if (parsed) 678 ntok = lookup(mdoc, tok, line, ppos, p); 679 680 if (ntok == MDOC_MAX) { 681 dword(mdoc, line, ppos, p, DELIM_MAX, tok == MDOC_MAX || 682 mdoc_macros[tok].flags & MDOC_JOIN); 683 return(0); 684 } else { 685 if (mdoc_macros[tok].fp == in_line_eoln) 686 rew_elem(mdoc, tok); 687 mdoc_macro(mdoc, ntok, line, ppos, pos, buf); 688 if (tok == MDOC_MAX) 689 append_delims(mdoc, line, pos, buf); 690 return(1); 691 } 692 } 693 694 /* 695 * Close out block partial/full explicit. 696 */ 697 static void 698 blk_exp_close(MACRO_PROT_ARGS) 699 { 700 struct mdoc_node *body; /* Our own body. */ 701 struct mdoc_node *endbody; /* Our own end marker. */ 702 struct mdoc_node *later; /* A sub-block starting later. */ 703 struct mdoc_node *n; /* For searching backwards. */ 704 705 int j, lastarg, maxargs, flushed, nl; 706 enum margserr ac; 707 enum mdoct atok, ntok; 708 char *p; 709 710 nl = MDOC_NEWLINE & mdoc->flags; 711 712 switch (tok) { 713 case MDOC_Ec: 714 maxargs = 1; 715 break; 716 case MDOC_Ek: 717 mdoc->flags &= ~MDOC_KEEP; 718 /* FALLTHROUGH */ 719 default: 720 maxargs = 0; 721 break; 722 } 723 724 /* 725 * Search backwards for beginnings of blocks, 726 * both of our own and of pending sub-blocks. 727 */ 728 729 atok = rew_alt(tok); 730 body = endbody = later = NULL; 731 for (n = mdoc->last; n; n = n->parent) { 732 if (n->flags & MDOC_VALID) 733 continue; 734 735 /* Remember the start of our own body. */ 736 737 if (n->type == MDOC_BODY && atok == n->tok) { 738 if (n->end == ENDBODY_NOT) 739 body = n; 740 continue; 741 } 742 743 if (n->type != MDOC_BLOCK || n->tok == MDOC_Nm) 744 continue; 745 if (atok == n->tok) { 746 assert(body); 747 748 /* 749 * Found the start of our own block. 750 * When there is no pending sub block, 751 * just proceed to closing out. 752 */ 753 754 if (later == NULL) 755 break; 756 757 /* 758 * When there is a pending sub block, 759 * postpone closing out the current block 760 * until the rew_sub() closing out the sub-block. 761 */ 762 763 make_pending(later, tok, mdoc, line, ppos); 764 765 /* 766 * Mark the place where the formatting - but not 767 * the scope - of the current block ends. 768 */ 769 770 mdoc_endbody_alloc(mdoc, line, ppos, 771 atok, body, ENDBODY_SPACE); 772 773 /* 774 * If a block closing macro taking arguments 775 * breaks another block, put the arguments 776 * into the end marker and remeber the 777 * end marker in order to close it out. 778 */ 779 780 if (maxargs) { 781 endbody = mdoc->last; 782 mdoc->next = MDOC_NEXT_CHILD; 783 } 784 break; 785 } 786 787 /* 788 * When finding an open sub block, remember the last 789 * open explicit block, or, in case there are only 790 * implicit ones, the first open implicit block. 791 */ 792 793 if (later && 794 mdoc_macros[later->tok].flags & MDOC_EXPLICIT) 795 continue; 796 if (n->tok != MDOC_It) 797 later = n; 798 } 799 rew_sub(MDOC_BODY, mdoc, tok, line, ppos); 800 801 if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) { 802 if (buf[*pos] != '\0') 803 mandoc_vmsg(MANDOCERR_ARG_SKIP, 804 mdoc->parse, line, ppos, 805 "%s %s", mdoc_macronames[tok], 806 buf + *pos); 807 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos); 808 return; 809 } 810 811 if (maxargs && endbody == NULL) { 812 if (n == NULL) { 813 /* 814 * Stray .Ec without previous .Eo: 815 * Break the output line, ignore any arguments. 816 */ 817 mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL); 818 rew_elem(mdoc, MDOC_br); 819 } else 820 mdoc_tail_alloc(mdoc, line, ppos, atok); 821 } 822 823 flushed = n == NULL; 824 for (j = 0; ; j++) { 825 lastarg = *pos; 826 827 if (j == maxargs && ! flushed) { 828 if (endbody == NULL) 829 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos); 830 else 831 rew_last(mdoc, endbody); 832 flushed = 1; 833 } 834 835 ac = mdoc_args(mdoc, line, pos, buf, tok, &p); 836 if (ac == ARGS_PUNCT || ac == ARGS_EOLN) 837 break; 838 839 ntok = ac == ARGS_QWORD ? MDOC_MAX : 840 lookup(mdoc, tok, line, lastarg, p); 841 842 if (ntok == MDOC_MAX) { 843 dword(mdoc, line, lastarg, p, DELIM_MAX, 844 MDOC_JOIN & mdoc_macros[tok].flags); 845 continue; 846 } 847 848 if ( ! flushed) { 849 if (endbody == NULL) 850 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos); 851 else 852 rew_last(mdoc, endbody); 853 flushed = 1; 854 } 855 mdoc->flags &= ~MDOC_NEWLINE; 856 mdoc_macro(mdoc, ntok, line, lastarg, pos, buf); 857 break; 858 } 859 860 if ( ! flushed) { 861 if (endbody == NULL) 862 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos); 863 else 864 rew_last(mdoc, endbody); 865 } 866 if (nl) 867 append_delims(mdoc, line, pos, buf); 868 } 869 870 static void 871 in_line(MACRO_PROT_ARGS) 872 { 873 int la, scope, cnt, firstarg, mayopen, nc, nl; 874 enum mdoct ntok; 875 enum margserr ac; 876 enum mdelim d; 877 struct mdoc_arg *arg; 878 char *p; 879 880 nl = MDOC_NEWLINE & mdoc->flags; 881 882 /* 883 * Whether we allow ignored elements (those without content, 884 * usually because of reserved words) to squeak by. 885 */ 886 887 switch (tok) { 888 case MDOC_An: 889 /* FALLTHROUGH */ 890 case MDOC_Ar: 891 /* FALLTHROUGH */ 892 case MDOC_Fl: 893 /* FALLTHROUGH */ 894 case MDOC_Mt: 895 /* FALLTHROUGH */ 896 case MDOC_Nm: 897 /* FALLTHROUGH */ 898 case MDOC_Pa: 899 nc = 1; 900 break; 901 default: 902 nc = 0; 903 break; 904 } 905 906 mdoc_argv(mdoc, line, tok, &arg, pos, buf); 907 908 d = DELIM_NONE; 909 firstarg = 1; 910 mayopen = 1; 911 for (cnt = scope = 0;; ) { 912 la = *pos; 913 ac = mdoc_args(mdoc, line, pos, buf, tok, &p); 914 915 /* 916 * At the end of a macro line, 917 * opening delimiters do not suppress spacing. 918 */ 919 920 if (ac == ARGS_EOLN) { 921 if (d == DELIM_OPEN) 922 mdoc->last->flags &= ~MDOC_DELIMO; 923 break; 924 } 925 926 /* 927 * The rest of the macro line is only punctuation, 928 * to be handled by append_delims(). 929 * If there were no other arguments, 930 * do not allow the first one to suppress spacing, 931 * even if it turns out to be a closing one. 932 */ 933 934 if (ac == ARGS_PUNCT) { 935 if (cnt == 0 && nc == 0) 936 mdoc->flags |= MDOC_NODELIMC; 937 break; 938 } 939 940 ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ? 941 MDOC_MAX : lookup(mdoc, tok, line, la, p); 942 943 /* 944 * In this case, we've located a submacro and must 945 * execute it. Close out scope, if open. If no 946 * elements have been generated, either create one (nc) 947 * or raise a warning. 948 */ 949 950 if (ntok != MDOC_MAX) { 951 if (scope) 952 rew_elem(mdoc, tok); 953 if (nc && ! cnt) { 954 mdoc_elem_alloc(mdoc, line, ppos, tok, arg); 955 rew_last(mdoc, mdoc->last); 956 } else if ( ! nc && ! cnt) { 957 mdoc_argv_free(arg); 958 mandoc_msg(MANDOCERR_MACRO_EMPTY, 959 mdoc->parse, line, ppos, 960 mdoc_macronames[tok]); 961 } 962 mdoc_macro(mdoc, ntok, line, la, pos, buf); 963 if (nl) 964 append_delims(mdoc, line, pos, buf); 965 return; 966 } 967 968 /* 969 * Non-quote-enclosed punctuation. Set up our scope, if 970 * a word; rewind the scope, if a delimiter; then append 971 * the word. 972 */ 973 974 d = ac == ARGS_QWORD ? DELIM_NONE : mdoc_isdelim(p); 975 976 if (DELIM_NONE != d) { 977 /* 978 * If we encounter closing punctuation, no word 979 * has been emitted, no scope is open, and we're 980 * allowed to have an empty element, then start 981 * a new scope. 982 */ 983 if ((d == DELIM_CLOSE || 984 (d == DELIM_MIDDLE && tok == MDOC_Fl)) && 985 !cnt && !scope && nc && mayopen) { 986 mdoc_elem_alloc(mdoc, line, ppos, tok, arg); 987 scope = 1; 988 cnt++; 989 if (tok == MDOC_Nm) 990 mayopen = 0; 991 } 992 /* 993 * Close out our scope, if one is open, before 994 * any punctuation. 995 */ 996 if (scope) 997 rew_elem(mdoc, tok); 998 scope = 0; 999 if (tok == MDOC_Fn) 1000 mayopen = 0; 1001 } else if (mayopen && !scope) { 1002 mdoc_elem_alloc(mdoc, line, ppos, tok, arg); 1003 scope = 1; 1004 cnt++; 1005 } 1006 1007 dword(mdoc, line, la, p, d, 1008 MDOC_JOIN & mdoc_macros[tok].flags); 1009 1010 /* 1011 * If the first argument is a closing delimiter, 1012 * do not suppress spacing before it. 1013 */ 1014 1015 if (firstarg && d == DELIM_CLOSE && !nc) 1016 mdoc->last->flags &= ~MDOC_DELIMC; 1017 firstarg = 0; 1018 1019 /* 1020 * `Fl' macros have their scope re-opened with each new 1021 * word so that the `-' can be added to each one without 1022 * having to parse out spaces. 1023 */ 1024 if (scope && tok == MDOC_Fl) { 1025 rew_elem(mdoc, tok); 1026 scope = 0; 1027 } 1028 } 1029 1030 if (scope) 1031 rew_elem(mdoc, tok); 1032 1033 /* 1034 * If no elements have been collected and we're allowed to have 1035 * empties (nc), open a scope and close it out. Otherwise, 1036 * raise a warning. 1037 */ 1038 1039 if ( ! cnt) { 1040 if (nc) { 1041 mdoc_elem_alloc(mdoc, line, ppos, tok, arg); 1042 rew_last(mdoc, mdoc->last); 1043 } else { 1044 mdoc_argv_free(arg); 1045 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, 1046 line, ppos, mdoc_macronames[tok]); 1047 } 1048 } 1049 if (nl) 1050 append_delims(mdoc, line, pos, buf); 1051 } 1052 1053 static void 1054 blk_full(MACRO_PROT_ARGS) 1055 { 1056 int la, nl, parsed; 1057 struct mdoc_arg *arg; 1058 struct mdoc_node *head; /* save of head macro */ 1059 struct mdoc_node *body; /* save of body macro */ 1060 struct mdoc_node *n; 1061 enum margserr ac, lac; 1062 char *p; 1063 1064 nl = MDOC_NEWLINE & mdoc->flags; 1065 1066 /* Skip items outside lists. */ 1067 1068 if (tok == MDOC_It) { 1069 for (n = mdoc->last; n; n = n->parent) 1070 if (n->tok == MDOC_Bl && 1071 ! (n->flags & MDOC_VALID)) 1072 break; 1073 if (n == NULL) { 1074 mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse, 1075 line, ppos, "It %s", buf + *pos); 1076 mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL); 1077 rew_elem(mdoc, MDOC_br); 1078 return; 1079 } 1080 } 1081 1082 /* Close out prior implicit scope. */ 1083 1084 if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) { 1085 rew_sub(MDOC_BODY, mdoc, tok, line, ppos); 1086 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos); 1087 } 1088 1089 /* 1090 * This routine accommodates implicitly- and explicitly-scoped 1091 * macro openings. Implicit ones first close out prior scope 1092 * (seen above). Delay opening the head until necessary to 1093 * allow leading punctuation to print. Special consideration 1094 * for `It -column', which has phrase-part syntax instead of 1095 * regular child nodes. 1096 */ 1097 1098 mdoc_argv(mdoc, line, tok, &arg, pos, buf); 1099 mdoc_block_alloc(mdoc, line, ppos, tok, arg); 1100 head = body = NULL; 1101 1102 /* 1103 * Exception: Heads of `It' macros in `-diag' lists are not 1104 * parsed, even though `It' macros in general are parsed. 1105 */ 1106 1107 parsed = tok != MDOC_It || 1108 mdoc->last->parent->tok != MDOC_Bl || 1109 mdoc->last->parent->norm->Bl.type != LIST_diag; 1110 1111 /* 1112 * The `Nd' macro has all arguments in its body: it's a hybrid 1113 * of block partial-explicit and full-implicit. Stupid. 1114 */ 1115 1116 if (tok == MDOC_Nd) { 1117 head = mdoc_head_alloc(mdoc, line, ppos, tok); 1118 rew_sub(MDOC_HEAD, mdoc, tok, line, ppos); 1119 body = mdoc_body_alloc(mdoc, line, ppos, tok); 1120 } 1121 1122 if (tok == MDOC_Bk) 1123 mdoc->flags |= MDOC_KEEP; 1124 1125 ac = ARGS_PEND; 1126 for (;;) { 1127 la = *pos; 1128 lac = ac; 1129 ac = mdoc_args(mdoc, line, pos, buf, tok, &p); 1130 if (ac == ARGS_PUNCT) 1131 break; 1132 if (ac == ARGS_EOLN) { 1133 if (lac != ARGS_PPHRASE && lac != ARGS_PHRASE) 1134 break; 1135 /* 1136 * This is necessary: if the last token on a 1137 * line is a `Ta' or tab, then we'll get 1138 * ARGS_EOLN, so we must be smart enough to 1139 * reopen our scope if the last parse was a 1140 * phrase or partial phrase. 1141 */ 1142 rew_sub(MDOC_BODY, mdoc, tok, line, ppos); 1143 body = mdoc_body_alloc(mdoc, line, ppos, tok); 1144 break; 1145 } 1146 1147 /* 1148 * Emit leading punctuation (i.e., punctuation before 1149 * the MDOC_HEAD) for non-phrase types. 1150 */ 1151 1152 if (head == NULL && 1153 ac != ARGS_PEND && 1154 ac != ARGS_PHRASE && 1155 ac != ARGS_PPHRASE && 1156 ac != ARGS_QWORD && 1157 mdoc_isdelim(p) == DELIM_OPEN) { 1158 dword(mdoc, line, la, p, DELIM_OPEN, 0); 1159 continue; 1160 } 1161 1162 /* Open a head if one hasn't been opened. */ 1163 1164 if (head == NULL) 1165 head = mdoc_head_alloc(mdoc, line, ppos, tok); 1166 1167 if (ac == ARGS_PHRASE || 1168 ac == ARGS_PEND || 1169 ac == ARGS_PPHRASE) { 1170 1171 /* 1172 * If we haven't opened a body yet, rewind the 1173 * head; if we have, rewind that instead. 1174 */ 1175 1176 rew_sub(body ? MDOC_BODY : MDOC_HEAD, 1177 mdoc, tok, line, ppos); 1178 body = mdoc_body_alloc(mdoc, line, ppos, tok); 1179 1180 /* 1181 * Process phrases: set whether we're in a 1182 * partial-phrase (this effects line handling) 1183 * then call down into the phrase parser. 1184 */ 1185 1186 if (ac == ARGS_PPHRASE) 1187 mdoc->flags |= MDOC_PPHRASE; 1188 if (ac == ARGS_PEND && lac == ARGS_PPHRASE) 1189 mdoc->flags |= MDOC_PPHRASE; 1190 parse_rest(mdoc, MDOC_MAX, line, &la, buf); 1191 mdoc->flags &= ~MDOC_PPHRASE; 1192 continue; 1193 } 1194 1195 if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed)) 1196 break; 1197 } 1198 1199 if (head == NULL) 1200 head = mdoc_head_alloc(mdoc, line, ppos, tok); 1201 if (nl) 1202 append_delims(mdoc, line, pos, buf); 1203 if (body != NULL) 1204 goto out; 1205 1206 /* 1207 * If there is an open (i.e., unvalidated) sub-block requiring 1208 * explicit close-out, postpone switching the current block from 1209 * head to body until the rew_sub() call closing out that 1210 * sub-block. 1211 */ 1212 for (n = mdoc->last; n && n != head; n = n->parent) { 1213 if (n->type == MDOC_BLOCK && 1214 mdoc_macros[n->tok].flags & MDOC_EXPLICIT && 1215 ! (n->flags & MDOC_VALID)) { 1216 n->pending = head; 1217 return; 1218 } 1219 } 1220 1221 /* Close out scopes to remain in a consistent state. */ 1222 1223 rew_sub(MDOC_HEAD, mdoc, tok, line, ppos); 1224 mdoc_body_alloc(mdoc, line, ppos, tok); 1225 out: 1226 if (mdoc->flags & MDOC_FREECOL) { 1227 rew_sub(MDOC_BODY, mdoc, tok, line, ppos); 1228 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos); 1229 mdoc->flags &= ~MDOC_FREECOL; 1230 } 1231 } 1232 1233 static void 1234 blk_part_imp(MACRO_PROT_ARGS) 1235 { 1236 int la, nl; 1237 enum margserr ac; 1238 char *p; 1239 struct mdoc_node *blk; /* saved block context */ 1240 struct mdoc_node *body; /* saved body context */ 1241 struct mdoc_node *n; 1242 1243 nl = MDOC_NEWLINE & mdoc->flags; 1244 1245 /* 1246 * A macro that spans to the end of the line. This is generally 1247 * (but not necessarily) called as the first macro. The block 1248 * has a head as the immediate child, which is always empty, 1249 * followed by zero or more opening punctuation nodes, then the 1250 * body (which may be empty, depending on the macro), then zero 1251 * or more closing punctuation nodes. 1252 */ 1253 1254 blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL); 1255 mdoc_head_alloc(mdoc, line, ppos, tok); 1256 rew_sub(MDOC_HEAD, mdoc, tok, line, ppos); 1257 1258 /* 1259 * Open the body scope "on-demand", that is, after we've 1260 * processed all our the leading delimiters (open parenthesis, 1261 * etc.). 1262 */ 1263 1264 for (body = NULL; ; ) { 1265 la = *pos; 1266 ac = mdoc_args(mdoc, line, pos, buf, tok, &p); 1267 if (ac == ARGS_EOLN || ac == ARGS_PUNCT) 1268 break; 1269 1270 if (body == NULL && ac != ARGS_QWORD && 1271 mdoc_isdelim(p) == DELIM_OPEN) { 1272 dword(mdoc, line, la, p, DELIM_OPEN, 0); 1273 continue; 1274 } 1275 1276 if (body == NULL) 1277 body = mdoc_body_alloc(mdoc, line, ppos, tok); 1278 1279 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) 1280 break; 1281 } 1282 if (body == NULL) 1283 body = mdoc_body_alloc(mdoc, line, ppos, tok); 1284 1285 /* 1286 * If there is an open sub-block requiring explicit close-out, 1287 * postpone closing out the current block 1288 * until the rew_sub() call closing out the sub-block. 1289 */ 1290 1291 for (n = mdoc->last; n && n != body && n != blk->parent; 1292 n = n->parent) { 1293 if (n->type == MDOC_BLOCK && 1294 mdoc_macros[n->tok].flags & MDOC_EXPLICIT && 1295 ! (n->flags & MDOC_VALID)) { 1296 make_pending(n, tok, mdoc, line, ppos); 1297 mdoc_endbody_alloc(mdoc, line, ppos, 1298 tok, body, ENDBODY_NOSPACE); 1299 return; 1300 } 1301 } 1302 assert(n == body); 1303 rew_sub(MDOC_BODY, mdoc, tok, line, ppos); 1304 if (nl) 1305 append_delims(mdoc, line, pos, buf); 1306 rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos); 1307 1308 /* Move trailing .Ns out of scope. */ 1309 1310 for (n = body->child; n && n->next; n = n->next) 1311 /* Do nothing. */ ; 1312 if (n && n->tok == MDOC_Ns) 1313 mdoc_node_relink(mdoc, n); 1314 } 1315 1316 static void 1317 blk_part_exp(MACRO_PROT_ARGS) 1318 { 1319 int la, nl; 1320 enum margserr ac; 1321 struct mdoc_node *head; /* keep track of head */ 1322 struct mdoc_node *body; /* keep track of body */ 1323 char *p; 1324 1325 nl = MDOC_NEWLINE & mdoc->flags; 1326 1327 /* 1328 * The opening of an explicit macro having zero or more leading 1329 * punctuation nodes; a head with optional single element (the 1330 * case of `Eo'); and a body that may be empty. 1331 */ 1332 1333 mdoc_block_alloc(mdoc, line, ppos, tok, NULL); 1334 for (head = body = NULL; ; ) { 1335 la = *pos; 1336 ac = mdoc_args(mdoc, line, pos, buf, tok, &p); 1337 if (ac == ARGS_PUNCT || ac == ARGS_EOLN) 1338 break; 1339 1340 /* Flush out leading punctuation. */ 1341 1342 if (head == NULL && ac != ARGS_QWORD && 1343 mdoc_isdelim(p) == DELIM_OPEN) { 1344 assert(NULL == body); 1345 dword(mdoc, line, la, p, DELIM_OPEN, 0); 1346 continue; 1347 } 1348 1349 if (head == NULL) { 1350 assert(body == NULL); 1351 head = mdoc_head_alloc(mdoc, line, ppos, tok); 1352 } 1353 1354 /* 1355 * `Eo' gobbles any data into the head, but most other 1356 * macros just immediately close out and begin the body. 1357 */ 1358 1359 if (body == NULL) { 1360 assert(head); 1361 /* No check whether it's a macro! */ 1362 if (tok == MDOC_Eo) 1363 dword(mdoc, line, la, p, DELIM_MAX, 0); 1364 rew_sub(MDOC_HEAD, mdoc, tok, line, ppos); 1365 body = mdoc_body_alloc(mdoc, line, ppos, tok); 1366 if (tok == MDOC_Eo) 1367 continue; 1368 } 1369 assert(head != NULL && body != NULL); 1370 1371 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) 1372 break; 1373 } 1374 1375 /* Clean-up to leave in a consistent state. */ 1376 1377 if (head == NULL) 1378 mdoc_head_alloc(mdoc, line, ppos, tok); 1379 1380 if (body == NULL) { 1381 rew_sub(MDOC_HEAD, mdoc, tok, line, ppos); 1382 mdoc_body_alloc(mdoc, line, ppos, tok); 1383 } 1384 if (nl) 1385 append_delims(mdoc, line, pos, buf); 1386 } 1387 1388 static void 1389 in_line_argn(MACRO_PROT_ARGS) 1390 { 1391 int la, flushed, j, maxargs, nl; 1392 enum margserr ac; 1393 struct mdoc_arg *arg; 1394 char *p; 1395 enum mdoct ntok; 1396 1397 nl = mdoc->flags & MDOC_NEWLINE; 1398 1399 /* 1400 * A line macro that has a fixed number of arguments (maxargs). 1401 * Only open the scope once the first non-leading-punctuation is 1402 * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then 1403 * keep it open until the maximum number of arguments are 1404 * exhausted. 1405 */ 1406 1407 switch (tok) { 1408 case MDOC_Ap: 1409 /* FALLTHROUGH */ 1410 case MDOC_Ns: 1411 /* FALLTHROUGH */ 1412 case MDOC_Ux: 1413 maxargs = 0; 1414 break; 1415 case MDOC_Bx: 1416 /* FALLTHROUGH */ 1417 case MDOC_Es: 1418 /* FALLTHROUGH */ 1419 case MDOC_Xr: 1420 maxargs = 2; 1421 break; 1422 default: 1423 maxargs = 1; 1424 break; 1425 } 1426 1427 mdoc_argv(mdoc, line, tok, &arg, pos, buf); 1428 1429 p = NULL; 1430 flushed = j = 0; 1431 for (;;) { 1432 la = *pos; 1433 ac = mdoc_args(mdoc, line, pos, buf, tok, &p); 1434 if (ac == ARGS_PUNCT || ac == ARGS_EOLN) { 1435 if (j < 2 && tok == MDOC_Pf) 1436 mandoc_vmsg(MANDOCERR_PF_SKIP, 1437 mdoc->parse, line, ppos, "Pf %s", 1438 p == NULL ? "at eol" : p); 1439 break; 1440 } 1441 1442 if ( ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) && 1443 ac != ARGS_QWORD && j == 0 && 1444 mdoc_isdelim(p) == DELIM_OPEN) { 1445 dword(mdoc, line, la, p, DELIM_OPEN, 0); 1446 continue; 1447 } else if (j == 0) 1448 mdoc_elem_alloc(mdoc, line, ppos, tok, arg); 1449 1450 if (j == maxargs && ! flushed) { 1451 rew_elem(mdoc, tok); 1452 flushed = 1; 1453 } 1454 1455 ntok = (ac == ARGS_QWORD || (tok == MDOC_Pf && j == 0)) ? 1456 MDOC_MAX : lookup(mdoc, tok, line, la, p); 1457 1458 if (ntok != MDOC_MAX) { 1459 if ( ! flushed) 1460 rew_elem(mdoc, tok); 1461 flushed = 1; 1462 mdoc_macro(mdoc, ntok, line, la, pos, buf); 1463 j++; 1464 break; 1465 } 1466 1467 if ( ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) && 1468 ac != ARGS_QWORD && ! flushed && 1469 mdoc_isdelim(p) != DELIM_NONE) { 1470 rew_elem(mdoc, tok); 1471 flushed = 1; 1472 } 1473 1474 dword(mdoc, line, la, p, DELIM_MAX, 1475 MDOC_JOIN & mdoc_macros[tok].flags); 1476 j++; 1477 } 1478 1479 if (j == 0) { 1480 mdoc_elem_alloc(mdoc, line, ppos, tok, arg); 1481 if (ac == ARGS_PUNCT && tok == MDOC_Pf) 1482 append_delims(mdoc, line, pos, buf); 1483 } 1484 if ( ! flushed) 1485 rew_elem(mdoc, tok); 1486 if (nl) 1487 append_delims(mdoc, line, pos, buf); 1488 } 1489 1490 static void 1491 in_line_eoln(MACRO_PROT_ARGS) 1492 { 1493 struct mdoc_arg *arg; 1494 1495 if (tok == MDOC_Pp) 1496 rew_sub(MDOC_BLOCK, mdoc, MDOC_Nm, line, ppos); 1497 1498 mdoc_argv(mdoc, line, tok, &arg, pos, buf); 1499 mdoc_elem_alloc(mdoc, line, ppos, tok, arg); 1500 if (parse_rest(mdoc, tok, line, pos, buf)) 1501 return; 1502 rew_elem(mdoc, tok); 1503 } 1504 1505 /* 1506 * The simplest argument parser available: Parse the remaining 1507 * words until the end of the phrase or line and return 0 1508 * or until the next macro, call that macro, and return 1. 1509 */ 1510 static int 1511 parse_rest(struct mdoc *mdoc, enum mdoct tok, int line, int *pos, char *buf) 1512 { 1513 int la; 1514 1515 for (;;) { 1516 la = *pos; 1517 if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN) 1518 return(0); 1519 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) 1520 return(1); 1521 } 1522 } 1523 1524 static void 1525 ctx_synopsis(MACRO_PROT_ARGS) 1526 { 1527 1528 if (~mdoc->flags & (MDOC_SYNOPSIS | MDOC_NEWLINE)) 1529 in_line(mdoc, tok, line, ppos, pos, buf); 1530 else if (tok == MDOC_Nm) 1531 blk_full(mdoc, tok, line, ppos, pos, buf); 1532 else { 1533 assert(tok == MDOC_Vt); 1534 blk_part_imp(mdoc, tok, line, ppos, pos, buf); 1535 } 1536 } 1537 1538 /* 1539 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs. 1540 * They're unusual because they're basically free-form text until a 1541 * macro is encountered. 1542 */ 1543 static void 1544 phrase_ta(MACRO_PROT_ARGS) 1545 { 1546 struct mdoc_node *n; 1547 1548 /* Make sure we are in a column list or ignore this macro. */ 1549 1550 n = mdoc->last; 1551 while (n != NULL && n->tok != MDOC_Bl) 1552 n = n->parent; 1553 if (n == NULL || n->norm->Bl.type != LIST_column) { 1554 mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse, 1555 line, ppos, "Ta"); 1556 return; 1557 } 1558 1559 /* Advance to the next column. */ 1560 1561 rew_sub(MDOC_BODY, mdoc, MDOC_It, line, ppos); 1562 mdoc_body_alloc(mdoc, line, ppos, MDOC_It); 1563 parse_rest(mdoc, MDOC_MAX, line, pos, buf); 1564 } 1565