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