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