1 /* $Id: man_macro.c,v 1.43 2013/12/30 00:52:18 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4 * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org> 5 * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #include <assert.h> 20 #include <ctype.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include "man.h" 25 #include "mandoc.h" 26 #include "libmandoc.h" 27 #include "libman.h" 28 29 enum rew { 30 REW_REWIND, 31 REW_NOHALT, 32 REW_HALT 33 }; 34 35 static int blk_close(MACRO_PROT_ARGS); 36 static int blk_exp(MACRO_PROT_ARGS); 37 static int blk_imp(MACRO_PROT_ARGS); 38 static int in_line_eoln(MACRO_PROT_ARGS); 39 static int man_args(struct man *, int, 40 int *, char *, char **); 41 42 static int rew_scope(enum man_type, 43 struct man *, enum mant); 44 static enum rew rew_dohalt(enum mant, enum man_type, 45 const struct man_node *); 46 static enum rew rew_block(enum mant, enum man_type, 47 const struct man_node *); 48 static void rew_warn(struct man *, 49 struct man_node *, enum mandocerr); 50 51 const struct man_macro __man_macros[MAN_MAX] = { 52 { in_line_eoln, MAN_NSCOPED }, /* br */ 53 { in_line_eoln, MAN_BSCOPE }, /* TH */ 54 { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */ 55 { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */ 56 { blk_imp, MAN_BSCOPE | MAN_SCOPED | MAN_FSCOPED }, /* TP */ 57 { blk_imp, MAN_BSCOPE }, /* LP */ 58 { blk_imp, MAN_BSCOPE }, /* PP */ 59 { blk_imp, MAN_BSCOPE }, /* P */ 60 { blk_imp, MAN_BSCOPE }, /* IP */ 61 { blk_imp, MAN_BSCOPE }, /* HP */ 62 { in_line_eoln, MAN_SCOPED }, /* SM */ 63 { in_line_eoln, MAN_SCOPED }, /* SB */ 64 { in_line_eoln, 0 }, /* BI */ 65 { in_line_eoln, 0 }, /* IB */ 66 { in_line_eoln, 0 }, /* BR */ 67 { in_line_eoln, 0 }, /* RB */ 68 { in_line_eoln, MAN_SCOPED }, /* R */ 69 { in_line_eoln, MAN_SCOPED }, /* B */ 70 { in_line_eoln, MAN_SCOPED }, /* I */ 71 { in_line_eoln, 0 }, /* IR */ 72 { in_line_eoln, 0 }, /* RI */ 73 { in_line_eoln, MAN_NSCOPED }, /* na */ 74 { in_line_eoln, MAN_NSCOPED }, /* sp */ 75 { in_line_eoln, MAN_BSCOPE }, /* nf */ 76 { in_line_eoln, MAN_BSCOPE }, /* fi */ 77 { blk_close, 0 }, /* RE */ 78 { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */ 79 { in_line_eoln, 0 }, /* DT */ 80 { in_line_eoln, 0 }, /* UC */ 81 { in_line_eoln, 0 }, /* PD */ 82 { in_line_eoln, 0 }, /* AT */ 83 { in_line_eoln, 0 }, /* in */ 84 { in_line_eoln, 0 }, /* ft */ 85 { in_line_eoln, 0 }, /* OP */ 86 { in_line_eoln, MAN_BSCOPE }, /* EX */ 87 { in_line_eoln, MAN_BSCOPE }, /* EE */ 88 { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */ 89 { blk_close, 0 }, /* UE */ 90 }; 91 92 const struct man_macro * const man_macros = __man_macros; 93 94 95 /* 96 * Warn when "n" is an explicit non-roff macro. 97 */ 98 static void 99 rew_warn(struct man *man, struct man_node *n, enum mandocerr er) 100 { 101 102 if (er == MANDOCERR_MAX || MAN_BLOCK != n->type) 103 return; 104 if (MAN_VALID & n->flags) 105 return; 106 if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags)) 107 return; 108 109 assert(er < MANDOCERR_FATAL); 110 man_nmsg(man, n, er); 111 } 112 113 114 /* 115 * Rewind scope. If a code "er" != MANDOCERR_MAX has been provided, it 116 * will be used if an explicit block scope is being closed out. 117 */ 118 int 119 man_unscope(struct man *man, const struct man_node *to, 120 enum mandocerr er) 121 { 122 struct man_node *n; 123 124 assert(to); 125 126 man->next = MAN_NEXT_SIBLING; 127 128 /* LINTED */ 129 while (man->last != to) { 130 /* 131 * Save the parent here, because we may delete the 132 * man->last node in the post-validation phase and reset 133 * it to man->last->parent, causing a step in the closing 134 * out to be lost. 135 */ 136 n = man->last->parent; 137 rew_warn(man, man->last, er); 138 if ( ! man_valid_post(man)) 139 return(0); 140 man->last = n; 141 assert(man->last); 142 } 143 144 rew_warn(man, man->last, er); 145 if ( ! man_valid_post(man)) 146 return(0); 147 148 return(1); 149 } 150 151 152 static enum rew 153 rew_block(enum mant ntok, enum man_type type, const struct man_node *n) 154 { 155 156 if (MAN_BLOCK == type && ntok == n->parent->tok && 157 MAN_BODY == n->parent->type) 158 return(REW_REWIND); 159 return(ntok == n->tok ? REW_HALT : REW_NOHALT); 160 } 161 162 163 /* 164 * There are three scope levels: scoped to the root (all), scoped to the 165 * section (all less sections), and scoped to subsections (all less 166 * sections and subsections). 167 */ 168 static enum rew 169 rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n) 170 { 171 enum rew c; 172 173 /* We cannot progress beyond the root ever. */ 174 if (MAN_ROOT == n->type) 175 return(REW_HALT); 176 177 assert(n->parent); 178 179 /* Normal nodes shouldn't go to the level of the root. */ 180 if (MAN_ROOT == n->parent->type) 181 return(REW_REWIND); 182 183 /* Already-validated nodes should be closed out. */ 184 if (MAN_VALID & n->flags) 185 return(REW_NOHALT); 186 187 /* First: rewind to ourselves. */ 188 if (type == n->type && tok == n->tok) { 189 if (MAN_EXPLICIT & man_macros[n->tok].flags) 190 return(REW_HALT); 191 else 192 return(REW_REWIND); 193 } 194 195 /* 196 * Next follow the implicit scope-smashings as defined by man.7: 197 * section, sub-section, etc. 198 */ 199 200 switch (tok) { 201 case (MAN_SH): 202 break; 203 case (MAN_SS): 204 /* Rewind to a section, if a block. */ 205 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 206 return(c); 207 break; 208 case (MAN_RS): 209 /* Preserve empty paragraphs before RS. */ 210 if (0 == n->nchild && (MAN_P == n->tok || 211 MAN_PP == n->tok || MAN_LP == n->tok)) 212 return(REW_HALT); 213 /* Rewind to a subsection, if a block. */ 214 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) 215 return(c); 216 /* Rewind to a section, if a block. */ 217 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 218 return(c); 219 break; 220 default: 221 /* Rewind to an offsetter, if a block. */ 222 if (REW_NOHALT != (c = rew_block(MAN_RS, type, n))) 223 return(c); 224 /* Rewind to a subsection, if a block. */ 225 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) 226 return(c); 227 /* Rewind to a section, if a block. */ 228 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 229 return(c); 230 break; 231 } 232 233 return(REW_NOHALT); 234 } 235 236 237 /* 238 * Rewinding entails ascending the parse tree until a coherent point, 239 * for example, the `SH' macro will close out any intervening `SS' 240 * scopes. When a scope is closed, it must be validated and actioned. 241 */ 242 static int 243 rew_scope(enum man_type type, struct man *man, enum mant tok) 244 { 245 struct man_node *n; 246 enum rew c; 247 248 /* LINTED */ 249 for (n = man->last; n; n = n->parent) { 250 /* 251 * Whether we should stop immediately (REW_HALT), stop 252 * and rewind until this point (REW_REWIND), or keep 253 * rewinding (REW_NOHALT). 254 */ 255 c = rew_dohalt(tok, type, n); 256 if (REW_HALT == c) 257 return(1); 258 if (REW_REWIND == c) 259 break; 260 } 261 262 /* 263 * Rewind until the current point. Warn if we're a roff 264 * instruction that's mowing over explicit scopes. 265 */ 266 assert(n); 267 268 return(man_unscope(man, n, MANDOCERR_MAX)); 269 } 270 271 272 /* 273 * Close out a generic explicit macro. 274 */ 275 /* ARGSUSED */ 276 int 277 blk_close(MACRO_PROT_ARGS) 278 { 279 enum mant ntok; 280 const struct man_node *nn; 281 282 switch (tok) { 283 case (MAN_RE): 284 ntok = MAN_RS; 285 break; 286 case (MAN_UE): 287 ntok = MAN_UR; 288 break; 289 default: 290 abort(); 291 /* NOTREACHED */ 292 } 293 294 for (nn = man->last->parent; nn; nn = nn->parent) 295 if (ntok == nn->tok && MAN_BLOCK == nn->type) 296 break; 297 298 if (NULL == nn) { 299 man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE); 300 if ( ! rew_scope(MAN_BLOCK, man, MAN_PP)) 301 return(0); 302 } else 303 man_unscope(man, nn, MANDOCERR_MAX); 304 305 return(1); 306 } 307 308 309 /* ARGSUSED */ 310 int 311 blk_exp(MACRO_PROT_ARGS) 312 { 313 struct man_node *n; 314 int la; 315 char *p; 316 317 /* Close out prior implicit scopes. */ 318 319 if ( ! rew_scope(MAN_BLOCK, man, tok)) 320 return(0); 321 322 if ( ! man_block_alloc(man, line, ppos, tok)) 323 return(0); 324 if ( ! man_head_alloc(man, line, ppos, tok)) 325 return(0); 326 327 for (;;) { 328 la = *pos; 329 if ( ! man_args(man, line, pos, buf, &p)) 330 break; 331 if ( ! man_word_alloc(man, line, la, p)) 332 return(0); 333 } 334 335 assert(man); 336 assert(tok != MAN_MAX); 337 338 for (n = man->last; n; n = n->parent) { 339 if (n->tok != tok) 340 continue; 341 assert(MAN_HEAD == n->type); 342 man_unscope(man, n, MANDOCERR_MAX); 343 break; 344 } 345 346 return(man_body_alloc(man, line, ppos, tok)); 347 } 348 349 350 351 /* 352 * Parse an implicit-block macro. These contain a MAN_HEAD and a 353 * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other 354 * scopes, such as `SH' closing out an `SS', are defined in the rew 355 * routines. 356 */ 357 /* ARGSUSED */ 358 int 359 blk_imp(MACRO_PROT_ARGS) 360 { 361 int la; 362 char *p; 363 struct man_node *n; 364 365 /* Close out prior scopes. */ 366 367 if ( ! rew_scope(MAN_BODY, man, tok)) 368 return(0); 369 if ( ! rew_scope(MAN_BLOCK, man, tok)) 370 return(0); 371 372 /* Allocate new block & head scope. */ 373 374 if ( ! man_block_alloc(man, line, ppos, tok)) 375 return(0); 376 if ( ! man_head_alloc(man, line, ppos, tok)) 377 return(0); 378 379 n = man->last; 380 381 /* Add line arguments. */ 382 383 for (;;) { 384 la = *pos; 385 if ( ! man_args(man, line, pos, buf, &p)) 386 break; 387 if ( ! man_word_alloc(man, line, la, p)) 388 return(0); 389 } 390 391 /* Close out head and open body (unless MAN_SCOPE). */ 392 393 if (MAN_SCOPED & man_macros[tok].flags) { 394 /* If we're forcing scope (`TP'), keep it open. */ 395 if (MAN_FSCOPED & man_macros[tok].flags) { 396 man->flags |= MAN_BLINE; 397 return(1); 398 } else if (n == man->last) { 399 man->flags |= MAN_BLINE; 400 return(1); 401 } 402 } 403 404 if ( ! rew_scope(MAN_HEAD, man, tok)) 405 return(0); 406 return(man_body_alloc(man, line, ppos, tok)); 407 } 408 409 410 /* ARGSUSED */ 411 int 412 in_line_eoln(MACRO_PROT_ARGS) 413 { 414 int la; 415 char *p; 416 struct man_node *n; 417 418 if ( ! man_elem_alloc(man, line, ppos, tok)) 419 return(0); 420 421 n = man->last; 422 423 for (;;) { 424 la = *pos; 425 if ( ! man_args(man, line, pos, buf, &p)) 426 break; 427 if ( ! man_word_alloc(man, line, la, p)) 428 return(0); 429 } 430 431 /* 432 * Append MAN_EOS in case the last snipped argument 433 * ends with a dot, e.g. `.IR syslog (3).' 434 */ 435 436 if (n != man->last && 437 mandoc_eos(man->last->string, strlen(man->last->string))) 438 man->last->flags |= MAN_EOS; 439 440 /* 441 * If no arguments are specified and this is MAN_SCOPED (i.e., 442 * next-line scoped), then set our mode to indicate that we're 443 * waiting for terms to load into our context. 444 */ 445 446 if (n == man->last && MAN_SCOPED & man_macros[tok].flags) { 447 assert( ! (MAN_NSCOPED & man_macros[tok].flags)); 448 man->flags |= MAN_ELINE; 449 return(1); 450 } 451 452 /* Set ignorable context, if applicable. */ 453 454 if (MAN_NSCOPED & man_macros[tok].flags) { 455 assert( ! (MAN_SCOPED & man_macros[tok].flags)); 456 man->flags |= MAN_ILINE; 457 } 458 459 assert(MAN_ROOT != man->last->type); 460 man->next = MAN_NEXT_SIBLING; 461 462 /* 463 * Rewind our element scope. Note that when TH is pruned, we'll 464 * be back at the root, so make sure that we don't clobber as 465 * its sibling. 466 */ 467 468 for ( ; man->last; man->last = man->last->parent) { 469 if (man->last == n) 470 break; 471 if (man->last->type == MAN_ROOT) 472 break; 473 if ( ! man_valid_post(man)) 474 return(0); 475 } 476 477 assert(man->last); 478 479 /* 480 * Same here regarding whether we're back at the root. 481 */ 482 483 if (man->last->type != MAN_ROOT && ! man_valid_post(man)) 484 return(0); 485 486 return(1); 487 } 488 489 490 int 491 man_macroend(struct man *man) 492 { 493 494 return(man_unscope(man, man->first, MANDOCERR_SCOPEEXIT)); 495 } 496 497 static int 498 man_args(struct man *man, int line, int *pos, char *buf, char **v) 499 { 500 char *start; 501 502 assert(*pos); 503 *v = start = buf + *pos; 504 assert(' ' != *start); 505 506 if ('\0' == *start) 507 return(0); 508 509 *v = mandoc_getarg(man->parse, v, line, pos); 510 return(1); 511 } 512