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
rew_warn(struct man * man,struct man_node * n,enum mandocerr er)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
man_unscope(struct man * man,const struct man_node * to,enum mandocerr er)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
rew_block(enum mant ntok,enum man_type type,const struct man_node * n)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
rew_dohalt(enum mant tok,enum man_type type,const struct man_node * n)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
rew_scope(enum man_type type,struct man * man,enum mant tok)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
blk_close(MACRO_PROT_ARGS)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
blk_exp(MACRO_PROT_ARGS)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
blk_imp(MACRO_PROT_ARGS)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
in_line_eoln(MACRO_PROT_ARGS)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
man_macroend(struct man * man)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
man_args(struct man * man,int line,int * pos,char * buf,char ** v)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