1*ffb8ebfaSGarrett D'Amore /* $Id: man_macro.c,v 1.79 2013/12/25 00:50:05 schwarze Exp $ */
232a712daSGarrett D'Amore /*
332a712daSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*ffb8ebfaSGarrett D'Amore * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
5*ffb8ebfaSGarrett D'Amore * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
632a712daSGarrett D'Amore *
732a712daSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
832a712daSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
932a712daSGarrett D'Amore * copyright notice and this permission notice appear in all copies.
1032a712daSGarrett D'Amore *
1132a712daSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1232a712daSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1332a712daSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1432a712daSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1532a712daSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1632a712daSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1732a712daSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1832a712daSGarrett D'Amore */
1932a712daSGarrett D'Amore #ifdef HAVE_CONFIG_H
2032a712daSGarrett D'Amore #include "config.h"
2132a712daSGarrett D'Amore #endif
2232a712daSGarrett D'Amore
2332a712daSGarrett D'Amore #include <assert.h>
2432a712daSGarrett D'Amore #include <ctype.h>
2532a712daSGarrett D'Amore #include <stdlib.h>
2632a712daSGarrett D'Amore #include <string.h>
2732a712daSGarrett D'Amore
2832a712daSGarrett D'Amore #include "man.h"
2932a712daSGarrett D'Amore #include "mandoc.h"
3032a712daSGarrett D'Amore #include "libmandoc.h"
3132a712daSGarrett D'Amore #include "libman.h"
3232a712daSGarrett D'Amore
3332a712daSGarrett D'Amore enum rew {
3432a712daSGarrett D'Amore REW_REWIND,
3532a712daSGarrett D'Amore REW_NOHALT,
3632a712daSGarrett D'Amore REW_HALT
3732a712daSGarrett D'Amore };
3832a712daSGarrett D'Amore
3932a712daSGarrett D'Amore static int blk_close(MACRO_PROT_ARGS);
4032a712daSGarrett D'Amore static int blk_exp(MACRO_PROT_ARGS);
4132a712daSGarrett D'Amore static int blk_imp(MACRO_PROT_ARGS);
4232a712daSGarrett D'Amore static int in_line_eoln(MACRO_PROT_ARGS);
4332a712daSGarrett D'Amore static int man_args(struct man *, int,
4432a712daSGarrett D'Amore int *, char *, char **);
4532a712daSGarrett D'Amore
4632a712daSGarrett D'Amore static int rew_scope(enum man_type,
4732a712daSGarrett D'Amore struct man *, enum mant);
4832a712daSGarrett D'Amore static enum rew rew_dohalt(enum mant, enum man_type,
4932a712daSGarrett D'Amore const struct man_node *);
5032a712daSGarrett D'Amore static enum rew rew_block(enum mant, enum man_type,
5132a712daSGarrett D'Amore const struct man_node *);
5232a712daSGarrett D'Amore static void rew_warn(struct man *,
5332a712daSGarrett D'Amore struct man_node *, enum mandocerr);
5432a712daSGarrett D'Amore
5532a712daSGarrett D'Amore const struct man_macro __man_macros[MAN_MAX] = {
5632a712daSGarrett D'Amore { in_line_eoln, MAN_NSCOPED }, /* br */
5732a712daSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* TH */
5832a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */
5932a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */
6032a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE | MAN_SCOPED | MAN_FSCOPED }, /* TP */
6132a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* LP */
6232a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* PP */
6332a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* P */
6432a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* IP */
6532a712daSGarrett D'Amore { blk_imp, MAN_BSCOPE }, /* HP */
6632a712daSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* SM */
6732a712daSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* SB */
6832a712daSGarrett D'Amore { in_line_eoln, 0 }, /* BI */
6932a712daSGarrett D'Amore { in_line_eoln, 0 }, /* IB */
7032a712daSGarrett D'Amore { in_line_eoln, 0 }, /* BR */
7132a712daSGarrett D'Amore { in_line_eoln, 0 }, /* RB */
7232a712daSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* R */
7332a712daSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* B */
7432a712daSGarrett D'Amore { in_line_eoln, MAN_SCOPED }, /* I */
7532a712daSGarrett D'Amore { in_line_eoln, 0 }, /* IR */
7632a712daSGarrett D'Amore { in_line_eoln, 0 }, /* RI */
7732a712daSGarrett D'Amore { in_line_eoln, MAN_NSCOPED }, /* na */
7832a712daSGarrett D'Amore { in_line_eoln, MAN_NSCOPED }, /* sp */
7932a712daSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* nf */
8032a712daSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* fi */
8132a712daSGarrett D'Amore { blk_close, 0 }, /* RE */
82*ffb8ebfaSGarrett D'Amore { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */
8332a712daSGarrett D'Amore { in_line_eoln, 0 }, /* DT */
8432a712daSGarrett D'Amore { in_line_eoln, 0 }, /* UC */
8532a712daSGarrett D'Amore { in_line_eoln, 0 }, /* PD */
8632a712daSGarrett D'Amore { in_line_eoln, 0 }, /* AT */
8732a712daSGarrett D'Amore { in_line_eoln, 0 }, /* in */
8832a712daSGarrett D'Amore { in_line_eoln, 0 }, /* ft */
8932a712daSGarrett D'Amore { in_line_eoln, 0 }, /* OP */
90*ffb8ebfaSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* EX */
91*ffb8ebfaSGarrett D'Amore { in_line_eoln, MAN_BSCOPE }, /* EE */
92*ffb8ebfaSGarrett D'Amore { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */
93*ffb8ebfaSGarrett D'Amore { blk_close, 0 }, /* UE */
9432a712daSGarrett D'Amore };
9532a712daSGarrett D'Amore
9632a712daSGarrett D'Amore const struct man_macro * const man_macros = __man_macros;
9732a712daSGarrett D'Amore
9832a712daSGarrett D'Amore
9932a712daSGarrett D'Amore /*
10032a712daSGarrett D'Amore * Warn when "n" is an explicit non-roff macro.
10132a712daSGarrett D'Amore */
10232a712daSGarrett D'Amore static void
rew_warn(struct man * man,struct man_node * n,enum mandocerr er)103*ffb8ebfaSGarrett D'Amore rew_warn(struct man *man, struct man_node *n, enum mandocerr er)
10432a712daSGarrett D'Amore {
10532a712daSGarrett D'Amore
10632a712daSGarrett D'Amore if (er == MANDOCERR_MAX || MAN_BLOCK != n->type)
10732a712daSGarrett D'Amore return;
10832a712daSGarrett D'Amore if (MAN_VALID & n->flags)
10932a712daSGarrett D'Amore return;
11032a712daSGarrett D'Amore if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
11132a712daSGarrett D'Amore return;
11232a712daSGarrett D'Amore
11332a712daSGarrett D'Amore assert(er < MANDOCERR_FATAL);
114*ffb8ebfaSGarrett D'Amore man_nmsg(man, n, er);
11532a712daSGarrett D'Amore }
11632a712daSGarrett D'Amore
11732a712daSGarrett D'Amore
11832a712daSGarrett D'Amore /*
11932a712daSGarrett D'Amore * Rewind scope. If a code "er" != MANDOCERR_MAX has been provided, it
12032a712daSGarrett D'Amore * will be used if an explicit block scope is being closed out.
12132a712daSGarrett D'Amore */
12232a712daSGarrett D'Amore int
man_unscope(struct man * man,const struct man_node * to,enum mandocerr er)123*ffb8ebfaSGarrett D'Amore man_unscope(struct man *man, const struct man_node *to,
12432a712daSGarrett D'Amore enum mandocerr er)
12532a712daSGarrett D'Amore {
12632a712daSGarrett D'Amore struct man_node *n;
12732a712daSGarrett D'Amore
12832a712daSGarrett D'Amore assert(to);
12932a712daSGarrett D'Amore
130*ffb8ebfaSGarrett D'Amore man->next = MAN_NEXT_SIBLING;
13132a712daSGarrett D'Amore
13232a712daSGarrett D'Amore /* LINTED */
133*ffb8ebfaSGarrett D'Amore while (man->last != to) {
13432a712daSGarrett D'Amore /*
13532a712daSGarrett D'Amore * Save the parent here, because we may delete the
136*ffb8ebfaSGarrett D'Amore * man->last node in the post-validation phase and reset
137*ffb8ebfaSGarrett D'Amore * it to man->last->parent, causing a step in the closing
13832a712daSGarrett D'Amore * out to be lost.
13932a712daSGarrett D'Amore */
140*ffb8ebfaSGarrett D'Amore n = man->last->parent;
141*ffb8ebfaSGarrett D'Amore rew_warn(man, man->last, er);
142*ffb8ebfaSGarrett D'Amore if ( ! man_valid_post(man))
14332a712daSGarrett D'Amore return(0);
144*ffb8ebfaSGarrett D'Amore man->last = n;
145*ffb8ebfaSGarrett D'Amore assert(man->last);
14632a712daSGarrett D'Amore }
14732a712daSGarrett D'Amore
148*ffb8ebfaSGarrett D'Amore rew_warn(man, man->last, er);
149*ffb8ebfaSGarrett D'Amore if ( ! man_valid_post(man))
15032a712daSGarrett D'Amore return(0);
15132a712daSGarrett D'Amore
15232a712daSGarrett D'Amore return(1);
15332a712daSGarrett D'Amore }
15432a712daSGarrett D'Amore
15532a712daSGarrett D'Amore
15632a712daSGarrett D'Amore static enum rew
rew_block(enum mant ntok,enum man_type type,const struct man_node * n)15732a712daSGarrett D'Amore rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
15832a712daSGarrett D'Amore {
15932a712daSGarrett D'Amore
16032a712daSGarrett D'Amore if (MAN_BLOCK == type && ntok == n->parent->tok &&
16132a712daSGarrett D'Amore MAN_BODY == n->parent->type)
16232a712daSGarrett D'Amore return(REW_REWIND);
16332a712daSGarrett D'Amore return(ntok == n->tok ? REW_HALT : REW_NOHALT);
16432a712daSGarrett D'Amore }
16532a712daSGarrett D'Amore
16632a712daSGarrett D'Amore
16732a712daSGarrett D'Amore /*
16832a712daSGarrett D'Amore * There are three scope levels: scoped to the root (all), scoped to the
16932a712daSGarrett D'Amore * section (all less sections), and scoped to subsections (all less
17032a712daSGarrett D'Amore * sections and subsections).
17132a712daSGarrett D'Amore */
17232a712daSGarrett D'Amore static enum rew
rew_dohalt(enum mant tok,enum man_type type,const struct man_node * n)17332a712daSGarrett D'Amore rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
17432a712daSGarrett D'Amore {
17532a712daSGarrett D'Amore enum rew c;
17632a712daSGarrett D'Amore
17732a712daSGarrett D'Amore /* We cannot progress beyond the root ever. */
17832a712daSGarrett D'Amore if (MAN_ROOT == n->type)
17932a712daSGarrett D'Amore return(REW_HALT);
18032a712daSGarrett D'Amore
18132a712daSGarrett D'Amore assert(n->parent);
18232a712daSGarrett D'Amore
18332a712daSGarrett D'Amore /* Normal nodes shouldn't go to the level of the root. */
18432a712daSGarrett D'Amore if (MAN_ROOT == n->parent->type)
18532a712daSGarrett D'Amore return(REW_REWIND);
18632a712daSGarrett D'Amore
18732a712daSGarrett D'Amore /* Already-validated nodes should be closed out. */
18832a712daSGarrett D'Amore if (MAN_VALID & n->flags)
18932a712daSGarrett D'Amore return(REW_NOHALT);
19032a712daSGarrett D'Amore
19132a712daSGarrett D'Amore /* First: rewind to ourselves. */
192*ffb8ebfaSGarrett D'Amore if (type == n->type && tok == n->tok) {
193*ffb8ebfaSGarrett D'Amore if (MAN_EXPLICIT & man_macros[n->tok].flags)
194*ffb8ebfaSGarrett D'Amore return(REW_HALT);
195*ffb8ebfaSGarrett D'Amore else
19632a712daSGarrett D'Amore return(REW_REWIND);
197*ffb8ebfaSGarrett D'Amore }
19832a712daSGarrett D'Amore
19932a712daSGarrett D'Amore /*
20032a712daSGarrett D'Amore * Next follow the implicit scope-smashings as defined by man.7:
20132a712daSGarrett D'Amore * section, sub-section, etc.
20232a712daSGarrett D'Amore */
20332a712daSGarrett D'Amore
20432a712daSGarrett D'Amore switch (tok) {
20532a712daSGarrett D'Amore case (MAN_SH):
20632a712daSGarrett D'Amore break;
20732a712daSGarrett D'Amore case (MAN_SS):
20832a712daSGarrett D'Amore /* Rewind to a section, if a block. */
20932a712daSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
21032a712daSGarrett D'Amore return(c);
21132a712daSGarrett D'Amore break;
21232a712daSGarrett D'Amore case (MAN_RS):
213*ffb8ebfaSGarrett D'Amore /* Preserve empty paragraphs before RS. */
214*ffb8ebfaSGarrett D'Amore if (0 == n->nchild && (MAN_P == n->tok ||
215*ffb8ebfaSGarrett D'Amore MAN_PP == n->tok || MAN_LP == n->tok))
216*ffb8ebfaSGarrett D'Amore return(REW_HALT);
21732a712daSGarrett D'Amore /* Rewind to a subsection, if a block. */
21832a712daSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
21932a712daSGarrett D'Amore return(c);
22032a712daSGarrett D'Amore /* Rewind to a section, if a block. */
22132a712daSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
22232a712daSGarrett D'Amore return(c);
22332a712daSGarrett D'Amore break;
22432a712daSGarrett D'Amore default:
22532a712daSGarrett D'Amore /* Rewind to an offsetter, if a block. */
22632a712daSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_RS, type, n)))
22732a712daSGarrett D'Amore return(c);
22832a712daSGarrett D'Amore /* Rewind to a subsection, if a block. */
22932a712daSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
23032a712daSGarrett D'Amore return(c);
23132a712daSGarrett D'Amore /* Rewind to a section, if a block. */
23232a712daSGarrett D'Amore if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
23332a712daSGarrett D'Amore return(c);
23432a712daSGarrett D'Amore break;
23532a712daSGarrett D'Amore }
23632a712daSGarrett D'Amore
23732a712daSGarrett D'Amore return(REW_NOHALT);
23832a712daSGarrett D'Amore }
23932a712daSGarrett D'Amore
24032a712daSGarrett D'Amore
24132a712daSGarrett D'Amore /*
24232a712daSGarrett D'Amore * Rewinding entails ascending the parse tree until a coherent point,
24332a712daSGarrett D'Amore * for example, the `SH' macro will close out any intervening `SS'
24432a712daSGarrett D'Amore * scopes. When a scope is closed, it must be validated and actioned.
24532a712daSGarrett D'Amore */
24632a712daSGarrett D'Amore static int
rew_scope(enum man_type type,struct man * man,enum mant tok)247*ffb8ebfaSGarrett D'Amore rew_scope(enum man_type type, struct man *man, enum mant tok)
24832a712daSGarrett D'Amore {
24932a712daSGarrett D'Amore struct man_node *n;
25032a712daSGarrett D'Amore enum rew c;
25132a712daSGarrett D'Amore
25232a712daSGarrett D'Amore /* LINTED */
253*ffb8ebfaSGarrett D'Amore for (n = man->last; n; n = n->parent) {
25432a712daSGarrett D'Amore /*
25532a712daSGarrett D'Amore * Whether we should stop immediately (REW_HALT), stop
25632a712daSGarrett D'Amore * and rewind until this point (REW_REWIND), or keep
25732a712daSGarrett D'Amore * rewinding (REW_NOHALT).
25832a712daSGarrett D'Amore */
25932a712daSGarrett D'Amore c = rew_dohalt(tok, type, n);
26032a712daSGarrett D'Amore if (REW_HALT == c)
26132a712daSGarrett D'Amore return(1);
26232a712daSGarrett D'Amore if (REW_REWIND == c)
26332a712daSGarrett D'Amore break;
26432a712daSGarrett D'Amore }
26532a712daSGarrett D'Amore
26632a712daSGarrett D'Amore /*
26732a712daSGarrett D'Amore * Rewind until the current point. Warn if we're a roff
26832a712daSGarrett D'Amore * instruction that's mowing over explicit scopes.
26932a712daSGarrett D'Amore */
27032a712daSGarrett D'Amore assert(n);
27132a712daSGarrett D'Amore
272*ffb8ebfaSGarrett D'Amore return(man_unscope(man, n, MANDOCERR_MAX));
27332a712daSGarrett D'Amore }
27432a712daSGarrett D'Amore
27532a712daSGarrett D'Amore
27632a712daSGarrett D'Amore /*
27732a712daSGarrett D'Amore * Close out a generic explicit macro.
27832a712daSGarrett D'Amore */
27932a712daSGarrett D'Amore /* ARGSUSED */
28032a712daSGarrett D'Amore int
blk_close(MACRO_PROT_ARGS)28132a712daSGarrett D'Amore blk_close(MACRO_PROT_ARGS)
28232a712daSGarrett D'Amore {
28332a712daSGarrett D'Amore enum mant ntok;
28432a712daSGarrett D'Amore const struct man_node *nn;
28532a712daSGarrett D'Amore
28632a712daSGarrett D'Amore switch (tok) {
28732a712daSGarrett D'Amore case (MAN_RE):
28832a712daSGarrett D'Amore ntok = MAN_RS;
28932a712daSGarrett D'Amore break;
290*ffb8ebfaSGarrett D'Amore case (MAN_UE):
291*ffb8ebfaSGarrett D'Amore ntok = MAN_UR;
292*ffb8ebfaSGarrett D'Amore break;
29332a712daSGarrett D'Amore default:
29432a712daSGarrett D'Amore abort();
29532a712daSGarrett D'Amore /* NOTREACHED */
29632a712daSGarrett D'Amore }
29732a712daSGarrett D'Amore
298*ffb8ebfaSGarrett D'Amore for (nn = man->last->parent; nn; nn = nn->parent)
299*ffb8ebfaSGarrett D'Amore if (ntok == nn->tok && MAN_BLOCK == nn->type)
30032a712daSGarrett D'Amore break;
30132a712daSGarrett D'Amore
302*ffb8ebfaSGarrett D'Amore if (NULL == nn) {
303*ffb8ebfaSGarrett D'Amore man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE);
304*ffb8ebfaSGarrett D'Amore if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
30532a712daSGarrett D'Amore return(0);
306*ffb8ebfaSGarrett D'Amore } else
307*ffb8ebfaSGarrett D'Amore man_unscope(man, nn, MANDOCERR_MAX);
30832a712daSGarrett D'Amore
30932a712daSGarrett D'Amore return(1);
31032a712daSGarrett D'Amore }
31132a712daSGarrett D'Amore
31232a712daSGarrett D'Amore
31332a712daSGarrett D'Amore /* ARGSUSED */
31432a712daSGarrett D'Amore int
blk_exp(MACRO_PROT_ARGS)31532a712daSGarrett D'Amore blk_exp(MACRO_PROT_ARGS)
31632a712daSGarrett D'Amore {
317*ffb8ebfaSGarrett D'Amore struct man_node *n;
31832a712daSGarrett D'Amore int la;
31932a712daSGarrett D'Amore char *p;
32032a712daSGarrett D'Amore
321*ffb8ebfaSGarrett D'Amore /* Close out prior implicit scopes. */
32232a712daSGarrett D'Amore
323*ffb8ebfaSGarrett D'Amore if ( ! rew_scope(MAN_BLOCK, man, tok))
32432a712daSGarrett D'Amore return(0);
325*ffb8ebfaSGarrett D'Amore
326*ffb8ebfaSGarrett D'Amore if ( ! man_block_alloc(man, line, ppos, tok))
327*ffb8ebfaSGarrett D'Amore return(0);
328*ffb8ebfaSGarrett D'Amore if ( ! man_head_alloc(man, line, ppos, tok))
32932a712daSGarrett D'Amore return(0);
33032a712daSGarrett D'Amore
33132a712daSGarrett D'Amore for (;;) {
33232a712daSGarrett D'Amore la = *pos;
333*ffb8ebfaSGarrett D'Amore if ( ! man_args(man, line, pos, buf, &p))
33432a712daSGarrett D'Amore break;
335*ffb8ebfaSGarrett D'Amore if ( ! man_word_alloc(man, line, la, p))
33632a712daSGarrett D'Amore return(0);
33732a712daSGarrett D'Amore }
33832a712daSGarrett D'Amore
339*ffb8ebfaSGarrett D'Amore assert(man);
34032a712daSGarrett D'Amore assert(tok != MAN_MAX);
34132a712daSGarrett D'Amore
342*ffb8ebfaSGarrett D'Amore for (n = man->last; n; n = n->parent) {
343*ffb8ebfaSGarrett D'Amore if (n->tok != tok)
344*ffb8ebfaSGarrett D'Amore continue;
345*ffb8ebfaSGarrett D'Amore assert(MAN_HEAD == n->type);
346*ffb8ebfaSGarrett D'Amore man_unscope(man, n, MANDOCERR_MAX);
347*ffb8ebfaSGarrett D'Amore break;
348*ffb8ebfaSGarrett D'Amore }
349*ffb8ebfaSGarrett D'Amore
350*ffb8ebfaSGarrett D'Amore return(man_body_alloc(man, line, ppos, tok));
35132a712daSGarrett D'Amore }
35232a712daSGarrett D'Amore
35332a712daSGarrett D'Amore
35432a712daSGarrett D'Amore
35532a712daSGarrett D'Amore /*
35632a712daSGarrett D'Amore * Parse an implicit-block macro. These contain a MAN_HEAD and a
35732a712daSGarrett D'Amore * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other
35832a712daSGarrett D'Amore * scopes, such as `SH' closing out an `SS', are defined in the rew
35932a712daSGarrett D'Amore * routines.
36032a712daSGarrett D'Amore */
36132a712daSGarrett D'Amore /* ARGSUSED */
36232a712daSGarrett D'Amore int
blk_imp(MACRO_PROT_ARGS)36332a712daSGarrett D'Amore blk_imp(MACRO_PROT_ARGS)
36432a712daSGarrett D'Amore {
36532a712daSGarrett D'Amore int la;
36632a712daSGarrett D'Amore char *p;
36732a712daSGarrett D'Amore struct man_node *n;
36832a712daSGarrett D'Amore
36932a712daSGarrett D'Amore /* Close out prior scopes. */
37032a712daSGarrett D'Amore
371*ffb8ebfaSGarrett D'Amore if ( ! rew_scope(MAN_BODY, man, tok))
37232a712daSGarrett D'Amore return(0);
373*ffb8ebfaSGarrett D'Amore if ( ! rew_scope(MAN_BLOCK, man, tok))
37432a712daSGarrett D'Amore return(0);
37532a712daSGarrett D'Amore
37632a712daSGarrett D'Amore /* Allocate new block & head scope. */
37732a712daSGarrett D'Amore
378*ffb8ebfaSGarrett D'Amore if ( ! man_block_alloc(man, line, ppos, tok))
37932a712daSGarrett D'Amore return(0);
380*ffb8ebfaSGarrett D'Amore if ( ! man_head_alloc(man, line, ppos, tok))
38132a712daSGarrett D'Amore return(0);
38232a712daSGarrett D'Amore
383*ffb8ebfaSGarrett D'Amore n = man->last;
38432a712daSGarrett D'Amore
38532a712daSGarrett D'Amore /* Add line arguments. */
38632a712daSGarrett D'Amore
38732a712daSGarrett D'Amore for (;;) {
38832a712daSGarrett D'Amore la = *pos;
389*ffb8ebfaSGarrett D'Amore if ( ! man_args(man, line, pos, buf, &p))
39032a712daSGarrett D'Amore break;
391*ffb8ebfaSGarrett D'Amore if ( ! man_word_alloc(man, line, la, p))
39232a712daSGarrett D'Amore return(0);
39332a712daSGarrett D'Amore }
39432a712daSGarrett D'Amore
39532a712daSGarrett D'Amore /* Close out head and open body (unless MAN_SCOPE). */
39632a712daSGarrett D'Amore
39732a712daSGarrett D'Amore if (MAN_SCOPED & man_macros[tok].flags) {
39832a712daSGarrett D'Amore /* If we're forcing scope (`TP'), keep it open. */
39932a712daSGarrett D'Amore if (MAN_FSCOPED & man_macros[tok].flags) {
400*ffb8ebfaSGarrett D'Amore man->flags |= MAN_BLINE;
40132a712daSGarrett D'Amore return(1);
402*ffb8ebfaSGarrett D'Amore } else if (n == man->last) {
403*ffb8ebfaSGarrett D'Amore man->flags |= MAN_BLINE;
40432a712daSGarrett D'Amore return(1);
40532a712daSGarrett D'Amore }
40632a712daSGarrett D'Amore }
40732a712daSGarrett D'Amore
408*ffb8ebfaSGarrett D'Amore if ( ! rew_scope(MAN_HEAD, man, tok))
40932a712daSGarrett D'Amore return(0);
410*ffb8ebfaSGarrett D'Amore return(man_body_alloc(man, line, ppos, tok));
41132a712daSGarrett D'Amore }
41232a712daSGarrett D'Amore
41332a712daSGarrett D'Amore
41432a712daSGarrett D'Amore /* ARGSUSED */
41532a712daSGarrett D'Amore int
in_line_eoln(MACRO_PROT_ARGS)41632a712daSGarrett D'Amore in_line_eoln(MACRO_PROT_ARGS)
41732a712daSGarrett D'Amore {
41832a712daSGarrett D'Amore int la;
41932a712daSGarrett D'Amore char *p;
42032a712daSGarrett D'Amore struct man_node *n;
42132a712daSGarrett D'Amore
422*ffb8ebfaSGarrett D'Amore if ( ! man_elem_alloc(man, line, ppos, tok))
42332a712daSGarrett D'Amore return(0);
42432a712daSGarrett D'Amore
425*ffb8ebfaSGarrett D'Amore n = man->last;
42632a712daSGarrett D'Amore
42732a712daSGarrett D'Amore for (;;) {
42832a712daSGarrett D'Amore la = *pos;
429*ffb8ebfaSGarrett D'Amore if ( ! man_args(man, line, pos, buf, &p))
43032a712daSGarrett D'Amore break;
431*ffb8ebfaSGarrett D'Amore if ( ! man_word_alloc(man, line, la, p))
43232a712daSGarrett D'Amore return(0);
43332a712daSGarrett D'Amore }
43432a712daSGarrett D'Amore
43532a712daSGarrett D'Amore /*
436*ffb8ebfaSGarrett D'Amore * Append MAN_EOS in case the last snipped argument
437*ffb8ebfaSGarrett D'Amore * ends with a dot, e.g. `.IR syslog (3).'
438*ffb8ebfaSGarrett D'Amore */
439*ffb8ebfaSGarrett D'Amore
440*ffb8ebfaSGarrett D'Amore if (n != man->last &&
441*ffb8ebfaSGarrett D'Amore mandoc_eos(man->last->string, strlen(man->last->string), 0))
442*ffb8ebfaSGarrett D'Amore man->last->flags |= MAN_EOS;
443*ffb8ebfaSGarrett D'Amore
444*ffb8ebfaSGarrett D'Amore /*
44532a712daSGarrett D'Amore * If no arguments are specified and this is MAN_SCOPED (i.e.,
44632a712daSGarrett D'Amore * next-line scoped), then set our mode to indicate that we're
44732a712daSGarrett D'Amore * waiting for terms to load into our context.
44832a712daSGarrett D'Amore */
44932a712daSGarrett D'Amore
450*ffb8ebfaSGarrett D'Amore if (n == man->last && MAN_SCOPED & man_macros[tok].flags) {
45132a712daSGarrett D'Amore assert( ! (MAN_NSCOPED & man_macros[tok].flags));
452*ffb8ebfaSGarrett D'Amore man->flags |= MAN_ELINE;
45332a712daSGarrett D'Amore return(1);
45432a712daSGarrett D'Amore }
45532a712daSGarrett D'Amore
45632a712daSGarrett D'Amore /* Set ignorable context, if applicable. */
45732a712daSGarrett D'Amore
45832a712daSGarrett D'Amore if (MAN_NSCOPED & man_macros[tok].flags) {
45932a712daSGarrett D'Amore assert( ! (MAN_SCOPED & man_macros[tok].flags));
460*ffb8ebfaSGarrett D'Amore man->flags |= MAN_ILINE;
46132a712daSGarrett D'Amore }
46232a712daSGarrett D'Amore
463*ffb8ebfaSGarrett D'Amore assert(MAN_ROOT != man->last->type);
464*ffb8ebfaSGarrett D'Amore man->next = MAN_NEXT_SIBLING;
46532a712daSGarrett D'Amore
46632a712daSGarrett D'Amore /*
46732a712daSGarrett D'Amore * Rewind our element scope. Note that when TH is pruned, we'll
46832a712daSGarrett D'Amore * be back at the root, so make sure that we don't clobber as
46932a712daSGarrett D'Amore * its sibling.
47032a712daSGarrett D'Amore */
47132a712daSGarrett D'Amore
472*ffb8ebfaSGarrett D'Amore for ( ; man->last; man->last = man->last->parent) {
473*ffb8ebfaSGarrett D'Amore if (man->last == n)
47432a712daSGarrett D'Amore break;
475*ffb8ebfaSGarrett D'Amore if (man->last->type == MAN_ROOT)
47632a712daSGarrett D'Amore break;
477*ffb8ebfaSGarrett D'Amore if ( ! man_valid_post(man))
47832a712daSGarrett D'Amore return(0);
47932a712daSGarrett D'Amore }
48032a712daSGarrett D'Amore
481*ffb8ebfaSGarrett D'Amore assert(man->last);
48232a712daSGarrett D'Amore
48332a712daSGarrett D'Amore /*
48432a712daSGarrett D'Amore * Same here regarding whether we're back at the root.
48532a712daSGarrett D'Amore */
48632a712daSGarrett D'Amore
487*ffb8ebfaSGarrett D'Amore if (man->last->type != MAN_ROOT && ! man_valid_post(man))
48832a712daSGarrett D'Amore return(0);
48932a712daSGarrett D'Amore
49032a712daSGarrett D'Amore return(1);
49132a712daSGarrett D'Amore }
49232a712daSGarrett D'Amore
49332a712daSGarrett D'Amore
49432a712daSGarrett D'Amore int
man_macroend(struct man * man)495*ffb8ebfaSGarrett D'Amore man_macroend(struct man *man)
49632a712daSGarrett D'Amore {
49732a712daSGarrett D'Amore
498*ffb8ebfaSGarrett D'Amore return(man_unscope(man, man->first, MANDOCERR_SCOPEEXIT));
49932a712daSGarrett D'Amore }
50032a712daSGarrett D'Amore
50132a712daSGarrett D'Amore static int
man_args(struct man * man,int line,int * pos,char * buf,char ** v)502*ffb8ebfaSGarrett D'Amore man_args(struct man *man, int line, int *pos, char *buf, char **v)
50332a712daSGarrett D'Amore {
50432a712daSGarrett D'Amore char *start;
50532a712daSGarrett D'Amore
50632a712daSGarrett D'Amore assert(*pos);
50732a712daSGarrett D'Amore *v = start = buf + *pos;
50832a712daSGarrett D'Amore assert(' ' != *start);
50932a712daSGarrett D'Amore
51032a712daSGarrett D'Amore if ('\0' == *start)
51132a712daSGarrett D'Amore return(0);
51232a712daSGarrett D'Amore
513*ffb8ebfaSGarrett D'Amore *v = mandoc_getarg(man->parse, v, line, pos);
51432a712daSGarrett D'Amore return(1);
51532a712daSGarrett D'Amore }
516