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