Annotation of mandoc/mdoc_macro.c, Revision 1.150
1.150 ! schwarze 1: /* $Id: mdoc_macro.c,v 1.149 2014/11/28 01:05:43 schwarze Exp $ */
1.1 kristaps 2: /*
1.116 schwarze 3: * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
1.143 schwarze 4: * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 5: *
6: * Permission to use, copy, modify, and distribute this software for any
1.8 kristaps 7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
1.1 kristaps 9: *
1.8 kristaps 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 kristaps 17: */
1.40 kristaps 18: #include "config.h"
1.140 schwarze 19:
20: #include <sys/types.h>
1.40 kristaps 21:
1.1 kristaps 22: #include <assert.h>
23: #include <ctype.h>
24: #include <stdlib.h>
25: #include <stdio.h>
26: #include <string.h>
1.38 kristaps 27: #include <time.h>
1.1 kristaps 28:
1.106 kristaps 29: #include "mdoc.h"
1.68 kristaps 30: #include "mandoc.h"
1.1 kristaps 31: #include "libmdoc.h"
1.64 kristaps 32: #include "libmandoc.h"
1.1 kristaps 33:
1.84 schwarze 34: enum rew { /* see rew_dohalt() */
35: REWIND_NONE,
36: REWIND_THIS,
37: REWIND_MORE,
1.98 kristaps 38: REWIND_FORCE,
1.84 schwarze 39: REWIND_LATER,
1.91 kristaps 40: REWIND_ERROR
1.51 kristaps 41: };
1.1 kristaps 42:
1.131 schwarze 43: static int blk_full(MACRO_PROT_ARGS);
44: static int blk_exp_close(MACRO_PROT_ARGS);
45: static int blk_part_exp(MACRO_PROT_ARGS);
46: static int blk_part_imp(MACRO_PROT_ARGS);
47: static int ctx_synopsis(MACRO_PROT_ARGS);
48: static int in_line_eoln(MACRO_PROT_ARGS);
49: static int in_line_argn(MACRO_PROT_ARGS);
50: static int in_line(MACRO_PROT_ARGS);
51: static int phrase_ta(MACRO_PROT_ARGS);
1.53 kristaps 52:
1.150 ! schwarze 53: static void dword(struct mdoc *, int, int, const char *,
1.123 schwarze 54: enum mdelim, int);
1.150 ! schwarze 55: static void append_delims(struct mdoc *, int, int *, char *);
1.58 kristaps 56: static enum mdoct lookup(enum mdoct, const char *);
1.53 kristaps 57: static enum mdoct lookup_raw(const char *);
1.85 schwarze 58: static int make_pending(struct mdoc_node *, enum mdoct,
1.83 schwarze 59: struct mdoc *, int, int);
1.131 schwarze 60: static int phrase(struct mdoc *, int, int, char *);
61: static enum mdoct rew_alt(enum mdoct);
62: static enum rew rew_dohalt(enum mdoct, enum mdoc_type,
1.53 kristaps 63: const struct mdoc_node *);
1.149 schwarze 64: static void rew_elem(struct mdoc *, enum mdoct);
65: static void rew_last(struct mdoc *, const struct mdoc_node *);
1.150 ! schwarze 66: static void rew_sub(enum mdoc_type, struct mdoc *,
1.53 kristaps 67: enum mdoct, int, int);
1.1 kristaps 68:
69: const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
1.123 schwarze 70: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
1.1 kristaps 71: { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
72: { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
73: { in_line_eoln, MDOC_PROLOGUE }, /* Os */
1.123 schwarze 74: { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */
75: { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Ss */
76: { in_line_eoln, 0 }, /* Pp */
77: { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* D1 */
78: { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* Dl */
1.1 kristaps 79: { blk_full, MDOC_EXPLICIT }, /* Bd */
1.123 schwarze 80: { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */
1.1 kristaps 81: { blk_full, MDOC_EXPLICIT }, /* Bl */
1.123 schwarze 82: { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* El */
83: { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */
84: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
85: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */
1.1 kristaps 86: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
1.129 schwarze 87: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */
1.1 kristaps 88: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
1.123 schwarze 89: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
90: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
91: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
1.1 kristaps 92: { in_line_eoln, 0 }, /* Ex */
1.123 schwarze 93: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
94: { in_line_eoln, 0 }, /* Fd */
1.1 kristaps 95: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
1.123 schwarze 96: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
97: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
1.128 schwarze 98: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ic */
1.18 kristaps 99: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
1.123 schwarze 100: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Li */
101: { blk_full, MDOC_JOIN }, /* Nd */
102: { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
1.1 kristaps 103: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
1.132 schwarze 104: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ot */
1.1 kristaps 105: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
106: { in_line_eoln, 0 }, /* Rv */
1.123 schwarze 107: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
1.1 kristaps 108: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
1.123 schwarze 109: { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
1.42 kristaps 110: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
1.123 schwarze 111: { in_line_eoln, MDOC_JOIN }, /* %A */
112: { in_line_eoln, MDOC_JOIN }, /* %B */
113: { in_line_eoln, MDOC_JOIN }, /* %D */
114: { in_line_eoln, MDOC_JOIN }, /* %I */
115: { in_line_eoln, MDOC_JOIN }, /* %J */
1.1 kristaps 116: { in_line_eoln, 0 }, /* %N */
1.123 schwarze 117: { in_line_eoln, MDOC_JOIN }, /* %O */
1.1 kristaps 118: { in_line_eoln, 0 }, /* %P */
1.123 schwarze 119: { in_line_eoln, MDOC_JOIN }, /* %R */
120: { in_line_eoln, MDOC_JOIN }, /* %T */
1.1 kristaps 121: { in_line_eoln, 0 }, /* %V */
1.123 schwarze 122: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
123: MDOC_EXPLICIT | MDOC_JOIN }, /* Ac */
124: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
125: MDOC_EXPLICIT | MDOC_JOIN }, /* Ao */
126: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Aq */
1.1 kristaps 127: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
1.123 schwarze 128: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
129: MDOC_EXPLICIT | MDOC_JOIN }, /* Bc */
130: { blk_full, MDOC_EXPLICIT }, /* Bf */
131: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
132: MDOC_EXPLICIT | MDOC_JOIN }, /* Bo */
133: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Bq */
1.1 kristaps 134: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
135: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
136: { in_line_eoln, 0 }, /* Db */
1.123 schwarze 137: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
138: MDOC_EXPLICIT | MDOC_JOIN }, /* Dc */
139: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
140: MDOC_EXPLICIT | MDOC_JOIN }, /* Do */
141: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Dq */
142: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ec */
143: { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ef */
144: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Em */
1.1 kristaps 145: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
146: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
1.11 kristaps 147: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
1.144 schwarze 148: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* No */
1.123 schwarze 149: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
150: MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */
1.1 kristaps 151: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
152: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
1.123 schwarze 153: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
154: MDOC_EXPLICIT | MDOC_JOIN }, /* Pc */
1.52 kristaps 155: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
1.123 schwarze 156: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
157: MDOC_EXPLICIT | MDOC_JOIN }, /* Po */
158: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Pq */
159: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
160: MDOC_EXPLICIT | MDOC_JOIN }, /* Qc */
161: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ql */
162: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
163: MDOC_EXPLICIT | MDOC_JOIN }, /* Qo */
164: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Qq */
165: { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Re */
1.1 kristaps 166: { blk_full, MDOC_EXPLICIT }, /* Rs */
1.123 schwarze 167: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
168: MDOC_EXPLICIT | MDOC_JOIN }, /* Sc */
169: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
170: MDOC_EXPLICIT | MDOC_JOIN }, /* So */
171: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */
1.147 schwarze 172: { in_line_argn, 0 }, /* Sm */
1.123 schwarze 173: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */
174: { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */
1.1 kristaps 175: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
1.123 schwarze 176: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ux */
1.1 kristaps 177: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
178: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
1.123 schwarze 179: { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
180: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
181: MDOC_EXPLICIT | MDOC_JOIN }, /* Fc */
182: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
183: MDOC_EXPLICIT | MDOC_JOIN }, /* Oo */
184: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
185: MDOC_EXPLICIT | MDOC_JOIN }, /* Oc */
1.1 kristaps 186: { blk_full, MDOC_EXPLICIT }, /* Bk */
1.123 schwarze 187: { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ek */
1.1 kristaps 188: { in_line_eoln, 0 }, /* Bt */
189: { in_line_eoln, 0 }, /* Hf */
1.132 schwarze 190: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fr */
1.1 kristaps 191: { in_line_eoln, 0 }, /* Ud */
1.69 kristaps 192: { in_line, 0 }, /* Lb */
1.123 schwarze 193: { in_line_eoln, 0 }, /* Lp */
194: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
195: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
196: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */
197: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
198: MDOC_EXPLICIT | MDOC_JOIN }, /* Bro */
199: { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
200: MDOC_EXPLICIT | MDOC_JOIN }, /* Brc */
201: { in_line_eoln, MDOC_JOIN }, /* %C */
1.132 schwarze 202: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Es */
203: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* En */
1.1 kristaps 204: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
1.123 schwarze 205: { in_line_eoln, MDOC_JOIN }, /* %Q */
1.20 kristaps 206: { in_line_eoln, 0 }, /* br */
207: { in_line_eoln, 0 }, /* sp */
1.37 kristaps 208: { in_line_eoln, 0 }, /* %U */
1.123 schwarze 209: { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
1.143 schwarze 210: { in_line_eoln, MDOC_PROLOGUE }, /* ll */
1.1 kristaps 211: };
212:
213: const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
214:
215:
216: /*
217: * This is called at the end of parsing. It must traverse up the tree,
218: * closing out open [implicit] scopes. Obviously, open explicit scopes
219: * are errors.
220: */
221: int
1.119 schwarze 222: mdoc_macroend(struct mdoc *mdoc)
1.1 kristaps 223: {
224: struct mdoc_node *n;
225:
226: /* Scan for open explicit scopes. */
227:
1.119 schwarze 228: n = MDOC_VALID & mdoc->last->flags ?
1.131 schwarze 229: mdoc->last->parent : mdoc->last;
1.1 kristaps 230:
1.94 schwarze 231: for ( ; n; n = n->parent)
232: if (MDOC_BLOCK == n->type &&
233: MDOC_EXPLICIT & mdoc_macros[n->tok].flags)
1.137 schwarze 234: mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,
235: n->line, n->pos, mdoc_macronames[n->tok]);
1.1 kristaps 236:
1.32 kristaps 237: /* Rewind to the first. */
238:
1.149 schwarze 239: rew_last(mdoc, mdoc->first);
240: return(1);
1.1 kristaps 241: }
242:
1.32 kristaps 243: /*
244: * Look up a macro from within a subsequent context.
245: */
1.53 kristaps 246: static enum mdoct
1.58 kristaps 247: lookup(enum mdoct from, const char *p)
1.28 kristaps 248: {
249:
250: if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
251: return(MDOC_MAX);
1.35 kristaps 252: return(lookup_raw(p));
1.28 kristaps 253: }
254:
1.32 kristaps 255: /*
256: * Lookup a macro following the initial line macro.
257: */
1.53 kristaps 258: static enum mdoct
1.35 kristaps 259: lookup_raw(const char *p)
1.1 kristaps 260: {
1.58 kristaps 261: enum mdoct res;
1.1 kristaps 262:
1.34 kristaps 263: if (MDOC_MAX == (res = mdoc_hash_find(p)))
1.28 kristaps 264: return(MDOC_MAX);
265: if (MDOC_CALLABLE & mdoc_macros[res].flags)
1.1 kristaps 266: return(res);
267: return(MDOC_MAX);
268: }
269:
1.149 schwarze 270: static void
1.32 kristaps 271: rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
1.1 kristaps 272: {
1.100 kristaps 273: struct mdoc_node *n, *np;
1.1 kristaps 274:
275: assert(to);
276: mdoc->next = MDOC_NEXT_SIBLING;
277: while (mdoc->last != to) {
1.100 kristaps 278: /*
279: * Save the parent here, because we may delete the
1.119 schwarze 280: * mdoc->last node in the post-validation phase and reset
281: * it to mdoc->last->parent, causing a step in the closing
1.100 kristaps 282: * out to be lost.
283: */
284: np = mdoc->last->parent;
1.149 schwarze 285: mdoc_valid_post(mdoc);
1.99 kristaps 286: n = mdoc->last;
1.100 kristaps 287: mdoc->last = np;
1.1 kristaps 288: assert(mdoc->last);
1.99 kristaps 289: mdoc->last->last = n;
1.1 kristaps 290: }
1.149 schwarze 291: mdoc_valid_post(mdoc);
1.1 kristaps 292: }
293:
1.32 kristaps 294: /*
1.84 schwarze 295: * For a block closing macro, return the corresponding opening one.
296: * Otherwise, return the macro itself.
1.32 kristaps 297: */
1.47 kristaps 298: static enum mdoct
299: rew_alt(enum mdoct tok)
1.1 kristaps 300: {
301: switch (tok) {
1.131 schwarze 302: case MDOC_Ac:
1.1 kristaps 303: return(MDOC_Ao);
1.131 schwarze 304: case MDOC_Bc:
1.1 kristaps 305: return(MDOC_Bo);
1.131 schwarze 306: case MDOC_Brc:
1.1 kristaps 307: return(MDOC_Bro);
1.131 schwarze 308: case MDOC_Dc:
1.1 kristaps 309: return(MDOC_Do);
1.131 schwarze 310: case MDOC_Ec:
1.1 kristaps 311: return(MDOC_Eo);
1.131 schwarze 312: case MDOC_Ed:
1.1 kristaps 313: return(MDOC_Bd);
1.131 schwarze 314: case MDOC_Ef:
1.1 kristaps 315: return(MDOC_Bf);
1.131 schwarze 316: case MDOC_Ek:
1.1 kristaps 317: return(MDOC_Bk);
1.131 schwarze 318: case MDOC_El:
1.1 kristaps 319: return(MDOC_Bl);
1.131 schwarze 320: case MDOC_Fc:
1.1 kristaps 321: return(MDOC_Fo);
1.131 schwarze 322: case MDOC_Oc:
1.1 kristaps 323: return(MDOC_Oo);
1.131 schwarze 324: case MDOC_Pc:
1.1 kristaps 325: return(MDOC_Po);
1.131 schwarze 326: case MDOC_Qc:
1.1 kristaps 327: return(MDOC_Qo);
1.131 schwarze 328: case MDOC_Re:
1.1 kristaps 329: return(MDOC_Rs);
1.131 schwarze 330: case MDOC_Sc:
1.1 kristaps 331: return(MDOC_So);
1.131 schwarze 332: case MDOC_Xc:
1.1 kristaps 333: return(MDOC_Xo);
334: default:
1.84 schwarze 335: return(tok);
1.1 kristaps 336: }
337: /* NOTREACHED */
338: }
339:
1.84 schwarze 340: /*
341: * Rewinding to tok, how do we have to handle *p?
342: * REWIND_NONE: *p would delimit tok, but no tok scope is open
343: * inside *p, so there is no need to rewind anything at all.
344: * REWIND_THIS: *p matches tok, so rewind *p and nothing else.
345: * REWIND_MORE: *p is implicit, rewind it and keep searching for tok.
1.98 kristaps 346: * REWIND_FORCE: *p is explicit, but tok is full, force rewinding *p.
1.84 schwarze 347: * REWIND_LATER: *p is explicit and still open, postpone rewinding.
348: * REWIND_ERROR: No tok block is open at all.
1.1 kristaps 349: */
1.51 kristaps 350: static enum rew
1.131 schwarze 351: rew_dohalt(enum mdoct tok, enum mdoc_type type,
1.47 kristaps 352: const struct mdoc_node *p)
1.1 kristaps 353: {
354:
1.86 schwarze 355: /*
356: * No matching token, no delimiting block, no broken block.
357: * This can happen when full implicit macros are called for
358: * the first time but try to rewind their previous
359: * instance anyway.
360: */
1.1 kristaps 361: if (MDOC_ROOT == p->type)
1.84 schwarze 362: return(MDOC_BLOCK == type &&
363: MDOC_EXPLICIT & mdoc_macros[tok].flags ?
364: REWIND_ERROR : REWIND_NONE);
1.86 schwarze 365:
366: /*
1.131 schwarze 367: * When starting to rewind, skip plain text
1.86 schwarze 368: * and nodes that have already been rewound.
369: */
1.84 schwarze 370: if (MDOC_TEXT == p->type || MDOC_VALID & p->flags)
371: return(REWIND_MORE);
372:
1.86 schwarze 373: /*
374: * The easiest case: Found a matching token.
375: * This applies to both blocks and elements.
376: */
1.84 schwarze 377: tok = rew_alt(tok);
378: if (tok == p->tok)
379: return(p->end ? REWIND_NONE :
380: type == p->type ? REWIND_THIS : REWIND_MORE);
381:
1.86 schwarze 382: /*
383: * While elements do require rewinding for themselves,
384: * they never affect rewinding of other nodes.
385: */
1.84 schwarze 386: if (MDOC_ELEM == p->type)
387: return(REWIND_MORE);
1.1 kristaps 388:
1.86 schwarze 389: /*
390: * Blocks delimited by our target token get REWIND_MORE.
1.131 schwarze 391: * Blocks delimiting our target token get REWIND_NONE.
1.86 schwarze 392: */
1.1 kristaps 393: switch (tok) {
1.131 schwarze 394: case MDOC_Bl:
1.84 schwarze 395: if (MDOC_It == p->tok)
396: return(REWIND_MORE);
1.1 kristaps 397: break;
1.131 schwarze 398: case MDOC_It:
1.1 kristaps 399: if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
1.84 schwarze 400: return(REWIND_NONE);
1.1 kristaps 401: break;
1.84 schwarze 402: /*
403: * XXX Badly nested block handling still fails badly
404: * when one block is breaking two blocks of the same type.
405: * This is an incomplete and extremely ugly workaround,
406: * required to let the OpenBSD tree build.
407: */
1.131 schwarze 408: case MDOC_Oo:
1.84 schwarze 409: if (MDOC_Op == p->tok)
410: return(REWIND_MORE);
1.1 kristaps 411: break;
1.131 schwarze 412: case MDOC_Nm:
1.88 schwarze 413: return(REWIND_NONE);
1.131 schwarze 414: case MDOC_Nd:
1.19 kristaps 415: /* FALLTHROUGH */
1.131 schwarze 416: case MDOC_Ss:
1.1 kristaps 417: if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
1.84 schwarze 418: return(REWIND_NONE);
1.1 kristaps 419: /* FALLTHROUGH */
1.131 schwarze 420: case MDOC_Sh:
1.138 schwarze 421: if (MDOC_ROOT == p->parent->type)
422: return(REWIND_THIS);
1.84 schwarze 423: if (MDOC_Nd == p->tok || MDOC_Ss == p->tok ||
424: MDOC_Sh == p->tok)
425: return(REWIND_MORE);
1.1 kristaps 426: break;
427: default:
428: break;
429: }
430:
1.86 schwarze 431: /*
432: * Default block rewinding rules.
1.88 schwarze 433: * In particular, always skip block end markers,
434: * and let all blocks rewind Nm children.
1.146 schwarze 435: * Do not warn again when closing a block,
436: * since closing the body already warned.
1.86 schwarze 437: */
1.88 schwarze 438: if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok ||
1.146 schwarze 439: MDOC_BLOCK == type || (MDOC_BLOCK == p->type &&
1.86 schwarze 440: ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)))
441: return(REWIND_MORE);
442:
443: /*
1.98 kristaps 444: * By default, closing out full blocks
445: * forces closing of broken explicit blocks,
446: * while closing out partial blocks
447: * allows delayed rewinding by default.
1.86 schwarze 448: */
1.98 kristaps 449: return (&blk_full == mdoc_macros[tok].fp ?
450: REWIND_FORCE : REWIND_LATER);
1.1 kristaps 451: }
452:
1.149 schwarze 453: static void
1.47 kristaps 454: rew_elem(struct mdoc *mdoc, enum mdoct tok)
1.1 kristaps 455: {
456: struct mdoc_node *n;
457:
458: n = mdoc->last;
459: if (MDOC_ELEM != n->type)
460: n = n->parent;
461: assert(MDOC_ELEM == n->type);
462: assert(tok == n->tok);
1.149 schwarze 463: rew_last(mdoc, n);
1.1 kristaps 464: }
465:
1.83 schwarze 466: /*
467: * We are trying to close a block identified by tok,
468: * but the child block *broken is still open.
469: * Thus, postpone closing the tok block
470: * until the rew_sub call closing *broken.
471: */
472: static int
473: make_pending(struct mdoc_node *broken, enum mdoct tok,
1.119 schwarze 474: struct mdoc *mdoc, int line, int ppos)
1.83 schwarze 475: {
476: struct mdoc_node *breaker;
477:
478: /*
479: * Iterate backwards, searching for the block matching tok,
480: * that is, the block breaking the *broken block.
481: */
482: for (breaker = broken->parent; breaker; breaker = breaker->parent) {
483:
484: /*
485: * If the *broken block had already been broken before
486: * and we encounter its breaker, make the tok block
487: * pending on the inner breaker.
488: * Graphically, "[A breaker=[B broken=[C->B B] tok=A] C]"
489: * becomes "[A broken=[B [C->B B] tok=A] C]"
490: * and finally "[A [B->A [C->B B] A] C]".
491: */
492: if (breaker == broken->pending) {
493: broken = breaker;
494: continue;
495: }
496:
1.84 schwarze 497: if (REWIND_THIS != rew_dohalt(tok, MDOC_BLOCK, breaker))
1.83 schwarze 498: continue;
499: if (MDOC_BODY == broken->type)
500: broken = broken->parent;
501:
502: /*
503: * Found the breaker.
504: * If another, outer breaker is already pending on
505: * the *broken block, we must not clobber the link
506: * to the outer breaker, but make it pending on the
507: * new, now inner breaker.
508: * Graphically, "[A breaker=[B broken=[C->A A] tok=B] C]"
509: * becomes "[A breaker=[B->A broken=[C A] tok=B] C]"
510: * and finally "[A [B->A [C->B A] B] C]".
511: */
512: if (broken->pending) {
513: struct mdoc_node *taker;
514:
515: /*
516: * If the breaker had also been broken before,
517: * it cannot take on the outer breaker itself,
518: * but must hand it on to its own breakers.
519: * Graphically, this is the following situation:
520: * "[A [B breaker=[C->B B] broken=[D->A A] tok=C] D]"
521: * "[A taker=[B->A breaker=[C->B B] [D->C A] C] D]"
522: */
523: taker = breaker;
524: while (taker->pending)
525: taker = taker->pending;
526: taker->pending = broken->pending;
527: }
528: broken->pending = breaker;
1.137 schwarze 529: mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos,
1.131 schwarze 530: "%s breaks %s", mdoc_macronames[tok],
531: mdoc_macronames[broken->tok]);
1.83 schwarze 532: return(1);
533: }
534:
535: /*
536: * Found no matching block for tok.
537: * Are you trying to close a block that is not open?
538: */
539: return(0);
540: }
541:
1.150 ! schwarze 542: static void
1.131 schwarze 543: rew_sub(enum mdoc_type t, struct mdoc *mdoc,
1.47 kristaps 544: enum mdoct tok, int line, int ppos)
1.1 kristaps 545: {
546: struct mdoc_node *n;
547:
1.119 schwarze 548: n = mdoc->last;
1.84 schwarze 549: while (n) {
550: switch (rew_dohalt(tok, t, n)) {
1.131 schwarze 551: case REWIND_NONE:
1.150 ! schwarze 552: return;
1.131 schwarze 553: case REWIND_THIS:
1.124 schwarze 554: n->lastline = line -
1.150 ! schwarze 555: (mdoc->flags & MDOC_NEWLINE &&
! 556: ! (mdoc_macros[tok].flags & MDOC_EXPLICIT));
1.84 schwarze 557: break;
1.131 schwarze 558: case REWIND_FORCE:
1.137 schwarze 559: mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse,
1.131 schwarze 560: line, ppos, "%s breaks %s",
561: mdoc_macronames[tok],
562: mdoc_macronames[n->tok]);
1.98 kristaps 563: /* FALLTHROUGH */
1.131 schwarze 564: case REWIND_MORE:
1.124 schwarze 565: n->lastline = line -
1.150 ! schwarze 566: (mdoc->flags & MDOC_NEWLINE ? 1 : 0);
1.84 schwarze 567: n = n->parent;
568: continue;
1.131 schwarze 569: case REWIND_LATER:
1.119 schwarze 570: if (make_pending(n, tok, mdoc, line, ppos) ||
1.150 ! schwarze 571: t != MDOC_BLOCK)
! 572: return;
1.98 kristaps 573: /* FALLTHROUGH */
1.131 schwarze 574: case REWIND_ERROR:
1.137 schwarze 575: mandoc_msg(MANDOCERR_BLK_NOTOPEN,
576: mdoc->parse, line, ppos,
577: mdoc_macronames[tok]);
1.150 ! schwarze 578: return;
1.32 kristaps 579: }
1.84 schwarze 580: break;
1.1 kristaps 581: }
582: assert(n);
1.149 schwarze 583: rew_last(mdoc, n);
1.47 kristaps 584:
585: /*
1.83 schwarze 586: * The current block extends an enclosing block.
587: * Now that the current block ends, close the enclosing block, too.
1.47 kristaps 588: */
1.150 ! schwarze 589: while ((n = n->pending) != NULL) {
1.149 schwarze 590: rew_last(mdoc, n);
1.150 ! schwarze 591: if (n->type == MDOC_HEAD)
! 592: mdoc_body_alloc(mdoc, n->line, n->pos, n->tok);
1.47 kristaps 593: }
1.1 kristaps 594: }
595:
1.105 kristaps 596: /*
597: * Allocate a word and check whether it's punctuation or not.
598: * Punctuation consists of those tokens found in mdoc_isdelim().
599: */
1.150 ! schwarze 600: static void
1.123 schwarze 601: dword(struct mdoc *mdoc, int line, int col, const char *p,
602: enum mdelim d, int may_append)
1.105 kristaps 603: {
1.131 schwarze 604:
1.150 ! schwarze 605: if (d == DELIM_MAX)
1.105 kristaps 606: d = mdoc_isdelim(p);
607:
1.123 schwarze 608: if (may_append &&
1.150 ! schwarze 609: ! (mdoc->flags & (MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF)) &&
! 610: d == DELIM_NONE && mdoc->last->type == MDOC_TEXT &&
! 611: mdoc_isdelim(mdoc->last->string) == DELIM_NONE) {
1.123 schwarze 612: mdoc_word_append(mdoc, p);
1.150 ! schwarze 613: return;
1.123 schwarze 614: }
615:
1.150 ! schwarze 616: mdoc_word_alloc(mdoc, line, col, p);
1.105 kristaps 617:
1.108 schwarze 618: /*
1.144 schwarze 619: * If the word consists of a bare delimiter,
620: * flag the new node accordingly,
621: * unless doing so was vetoed by the invoking macro.
622: * Always clear the veto, it is only valid for one word.
1.108 schwarze 623: */
624:
1.144 schwarze 625: if (d == DELIM_OPEN)
626: mdoc->last->flags |= MDOC_DELIMO;
627: else if (d == DELIM_CLOSE &&
628: ! (mdoc->flags & MDOC_NODELIMC) &&
1.131 schwarze 629: mdoc->last->parent->tok != MDOC_Fd)
1.119 schwarze 630: mdoc->last->flags |= MDOC_DELIMC;
1.144 schwarze 631: mdoc->flags &= ~MDOC_NODELIMC;
1.105 kristaps 632: }
1.1 kristaps 633:
1.150 ! schwarze 634: static void
1.119 schwarze 635: append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
1.1 kristaps 636: {
1.66 kristaps 637: int la;
1.55 kristaps 638: enum margserr ac;
1.1 kristaps 639: char *p;
640:
1.150 ! schwarze 641: if (buf[*pos] == '\0')
! 642: return;
1.1 kristaps 643:
644: for (;;) {
1.66 kristaps 645: la = *pos;
1.119 schwarze 646: ac = mdoc_zargs(mdoc, line, pos, buf, &p);
1.150 ! schwarze 647: if (ac == ARGS_EOLN)
1.1 kristaps 648: break;
1.123 schwarze 649: dword(mdoc, line, la, p, DELIM_MAX, 1);
1.66 kristaps 650:
651: /*
652: * If we encounter end-of-sentence symbols, then trigger
653: * the double-space.
654: *
1.109 kristaps 655: * XXX: it's easy to allow this to propagate outward to
1.66 kristaps 656: * the last symbol, such that `. )' will cause the
657: * correct double-spacing. However, (1) groff isn't
658: * smart enough to do this and (2) it would require
659: * knowing which symbols break this behaviour, for
1.109 kristaps 660: * example, `. ;' shouldn't propagate the double-space.
1.66 kristaps 661: */
1.150 ! schwarze 662:
1.127 schwarze 663: if (mandoc_eos(p, strlen(p)))
1.119 schwarze 664: mdoc->last->flags |= MDOC_EOS;
1.1 kristaps 665: }
666: }
667:
668: /*
1.131 schwarze 669: * Close out block partial/full explicit.
1.1 kristaps 670: */
671: static int
672: blk_exp_close(MACRO_PROT_ARGS)
673: {
1.83 schwarze 674: struct mdoc_node *body; /* Our own body. */
1.148 schwarze 675: struct mdoc_node *endbody; /* Our own end marker. */
1.83 schwarze 676: struct mdoc_node *later; /* A sub-block starting later. */
677: struct mdoc_node *n; /* For searching backwards. */
678:
1.131 schwarze 679: int j, lastarg, maxargs, flushed, nl;
1.55 kristaps 680: enum margserr ac;
1.83 schwarze 681: enum mdoct atok, ntok;
1.1 kristaps 682: char *p;
683:
1.119 schwarze 684: nl = MDOC_NEWLINE & mdoc->flags;
1.60 kristaps 685:
1.1 kristaps 686: switch (tok) {
1.131 schwarze 687: case MDOC_Ec:
1.1 kristaps 688: maxargs = 1;
689: break;
1.131 schwarze 690: case MDOC_Ek:
1.125 schwarze 691: mdoc->flags &= ~MDOC_KEEP;
1.1 kristaps 692: default:
693: maxargs = 0;
694: break;
695: }
696:
1.83 schwarze 697: /*
698: * Search backwards for beginnings of blocks,
699: * both of our own and of pending sub-blocks.
700: */
701: atok = rew_alt(tok);
1.148 schwarze 702: body = endbody = later = NULL;
1.119 schwarze 703: for (n = mdoc->last; n; n = n->parent) {
1.150 ! schwarze 704: if (n->flags & MDOC_VALID)
1.83 schwarze 705: continue;
706:
707: /* Remember the start of our own body. */
1.150 ! schwarze 708: if (n->type == MDOC_BODY && atok == n->tok) {
! 709: if (n->end == ENDBODY_NOT)
1.83 schwarze 710: body = n;
711: continue;
712: }
713:
1.150 ! schwarze 714: if (n->type != MDOC_BLOCK || n->tok == MDOC_Nm)
1.83 schwarze 715: continue;
716: if (atok == n->tok) {
717: assert(body);
718:
719: /*
720: * Found the start of our own block.
721: * When there is no pending sub block,
722: * just proceed to closing out.
723: */
1.150 ! schwarze 724: if (later == NULL)
1.83 schwarze 725: break;
726:
1.131 schwarze 727: /*
1.83 schwarze 728: * When there is a pending sub block,
729: * postpone closing out the current block
730: * until the rew_sub() closing out the sub-block.
731: */
1.119 schwarze 732: make_pending(later, tok, mdoc, line, ppos);
1.83 schwarze 733:
734: /*
735: * Mark the place where the formatting - but not
736: * the scope - of the current block ends.
737: */
1.150 ! schwarze 738: mdoc_endbody_alloc(mdoc, line, ppos,
! 739: atok, body, ENDBODY_SPACE);
1.148 schwarze 740: if (maxargs) {
741: endbody = mdoc->last;
742: mdoc->next = MDOC_NEXT_CHILD;
743: }
1.83 schwarze 744: break;
745: }
746:
747: /*
748: * When finding an open sub block, remember the last
749: * open explicit block, or, in case there are only
750: * implicit ones, the first open implicit block.
751: */
752: if (later &&
1.150 ! schwarze 753: mdoc_macros[later->tok].flags & MDOC_EXPLICIT)
1.83 schwarze 754: continue;
1.150 ! schwarze 755: if (n->tok != MDOC_It)
1.83 schwarze 756: later = n;
757: }
758:
1.150 ! schwarze 759: if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) {
! 760: if (buf[*pos] != '\0')
1.136 schwarze 761: mandoc_vmsg(MANDOCERR_ARG_SKIP,
762: mdoc->parse, line, ppos,
763: "%s %s", mdoc_macronames[tok],
764: buf + *pos);
1.150 ! schwarze 765: rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
! 766: rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
! 767: return(1);
1.1 kristaps 768: }
1.150 ! schwarze 769: rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
1.1 kristaps 770:
1.148 schwarze 771: if (maxargs && endbody == NULL) {
772: if (n == NULL) {
773: /*
774: * Stray .Ec without previous .Eo:
775: * Break the output line, ignore any arguments.
776: */
1.150 ! schwarze 777: mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL);
1.149 schwarze 778: rew_elem(mdoc, MDOC_br);
1.150 ! schwarze 779: } else
! 780: mdoc_tail_alloc(mdoc, line, ppos, atok);
1.148 schwarze 781: }
1.1 kristaps 782:
1.148 schwarze 783: flushed = n == NULL;
784: for (j = 0; ; j++) {
1.1 kristaps 785: lastarg = *pos;
786:
787: if (j == maxargs && ! flushed) {
1.150 ! schwarze 788: if (endbody == NULL)
! 789: rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
! 790: else
1.149 schwarze 791: rew_last(mdoc, endbody);
1.1 kristaps 792: flushed = 1;
793: }
794:
1.119 schwarze 795: ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.150 ! schwarze 796: if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
1.1 kristaps 797: break;
798:
1.150 ! schwarze 799: ntok = ac == ARGS_QWORD ? MDOC_MAX : lookup(tok, p);
1.54 kristaps 800:
1.150 ! schwarze 801: if (ntok == MDOC_MAX) {
! 802: dword(mdoc, line, lastarg, p, DELIM_MAX,
! 803: MDOC_JOIN & mdoc_macros[tok].flags);
1.54 kristaps 804: continue;
805: }
1.1 kristaps 806:
1.54 kristaps 807: if ( ! flushed) {
1.150 ! schwarze 808: if (endbody == NULL)
! 809: rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
! 810: else
1.149 schwarze 811: rew_last(mdoc, endbody);
1.54 kristaps 812: flushed = 1;
813: }
1.122 schwarze 814:
815: mdoc->flags &= ~MDOC_NEWLINE;
816:
1.119 schwarze 817: if ( ! mdoc_macro(mdoc, ntok, line, lastarg, pos, buf))
1.1 kristaps 818: return(0);
1.54 kristaps 819: break;
1.1 kristaps 820: }
821:
1.149 schwarze 822: if ( ! flushed) {
1.150 ! schwarze 823: if (endbody == NULL)
! 824: rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
! 825: else
1.149 schwarze 826: rew_last(mdoc, endbody);
827: }
1.150 ! schwarze 828: if (nl)
! 829: append_delims(mdoc, line, pos, buf);
! 830: return(1);
1.1 kristaps 831: }
832:
833: static int
834: in_line(MACRO_PROT_ARGS)
835: {
1.144 schwarze 836: int la, scope, cnt, firstarg, mayopen, nc, nl;
1.56 kristaps 837: enum margverr av;
1.53 kristaps 838: enum mdoct ntok;
1.55 kristaps 839: enum margserr ac;
1.67 schwarze 840: enum mdelim d;
1.53 kristaps 841: struct mdoc_arg *arg;
842: char *p;
1.1 kristaps 843:
1.119 schwarze 844: nl = MDOC_NEWLINE & mdoc->flags;
1.60 kristaps 845:
1.4 kristaps 846: /*
847: * Whether we allow ignored elements (those without content,
848: * usually because of reserved words) to squeak by.
849: */
1.45 kristaps 850:
1.4 kristaps 851: switch (tok) {
1.131 schwarze 852: case MDOC_An:
1.26 kristaps 853: /* FALLTHROUGH */
1.131 schwarze 854: case MDOC_Ar:
1.4 kristaps 855: /* FALLTHROUGH */
1.131 schwarze 856: case MDOC_Fl:
1.4 kristaps 857: /* FALLTHROUGH */
1.131 schwarze 858: case MDOC_Mt:
1.12 kristaps 859: /* FALLTHROUGH */
1.131 schwarze 860: case MDOC_Nm:
1.26 kristaps 861: /* FALLTHROUGH */
1.131 schwarze 862: case MDOC_Pa:
1.4 kristaps 863: nc = 1;
864: break;
865: default:
866: nc = 0;
867: break;
868: }
869:
1.27 kristaps 870: for (arg = NULL;; ) {
1.1 kristaps 871: la = *pos;
1.119 schwarze 872: av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1.1 kristaps 873:
1.56 kristaps 874: if (ARGV_WORD == av) {
1.1 kristaps 875: *pos = la;
876: break;
1.131 schwarze 877: }
1.56 kristaps 878: if (ARGV_EOLN == av)
1.1 kristaps 879: break;
1.56 kristaps 880: if (ARGV_ARG == av)
1.1 kristaps 881: continue;
882:
883: mdoc_argv_free(arg);
884: return(0);
885: }
886:
1.144 schwarze 887: d = DELIM_NONE;
888: firstarg = 1;
1.142 schwarze 889: mayopen = 1;
1.70 kristaps 890: for (cnt = scope = 0;; ) {
1.1 kristaps 891: la = *pos;
1.119 schwarze 892: ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.1 kristaps 893:
1.144 schwarze 894: /*
895: * At the end of a macro line,
896: * opening delimiters do not suppress spacing.
897: */
898:
899: if (ac == ARGS_EOLN) {
900: if (d == DELIM_OPEN)
901: mdoc->last->flags &= ~MDOC_DELIMO;
1.1 kristaps 902: break;
1.144 schwarze 903: }
904:
905: /*
906: * The rest of the macro line is only punctuation,
907: * to be handled by append_delims().
908: * If there were no other arguments,
909: * do not allow the first one to suppress spacing,
910: * even if it turns out to be a closing one.
911: */
912:
913: if (ac == ARGS_PUNCT) {
914: if (cnt == 0 && nc == 0)
915: mdoc->flags |= MDOC_NODELIMC;
1.1 kristaps 916: break;
1.144 schwarze 917: }
1.1 kristaps 918:
1.145 schwarze 919: ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ?
920: MDOC_MAX : lookup(tok, p);
1.1 kristaps 921:
1.131 schwarze 922: /*
1.4 kristaps 923: * In this case, we've located a submacro and must
924: * execute it. Close out scope, if open. If no
925: * elements have been generated, either create one (nc)
926: * or raise a warning.
927: */
1.1 kristaps 928:
1.150 ! schwarze 929: if (ntok != MDOC_MAX) {
1.149 schwarze 930: if (scope)
931: rew_elem(mdoc, tok);
1.150 ! schwarze 932: if (nc && ! cnt) {
! 933: mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1.149 schwarze 934: rew_last(mdoc, mdoc->last);
1.150 ! schwarze 935: } else if ( ! nc && ! cnt) {
1.7 kristaps 936: mdoc_argv_free(arg);
1.135 schwarze 937: mandoc_msg(MANDOCERR_MACRO_EMPTY,
938: mdoc->parse, line, ppos,
939: mdoc_macronames[tok]);
1.7 kristaps 940: }
1.103 kristaps 941:
1.119 schwarze 942: if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1.1 kristaps 943: return(0);
1.150 ! schwarze 944: if (nl)
! 945: append_delims(mdoc, line, pos, buf);
! 946: return(1);
1.131 schwarze 947: }
1.1 kristaps 948:
1.131 schwarze 949: /*
1.4 kristaps 950: * Non-quote-enclosed punctuation. Set up our scope, if
951: * a word; rewind the scope, if a delimiter; then append
1.131 schwarze 952: * the word.
1.4 kristaps 953: */
1.1 kristaps 954:
1.150 ! schwarze 955: d = ac == ARGS_QWORD ? DELIM_NONE : mdoc_isdelim(p);
1.3 kristaps 956:
1.70 kristaps 957: if (DELIM_NONE != d) {
958: /*
959: * If we encounter closing punctuation, no word
1.144 schwarze 960: * has been emitted, no scope is open, and we're
1.70 kristaps 961: * allowed to have an empty element, then start
1.142 schwarze 962: * a new scope.
1.70 kristaps 963: */
1.142 schwarze 964: if ((d == DELIM_CLOSE ||
965: (d == DELIM_MIDDLE && tok == MDOC_Fl)) &&
1.144 schwarze 966: !cnt && !scope && nc && mayopen) {
1.150 ! schwarze 967: mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1.70 kristaps 968: scope = 1;
1.142 schwarze 969: cnt++;
1.150 ! schwarze 970: if (tok == MDOC_Nm)
1.142 schwarze 971: mayopen = 0;
1.70 kristaps 972: }
973: /*
974: * Close out our scope, if one is open, before
975: * any punctuation.
976: */
1.149 schwarze 977: if (scope)
978: rew_elem(mdoc, tok);
1.70 kristaps 979: scope = 0;
1.145 schwarze 980: if (tok == MDOC_Fn)
981: mayopen = 0;
1.142 schwarze 982: } else if (mayopen && !scope) {
1.150 ! schwarze 983: mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1.70 kristaps 984: scope = 1;
1.142 schwarze 985: cnt++;
1.1 kristaps 986: }
1.105 kristaps 987:
1.150 ! schwarze 988: dword(mdoc, line, la, p, d,
! 989: MDOC_JOIN & mdoc_macros[tok].flags);
1.39 kristaps 990:
991: /*
1.144 schwarze 992: * If the first argument is a closing delimiter,
993: * do not suppress spacing before it.
994: */
995:
996: if (firstarg && d == DELIM_CLOSE && !nc)
997: mdoc->last->flags &= ~MDOC_DELIMC;
998: firstarg = 0;
999:
1000: /*
1.39 kristaps 1001: * `Fl' macros have their scope re-opened with each new
1002: * word so that the `-' can be added to each one without
1003: * having to parse out spaces.
1004: */
1.150 ! schwarze 1005: if (scope && tok == MDOC_Fl) {
1.149 schwarze 1006: rew_elem(mdoc, tok);
1.70 kristaps 1007: scope = 0;
1.39 kristaps 1008: }
1.1 kristaps 1009: }
1010:
1.149 schwarze 1011: if (scope)
1012: rew_elem(mdoc, tok);
1.4 kristaps 1013:
1014: /*
1015: * If no elements have been collected and we're allowed to have
1016: * empties (nc), open a scope and close it out. Otherwise,
1017: * raise a warning.
1018: */
1.45 kristaps 1019:
1.150 ! schwarze 1020: if ( ! cnt) {
! 1021: if (nc) {
! 1022: mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
! 1023: rew_last(mdoc, mdoc->last);
! 1024: } else {
! 1025: mdoc_argv_free(arg);
! 1026: mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
! 1027: line, ppos, mdoc_macronames[tok]);
! 1028: }
1.7 kristaps 1029: }
1.150 ! schwarze 1030: if (nl)
! 1031: append_delims(mdoc, line, pos, buf);
! 1032: return(1);
1.1 kristaps 1033: }
1034:
1035: static int
1036: blk_full(MACRO_PROT_ARGS)
1037: {
1.114 kristaps 1038: int la, nl, nparsed;
1.1 kristaps 1039: struct mdoc_arg *arg;
1.45 kristaps 1040: struct mdoc_node *head; /* save of head macro */
1.49 kristaps 1041: struct mdoc_node *body; /* save of body macro */
1.47 kristaps 1042: struct mdoc_node *n;
1.53 kristaps 1043: enum mdoct ntok;
1.59 kristaps 1044: enum margserr ac, lac;
1.56 kristaps 1045: enum margverr av;
1.1 kristaps 1046: char *p;
1047:
1.119 schwarze 1048: nl = MDOC_NEWLINE & mdoc->flags;
1.138 schwarze 1049:
1050: /* Skip items outside lists. */
1051:
1052: if (tok == MDOC_It) {
1053: for (n = mdoc->last; n; n = n->parent)
1.141 schwarze 1054: if (n->tok == MDOC_Bl &&
1055: ! (n->flags & MDOC_VALID))
1.138 schwarze 1056: break;
1057: if (n == NULL) {
1058: mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,
1059: line, ppos, "It %s", buf + *pos);
1.150 ! schwarze 1060: mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL);
1.149 schwarze 1061: rew_elem(mdoc, MDOC_br);
1062: return(1);
1.138 schwarze 1063: }
1064: }
1.63 kristaps 1065:
1.45 kristaps 1066: /* Close out prior implicit scope. */
1.19 kristaps 1067:
1.150 ! schwarze 1068: if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) {
! 1069: rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
! 1070: rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
1.1 kristaps 1071: }
1072:
1.45 kristaps 1073: /*
1.109 kristaps 1074: * This routine accommodates implicitly- and explicitly-scoped
1.45 kristaps 1075: * macro openings. Implicit ones first close out prior scope
1076: * (seen above). Delay opening the head until necessary to
1077: * allow leading punctuation to print. Special consideration
1078: * for `It -column', which has phrase-part syntax instead of
1079: * regular child nodes.
1080: */
1081:
1.1 kristaps 1082: for (arg = NULL;; ) {
1.45 kristaps 1083: la = *pos;
1.119 schwarze 1084: av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1.1 kristaps 1085:
1.56 kristaps 1086: if (ARGV_WORD == av) {
1.45 kristaps 1087: *pos = la;
1.1 kristaps 1088: break;
1.131 schwarze 1089: }
1.1 kristaps 1090:
1.56 kristaps 1091: if (ARGV_EOLN == av)
1.1 kristaps 1092: break;
1.56 kristaps 1093: if (ARGV_ARG == av)
1.1 kristaps 1094: continue;
1095:
1096: mdoc_argv_free(arg);
1097: return(0);
1098: }
1099:
1.150 ! schwarze 1100: mdoc_block_alloc(mdoc, line, ppos, tok, arg);
1.49 kristaps 1101: head = body = NULL;
1.115 schwarze 1102:
1103: /*
1104: * Exception: Heads of `It' macros in `-diag' lists are not
1105: * parsed, even though `It' macros in general are parsed.
1106: */
1.150 ! schwarze 1107: nparsed = tok == MDOC_It &&
! 1108: mdoc->last->parent->tok == MDOC_Bl &&
! 1109: mdoc->last->parent->norm->Bl.type == LIST_diag;
1.1 kristaps 1110:
1.45 kristaps 1111: /*
1112: * The `Nd' macro has all arguments in its body: it's a hybrid
1113: * of block partial-explicit and full-implicit. Stupid.
1114: */
1.19 kristaps 1115:
1.150 ! schwarze 1116: if (tok == MDOC_Nd) {
! 1117: head = mdoc_head_alloc(mdoc, line, ppos, tok);
! 1118: rew_sub(MDOC_HEAD, mdoc, tok, line, ppos);
! 1119: body = mdoc_body_alloc(mdoc, line, ppos, tok);
1.123 schwarze 1120: }
1121:
1.150 ! schwarze 1122: if (tok == MDOC_Bk)
1.123 schwarze 1123: mdoc->flags |= MDOC_KEEP;
1.19 kristaps 1124:
1.150 ! schwarze 1125: ac = ARGS_PEND;
! 1126: for (;;) {
1.45 kristaps 1127: la = *pos;
1.150 ! schwarze 1128: lac = ac;
1.119 schwarze 1129: ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.150 ! schwarze 1130: if (ac == ARGS_PUNCT)
1.89 schwarze 1131: break;
1.150 ! schwarze 1132: if (ac == ARGS_EOLN) {
! 1133: if (lac != ARGS_PPHRASE && lac != ARGS_PHRASE)
1.75 kristaps 1134: break;
1135: /*
1136: * This is necessary: if the last token on a
1137: * line is a `Ta' or tab, then we'll get
1138: * ARGS_EOLN, so we must be smart enough to
1139: * reopen our scope if the last parse was a
1140: * phrase or partial phrase.
1141: */
1.150 ! schwarze 1142: rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
! 1143: body = mdoc_body_alloc(mdoc, line, ppos, tok);
1.1 kristaps 1144: break;
1.75 kristaps 1145: }
1.45 kristaps 1146:
1.131 schwarze 1147: /*
1.73 kristaps 1148: * Emit leading punctuation (i.e., punctuation before
1149: * the MDOC_HEAD) for non-phrase types.
1150: */
1.45 kristaps 1151:
1.150 ! schwarze 1152: if (head == NULL &&
! 1153: ac != ARGS_PEND &&
! 1154: ac != ARGS_PHRASE &&
! 1155: ac != ARGS_PPHRASE &&
! 1156: ac != ARGS_QWORD &&
! 1157: mdoc_isdelim(p) == DELIM_OPEN) {
! 1158: dword(mdoc, line, la, p, DELIM_OPEN, 0);
1.45 kristaps 1159: continue;
1160: }
1161:
1.74 kristaps 1162: /* Open a head if one hasn't been opened. */
1.45 kristaps 1163:
1.150 ! schwarze 1164: if (head == NULL)
! 1165: head = mdoc_head_alloc(mdoc, line, ppos, tok);
1.45 kristaps 1166:
1.150 ! schwarze 1167: if (ac == ARGS_PHRASE ||
! 1168: ac == ARGS_PEND ||
! 1169: ac == ARGS_PPHRASE) {
1.73 kristaps 1170: /*
1.74 kristaps 1171: * If we haven't opened a body yet, rewind the
1172: * head; if we have, rewind that instead.
1173: */
1174:
1.150 ! schwarze 1175: rew_sub(body ? MDOC_BODY : MDOC_HEAD,
! 1176: mdoc, tok, line, ppos);
1.131 schwarze 1177:
1.74 kristaps 1178: /* Then allocate our body context. */
1179:
1.150 ! schwarze 1180: body = mdoc_body_alloc(mdoc, line, ppos, tok);
1.74 kristaps 1181:
1182: /*
1.73 kristaps 1183: * Process phrases: set whether we're in a
1184: * partial-phrase (this effects line handling)
1185: * then call down into the phrase parser.
1186: */
1.74 kristaps 1187:
1.150 ! schwarze 1188: if (ac == ARGS_PPHRASE)
1.119 schwarze 1189: mdoc->flags |= MDOC_PPHRASE;
1.150 ! schwarze 1190: if (ac == ARGS_PEND && lac == ARGS_PPHRASE)
1.119 schwarze 1191: mdoc->flags |= MDOC_PPHRASE;
1.71 kristaps 1192:
1.119 schwarze 1193: if ( ! phrase(mdoc, line, la, buf))
1.1 kristaps 1194: return(0);
1.71 kristaps 1195:
1.119 schwarze 1196: mdoc->flags &= ~MDOC_PPHRASE;
1.1 kristaps 1197: continue;
1198: }
1199:
1.150 ! schwarze 1200: ntok = nparsed || ac == ARGS_QWORD ?
1.131 schwarze 1201: MDOC_MAX : lookup(tok, p);
1.54 kristaps 1202:
1.150 ! schwarze 1203: if (ntok == MDOC_MAX) {
! 1204: dword(mdoc, line, la, p, DELIM_MAX,
! 1205: MDOC_JOIN & mdoc_macros[tok].flags);
1.53 kristaps 1206: continue;
1.45 kristaps 1207: }
1.53 kristaps 1208:
1.119 schwarze 1209: if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1.45 kristaps 1210: return(0);
1.53 kristaps 1211: break;
1.45 kristaps 1212: }
1.1 kristaps 1213:
1.150 ! schwarze 1214: if (head == NULL)
! 1215: head = mdoc_head_alloc(mdoc, line, ppos, tok);
! 1216: if (nl)
! 1217: append_delims(mdoc, line, pos, buf);
1.19 kristaps 1218:
1.49 kristaps 1219: /* If we've already opened our body, exit now. */
1.45 kristaps 1220:
1.49 kristaps 1221: if (NULL != body)
1.77 kristaps 1222: goto out;
1.19 kristaps 1223:
1.47 kristaps 1224: /*
1.49 kristaps 1225: * If there is an open (i.e., unvalidated) sub-block requiring
1226: * explicit close-out, postpone switching the current block from
1227: * head to body until the rew_sub() call closing out that
1228: * sub-block.
1.47 kristaps 1229: */
1.119 schwarze 1230: for (n = mdoc->last; n && n != head; n = n->parent) {
1.131 schwarze 1231: if (MDOC_BLOCK == n->type &&
1232: MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
1233: ! (MDOC_VALID & n->flags)) {
1.47 kristaps 1234: n->pending = head;
1235: return(1);
1236: }
1237: }
1238:
1.45 kristaps 1239: /* Close out scopes to remain in a consistent state. */
1240:
1.150 ! schwarze 1241: rew_sub(MDOC_HEAD, mdoc, tok, line, ppos);
! 1242: mdoc_body_alloc(mdoc, line, ppos, tok);
1.1 kristaps 1243:
1.77 kristaps 1244: out:
1.150 ! schwarze 1245: if (mdoc->flags & MDOC_FREECOL) {
! 1246: rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
! 1247: rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
! 1248: mdoc->flags &= ~MDOC_FREECOL;
! 1249: }
1.1 kristaps 1250: return(1);
1251: }
1252:
1253: static int
1254: blk_part_imp(MACRO_PROT_ARGS)
1255: {
1.63 kristaps 1256: int la, nl;
1.53 kristaps 1257: enum mdoct ntok;
1.55 kristaps 1258: enum margserr ac;
1.1 kristaps 1259: char *p;
1.43 kristaps 1260: struct mdoc_node *blk; /* saved block context */
1261: struct mdoc_node *body; /* saved body context */
1262: struct mdoc_node *n;
1.1 kristaps 1263:
1.119 schwarze 1264: nl = MDOC_NEWLINE & mdoc->flags;
1.63 kristaps 1265:
1.43 kristaps 1266: /*
1267: * A macro that spans to the end of the line. This is generally
1268: * (but not necessarily) called as the first macro. The block
1269: * has a head as the immediate child, which is always empty,
1270: * followed by zero or more opening punctuation nodes, then the
1271: * body (which may be empty, depending on the macro), then zero
1272: * or more closing punctuation nodes.
1273: */
1.32 kristaps 1274:
1.150 ! schwarze 1275: blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL);
! 1276: mdoc_head_alloc(mdoc, line, ppos, tok);
! 1277: rew_sub(MDOC_HEAD, mdoc, tok, line, ppos);
1.1 kristaps 1278:
1.43 kristaps 1279: /*
1280: * Open the body scope "on-demand", that is, after we've
1281: * processed all our the leading delimiters (open parenthesis,
1282: * etc.).
1283: */
1.1 kristaps 1284:
1.43 kristaps 1285: for (body = NULL; ; ) {
1.32 kristaps 1286: la = *pos;
1.119 schwarze 1287: ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.150 ! schwarze 1288: if (ac == ARGS_EOLN || ac == ARGS_PUNCT)
1.1 kristaps 1289: break;
1290:
1.150 ! schwarze 1291: if (body == NULL && ac != ARGS_QWORD &&
! 1292: mdoc_isdelim(p) == DELIM_OPEN) {
! 1293: dword(mdoc, line, la, p, DELIM_OPEN, 0);
1.1 kristaps 1294: continue;
1.123 schwarze 1295: }
1.1 kristaps 1296:
1.150 ! schwarze 1297: if (body == NULL)
! 1298: body = mdoc_body_alloc(mdoc, line, ppos, tok);
1.43 kristaps 1299:
1.150 ! schwarze 1300: ntok = ac == ARGS_QWORD ? MDOC_MAX : lookup(tok, p);
1.54 kristaps 1301:
1.150 ! schwarze 1302: if (ntok == MDOC_MAX) {
! 1303: dword(mdoc, line, la, p, DELIM_MAX,
! 1304: MDOC_JOIN & mdoc_macros[tok].flags);
1.53 kristaps 1305: continue;
1306: }
1.43 kristaps 1307:
1.119 schwarze 1308: if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1.1 kristaps 1309: return(0);
1.53 kristaps 1310: break;
1.1 kristaps 1311: }
1312:
1.43 kristaps 1313: /* Clean-ups to leave in a consistent state. */
1314:
1.150 ! schwarze 1315: if (body == NULL)
! 1316: body = mdoc_body_alloc(mdoc, line, ppos, tok);
1.43 kristaps 1317:
1.83 schwarze 1318: /*
1319: * If there is an open sub-block requiring explicit close-out,
1320: * postpone closing out the current block
1321: * until the rew_sub() call closing out the sub-block.
1322: */
1.119 schwarze 1323: for (n = mdoc->last; n && n != body && n != blk->parent;
1.131 schwarze 1324: n = n->parent) {
1.150 ! schwarze 1325: if (n->type == MDOC_BLOCK &&
! 1326: mdoc_macros[n->tok].flags & MDOC_EXPLICIT &&
! 1327: ! (n->flags & MDOC_VALID)) {
1.119 schwarze 1328: make_pending(n, tok, mdoc, line, ppos);
1.150 ! schwarze 1329: mdoc_endbody_alloc(mdoc, line, ppos,
! 1330: tok, body, ENDBODY_NOSPACE);
1.83 schwarze 1331: return(1);
1332: }
1333: }
1.134 schwarze 1334: assert(n == body);
1.150 ! schwarze 1335: rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
1.1 kristaps 1336:
1.32 kristaps 1337: /* Standard appending of delimiters. */
1.1 kristaps 1338:
1.150 ! schwarze 1339: if (nl)
! 1340: append_delims(mdoc, line, pos, buf);
1.1 kristaps 1341:
1.32 kristaps 1342: /* Rewind scope, if applicable. */
1.1 kristaps 1343:
1.150 ! schwarze 1344: rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
1.117 schwarze 1345:
1346: /* Move trailing .Ns out of scope. */
1347:
1348: for (n = body->child; n && n->next; n = n->next)
1349: /* Do nothing. */ ;
1.150 ! schwarze 1350: if (n && n->tok == MDOC_Ns)
1.119 schwarze 1351: mdoc_node_relink(mdoc, n);
1.1 kristaps 1352:
1353: return(1);
1354: }
1355:
1356: static int
1357: blk_part_exp(MACRO_PROT_ARGS)
1358: {
1.60 kristaps 1359: int la, nl;
1.55 kristaps 1360: enum margserr ac;
1.43 kristaps 1361: struct mdoc_node *head; /* keep track of head */
1362: struct mdoc_node *body; /* keep track of body */
1.1 kristaps 1363: char *p;
1.53 kristaps 1364: enum mdoct ntok;
1.1 kristaps 1365:
1.119 schwarze 1366: nl = MDOC_NEWLINE & mdoc->flags;
1.60 kristaps 1367:
1.43 kristaps 1368: /*
1369: * The opening of an explicit macro having zero or more leading
1370: * punctuation nodes; a head with optional single element (the
1371: * case of `Eo'); and a body that may be empty.
1372: */
1.32 kristaps 1373:
1.150 ! schwarze 1374: mdoc_block_alloc(mdoc, line, ppos, tok, NULL);
1.43 kristaps 1375: for (head = body = NULL; ; ) {
1.32 kristaps 1376: la = *pos;
1.119 schwarze 1377: ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.150 ! schwarze 1378: if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
1.1 kristaps 1379: break;
1.43 kristaps 1380:
1381: /* Flush out leading punctuation. */
1382:
1.150 ! schwarze 1383: if (head == NULL && ac != ARGS_QWORD &&
! 1384: mdoc_isdelim(p) == DELIM_OPEN) {
1.43 kristaps 1385: assert(NULL == body);
1.150 ! schwarze 1386: dword(mdoc, line, la, p, DELIM_OPEN, 0);
1.43 kristaps 1387: continue;
1.123 schwarze 1388: }
1.43 kristaps 1389:
1.150 ! schwarze 1390: if (head == NULL) {
! 1391: assert(body == NULL);
! 1392: head = mdoc_head_alloc(mdoc, line, ppos, tok);
1.1 kristaps 1393: }
1394:
1.43 kristaps 1395: /*
1396: * `Eo' gobbles any data into the head, but most other
1397: * macros just immediately close out and begin the body.
1398: */
1399:
1.150 ! schwarze 1400: if (body == NULL) {
1.43 kristaps 1401: assert(head);
1402: /* No check whether it's a macro! */
1.150 ! schwarze 1403: if (tok == MDOC_Eo)
! 1404: dword(mdoc, line, la, p, DELIM_MAX, 0);
! 1405: rew_sub(MDOC_HEAD, mdoc, tok, line, ppos);
! 1406: body = mdoc_body_alloc(mdoc, line, ppos, tok);
! 1407: if (tok == MDOC_Eo)
1.43 kristaps 1408: continue;
1.1 kristaps 1409: }
1.150 ! schwarze 1410: assert(head != NULL && body != NULL);
1.43 kristaps 1411:
1.150 ! schwarze 1412: ntok = ac == ARGS_QWORD ? MDOC_MAX : lookup(tok, p);
! 1413: if (ntok == MDOC_MAX) {
! 1414: dword(mdoc, line, la, p, DELIM_MAX,
! 1415: MDOC_JOIN & mdoc_macros[tok].flags);
1.53 kristaps 1416: continue;
1.43 kristaps 1417: }
1.119 schwarze 1418: if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1.1 kristaps 1419: return(0);
1.53 kristaps 1420: break;
1.1 kristaps 1421: }
1422:
1.43 kristaps 1423: /* Clean-up to leave in a consistent state. */
1.32 kristaps 1424:
1.150 ! schwarze 1425: if (head == NULL)
! 1426: mdoc_head_alloc(mdoc, line, ppos, tok);
1.43 kristaps 1427:
1.150 ! schwarze 1428: if (body == NULL) {
! 1429: rew_sub(MDOC_HEAD, mdoc, tok, line, ppos);
! 1430: mdoc_body_alloc(mdoc, line, ppos, tok);
1.1 kristaps 1431: }
1432:
1.32 kristaps 1433: /* Standard appending of delimiters. */
1434:
1.150 ! schwarze 1435: if (nl)
! 1436: append_delims(mdoc, line, pos, buf);
! 1437: return(1);
1.1 kristaps 1438: }
1439:
1440: static int
1441: in_line_argn(MACRO_PROT_ARGS)
1442: {
1.60 kristaps 1443: int la, flushed, j, maxargs, nl;
1.55 kristaps 1444: enum margserr ac;
1.56 kristaps 1445: enum margverr av;
1.53 kristaps 1446: struct mdoc_arg *arg;
1447: char *p;
1448: enum mdoct ntok;
1.1 kristaps 1449:
1.119 schwarze 1450: nl = MDOC_NEWLINE & mdoc->flags;
1.60 kristaps 1451:
1.46 kristaps 1452: /*
1453: * A line macro that has a fixed number of arguments (maxargs).
1454: * Only open the scope once the first non-leading-punctuation is
1455: * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then
1456: * keep it open until the maximum number of arguments are
1457: * exhausted.
1458: */
1.1 kristaps 1459:
1460: switch (tok) {
1.131 schwarze 1461: case MDOC_Ap:
1.1 kristaps 1462: /* FALLTHROUGH */
1.131 schwarze 1463: case MDOC_Ns:
1.1 kristaps 1464: /* FALLTHROUGH */
1.131 schwarze 1465: case MDOC_Ux:
1.1 kristaps 1466: maxargs = 0;
1467: break;
1.131 schwarze 1468: case MDOC_Bx:
1.101 kristaps 1469: /* FALLTHROUGH */
1.132 schwarze 1470: case MDOC_Es:
1471: /* FALLTHROUGH */
1.131 schwarze 1472: case MDOC_Xr:
1.42 kristaps 1473: maxargs = 2;
1474: break;
1.1 kristaps 1475: default:
1476: maxargs = 1;
1477: break;
1478: }
1479:
1.46 kristaps 1480: for (arg = NULL; ; ) {
1.32 kristaps 1481: la = *pos;
1.119 schwarze 1482: av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1.1 kristaps 1483:
1.56 kristaps 1484: if (ARGV_WORD == av) {
1.32 kristaps 1485: *pos = la;
1.1 kristaps 1486: break;
1.131 schwarze 1487: }
1.1 kristaps 1488:
1.56 kristaps 1489: if (ARGV_EOLN == av)
1.1 kristaps 1490: break;
1.56 kristaps 1491: if (ARGV_ARG == av)
1.1 kristaps 1492: continue;
1493:
1494: mdoc_argv_free(arg);
1495: return(0);
1496: }
1497:
1.46 kristaps 1498: for (flushed = j = 0; ; ) {
1.32 kristaps 1499: la = *pos;
1.119 schwarze 1500: ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.150 ! schwarze 1501: if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
1.1 kristaps 1502: break;
1503:
1.150 ! schwarze 1504: if ( ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) &&
! 1505: ac != ARGS_QWORD && j == 0 &&
! 1506: mdoc_isdelim(p) == DELIM_OPEN) {
! 1507: dword(mdoc, line, la, p, DELIM_OPEN, 0);
1.46 kristaps 1508: continue;
1.150 ! schwarze 1509: } else if (j == 0)
! 1510: mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1.46 kristaps 1511:
1512: if (j == maxargs && ! flushed) {
1.149 schwarze 1513: rew_elem(mdoc, tok);
1.46 kristaps 1514: flushed = 1;
1515: }
1516:
1.150 ! schwarze 1517: ntok = ac == ARGS_QWORD ? MDOC_MAX : lookup(tok, p);
1.54 kristaps 1518:
1.150 ! schwarze 1519: if (ntok != MDOC_MAX) {
1.149 schwarze 1520: if ( ! flushed)
1521: rew_elem(mdoc, tok);
1.1 kristaps 1522: flushed = 1;
1.119 schwarze 1523: if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1.1 kristaps 1524: return(0);
1.46 kristaps 1525: j++;
1.1 kristaps 1526: break;
1527: }
1528:
1.150 ! schwarze 1529: if ( ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) &&
! 1530: ac != ARGS_QWORD && ! flushed &&
! 1531: mdoc_isdelim(p) != DELIM_NONE) {
1.149 schwarze 1532: rew_elem(mdoc, tok);
1.1 kristaps 1533: flushed = 1;
1534: }
1.42 kristaps 1535:
1.150 ! schwarze 1536: dword(mdoc, line, la, p, DELIM_MAX,
! 1537: MDOC_JOIN & mdoc_macros[tok].flags);
1.46 kristaps 1538: j++;
1.1 kristaps 1539: }
1540:
1.150 ! schwarze 1541: if (j == 0)
! 1542: mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1.46 kristaps 1543:
1544: /* Close out in a consistent state. */
1.32 kristaps 1545:
1.149 schwarze 1546: if ( ! flushed)
1547: rew_elem(mdoc, tok);
1.150 ! schwarze 1548: if (nl)
! 1549: append_delims(mdoc, line, pos, buf);
! 1550: return(1);
1.1 kristaps 1551: }
1552:
1553: static int
1554: in_line_eoln(MACRO_PROT_ARGS)
1555: {
1.56 kristaps 1556: int la;
1.55 kristaps 1557: enum margserr ac;
1.56 kristaps 1558: enum margverr av;
1.53 kristaps 1559: struct mdoc_arg *arg;
1560: char *p;
1561: enum mdoct ntok;
1.1 kristaps 1562:
1563: assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1564:
1.90 schwarze 1565: if (tok == MDOC_Pp)
1.119 schwarze 1566: rew_sub(MDOC_BLOCK, mdoc, MDOC_Nm, line, ppos);
1.90 schwarze 1567:
1.32 kristaps 1568: /* Parse macro arguments. */
1.1 kristaps 1569:
1.32 kristaps 1570: for (arg = NULL; ; ) {
1.1 kristaps 1571: la = *pos;
1.119 schwarze 1572: av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1.1 kristaps 1573:
1.56 kristaps 1574: if (ARGV_WORD == av) {
1.1 kristaps 1575: *pos = la;
1576: break;
1577: }
1.131 schwarze 1578: if (ARGV_EOLN == av)
1.1 kristaps 1579: break;
1.56 kristaps 1580: if (ARGV_ARG == av)
1.1 kristaps 1581: continue;
1582:
1583: mdoc_argv_free(arg);
1584: return(0);
1585: }
1586:
1.32 kristaps 1587: /* Open element scope. */
1588:
1.150 ! schwarze 1589: mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
1.1 kristaps 1590:
1.32 kristaps 1591: /* Parse argument terms. */
1.1 kristaps 1592:
1593: for (;;) {
1594: la = *pos;
1.119 schwarze 1595: ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.150 ! schwarze 1596: if (ac == ARGS_EOLN)
1.1 kristaps 1597: break;
1598:
1.150 ! schwarze 1599: ntok = ac == ARGS_QWORD ? MDOC_MAX : lookup(tok, p);
1.1 kristaps 1600:
1.150 ! schwarze 1601: if (ntok == MDOC_MAX) {
! 1602: dword(mdoc, line, la, p, DELIM_MAX,
! 1603: MDOC_JOIN & mdoc_macros[tok].flags);
1.53 kristaps 1604: continue;
1605: }
1.149 schwarze 1606: rew_elem(mdoc, tok);
1.119 schwarze 1607: return(mdoc_macro(mdoc, ntok, line, la, pos, buf));
1.1 kristaps 1608: }
1609:
1.32 kristaps 1610: /* Close out (no delimiters). */
1611:
1.149 schwarze 1612: rew_elem(mdoc, tok);
1613: return(1);
1.1 kristaps 1614: }
1615:
1616: static int
1.41 kristaps 1617: ctx_synopsis(MACRO_PROT_ARGS)
1618: {
1.60 kristaps 1619: int nl;
1620:
1.119 schwarze 1621: nl = MDOC_NEWLINE & mdoc->flags;
1.41 kristaps 1622:
1623: /* If we're not in the SYNOPSIS, go straight to in-line. */
1.119 schwarze 1624: if ( ! (MDOC_SYNOPSIS & mdoc->flags))
1625: return(in_line(mdoc, tok, line, ppos, pos, buf));
1.41 kristaps 1626:
1627: /* If we're a nested call, same place. */
1.60 kristaps 1628: if ( ! nl)
1.119 schwarze 1629: return(in_line(mdoc, tok, line, ppos, pos, buf));
1.41 kristaps 1630:
1631: /*
1632: * XXX: this will open a block scope; however, if later we end
1633: * up formatting the block scope, then child nodes will inherit
1634: * the formatting. Be careful.
1635: */
1.88 schwarze 1636: if (MDOC_Nm == tok)
1.119 schwarze 1637: return(blk_full(mdoc, tok, line, ppos, pos, buf));
1.88 schwarze 1638: assert(MDOC_Vt == tok);
1.119 schwarze 1639: return(blk_part_imp(mdoc, tok, line, ppos, pos, buf));
1.1 kristaps 1640: }
1641:
1.24 kristaps 1642: /*
1643: * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1644: * They're unusual because they're basically free-form text until a
1645: * macro is encountered.
1646: */
1.1 kristaps 1647: static int
1.119 schwarze 1648: phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
1.1 kristaps 1649: {
1.53 kristaps 1650: int la, pos;
1.75 kristaps 1651: enum margserr ac;
1.53 kristaps 1652: enum mdoct ntok;
1653: char *p;
1.1 kristaps 1654:
1.24 kristaps 1655: for (pos = ppos; ; ) {
1656: la = pos;
1.1 kristaps 1657:
1.119 schwarze 1658: ac = mdoc_zargs(mdoc, line, &pos, buf, &p);
1.150 ! schwarze 1659: if (ac == ARGS_EOLN)
1.24 kristaps 1660: break;
1.1 kristaps 1661:
1.150 ! schwarze 1662: ntok = ac == ARGS_QWORD ? MDOC_MAX : lookup_raw(p);
1.1 kristaps 1663:
1.150 ! schwarze 1664: if (ntok == MDOC_MAX) {
! 1665: dword(mdoc, line, la, p, DELIM_MAX, 1);
1.53 kristaps 1666: continue;
1667: }
1.1 kristaps 1668:
1.119 schwarze 1669: if ( ! mdoc_macro(mdoc, ntok, line, la, &pos, buf))
1.1 kristaps 1670: return(0);
1.150 ! schwarze 1671: append_delims(mdoc, line, &pos, buf);
! 1672: return(1);
1.1 kristaps 1673: }
1674:
1675: return(1);
1676: }
1.24 kristaps 1677:
1.75 kristaps 1678: static int
1679: phrase_ta(MACRO_PROT_ARGS)
1680: {
1.121 schwarze 1681: struct mdoc_node *n;
1.75 kristaps 1682: int la;
1683: enum mdoct ntok;
1684: enum margserr ac;
1685: char *p;
1686:
1.121 schwarze 1687: /* Make sure we are in a column list or ignore this macro. */
1688: n = mdoc->last;
1689: while (NULL != n && MDOC_Bl != n->tok)
1690: n = n->parent;
1691: if (NULL == n || LIST_column != n->norm->Bl.type) {
1.137 schwarze 1692: mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse,
1.139 schwarze 1693: line, ppos, "Ta");
1.121 schwarze 1694: return(1);
1695: }
1.75 kristaps 1696:
1.121 schwarze 1697: /* Advance to the next column. */
1.150 ! schwarze 1698:
! 1699: rew_sub(MDOC_BODY, mdoc, MDOC_It, line, ppos);
! 1700: mdoc_body_alloc(mdoc, line, ppos, MDOC_It);
1.75 kristaps 1701:
1702: for (;;) {
1703: la = *pos;
1.119 schwarze 1704: ac = mdoc_zargs(mdoc, line, pos, buf, &p);
1.150 ! schwarze 1705: if (ac == ARGS_EOLN)
1.75 kristaps 1706: break;
1707:
1.150 ! schwarze 1708: ntok = ac == ARGS_QWORD ? MDOC_MAX : lookup_raw(p);
1.75 kristaps 1709:
1.150 ! schwarze 1710: if (ntok == MDOC_MAX) {
! 1711: dword(mdoc, line, la, p, DELIM_MAX,
! 1712: MDOC_JOIN & mdoc_macros[tok].flags);
1.75 kristaps 1713: continue;
1714: }
1715:
1.119 schwarze 1716: if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
1.75 kristaps 1717: return(0);
1.150 ! schwarze 1718: append_delims(mdoc, line, pos, buf);
! 1719: return(1);
1.75 kristaps 1720: }
1721:
1722: return(1);
1723: }
CVSweb