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