1*698f87a4SGarrett D'Amore /* $Id: man_macro.c,v 1.79 2013/12/25 00:50:05 schwarze Exp $ */ 295c635efSGarrett D'Amore /* 395c635efSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4*698f87a4SGarrett D'Amore * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org> 5*698f87a4SGarrett D'Amore * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de> 695c635efSGarrett D'Amore * 795c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 895c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 995c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 1095c635efSGarrett D'Amore * 1195c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1295c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1395c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1495c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1595c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1695c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1795c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1895c635efSGarrett D'Amore */ 1995c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 2095c635efSGarrett D'Amore #include "config.h" 2195c635efSGarrett D'Amore #endif 2295c635efSGarrett D'Amore 2395c635efSGarrett D'Amore #include <assert.h> 2495c635efSGarrett D'Amore #include <ctype.h> 2595c635efSGarrett D'Amore #include <stdlib.h> 2695c635efSGarrett D'Amore #include <string.h> 2795c635efSGarrett D'Amore 2895c635efSGarrett D'Amore #include "man.h" 2995c635efSGarrett D'Amore #include "mandoc.h" 3095c635efSGarrett D'Amore #include "libmandoc.h" 3195c635efSGarrett D'Amore #include "libman.h" 3295c635efSGarrett D'Amore 3395c635efSGarrett D'Amore enum rew { 3495c635efSGarrett D'Amore REW_REWIND, 3595c635efSGarrett D'Amore REW_NOHALT, 3695c635efSGarrett D'Amore REW_HALT 3795c635efSGarrett D'Amore }; 3895c635efSGarrett D'Amore 3995c635efSGarrett D'Amore static int blk_close(MACRO_PROT_ARGS); 4095c635efSGarrett D'Amore static int blk_exp(MACRO_PROT_ARGS); 4195c635efSGarrett D'Amore static int blk_imp(MACRO_PROT_ARGS); 4295c635efSGarrett D'Amore static int in_line_eoln(MACRO_PROT_ARGS); 4395c635efSGarrett D'Amore static int man_args(struct man *, int, 4495c635efSGarrett D'Amore int *, char *, char **); 4595c635efSGarrett D'Amore 4695c635efSGarrett D'Amore static int rew_scope(enum man_type, 4795c635efSGarrett D'Amore struct man *, enum mant); 4895c635efSGarrett D'Amore static enum rew rew_dohalt(enum mant, enum man_type, 4995c635efSGarrett D'Amore const struct man_node *); 5095c635efSGarrett D'Amore static enum rew rew_block(enum mant, enum man_type, 5195c635efSGarrett D'Amore const struct man_node *); 5295c635efSGarrett D'Amore static void rew_warn(struct man *, 5395c635efSGarrett D'Amore struct man_node *, enum mandocerr); 5495c635efSGarrett D'Amore 5595c635efSGarrett D'Amore const struct man_macro __man_macros[MAN_MAX] = { 5695c635efSGarrett D'Amore { in_line_eoln, MAN_NSCOPED }, /* br */ 5795c635efSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* TH */ 5895c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */ 5995c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */ 6095c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE | MAN_SCOPED | MAN_FSCOPED }, /* TP */ 6195c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* LP */ 6295c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* PP */ 6395c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* P */ 6495c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* IP */ 6595c635efSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* HP */ 6695c635efSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* SM */ 6795c635efSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* SB */ 6895c635efSGarrett D'Amore { in_line_eoln, 0 }, /* BI */ 6995c635efSGarrett D'Amore { in_line_eoln, 0 }, /* IB */ 7095c635efSGarrett D'Amore { in_line_eoln, 0 }, /* BR */ 7195c635efSGarrett D'Amore { in_line_eoln, 0 }, /* RB */ 7295c635efSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* R */ 7395c635efSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* B */ 7495c635efSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* I */ 7595c635efSGarrett D'Amore { in_line_eoln, 0 }, /* IR */ 7695c635efSGarrett D'Amore { in_line_eoln, 0 }, /* RI */ 7795c635efSGarrett D'Amore { in_line_eoln, MAN_NSCOPED }, /* na */ 7895c635efSGarrett D'Amore { in_line_eoln, MAN_NSCOPED }, /* sp */ 7995c635efSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* nf */ 8095c635efSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* fi */ 8195c635efSGarrett D'Amore { blk_close, 0 }, /* RE */ 82*698f87a4SGarrett D'Amore { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */ 8395c635efSGarrett D'Amore { in_line_eoln, 0 }, /* DT */ 8495c635efSGarrett D'Amore { in_line_eoln, 0 }, /* UC */ 8595c635efSGarrett D'Amore { in_line_eoln, 0 }, /* PD */ 8695c635efSGarrett D'Amore { in_line_eoln, 0 }, /* AT */ 8795c635efSGarrett D'Amore { in_line_eoln, 0 }, /* in */ 8895c635efSGarrett D'Amore { in_line_eoln, 0 }, /* ft */ 8995c635efSGarrett D'Amore { in_line_eoln, 0 }, /* OP */ 90*698f87a4SGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* EX */ 91*698f87a4SGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* EE */ 92*698f87a4SGarrett D'Amore { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */ 93*698f87a4SGarrett D'Amore { blk_close, 0 }, /* UE */ 9495c635efSGarrett D'Amore }; 9595c635efSGarrett D'Amore 9695c635efSGarrett D'Amore const struct man_macro * const man_macros = __man_macros; 9795c635efSGarrett D'Amore 9895c635efSGarrett D'Amore 9995c635efSGarrett D'Amore /* 10095c635efSGarrett D'Amore * Warn when "n" is an explicit non-roff macro. 10195c635efSGarrett D'Amore */ 10295c635efSGarrett D'Amore static void 103*698f87a4SGarrett D'Amore rew_warn(struct man *man, struct man_node *n, enum mandocerr er) 10495c635efSGarrett D'Amore { 10595c635efSGarrett D'Amore 10695c635efSGarrett D'Amore if (er == MANDOCERR_MAX || MAN_BLOCK != n->type) 10795c635efSGarrett D'Amore return; 10895c635efSGarrett D'Amore if (MAN_VALID & n->flags) 10995c635efSGarrett D'Amore return; 11095c635efSGarrett D'Amore if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags)) 11195c635efSGarrett D'Amore return; 11295c635efSGarrett D'Amore 11395c635efSGarrett D'Amore assert(er < MANDOCERR_FATAL); 114*698f87a4SGarrett D'Amore man_nmsg(man, n, er); 11595c635efSGarrett D'Amore } 11695c635efSGarrett D'Amore 11795c635efSGarrett D'Amore 11895c635efSGarrett D'Amore /* 11995c635efSGarrett D'Amore * Rewind scope. If a code "er" != MANDOCERR_MAX has been provided, it 12095c635efSGarrett D'Amore * will be used if an explicit block scope is being closed out. 12195c635efSGarrett D'Amore */ 12295c635efSGarrett D'Amore int 123*698f87a4SGarrett D'Amore man_unscope(struct man *man, const struct man_node *to, 12495c635efSGarrett D'Amore enum mandocerr er) 12595c635efSGarrett D'Amore { 12695c635efSGarrett D'Amore struct man_node *n; 12795c635efSGarrett D'Amore 12895c635efSGarrett D'Amore assert(to); 12995c635efSGarrett D'Amore 130*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING; 13195c635efSGarrett D'Amore 13295c635efSGarrett D'Amore /* LINTED */ 133*698f87a4SGarrett D'Amore while (man->last != to) { 13495c635efSGarrett D'Amore /* 13595c635efSGarrett D'Amore * Save the parent here, because we may delete the 136*698f87a4SGarrett D'Amore * man->last node in the post-validation phase and reset 137*698f87a4SGarrett D'Amore * it to man->last->parent, causing a step in the closing 13895c635efSGarrett D'Amore * out to be lost. 13995c635efSGarrett D'Amore */ 140*698f87a4SGarrett D'Amore n = man->last->parent; 141*698f87a4SGarrett D'Amore rew_warn(man, man->last, er); 142*698f87a4SGarrett D'Amore if ( ! man_valid_post(man)) 14395c635efSGarrett D'Amore return(0); 144*698f87a4SGarrett D'Amore man->last = n; 145*698f87a4SGarrett D'Amore assert(man->last); 14695c635efSGarrett D'Amore } 14795c635efSGarrett D'Amore 148*698f87a4SGarrett D'Amore rew_warn(man, man->last, er); 149*698f87a4SGarrett D'Amore if ( ! man_valid_post(man)) 15095c635efSGarrett D'Amore return(0); 15195c635efSGarrett D'Amore 15295c635efSGarrett D'Amore return(1); 15395c635efSGarrett D'Amore } 15495c635efSGarrett D'Amore 15595c635efSGarrett D'Amore 15695c635efSGarrett D'Amore static enum rew 15795c635efSGarrett D'Amore rew_block(enum mant ntok, enum man_type type, const struct man_node *n) 15895c635efSGarrett D'Amore { 15995c635efSGarrett D'Amore 16095c635efSGarrett D'Amore if (MAN_BLOCK == type && ntok == n->parent->tok && 16195c635efSGarrett D'Amore MAN_BODY == n->parent->type) 16295c635efSGarrett D'Amore return(REW_REWIND); 16395c635efSGarrett D'Amore return(ntok == n->tok ? REW_HALT : REW_NOHALT); 16495c635efSGarrett D'Amore } 16595c635efSGarrett D'Amore 16695c635efSGarrett D'Amore 16795c635efSGarrett D'Amore /* 16895c635efSGarrett D'Amore * There are three scope levels: scoped to the root (all), scoped to the 16995c635efSGarrett D'Amore * section (all less sections), and scoped to subsections (all less 17095c635efSGarrett D'Amore * sections and subsections). 17195c635efSGarrett D'Amore */ 17295c635efSGarrett D'Amore static enum rew 17395c635efSGarrett D'Amore rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n) 17495c635efSGarrett D'Amore { 17595c635efSGarrett D'Amore enum rew c; 17695c635efSGarrett D'Amore 17795c635efSGarrett D'Amore /* We cannot progress beyond the root ever. */ 17895c635efSGarrett D'Amore if (MAN_ROOT == n->type) 17995c635efSGarrett D'Amore return(REW_HALT); 18095c635efSGarrett D'Amore 18195c635efSGarrett D'Amore assert(n->parent); 18295c635efSGarrett D'Amore 18395c635efSGarrett D'Amore /* Normal nodes shouldn't go to the level of the root. */ 18495c635efSGarrett D'Amore if (MAN_ROOT == n->parent->type) 18595c635efSGarrett D'Amore return(REW_REWIND); 18695c635efSGarrett D'Amore 18795c635efSGarrett D'Amore /* Already-validated nodes should be closed out. */ 18895c635efSGarrett D'Amore if (MAN_VALID & n->flags) 18995c635efSGarrett D'Amore return(REW_NOHALT); 19095c635efSGarrett D'Amore 19195c635efSGarrett D'Amore /* First: rewind to ourselves. */ 192*698f87a4SGarrett D'Amore if (type == n->type && tok == n->tok) { 193*698f87a4SGarrett D'Amore if (MAN_EXPLICIT & man_macros[n->tok].flags) 194*698f87a4SGarrett D'Amore return(REW_HALT); 195*698f87a4SGarrett D'Amore else 19695c635efSGarrett D'Amore return(REW_REWIND); 197*698f87a4SGarrett D'Amore } 19895c635efSGarrett D'Amore 19995c635efSGarrett D'Amore /* 20095c635efSGarrett D'Amore * Next follow the implicit scope-smashings as defined by man.7: 20195c635efSGarrett D'Amore * section, sub-section, etc. 20295c635efSGarrett D'Amore */ 20395c635efSGarrett D'Amore 20495c635efSGarrett D'Amore switch (tok) { 20595c635efSGarrett D'Amore case (MAN_SH): 20695c635efSGarrett D'Amore break; 20795c635efSGarrett D'Amore case (MAN_SS): 20895c635efSGarrett D'Amore /* Rewind to a section, if a block. */ 20995c635efSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 21095c635efSGarrett D'Amore return(c); 21195c635efSGarrett D'Amore break; 21295c635efSGarrett D'Amore case (MAN_RS): 213*698f87a4SGarrett D'Amore /* Preserve empty paragraphs before RS. */ 214*698f87a4SGarrett D'Amore if (0 == n->nchild && (MAN_P == n->tok || 215*698f87a4SGarrett D'Amore MAN_PP == n->tok || MAN_LP == n->tok)) 216*698f87a4SGarrett D'Amore return(REW_HALT); 21795c635efSGarrett D'Amore /* Rewind to a subsection, if a block. */ 21895c635efSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) 21995c635efSGarrett D'Amore return(c); 22095c635efSGarrett D'Amore /* Rewind to a section, if a block. */ 22195c635efSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 22295c635efSGarrett D'Amore return(c); 22395c635efSGarrett D'Amore break; 22495c635efSGarrett D'Amore default: 22595c635efSGarrett D'Amore /* Rewind to an offsetter, if a block. */ 22695c635efSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_RS, type, n))) 22795c635efSGarrett D'Amore return(c); 22895c635efSGarrett D'Amore /* Rewind to a subsection, if a block. */ 22995c635efSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) 23095c635efSGarrett D'Amore return(c); 23195c635efSGarrett D'Amore /* Rewind to a section, if a block. */ 23295c635efSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) 23395c635efSGarrett D'Amore return(c); 23495c635efSGarrett D'Amore break; 23595c635efSGarrett D'Amore } 23695c635efSGarrett D'Amore 23795c635efSGarrett D'Amore return(REW_NOHALT); 23895c635efSGarrett D'Amore } 23995c635efSGarrett D'Amore 24095c635efSGarrett D'Amore 24195c635efSGarrett D'Amore /* 24295c635efSGarrett D'Amore * Rewinding entails ascending the parse tree until a coherent point, 24395c635efSGarrett D'Amore * for example, the `SH' macro will close out any intervening `SS' 24495c635efSGarrett D'Amore * scopes. When a scope is closed, it must be validated and actioned. 24595c635efSGarrett D'Amore */ 24695c635efSGarrett D'Amore static int 247*698f87a4SGarrett D'Amore rew_scope(enum man_type type, struct man *man, enum mant tok) 24895c635efSGarrett D'Amore { 24995c635efSGarrett D'Amore struct man_node *n; 25095c635efSGarrett D'Amore enum rew c; 25195c635efSGarrett D'Amore 25295c635efSGarrett D'Amore /* LINTED */ 253*698f87a4SGarrett D'Amore for (n = man->last; n; n = n->parent) { 25495c635efSGarrett D'Amore /* 25595c635efSGarrett D'Amore * Whether we should stop immediately (REW_HALT), stop 25695c635efSGarrett D'Amore * and rewind until this point (REW_REWIND), or keep 25795c635efSGarrett D'Amore * rewinding (REW_NOHALT). 25895c635efSGarrett D'Amore */ 25995c635efSGarrett D'Amore c = rew_dohalt(tok, type, n); 26095c635efSGarrett D'Amore if (REW_HALT == c) 26195c635efSGarrett D'Amore return(1); 26295c635efSGarrett D'Amore if (REW_REWIND == c) 26395c635efSGarrett D'Amore break; 26495c635efSGarrett D'Amore } 26595c635efSGarrett D'Amore 26695c635efSGarrett D'Amore /* 26795c635efSGarrett D'Amore * Rewind until the current point. Warn if we're a roff 26895c635efSGarrett D'Amore * instruction that's mowing over explicit scopes. 26995c635efSGarrett D'Amore */ 27095c635efSGarrett D'Amore assert(n); 27195c635efSGarrett D'Amore 272*698f87a4SGarrett D'Amore return(man_unscope(man, n, MANDOCERR_MAX)); 27395c635efSGarrett D'Amore } 27495c635efSGarrett D'Amore 27595c635efSGarrett D'Amore 27695c635efSGarrett D'Amore /* 27795c635efSGarrett D'Amore * Close out a generic explicit macro. 27895c635efSGarrett D'Amore */ 27995c635efSGarrett D'Amore /* ARGSUSED */ 28095c635efSGarrett D'Amore int 28195c635efSGarrett D'Amore blk_close(MACRO_PROT_ARGS) 28295c635efSGarrett D'Amore { 28395c635efSGarrett D'Amore enum mant ntok; 28495c635efSGarrett D'Amore const struct man_node *nn; 28595c635efSGarrett D'Amore 28695c635efSGarrett D'Amore switch (tok) { 28795c635efSGarrett D'Amore case (MAN_RE): 28895c635efSGarrett D'Amore ntok = MAN_RS; 28995c635efSGarrett D'Amore break; 290*698f87a4SGarrett D'Amore case (MAN_UE): 291*698f87a4SGarrett D'Amore ntok = MAN_UR; 292*698f87a4SGarrett D'Amore break; 29395c635efSGarrett D'Amore default: 29495c635efSGarrett D'Amore abort(); 29595c635efSGarrett D'Amore /* NOTREACHED */ 29695c635efSGarrett D'Amore } 29795c635efSGarrett D'Amore 298*698f87a4SGarrett D'Amore for (nn = man->last->parent; nn; nn = nn->parent) 299*698f87a4SGarrett D'Amore if (ntok == nn->tok && MAN_BLOCK == nn->type) 30095c635efSGarrett D'Amore break; 30195c635efSGarrett D'Amore 302*698f87a4SGarrett D'Amore if (NULL == nn) { 303*698f87a4SGarrett D'Amore man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE); 304*698f87a4SGarrett D'Amore if ( ! rew_scope(MAN_BLOCK, man, MAN_PP)) 30595c635efSGarrett D'Amore return(0); 306*698f87a4SGarrett D'Amore } else 307*698f87a4SGarrett D'Amore man_unscope(man, nn, MANDOCERR_MAX); 30895c635efSGarrett D'Amore 30995c635efSGarrett D'Amore return(1); 31095c635efSGarrett D'Amore } 31195c635efSGarrett D'Amore 31295c635efSGarrett D'Amore 31395c635efSGarrett D'Amore /* ARGSUSED */ 31495c635efSGarrett D'Amore int 31595c635efSGarrett D'Amore blk_exp(MACRO_PROT_ARGS) 31695c635efSGarrett D'Amore { 317*698f87a4SGarrett D'Amore struct man_node *n; 31895c635efSGarrett D'Amore int la; 31995c635efSGarrett D'Amore char *p; 32095c635efSGarrett D'Amore 321*698f87a4SGarrett D'Amore /* Close out prior implicit scopes. */ 32295c635efSGarrett D'Amore 323*698f87a4SGarrett D'Amore if ( ! rew_scope(MAN_BLOCK, man, tok)) 32495c635efSGarrett D'Amore return(0); 325*698f87a4SGarrett D'Amore 326*698f87a4SGarrett D'Amore if ( ! man_block_alloc(man, line, ppos, tok)) 327*698f87a4SGarrett D'Amore return(0); 328*698f87a4SGarrett D'Amore if ( ! man_head_alloc(man, line, ppos, tok)) 32995c635efSGarrett D'Amore return(0); 33095c635efSGarrett D'Amore 33195c635efSGarrett D'Amore for (;;) { 33295c635efSGarrett D'Amore la = *pos; 333*698f87a4SGarrett D'Amore if ( ! man_args(man, line, pos, buf, &p)) 33495c635efSGarrett D'Amore break; 335*698f87a4SGarrett D'Amore if ( ! man_word_alloc(man, line, la, p)) 33695c635efSGarrett D'Amore return(0); 33795c635efSGarrett D'Amore } 33895c635efSGarrett D'Amore 339*698f87a4SGarrett D'Amore assert(man); 34095c635efSGarrett D'Amore assert(tok != MAN_MAX); 34195c635efSGarrett D'Amore 342*698f87a4SGarrett D'Amore for (n = man->last; n; n = n->parent) { 343*698f87a4SGarrett D'Amore if (n->tok != tok) 344*698f87a4SGarrett D'Amore continue; 345*698f87a4SGarrett D'Amore assert(MAN_HEAD == n->type); 346*698f87a4SGarrett D'Amore man_unscope(man, n, MANDOCERR_MAX); 347*698f87a4SGarrett D'Amore break; 348*698f87a4SGarrett D'Amore } 349*698f87a4SGarrett D'Amore 350*698f87a4SGarrett D'Amore return(man_body_alloc(man, line, ppos, tok)); 35195c635efSGarrett D'Amore } 35295c635efSGarrett D'Amore 35395c635efSGarrett D'Amore 35495c635efSGarrett D'Amore 35595c635efSGarrett D'Amore /* 35695c635efSGarrett D'Amore * Parse an implicit-block macro. These contain a MAN_HEAD and a 35795c635efSGarrett D'Amore * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other 35895c635efSGarrett D'Amore * scopes, such as `SH' closing out an `SS', are defined in the rew 35995c635efSGarrett D'Amore * routines. 36095c635efSGarrett D'Amore */ 36195c635efSGarrett D'Amore /* ARGSUSED */ 36295c635efSGarrett D'Amore int 36395c635efSGarrett D'Amore blk_imp(MACRO_PROT_ARGS) 36495c635efSGarrett D'Amore { 36595c635efSGarrett D'Amore int la; 36695c635efSGarrett D'Amore char *p; 36795c635efSGarrett D'Amore struct man_node *n; 36895c635efSGarrett D'Amore 36995c635efSGarrett D'Amore /* Close out prior scopes. */ 37095c635efSGarrett D'Amore 371*698f87a4SGarrett D'Amore if ( ! rew_scope(MAN_BODY, man, tok)) 37295c635efSGarrett D'Amore return(0); 373*698f87a4SGarrett D'Amore if ( ! rew_scope(MAN_BLOCK, man, tok)) 37495c635efSGarrett D'Amore return(0); 37595c635efSGarrett D'Amore 37695c635efSGarrett D'Amore /* Allocate new block & head scope. */ 37795c635efSGarrett D'Amore 378*698f87a4SGarrett D'Amore if ( ! man_block_alloc(man, line, ppos, tok)) 37995c635efSGarrett D'Amore return(0); 380*698f87a4SGarrett D'Amore if ( ! man_head_alloc(man, line, ppos, tok)) 38195c635efSGarrett D'Amore return(0); 38295c635efSGarrett D'Amore 383*698f87a4SGarrett D'Amore n = man->last; 38495c635efSGarrett D'Amore 38595c635efSGarrett D'Amore /* Add line arguments. */ 38695c635efSGarrett D'Amore 38795c635efSGarrett D'Amore for (;;) { 38895c635efSGarrett D'Amore la = *pos; 389*698f87a4SGarrett D'Amore if ( ! man_args(man, line, pos, buf, &p)) 39095c635efSGarrett D'Amore break; 391*698f87a4SGarrett D'Amore if ( ! man_word_alloc(man, line, la, p)) 39295c635efSGarrett D'Amore return(0); 39395c635efSGarrett D'Amore } 39495c635efSGarrett D'Amore 39595c635efSGarrett D'Amore /* Close out head and open body (unless MAN_SCOPE). */ 39695c635efSGarrett D'Amore 39795c635efSGarrett D'Amore if (MAN_SCOPED & man_macros[tok].flags) { 39895c635efSGarrett D'Amore /* If we're forcing scope (`TP'), keep it open. */ 39995c635efSGarrett D'Amore if (MAN_FSCOPED & man_macros[tok].flags) { 400*698f87a4SGarrett D'Amore man->flags |= MAN_BLINE; 40195c635efSGarrett D'Amore return(1); 402*698f87a4SGarrett D'Amore } else if (n == man->last) { 403*698f87a4SGarrett D'Amore man->flags |= MAN_BLINE; 40495c635efSGarrett D'Amore return(1); 40595c635efSGarrett D'Amore } 40695c635efSGarrett D'Amore } 40795c635efSGarrett D'Amore 408*698f87a4SGarrett D'Amore if ( ! rew_scope(MAN_HEAD, man, tok)) 40995c635efSGarrett D'Amore return(0); 410*698f87a4SGarrett D'Amore return(man_body_alloc(man, line, ppos, tok)); 41195c635efSGarrett D'Amore } 41295c635efSGarrett D'Amore 41395c635efSGarrett D'Amore 41495c635efSGarrett D'Amore /* ARGSUSED */ 41595c635efSGarrett D'Amore int 41695c635efSGarrett D'Amore in_line_eoln(MACRO_PROT_ARGS) 41795c635efSGarrett D'Amore { 41895c635efSGarrett D'Amore int la; 41995c635efSGarrett D'Amore char *p; 42095c635efSGarrett D'Amore struct man_node *n; 42195c635efSGarrett D'Amore 422*698f87a4SGarrett D'Amore if ( ! man_elem_alloc(man, line, ppos, tok)) 42395c635efSGarrett D'Amore return(0); 42495c635efSGarrett D'Amore 425*698f87a4SGarrett D'Amore n = man->last; 42695c635efSGarrett D'Amore 42795c635efSGarrett D'Amore for (;;) { 42895c635efSGarrett D'Amore la = *pos; 429*698f87a4SGarrett D'Amore if ( ! man_args(man, line, pos, buf, &p)) 43095c635efSGarrett D'Amore break; 431*698f87a4SGarrett D'Amore if ( ! man_word_alloc(man, line, la, p)) 43295c635efSGarrett D'Amore return(0); 43395c635efSGarrett D'Amore } 43495c635efSGarrett D'Amore 43595c635efSGarrett D'Amore /* 436*698f87a4SGarrett D'Amore * Append MAN_EOS in case the last snipped argument 437*698f87a4SGarrett D'Amore * ends with a dot, e.g. `.IR syslog (3).' 438*698f87a4SGarrett D'Amore */ 439*698f87a4SGarrett D'Amore 440*698f87a4SGarrett D'Amore if (n != man->last && 441*698f87a4SGarrett D'Amore mandoc_eos(man->last->string, strlen(man->last->string), 0)) 442*698f87a4SGarrett D'Amore man->last->flags |= MAN_EOS; 443*698f87a4SGarrett D'Amore 444*698f87a4SGarrett D'Amore /* 44595c635efSGarrett D'Amore * If no arguments are specified and this is MAN_SCOPED (i.e., 44695c635efSGarrett D'Amore * next-line scoped), then set our mode to indicate that we're 44795c635efSGarrett D'Amore * waiting for terms to load into our context. 44895c635efSGarrett D'Amore */ 44995c635efSGarrett D'Amore 450*698f87a4SGarrett D'Amore if (n == man->last && MAN_SCOPED & man_macros[tok].flags) { 45195c635efSGarrett D'Amore assert( ! (MAN_NSCOPED & man_macros[tok].flags)); 452*698f87a4SGarrett D'Amore man->flags |= MAN_ELINE; 45395c635efSGarrett D'Amore return(1); 45495c635efSGarrett D'Amore } 45595c635efSGarrett D'Amore 45695c635efSGarrett D'Amore /* Set ignorable context, if applicable. */ 45795c635efSGarrett D'Amore 45895c635efSGarrett D'Amore if (MAN_NSCOPED & man_macros[tok].flags) { 45995c635efSGarrett D'Amore assert( ! (MAN_SCOPED & man_macros[tok].flags)); 460*698f87a4SGarrett D'Amore man->flags |= MAN_ILINE; 46195c635efSGarrett D'Amore } 46295c635efSGarrett D'Amore 463*698f87a4SGarrett D'Amore assert(MAN_ROOT != man->last->type); 464*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING; 46595c635efSGarrett D'Amore 46695c635efSGarrett D'Amore /* 46795c635efSGarrett D'Amore * Rewind our element scope. Note that when TH is pruned, we'll 46895c635efSGarrett D'Amore * be back at the root, so make sure that we don't clobber as 46995c635efSGarrett D'Amore * its sibling. 47095c635efSGarrett D'Amore */ 47195c635efSGarrett D'Amore 472*698f87a4SGarrett D'Amore for ( ; man->last; man->last = man->last->parent) { 473*698f87a4SGarrett D'Amore if (man->last == n) 47495c635efSGarrett D'Amore break; 475*698f87a4SGarrett D'Amore if (man->last->type == MAN_ROOT) 47695c635efSGarrett D'Amore break; 477*698f87a4SGarrett D'Amore if ( ! man_valid_post(man)) 47895c635efSGarrett D'Amore return(0); 47995c635efSGarrett D'Amore } 48095c635efSGarrett D'Amore 481*698f87a4SGarrett D'Amore assert(man->last); 48295c635efSGarrett D'Amore 48395c635efSGarrett D'Amore /* 48495c635efSGarrett D'Amore * Same here regarding whether we're back at the root. 48595c635efSGarrett D'Amore */ 48695c635efSGarrett D'Amore 487*698f87a4SGarrett D'Amore if (man->last->type != MAN_ROOT && ! man_valid_post(man)) 48895c635efSGarrett D'Amore return(0); 48995c635efSGarrett D'Amore 49095c635efSGarrett D'Amore return(1); 49195c635efSGarrett D'Amore } 49295c635efSGarrett D'Amore 49395c635efSGarrett D'Amore 49495c635efSGarrett D'Amore int 495*698f87a4SGarrett D'Amore man_macroend(struct man *man) 49695c635efSGarrett D'Amore { 49795c635efSGarrett D'Amore 498*698f87a4SGarrett D'Amore return(man_unscope(man, man->first, MANDOCERR_SCOPEEXIT)); 49995c635efSGarrett D'Amore } 50095c635efSGarrett D'Amore 50195c635efSGarrett D'Amore static int 502*698f87a4SGarrett D'Amore man_args(struct man *man, int line, int *pos, char *buf, char **v) 50395c635efSGarrett D'Amore { 50495c635efSGarrett D'Amore char *start; 50595c635efSGarrett D'Amore 50695c635efSGarrett D'Amore assert(*pos); 50795c635efSGarrett D'Amore *v = start = buf + *pos; 50895c635efSGarrett D'Amore assert(' ' != *start); 50995c635efSGarrett D'Amore 51095c635efSGarrett D'Amore if ('\0' == *start) 51195c635efSGarrett D'Amore return(0); 51295c635efSGarrett D'Amore 513*698f87a4SGarrett D'Amore *v = mandoc_getarg(man->parse, v, line, pos); 51495c635efSGarrett D'Amore return(1); 51595c635efSGarrett D'Amore } 516