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