1 /* $Vendor-Id: man_macro.c,v 1.30 2010/01/01 17:14:28 kristaps Exp $ */ 2 /* 3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #ifdef HAVE_CONFIG_H 18 #include "config.h" 19 #endif 20 21 #include <assert.h> 22 #include <ctype.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include "libman.h" 27 28 #define REW_REWIND (0) /* See rew_scope(). */ 29 #define REW_NOHALT (1) /* See rew_scope(). */ 30 #define REW_HALT (2) /* See rew_scope(). */ 31 32 static int in_line_eoln(MACRO_PROT_ARGS); 33 static int blk_imp(MACRO_PROT_ARGS); 34 static int blk_close(MACRO_PROT_ARGS); 35 36 static int rew_scope(enum man_type, struct man *, int); 37 static int rew_dohalt(int, enum man_type, 38 const struct man_node *); 39 static int rew_block(int, enum man_type, 40 const struct man_node *); 41 42 const struct man_macro __man_macros[MAN_MAX] = { 43 { in_line_eoln, 0 }, /* br */ 44 { in_line_eoln, 0 }, /* TH */ 45 { blk_imp, MAN_SCOPED }, /* SH */ 46 { blk_imp, MAN_SCOPED }, /* SS */ 47 { blk_imp, MAN_SCOPED | MAN_FSCOPED }, /* TP */ 48 { blk_imp, 0 }, /* LP */ 49 { blk_imp, 0 }, /* PP */ 50 { blk_imp, 0 }, /* P */ 51 { blk_imp, 0 }, /* IP */ 52 { blk_imp, 0 }, /* HP */ 53 { in_line_eoln, MAN_SCOPED }, /* SM */ 54 { in_line_eoln, MAN_SCOPED }, /* SB */ 55 { in_line_eoln, 0 }, /* BI */ 56 { in_line_eoln, 0 }, /* IB */ 57 { in_line_eoln, 0 }, /* BR */ 58 { in_line_eoln, 0 }, /* RB */ 59 { in_line_eoln, MAN_SCOPED }, /* R */ 60 { in_line_eoln, MAN_SCOPED }, /* B */ 61 { in_line_eoln, MAN_SCOPED }, /* I */ 62 { in_line_eoln, 0 }, /* IR */ 63 { in_line_eoln, 0 }, /* RI */ 64 { in_line_eoln, 0 }, /* na */ 65 { in_line_eoln, 0 }, /* i */ 66 { in_line_eoln, 0 }, /* sp */ 67 { in_line_eoln, 0 }, /* nf */ 68 { in_line_eoln, 0 }, /* fi */ 69 { in_line_eoln, 0 }, /* r */ 70 { blk_close, 0 }, /* RE */ 71 { blk_imp, MAN_EXPLICIT }, /* RS */ 72 { in_line_eoln, 0 }, /* DT */ 73 { in_line_eoln, 0 }, /* UC */ 74 { in_line_eoln, 0 }, /* PD */ 75 }; 76 77 const struct man_macro * const man_macros = __man_macros; 78 79 80 int 81 man_unscope(struct man *m, const struct man_node *n) 82 { 83 84 assert(n); 85 m->next = MAN_NEXT_SIBLING; 86 87 /* LINTED */ 88 while (m->last != n) { 89 if ( ! man_valid_post(m)) 90 return(0); 91 if ( ! man_action_post(m)) 92 return(0); 93 m->last = m->last->parent; 94 assert(m->last); 95 } 96 97 if ( ! man_valid_post(m)) 98 return(0); 99 return(man_action_post(m)); 100 } 101 102 103 static int 104 rew_block(int ntok, enum man_type type, const struct man_node *n) 105 { 106 107 if (MAN_BLOCK == type && ntok == n->parent->tok && 108 MAN_BODY == n->parent->type) 109 return(REW_REWIND); 110 return(ntok == n->tok ? REW_HALT : REW_NOHALT); 111 } 112 113 114 /* 115 * There are three scope levels: scoped to the root (all), scoped to the 116 * section (all less sections), and scoped to subsections (all less 117 * sections and subsections). 118 */ 119 static int 120 rew_dohalt(int tok, enum man_type type, const struct man_node *n) 121 { 122 int c; 123 124 if (MAN_ROOT == n->type) 125 return(REW_HALT); 126 assert(n->parent); 127 if (MAN_ROOT == n->parent->type) 128 return(REW_REWIND); 129 if (MAN_VALID & n->flags) 130 return(REW_NOHALT); 131 132 /* Rewind to ourselves, first. */ 133 if (type == n->type && tok == n->tok) 134 return(REW_REWIND); 135 136 switch (tok) { 137 case (MAN_SH): 138 break; 139 case (MAN_SS): 140 /* Rewind to a section, if a block. */ 141 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 142 return(c); 143 break; 144 case (MAN_RS): 145 /* Rewind to a subsection, if a block. */ 146 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) 147 return(c); 148 /* Rewind to a section, if a block. */ 149 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 150 return(c); 151 break; 152 default: 153 /* Rewind to an offsetter, if a block. */ 154 if (REW_NOHALT != (c = rew_block(MAN_RS, type, n))) 155 return(c); 156 /* Rewind to a subsection, if a block. */ 157 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) 158 return(c); 159 /* Rewind to a section, if a block. */ 160 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 161 return(c); 162 break; 163 } 164 165 return(REW_NOHALT); 166 } 167 168 169 /* 170 * Rewinding entails ascending the parse tree until a coherent point, 171 * for example, the `SH' macro will close out any intervening `SS' 172 * scopes. When a scope is closed, it must be validated and actioned. 173 */ 174 static int 175 rew_scope(enum man_type type, struct man *m, int tok) 176 { 177 struct man_node *n; 178 int c; 179 180 /* LINTED */ 181 for (n = m->last; n; n = n->parent) { 182 /* 183 * Whether we should stop immediately (REW_HALT), stop 184 * and rewind until this point (REW_REWIND), or keep 185 * rewinding (REW_NOHALT). 186 */ 187 c = rew_dohalt(tok, type, n); 188 if (REW_HALT == c) 189 return(1); 190 if (REW_REWIND == c) 191 break; 192 } 193 194 /* Rewind until the current point. */ 195 196 assert(n); 197 return(man_unscope(m, n)); 198 } 199 200 201 /* ARGSUSED */ 202 int 203 blk_close(MACRO_PROT_ARGS) 204 { 205 int ntok; 206 const struct man_node *nn; 207 208 switch (tok) { 209 case (MAN_RE): 210 ntok = MAN_RS; 211 break; 212 default: 213 abort(); 214 /* NOTREACHED */ 215 } 216 217 for (nn = m->last->parent; nn; nn = nn->parent) 218 if (ntok == nn->tok) 219 break; 220 221 if (NULL == nn) 222 if ( ! man_pwarn(m, line, ppos, WNOSCOPE)) 223 return(0); 224 225 if ( ! rew_scope(MAN_BODY, m, ntok)) 226 return(0); 227 if ( ! rew_scope(MAN_BLOCK, m, ntok)) 228 return(0); 229 m->next = MAN_NEXT_SIBLING; 230 return(1); 231 } 232 233 234 /* 235 * Parse an implicit-block macro. These contain a MAN_HEAD and a 236 * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other 237 * scopes, such as `SH' closing out an `SS', are defined in the rew 238 * routines. 239 */ 240 int 241 blk_imp(MACRO_PROT_ARGS) 242 { 243 int w, la; 244 char *p; 245 struct man_node *n; 246 247 /* Close out prior scopes. */ 248 249 if ( ! rew_scope(MAN_BODY, m, tok)) 250 return(0); 251 if ( ! rew_scope(MAN_BLOCK, m, tok)) 252 return(0); 253 254 /* Allocate new block & head scope. */ 255 256 if ( ! man_block_alloc(m, line, ppos, tok)) 257 return(0); 258 if ( ! man_head_alloc(m, line, ppos, tok)) 259 return(0); 260 261 n = m->last; 262 263 /* Add line arguments. */ 264 265 for (;;) { 266 la = *pos; 267 w = man_args(m, line, pos, buf, &p); 268 269 if (-1 == w) 270 return(0); 271 if (0 == w) 272 break; 273 274 if ( ! man_word_alloc(m, line, la, p)) 275 return(0); 276 } 277 278 /* Close out head and open body (unless MAN_SCOPE). */ 279 280 if (MAN_SCOPED & man_macros[tok].flags) { 281 /* If we're forcing scope (`TP'), keep it open. */ 282 if (MAN_FSCOPED & man_macros[tok].flags) { 283 m->flags |= MAN_BLINE; 284 return(1); 285 } else if (n == m->last) { 286 m->flags |= MAN_BLINE; 287 return(1); 288 } 289 } 290 291 if ( ! rew_scope(MAN_HEAD, m, tok)) 292 return(0); 293 294 return(man_body_alloc(m, line, ppos, tok)); 295 } 296 297 298 int 299 in_line_eoln(MACRO_PROT_ARGS) 300 { 301 int w, la; 302 char *p; 303 struct man_node *n; 304 305 if ( ! man_elem_alloc(m, line, ppos, tok)) 306 return(0); 307 308 n = m->last; 309 310 for (;;) { 311 la = *pos; 312 w = man_args(m, line, pos, buf, &p); 313 314 if (-1 == w) 315 return(0); 316 if (0 == w) 317 break; 318 319 if ( ! man_word_alloc(m, line, la, p)) 320 return(0); 321 } 322 323 if (n == m->last && MAN_SCOPED & man_macros[tok].flags) { 324 m->flags |= MAN_ELINE; 325 return(1); 326 } 327 328 /* 329 * Note that when TH is pruned, we'll be back at the root, so 330 * make sure that we don't clobber as its sibling. 331 */ 332 333 for ( ; m->last; m->last = m->last->parent) { 334 if (m->last == n) 335 break; 336 if (m->last->type == MAN_ROOT) 337 break; 338 if ( ! man_valid_post(m)) 339 return(0); 340 if ( ! man_action_post(m)) 341 return(0); 342 } 343 344 assert(m->last); 345 346 /* 347 * Same here regarding whether we're back at the root. 348 */ 349 350 if (m->last->type != MAN_ROOT && ! man_valid_post(m)) 351 return(0); 352 if (m->last->type != MAN_ROOT && ! man_action_post(m)) 353 return(0); 354 if (m->last->type != MAN_ROOT) 355 m->next = MAN_NEXT_SIBLING; 356 357 return(1); 358 } 359 360 361 int 362 man_macroend(struct man *m) 363 { 364 struct man_node *n; 365 366 n = MAN_VALID & m->last->flags ? 367 m->last->parent : m->last; 368 369 for ( ; n; n = n->parent) { 370 if (MAN_BLOCK != n->type) 371 continue; 372 if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags)) 373 continue; 374 if ( ! man_nwarn(m, n, WEXITSCOPE)) 375 return(0); 376 } 377 378 return(man_unscope(m, m->first)); 379 } 380 381