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