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