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