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}
|