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