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