Annotation of mandoc/macro.c, Revision 1.57
1.57 ! kristaps 1: /* $Id: macro.c,v 1.56 2009/03/05 12:08:53 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
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
7: * above copyright notice and this permission notice appear in all
8: * copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11: * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12: * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13: * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16: * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17: * PERFORMANCE OF THIS SOFTWARE.
18: */
1.2 kristaps 19: #include <assert.h>
20: #include <ctype.h>
1.1 kristaps 21: #include <stdlib.h>
1.2 kristaps 22: #include <stdio.h>
1.5 kristaps 23: #include <string.h>
1.11 kristaps 24: #ifdef __linux__
25: #include <time.h>
26: #endif
1.2 kristaps 27:
1.44 kristaps 28: /*
29: * This has scanning/parsing routines, each of which extract a macro and
30: * its arguments and parameters, then know how to progress to the next
1.51 kristaps 31: * macro.
1.44 kristaps 32: */
33:
1.56 kristaps 34: /*
35: * FIXME: don't use static mdoc_argv values, as they require us to do a
36: * complicated copy-over when actually assigning them to dynamic memory.
37: */
38:
1.2 kristaps 39: #include "private.h"
40:
1.51 kristaps 41: static int macro_obsolete(MACRO_PROT_ARGS);
42: static int macro_constant(MACRO_PROT_ARGS);
43: static int macro_constant_scoped(MACRO_PROT_ARGS);
44: static int macro_constant_delimited(MACRO_PROT_ARGS);
45: static int macro_text(MACRO_PROT_ARGS);
46: static int macro_scoped(MACRO_PROT_ARGS);
47: static int macro_scoped_close(MACRO_PROT_ARGS);
48: static int macro_scoped_line(MACRO_PROT_ARGS);
49:
1.35 kristaps 50: #define REWIND_REWIND (1 << 0)
51: #define REWIND_NOHALT (1 << 1)
52: #define REWIND_HALT (1 << 2)
1.49 kristaps 53:
1.44 kristaps 54: static int rewind_dohalt(int, enum mdoc_type,
55: const struct mdoc_node *);
56: static int rewind_alt(int);
1.41 kristaps 57: static int rewind_dobreak(int, const struct mdoc_node *);
1.28 kristaps 58: static int rewind_elem(struct mdoc *, int);
1.38 kristaps 59: static int rewind_impblock(struct mdoc *, int, int, int);
60: static int rewind_expblock(struct mdoc *, int, int, int);
1.41 kristaps 61: static int rewind_subblock(enum mdoc_type,
62: struct mdoc *, int, int, int);
63: static int rewind_last(struct mdoc *, struct mdoc_node *);
64: static int append_delims(struct mdoc *, int, int *, char *);
1.30 kristaps 65: static int lookup(struct mdoc *, int, int, int, const char *);
1.49 kristaps 66: static int pwarn(struct mdoc *, int, int, int);
67: static int perr(struct mdoc *, int, int, int);
68:
69: #define WMACPARM (1)
70: #define WOBS (2)
71:
72: #define ENOCTX (1)
73: #define ENOPARMS (2)
74: #define EARGVLIM (3)
75:
1.51 kristaps 76: /* Central table of library: who gets parsed how. */
77:
78: const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
79: { NULL, 0 }, /* \" */
80: { macro_constant, MDOC_PROLOGUE }, /* Dd */
81: { macro_constant, MDOC_PROLOGUE }, /* Dt */
82: { macro_constant, MDOC_PROLOGUE }, /* Os */
83: { macro_scoped, 0 }, /* Sh */
84: { macro_scoped, 0 }, /* Ss */
85: { macro_text, 0 }, /* Pp */
86: { macro_scoped_line, MDOC_PARSED }, /* D1 */
87: { macro_scoped_line, MDOC_PARSED }, /* Dl */
88: { macro_scoped, MDOC_EXPLICIT }, /* Bd */
89: { macro_scoped_close, MDOC_EXPLICIT }, /* Ed */
90: { macro_scoped, MDOC_EXPLICIT }, /* Bl */
91: { macro_scoped_close, MDOC_EXPLICIT }, /* El */
92: { macro_scoped, MDOC_PARSED }, /* It */
93: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
94: { macro_text, MDOC_PARSED }, /* An */
95: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
96: { macro_constant, 0 }, /* Cd */
97: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
98: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
99: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
100: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
101: { macro_constant, 0 }, /* Ex */
102: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
103: { macro_constant, 0 }, /* Fd */
104: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
105: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
106: { macro_text, MDOC_PARSED }, /* Ft */
107: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
108: { macro_constant, 0 }, /* In */
109: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
110: { macro_constant, 0 }, /* Nd */
111: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
112: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
113: { macro_obsolete, 0 }, /* Ot */
114: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
115: { macro_constant, 0 }, /* Rv */
116: /* XXX - .St supposed to be (but isn't) callable. */
117: { macro_constant_delimited, MDOC_PARSED }, /* St */
118: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
119: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
120: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
121: { macro_constant, 0 }, /* %A */
122: { macro_constant, 0 }, /* %B */
123: { macro_constant, 0 }, /* %D */
124: { macro_constant, 0 }, /* %I */
125: { macro_constant, 0 }, /* %J */
126: { macro_constant, 0 }, /* %N */
127: { macro_constant, 0 }, /* %O */
128: { macro_constant, 0 }, /* %P */
129: { macro_constant, 0 }, /* %R */
130: { macro_constant, 0 }, /* %T */
131: { macro_constant, 0 }, /* %V */
132: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
133: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
134: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
135: { macro_constant_delimited, 0 }, /* At */
136: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
137: { macro_scoped, MDOC_EXPLICIT }, /* Bf */
138: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
139: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
140: { macro_constant_delimited, MDOC_PARSED }, /* Bsx */
141: { macro_constant_delimited, MDOC_PARSED }, /* Bx */
142: { macro_constant, 0 }, /* Db */
143: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
144: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
145: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
146: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
147: { macro_scoped_close, MDOC_EXPLICIT }, /* Ef */
148: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
149: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
150: { macro_constant_delimited, MDOC_PARSED }, /* Fx */
151: { macro_text, MDOC_PARSED }, /* Ms */
152: { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* No */
153: { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
154: { macro_constant_delimited, MDOC_PARSED }, /* Nx */
155: { macro_constant_delimited, MDOC_PARSED }, /* Ox */
156: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
157: { macro_constant_delimited, MDOC_PARSED }, /* Pf */
158: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
159: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
160: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
161: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
162: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
163: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
164: { macro_scoped_close, MDOC_EXPLICIT }, /* Re */
165: { macro_scoped, MDOC_EXPLICIT }, /* Rs */
166: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
167: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
168: { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
169: { macro_constant, 0 }, /* Sm */
170: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
171: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
172: { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
173: { macro_constant_delimited, MDOC_PARSED }, /* Ux */
174: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
175: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
176: /* XXX - .Fo supposed to be (but isn't) callable. */
177: { macro_scoped, MDOC_EXPLICIT }, /* Fo */
1.52 kristaps 178: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
1.51 kristaps 179: { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
180: { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
181: { macro_scoped, MDOC_EXPLICIT }, /* Bk */
182: { macro_scoped_close, MDOC_EXPLICIT }, /* Ek */
183: { macro_constant, 0 }, /* Bt */
184: { macro_constant, 0 }, /* Hf */
185: { macro_obsolete, 0 }, /* Fr */
186: { macro_constant, 0 }, /* Ud */
1.57 ! kristaps 187: { macro_constant, 0 }, /* Lb */
1.51 kristaps 188: };
189:
190: const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
191:
1.49 kristaps 192:
193: static int
194: perr(struct mdoc *mdoc, int line, int pos, int type)
195: {
196: int c;
197:
198: switch (type) {
199: case (ENOCTX):
200: c = mdoc_perr(mdoc, line, pos,
201: "closing macro has prior context");
202: break;
203: case (ENOPARMS):
204: c = mdoc_perr(mdoc, line, pos,
205: "macro doesn't expect parameters");
206: break;
207: case (EARGVLIM):
208: c = mdoc_perr(mdoc, line, pos,
209: "argument hard-limit %d reached",
210: MDOC_LINEARG_MAX);
211: break;
212: default:
213: abort();
214: /* NOTREACHED */
215: }
216: return(c);
217: }
218:
219: static int
220: pwarn(struct mdoc *mdoc, int line, int pos, int type)
221: {
222: int c;
223:
224: switch (type) {
225: case (WMACPARM):
226: c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX,
227: "macro-like parameter");
228: break;
229: case (WOBS):
230: c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX,
231: "macro is marked obsolete");
232: break;
233: default:
234: abort();
235: /* NOTREACHED */
236: }
237: return(c);
238: }
1.24 kristaps 239:
240:
241: static int
1.30 kristaps 242: lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
1.24 kristaps 243: {
1.30 kristaps 244: int res;
1.24 kristaps 245:
1.30 kristaps 246: res = mdoc_find(mdoc, p);
247: if (MDOC_PARSED & mdoc_macros[from].flags)
248: return(res);
249: if (MDOC_MAX == res)
250: return(res);
1.49 kristaps 251: if ( ! pwarn(mdoc, line, pos, WMACPARM))
1.30 kristaps 252: return(-1);
253: return(MDOC_MAX);
1.24 kristaps 254: }
1.19 kristaps 255:
256:
257: static int
1.41 kristaps 258: rewind_last(struct mdoc *mdoc, struct mdoc_node *to)
1.25 kristaps 259: {
260:
261: assert(to);
1.30 kristaps 262: mdoc->next = MDOC_NEXT_SIBLING;
1.42 kristaps 263:
1.49 kristaps 264: /* LINTED */
1.42 kristaps 265: while (mdoc->last != to) {
1.30 kristaps 266: if ( ! mdoc_valid_post(mdoc))
267: return(0);
268: if ( ! mdoc_action_post(mdoc))
269: return(0);
1.29 kristaps 270: mdoc->last = mdoc->last->parent;
271: assert(mdoc->last);
1.42 kristaps 272: }
1.28 kristaps 273:
1.42 kristaps 274: if ( ! mdoc_valid_post(mdoc))
275: return(0);
276: return(mdoc_action_post(mdoc));
1.25 kristaps 277: }
278:
279:
280: static int
1.35 kristaps 281: rewind_alt(int tok)
282: {
283: switch (tok) {
284: case (MDOC_Ac):
285: return(MDOC_Ao);
286: case (MDOC_Bc):
287: return(MDOC_Bo);
288: case (MDOC_Dc):
289: return(MDOC_Do);
290: case (MDOC_Ec):
291: return(MDOC_Eo);
292: case (MDOC_Ed):
293: return(MDOC_Bd);
294: case (MDOC_Ef):
295: return(MDOC_Bf);
296: case (MDOC_Ek):
297: return(MDOC_Bk);
298: case (MDOC_El):
299: return(MDOC_Bl);
300: case (MDOC_Fc):
301: return(MDOC_Fo);
302: case (MDOC_Oc):
303: return(MDOC_Oo);
304: case (MDOC_Pc):
305: return(MDOC_Po);
306: case (MDOC_Qc):
307: return(MDOC_Qo);
308: case (MDOC_Re):
309: return(MDOC_Rs);
310: case (MDOC_Sc):
311: return(MDOC_So);
312: case (MDOC_Xc):
313: return(MDOC_Xo);
314: default:
315: break;
316: }
317: abort();
318: /* NOTREACHED */
319: }
320:
321:
322: static int
323: rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
324: {
325:
326: if (MDOC_ROOT == p->type)
327: return(REWIND_HALT);
1.42 kristaps 328: if (MDOC_VALID & p->flags)
1.35 kristaps 329: return(REWIND_NOHALT);
330:
331: switch (tok) {
332: /* One-liner implicit-scope. */
333: case (MDOC_Aq):
334: /* FALLTHROUGH */
335: case (MDOC_Bq):
336: /* FALLTHROUGH */
337: case (MDOC_D1):
338: /* FALLTHROUGH */
339: case (MDOC_Dl):
340: /* FALLTHROUGH */
341: case (MDOC_Dq):
342: /* FALLTHROUGH */
343: case (MDOC_Op):
344: /* FALLTHROUGH */
345: case (MDOC_Pq):
346: /* FALLTHROUGH */
347: case (MDOC_Ql):
348: /* FALLTHROUGH */
349: case (MDOC_Qq):
350: /* FALLTHROUGH */
351: case (MDOC_Sq):
1.44 kristaps 352: assert(MDOC_HEAD != type);
1.35 kristaps 353: assert(MDOC_TAIL != type);
354: if (type == p->type && tok == p->tok)
355: return(REWIND_REWIND);
356: break;
357:
358: /* Multi-line implicit-scope. */
359: case (MDOC_It):
360: assert(MDOC_TAIL != type);
361: if (type == p->type && tok == p->tok)
362: return(REWIND_REWIND);
1.36 kristaps 363: if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
1.35 kristaps 364: return(REWIND_HALT);
365: break;
366: case (MDOC_Sh):
1.36 kristaps 367: if (type == p->type && tok == p->tok)
368: return(REWIND_REWIND);
369: break;
1.35 kristaps 370: case (MDOC_Ss):
1.36 kristaps 371: assert(MDOC_TAIL != type);
1.35 kristaps 372: if (type == p->type && tok == p->tok)
373: return(REWIND_REWIND);
1.36 kristaps 374: if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
375: return(REWIND_HALT);
1.35 kristaps 376: break;
377:
378: /* Multi-line explicit scope start. */
379: case (MDOC_Ao):
380: /* FALLTHROUGH */
381: case (MDOC_Bd):
382: /* FALLTHROUGH */
383: case (MDOC_Bf):
384: /* FALLTHROUGH */
385: case (MDOC_Bk):
386: /* FALLTHROUGH */
387: case (MDOC_Bl):
388: /* FALLTHROUGH */
389: case (MDOC_Bo):
390: /* FALLTHROUGH */
391: case (MDOC_Do):
392: /* FALLTHROUGH */
393: case (MDOC_Eo):
394: /* FALLTHROUGH */
395: case (MDOC_Fo):
396: /* FALLTHROUGH */
397: case (MDOC_Oo):
398: /* FALLTHROUGH */
399: case (MDOC_Po):
400: /* FALLTHROUGH */
401: case (MDOC_Qo):
402: /* FALLTHROUGH */
403: case (MDOC_Rs):
404: /* FALLTHROUGH */
405: case (MDOC_So):
406: /* FALLTHROUGH */
407: case (MDOC_Xo):
408: if (type == p->type && tok == p->tok)
409: return(REWIND_REWIND);
410: break;
411:
412: /* Multi-line explicit scope close. */
413: case (MDOC_Ac):
414: /* FALLTHROUGH */
415: case (MDOC_Bc):
416: /* FALLTHROUGH */
417: case (MDOC_Dc):
418: /* FALLTHROUGH */
419: case (MDOC_Ec):
420: /* FALLTHROUGH */
421: case (MDOC_Ed):
422: /* FALLTHROUGH */
423: case (MDOC_Ek):
424: /* FALLTHROUGH */
425: case (MDOC_El):
426: /* FALLTHROUGH */
427: case (MDOC_Fc):
428: /* FALLTHROUGH */
429: case (MDOC_Ef):
430: /* FALLTHROUGH */
431: case (MDOC_Oc):
432: /* FALLTHROUGH */
433: case (MDOC_Pc):
434: /* FALLTHROUGH */
435: case (MDOC_Qc):
436: /* FALLTHROUGH */
437: case (MDOC_Re):
438: /* FALLTHROUGH */
439: case (MDOC_Sc):
440: /* FALLTHROUGH */
441: case (MDOC_Xc):
442: if (type == p->type && rewind_alt(tok) == p->tok)
443: return(REWIND_REWIND);
444: break;
445: default:
446: abort();
447: /* NOTREACHED */
448: }
449:
450: return(REWIND_NOHALT);
451: }
452:
453:
454: static int
1.41 kristaps 455: rewind_dobreak(int tok, const struct mdoc_node *p)
1.35 kristaps 456: {
457:
458: assert(MDOC_ROOT != p->type);
459: if (MDOC_ELEM == p->type)
460: return(1);
461: if (MDOC_TEXT == p->type)
462: return(1);
1.42 kristaps 463: if (MDOC_VALID & p->flags)
464: return(1);
1.35 kristaps 465:
466: switch (tok) {
1.36 kristaps 467: /* Implicit rules. */
1.35 kristaps 468: case (MDOC_It):
469: return(MDOC_It == p->tok);
470: case (MDOC_Ss):
471: return(MDOC_Ss == p->tok);
472: case (MDOC_Sh):
473: if (MDOC_Ss == p->tok)
474: return(1);
475: return(MDOC_Sh == p->tok);
1.36 kristaps 476:
477: /* Extra scope rules. */
478: case (MDOC_El):
479: if (MDOC_It == p->tok)
480: return(1);
481: break;
482: default:
483: break;
1.35 kristaps 484: }
485:
486: if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
487: return(p->tok == rewind_alt(tok));
488: else if (MDOC_BLOCK == p->type)
489: return(1);
490:
491: return(tok == p->tok);
492: }
493:
494:
495: static int
1.28 kristaps 496: rewind_elem(struct mdoc *mdoc, int tok)
1.19 kristaps 497: {
498: struct mdoc_node *n;
1.2 kristaps 499:
1.19 kristaps 500: n = mdoc->last;
501: if (MDOC_ELEM != n->type)
502: n = n->parent;
503: assert(MDOC_ELEM == n->type);
1.32 kristaps 504: assert(tok == n->tok);
1.19 kristaps 505:
1.41 kristaps 506: return(rewind_last(mdoc, n));
1.19 kristaps 507: }
1.6 kristaps 508:
509:
510: static int
1.41 kristaps 511: rewind_subblock(enum mdoc_type type, struct mdoc *mdoc,
512: int tok, int line, int ppos)
1.22 kristaps 513: {
514: struct mdoc_node *n;
1.35 kristaps 515: int c;
1.28 kristaps 516:
1.6 kristaps 517: /* LINTED */
1.42 kristaps 518: for (n = mdoc->last; n; n = n->parent) {
1.36 kristaps 519: c = rewind_dohalt(tok, type, n);
1.35 kristaps 520: if (REWIND_HALT == c)
521: return(1);
522: if (REWIND_REWIND == c)
1.6 kristaps 523: break;
1.41 kristaps 524: else if (rewind_dobreak(tok, n))
1.7 kristaps 525: continue;
1.57 ! kristaps 526: return(mdoc_perr(mdoc, line, ppos,
! 527: "scope breaks %s", MDOC_ROOT == n->type ?
! 528: "<root>" : mdoc_macronames[n->tok]));
1.6 kristaps 529: }
530:
1.25 kristaps 531: assert(n);
1.41 kristaps 532: return(rewind_last(mdoc, n));
1.6 kristaps 533: }
534:
535:
536: static int
1.38 kristaps 537: rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
1.6 kristaps 538: {
1.7 kristaps 539: struct mdoc_node *n;
1.35 kristaps 540: int c;
1.6 kristaps 541:
1.7 kristaps 542: /* LINTED */
1.42 kristaps 543: for (n = mdoc->last; n; n = n->parent) {
1.35 kristaps 544: c = rewind_dohalt(tok, MDOC_BLOCK, n);
545: if (REWIND_HALT == c)
1.49 kristaps 546: return(perr(mdoc, line, ppos, ENOCTX));
1.35 kristaps 547: if (REWIND_REWIND == c)
1.16 kristaps 548: break;
1.41 kristaps 549: else if (rewind_dobreak(tok, n))
1.22 kristaps 550: continue;
1.51 kristaps 551: return(mdoc_perr(mdoc, line, ppos,
1.57 ! kristaps 552: "scope breaks %s", MDOC_ROOT == n->type ?
! 553: "<root>" : mdoc_macronames[n->tok]));
1.16 kristaps 554: }
555:
1.28 kristaps 556: assert(n);
1.41 kristaps 557: return(rewind_last(mdoc, n));
1.21 kristaps 558: }
559:
560:
561: static int
1.38 kristaps 562: rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
1.21 kristaps 563: {
564: struct mdoc_node *n;
1.35 kristaps 565: int c;
1.21 kristaps 566:
567: /* LINTED */
1.42 kristaps 568: for (n = mdoc->last; n; n = n->parent) {
1.35 kristaps 569: c = rewind_dohalt(tok, MDOC_BLOCK, n);
570: if (REWIND_HALT == c)
571: return(1);
572: else if (REWIND_REWIND == c)
1.21 kristaps 573: break;
1.41 kristaps 574: else if (rewind_dobreak(tok, n))
1.21 kristaps 575: continue;
1.51 kristaps 576: return(mdoc_perr(mdoc, line, ppos,
1.57 ! kristaps 577: "scope breaks %s", MDOC_ROOT == n->type ?
! 578: "<root>" : mdoc_macronames[n->tok]));
1.21 kristaps 579: }
580:
1.35 kristaps 581: assert(n);
1.41 kristaps 582: return(rewind_last(mdoc, n));
1.16 kristaps 583: }
584:
585:
1.22 kristaps 586: static int
1.41 kristaps 587: append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
1.22 kristaps 588: {
589: int c, lastarg;
590: char *p;
591:
592: if (0 == buf[*pos])
593: return(1);
594:
595: for (;;) {
596: lastarg = *pos;
1.28 kristaps 597: c = mdoc_args(mdoc, line, pos, buf, 0, &p);
1.49 kristaps 598: assert(ARGS_PHRASE != c);
599:
1.22 kristaps 600: if (ARGS_ERROR == c)
601: return(0);
602: else if (ARGS_EOLN == c)
603: break;
604: assert(mdoc_isdelim(p));
1.28 kristaps 605: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
606: return(0);
1.22 kristaps 607: mdoc->next = MDOC_NEXT_SIBLING;
608: }
609:
610: return(1);
611: }
612:
613:
1.44 kristaps 614: /*
615: * Close out an explicit scope. This optionally parses a TAIL type with
616: * a set number of TEXT children.
617: */
1.51 kristaps 618: static int
1.35 kristaps 619: macro_scoped_close(MACRO_PROT_ARGS)
1.19 kristaps 620: {
1.28 kristaps 621: int tt, j, c, lastarg, maxargs, flushed;
1.22 kristaps 622: char *p;
1.19 kristaps 623:
624: switch (tok) {
1.22 kristaps 625: case (MDOC_Ec):
626: maxargs = 1;
627: break;
628: default:
629: maxargs = 0;
630: break;
631: }
632:
1.35 kristaps 633: tt = rewind_alt(tok);
634:
1.41 kristaps 635: mdoc_msg(mdoc, "parse: %s closing %s",
1.36 kristaps 636: mdoc_macronames[tok], mdoc_macronames[tt]);
637:
1.22 kristaps 638: if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
1.35 kristaps 639: if (0 == buf[*pos]) {
1.51 kristaps 640: if ( ! rewind_subblock(MDOC_BODY, mdoc,
641: tok, line, ppos))
1.35 kristaps 642: return(0);
1.38 kristaps 643: return(rewind_expblock(mdoc, tok, line, ppos));
1.35 kristaps 644: }
1.49 kristaps 645: return(perr(mdoc, line, ppos, ENOPARMS));
1.22 kristaps 646: }
1.19 kristaps 647:
1.41 kristaps 648: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.22 kristaps 649: return(0);
1.19 kristaps 650:
1.22 kristaps 651: lastarg = ppos;
652: flushed = 0;
1.15 kristaps 653:
1.22 kristaps 654: if (maxargs > 0) {
1.28 kristaps 655: if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
656: return(0);
1.22 kristaps 657: mdoc->next = MDOC_NEXT_CHILD;
658: }
1.15 kristaps 659:
1.41 kristaps 660: for (j = 0; /* No sentinel. */; j++) {
1.15 kristaps 661: lastarg = *pos;
1.22 kristaps 662:
663: if (j == maxargs && ! flushed) {
1.38 kristaps 664: if ( ! rewind_expblock(mdoc, tok, line, ppos))
1.22 kristaps 665: return(0);
666: flushed = 1;
667: }
668:
1.48 kristaps 669: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 670: assert(ARGS_PHRASE != c);
671:
1.15 kristaps 672: if (ARGS_ERROR == c)
673: return(0);
1.22 kristaps 674: if (ARGS_PUNCT == c)
675: break;
676: if (ARGS_EOLN == c)
677: break;
678:
1.30 kristaps 679: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
680: return(0);
681: else if (MDOC_MAX != c) {
1.22 kristaps 682: if ( ! flushed) {
1.51 kristaps 683: if ( ! rewind_expblock(mdoc, tok,
684: line, ppos))
1.22 kristaps 685: return(0);
686: flushed = 1;
687: }
1.26 kristaps 688: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22 kristaps 689: return(0);
1.15 kristaps 690: break;
1.30 kristaps 691: }
1.22 kristaps 692:
1.28 kristaps 693: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
694: return(0);
1.16 kristaps 695: mdoc->next = MDOC_NEXT_SIBLING;
1.15 kristaps 696: }
1.2 kristaps 697:
1.38 kristaps 698: if ( ! flushed && ! rewind_expblock(mdoc, tok, line, ppos))
1.28 kristaps 699: return(0);
1.22 kristaps 700:
701: if (ppos > 1)
702: return(1);
1.41 kristaps 703: return(append_delims(mdoc, line, pos, buf));
1.1 kristaps 704: }
705:
1.2 kristaps 706:
1.44 kristaps 707: /*
708: * A general text macro. This is a complex case because of punctuation.
709: * If a text macro is followed by words, then punctuation, the macro is
710: * "stopped" and "reopened" following the punctuation. Thus, the
711: * following arises:
712: *
713: * .Fl a ; b
714: *
715: * ELEMENT (.Fl)
716: * TEXT (`a')
717: * TEXT (`;')
718: * ELEMENT (.Fl)
719: * TEXT (`b')
720: *
721: * This must handle the following situations:
722: *
723: * .Fl Ar b ; ;
724: *
725: * ELEMENT (.Fl)
726: * ELEMENT (.Ar)
727: * TEXT (`b')
728: * TEXT (`;')
729: * TEXT (`;')
730: */
1.51 kristaps 731: static int
1.19 kristaps 732: macro_text(MACRO_PROT_ARGS)
1.13 kristaps 733: {
1.48 kristaps 734: int la, lastpunct, c, w, argc;
1.19 kristaps 735: struct mdoc_arg argv[MDOC_LINEARG_MAX];
736: char *p;
1.13 kristaps 737:
1.28 kristaps 738: la = ppos;
1.19 kristaps 739: lastpunct = 0;
1.17 kristaps 740:
1.19 kristaps 741: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.28 kristaps 742: la = *pos;
743: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 744: if (ARGV_EOLN == c)
1.19 kristaps 745: break;
1.38 kristaps 746: if (ARGV_WORD == c) {
747: *pos = la;
748: break;
749: } else if (ARGV_ARG == c)
1.19 kristaps 750: continue;
1.38 kristaps 751:
1.19 kristaps 752: mdoc_argv_free(argc, argv);
1.14 kristaps 753: return(0);
1.10 kristaps 754: }
755:
1.28 kristaps 756: if (MDOC_LINEARG_MAX == argc) {
1.41 kristaps 757: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 758: return(perr(mdoc, line, ppos, EARGVLIM));
1.28 kristaps 759: }
760:
1.54 kristaps 761: c = mdoc_elem_alloc(mdoc, line, ppos,
762: tok, (size_t)argc, argv);
1.28 kristaps 763:
764: if (0 == c) {
1.19 kristaps 765: mdoc_argv_free(argc, argv);
766: return(0);
1.7 kristaps 767: }
768:
1.28 kristaps 769: mdoc->next = MDOC_NEXT_CHILD;
770:
1.41 kristaps 771: lastpunct = 0;
772: for (;;) {
1.28 kristaps 773: la = *pos;
1.48 kristaps 774: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 775: assert(ARGS_PHRASE != c);
776:
1.45 kristaps 777: if (ARGS_ERROR == w) {
1.19 kristaps 778: mdoc_argv_free(argc, argv);
1.7 kristaps 779: return(0);
1.19 kristaps 780: }
781:
1.45 kristaps 782: if (ARGS_EOLN == w)
1.19 kristaps 783: break;
1.45 kristaps 784: if (ARGS_PUNCT == w)
1.19 kristaps 785: break;
1.2 kristaps 786:
1.45 kristaps 787: c = ARGS_QWORD == w ? MDOC_MAX :
788: lookup(mdoc, line, la, tok, p);
789:
790: if (MDOC_MAX != c && -1 != c) {
1.36 kristaps 791: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 792: mdoc_argv_free(argc, argv);
793: return(0);
794: }
795: mdoc_argv_free(argc, argv);
1.28 kristaps 796: c = mdoc_macro(mdoc, c, line, la, pos, buf);
797: if (0 == c)
1.19 kristaps 798: return(0);
799: if (ppos > 1)
800: return(1);
1.41 kristaps 801: return(append_delims(mdoc, line, pos, buf));
1.45 kristaps 802: } else if (-1 == c) {
803: mdoc_argv_free(argc, argv);
804: return(0);
1.19 kristaps 805: }
1.2 kristaps 806:
1.55 kristaps 807: /* FIXME: .Fl and .Ar handling of `|'. */
808:
1.45 kristaps 809: if (ARGS_QWORD != w && mdoc_isdelim(p)) {
1.36 kristaps 810: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 811: mdoc_argv_free(argc, argv);
812: return(0);
813: }
814: lastpunct = 1;
1.36 kristaps 815: } else if (lastpunct) {
1.54 kristaps 816: c = mdoc_elem_alloc(mdoc, line, ppos,
817: tok, (size_t)argc, argv);
1.36 kristaps 818: if (0 == c) {
819: mdoc_argv_free(argc, argv);
820: return(0);
821: }
822: mdoc->next = MDOC_NEXT_CHILD;
823: lastpunct = 0;
1.19 kristaps 824: }
1.36 kristaps 825:
1.28 kristaps 826: if ( ! mdoc_word_alloc(mdoc, line, la, p))
827: return(0);
1.19 kristaps 828: mdoc->next = MDOC_NEXT_SIBLING;
1.2 kristaps 829: }
830:
1.19 kristaps 831: mdoc_argv_free(argc, argv);
1.2 kristaps 832:
1.36 kristaps 833: if (0 == lastpunct && ! rewind_elem(mdoc, tok))
1.7 kristaps 834: return(0);
1.19 kristaps 835: if (ppos > 1)
836: return(1);
1.41 kristaps 837: return(append_delims(mdoc, line, pos, buf));
1.5 kristaps 838: }
839:
840:
1.44 kristaps 841: /*
842: * Handle explicit-scope (having a different closure token) and implicit
843: * scope (closing out prior scopes when re-invoked) macros. These
844: * constitute the BLOCK type and usually span multiple lines. These
845: * always have HEAD and sometimes have BODY types. In the multi-line
846: * case:
847: *
848: * .Bd -ragged
849: * Text.
850: * .Fl macro
851: * Another.
852: * .Ed
853: *
854: * BLOCK (.Bd)
855: * HEAD
856: * BODY
857: * TEXT (`Text.')
858: * ELEMENT (.Fl)
859: * TEXT (`macro')
860: * TEXT (`Another.')
861: *
862: * Note that the `.It' macro, possibly the most difficult (as it has
863: * embedded scope, etc.) is handled by this routine.
864: */
1.51 kristaps 865: static int
1.16 kristaps 866: macro_scoped(MACRO_PROT_ARGS)
1.6 kristaps 867: {
1.48 kristaps 868: int c, lastarg, argc;
1.6 kristaps 869: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.24 kristaps 870: char *p;
1.6 kristaps 871:
1.16 kristaps 872: assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.6 kristaps 873:
1.47 kristaps 874: /* First rewind extant implicit scope. */
875:
1.35 kristaps 876: if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
1.41 kristaps 877: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.35 kristaps 878: return(0);
1.38 kristaps 879: if ( ! rewind_impblock(mdoc, tok, line, ppos))
1.16 kristaps 880: return(0);
1.35 kristaps 881: }
1.2 kristaps 882:
1.47 kristaps 883: /* Parse arguments. */
884:
1.16 kristaps 885: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
886: lastarg = *pos;
1.28 kristaps 887: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 888: if (ARGV_EOLN == c)
889: break;
890: if (ARGV_WORD == c) {
891: *pos = lastarg;
1.16 kristaps 892: break;
1.38 kristaps 893: } else if (ARGV_ARG == c)
1.16 kristaps 894: continue;
895: mdoc_argv_free(argc, argv);
1.8 kristaps 896: return(0);
1.16 kristaps 897: }
1.2 kristaps 898:
1.28 kristaps 899: if (MDOC_LINEARG_MAX == argc) {
1.41 kristaps 900: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 901: return(perr(mdoc, line, ppos, EARGVLIM));
1.28 kristaps 902: }
903:
904: c = mdoc_block_alloc(mdoc, line, ppos,
905: tok, (size_t)argc, argv);
906: mdoc_argv_free(argc, argv);
907:
908: if (0 == c)
1.16 kristaps 909: return(0);
1.8 kristaps 910:
1.19 kristaps 911: mdoc->next = MDOC_NEXT_CHILD;
912:
1.24 kristaps 913: if (0 == buf[*pos]) {
1.28 kristaps 914: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
915: return(0);
1.51 kristaps 916: if ( ! rewind_subblock(MDOC_HEAD, mdoc,
917: tok, line, ppos))
1.28 kristaps 918: return(0);
919: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 920: return(0);
1.19 kristaps 921: mdoc->next = MDOC_NEXT_CHILD;
1.24 kristaps 922: return(1);
923: }
1.19 kristaps 924:
1.28 kristaps 925: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
926: return(0);
1.24 kristaps 927: mdoc->next = MDOC_NEXT_CHILD;
1.7 kristaps 928:
1.41 kristaps 929: for (;;) {
1.24 kristaps 930: lastarg = *pos;
1.48 kristaps 931: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 932:
1.24 kristaps 933: if (ARGS_ERROR == c)
1.19 kristaps 934: return(0);
1.24 kristaps 935: if (ARGS_EOLN == c)
936: break;
1.49 kristaps 937: if (ARGS_PHRASE == c) {
938: /*
939: if ( ! mdoc_phrase(mdoc, line, lastarg, buf))
940: return(0);
941: */
942: continue;
943: }
944:
1.48 kristaps 945: /* FIXME: if .It -column, the lookup must be for a
946: * sub-line component. BLAH. */
1.24 kristaps 947:
1.30 kristaps 948: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
949: return(0);
1.48 kristaps 950:
951: if (MDOC_MAX == c) {
1.28 kristaps 952: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
953: return(0);
1.24 kristaps 954: mdoc->next = MDOC_NEXT_SIBLING;
955: continue;
1.30 kristaps 956: }
1.2 kristaps 957:
1.26 kristaps 958: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.24 kristaps 959: return(0);
960: break;
1.7 kristaps 961: }
1.48 kristaps 962:
1.53 kristaps 963: if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
964: return(0);
1.41 kristaps 965: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.24 kristaps 966: return(0);
967:
1.28 kristaps 968: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
969: return(0);
1.16 kristaps 970: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 971:
1.16 kristaps 972: return(1);
1.1 kristaps 973: }
1.5 kristaps 974:
1.7 kristaps 975:
1.44 kristaps 976: /*
977: * This handles a case of implicitly-scoped macro (BLOCK) limited to a
978: * single line. Instead of being closed out by a subsequent call to
979: * another macro, the scope is closed at the end of line. These don't
980: * have BODY or TAIL types. Notice that the punctuation falls outside
981: * of the HEAD type.
982: *
983: * .Qq a Fl b Ar d ; ;
984: *
985: * BLOCK (Qq)
986: * HEAD
987: * TEXT (`a')
988: * ELEMENT (.Fl)
989: * TEXT (`b')
990: * ELEMENT (.Ar)
991: * TEXT (`d')
992: * TEXT (`;')
993: * TEXT (`;')
994: */
1.51 kristaps 995: static int
1.16 kristaps 996: macro_scoped_line(MACRO_PROT_ARGS)
1.7 kristaps 997: {
1.41 kristaps 998: int lastarg, c;
1.8 kristaps 999: char *p;
1.7 kristaps 1000:
1.28 kristaps 1001: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
1002: return(0);
1.16 kristaps 1003: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 1004:
1.28 kristaps 1005: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1006: return(0);
1.44 kristaps 1007: mdoc->next = MDOC_NEXT_SIBLING;
1008: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1009: return(0);
1.16 kristaps 1010: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 1011:
1.19 kristaps 1012: /* XXX - no known argument macros. */
1013:
1.41 kristaps 1014: lastarg = ppos;
1015: for (;;) {
1.19 kristaps 1016: lastarg = *pos;
1.48 kristaps 1017: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1018: assert(ARGS_PHRASE != c);
1.8 kristaps 1019:
1.19 kristaps 1020: if (ARGS_ERROR == c)
1021: return(0);
1022: if (ARGS_PUNCT == c)
1023: break;
1024: if (ARGS_EOLN == c)
1025: break;
1.8 kristaps 1026:
1.30 kristaps 1027: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1028: return(0);
1029: else if (MDOC_MAX == c) {
1.28 kristaps 1030: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1031: return(0);
1.19 kristaps 1032: mdoc->next = MDOC_NEXT_SIBLING;
1033: continue;
1.30 kristaps 1034: }
1.8 kristaps 1035:
1.26 kristaps 1036: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 1037: return(0);
1.8 kristaps 1038: break;
1039: }
1040:
1.19 kristaps 1041: if (1 == ppos) {
1.44 kristaps 1042: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.16 kristaps 1043: return(0);
1.41 kristaps 1044: if ( ! append_delims(mdoc, line, pos, buf))
1.8 kristaps 1045: return(0);
1.44 kristaps 1046: } else if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.35 kristaps 1047: return(0);
1.38 kristaps 1048: return(rewind_impblock(mdoc, tok, line, ppos));
1.22 kristaps 1049: }
1050:
1051:
1.44 kristaps 1052: /*
1053: * A constant-scoped macro is like a simple-scoped macro (mdoc_scoped)
1054: * except that it doesn't handle implicit scopes and explicit ones have
1055: * a fixed number of TEXT children to the BODY.
1056: *
1057: * .Fl a So b Sc ;
1058: *
1059: * ELEMENT (.Fl)
1060: * TEXT (`a')
1061: * BLOCK (.So)
1062: * HEAD
1063: * BODY
1064: * TEXT (`b')
1065: * TEXT (';')
1066: */
1.51 kristaps 1067: static int
1.22 kristaps 1068: macro_constant_scoped(MACRO_PROT_ARGS)
1069: {
1070: int lastarg, flushed, j, c, maxargs;
1071: char *p;
1072:
1073: lastarg = ppos;
1074: flushed = 0;
1075:
1076: switch (tok) {
1077: case (MDOC_Eo):
1078: maxargs = 1;
1079: break;
1080: default:
1081: maxargs = 0;
1082: break;
1083: }
1084:
1.28 kristaps 1085: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
1086: return(0);
1.22 kristaps 1087: mdoc->next = MDOC_NEXT_CHILD;
1088:
1089: if (0 == maxargs) {
1.28 kristaps 1090: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1091: return(0);
1.41 kristaps 1092: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.28 kristaps 1093: return(0);
1094: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 1095: return(0);
1.22 kristaps 1096: flushed = 1;
1.28 kristaps 1097: } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1098: return(0);
1.22 kristaps 1099:
1100: mdoc->next = MDOC_NEXT_CHILD;
1101:
1.41 kristaps 1102: for (j = 0; /* No sentinel. */; j++) {
1.22 kristaps 1103: lastarg = *pos;
1104:
1105: if (j == maxargs && ! flushed) {
1.41 kristaps 1106: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.22 kristaps 1107: return(0);
1108: flushed = 1;
1.28 kristaps 1109: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1110: return(0);
1.22 kristaps 1111: mdoc->next = MDOC_NEXT_CHILD;
1112: }
1113:
1.48 kristaps 1114: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1115: assert(ARGS_PHRASE != c);
1116:
1.22 kristaps 1117: if (ARGS_ERROR == c)
1118: return(0);
1119: if (ARGS_PUNCT == c)
1120: break;
1121: if (ARGS_EOLN == c)
1122: break;
1123:
1.30 kristaps 1124: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1125: return(0);
1126: else if (MDOC_MAX != c) {
1.22 kristaps 1127: if ( ! flushed) {
1.51 kristaps 1128: if ( ! rewind_subblock(MDOC_HEAD, mdoc,
1129: tok, line, ppos))
1.22 kristaps 1130: return(0);
1131: flushed = 1;
1.51 kristaps 1132: if ( ! mdoc_body_alloc(mdoc, line,
1133: ppos, tok))
1.28 kristaps 1134: return(0);
1.22 kristaps 1135: mdoc->next = MDOC_NEXT_CHILD;
1136: }
1.51 kristaps 1137: if ( ! mdoc_macro(mdoc, c, line, lastarg,
1138: pos, buf))
1.22 kristaps 1139: return(0);
1140: break;
1141: }
1142:
1143: if ( ! flushed && mdoc_isdelim(p)) {
1.51 kristaps 1144: if ( ! rewind_subblock(MDOC_HEAD, mdoc,
1145: tok, line, ppos))
1.22 kristaps 1146: return(0);
1147: flushed = 1;
1.28 kristaps 1148: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1149: return(0);
1.22 kristaps 1150: mdoc->next = MDOC_NEXT_CHILD;
1151: }
1152:
1.28 kristaps 1153: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1154: return(0);
1.22 kristaps 1155: mdoc->next = MDOC_NEXT_SIBLING;
1156: }
1157:
1158: if ( ! flushed) {
1.41 kristaps 1159: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.28 kristaps 1160: return(0);
1161: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.22 kristaps 1162: return(0);
1163: mdoc->next = MDOC_NEXT_CHILD;
1164: }
1165:
1166: if (ppos > 1)
1167: return(1);
1.41 kristaps 1168: return(append_delims(mdoc, line, pos, buf));
1.7 kristaps 1169: }
1.8 kristaps 1170:
1.10 kristaps 1171:
1.44 kristaps 1172: /*
1173: * A delimited constant is very similar to the macros parsed by
1174: * macro_text except that, in the event of punctuation, the macro isn't
1175: * "re-opened" as it is in macro_text. Also, these macros have a fixed
1176: * number of parameters.
1177: *
1178: * .Fl a No b
1179: *
1180: * ELEMENT (.Fl)
1181: * TEXT (`a')
1182: * ELEMENT (.No)
1183: * TEXT (`b')
1184: */
1.51 kristaps 1185: static int
1.10 kristaps 1186: macro_constant_delimited(MACRO_PROT_ARGS)
1187: {
1.50 kristaps 1188: int lastarg, flushed, j, c, maxargs, argc,
1.57 ! kristaps 1189: igndelim, ignargs;
1.24 kristaps 1190: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.13 kristaps 1191: char *p;
1.10 kristaps 1192:
1193: lastarg = ppos;
1194: flushed = 0;
1195:
1.57 ! kristaps 1196:
! 1197: /*
! 1198: * Maximum arguments per macro. Some of these have none and
! 1199: * exit as soon as they're parsed.
! 1200: */
! 1201:
1.10 kristaps 1202: switch (tok) {
1.16 kristaps 1203: case (MDOC_No):
1204: /* FALLTHROUGH */
1205: case (MDOC_Ns):
1206: /* FALLTHROUGH */
1.10 kristaps 1207: case (MDOC_Ux):
1208: maxargs = 0;
1209: break;
1210: default:
1211: maxargs = 1;
1212: break;
1213: }
1214:
1.57 ! kristaps 1215: /*
! 1216: * Whether to ignore delimiter characters. `Pf' accepts its
! 1217: * first token as a parameter no matter what it looks like (if
! 1218: * it's text).
! 1219: */
! 1220:
1.50 kristaps 1221: switch (tok) {
1222: case (MDOC_Pf):
1223: igndelim = 1;
1224: break;
1225: default:
1226: igndelim = 0;
1227: break;
1228: }
1229:
1.57 ! kristaps 1230: /*
! 1231: * Whether to ignore arguments: `St', for example, handles its
! 1232: * argument-like parameters as regular parameters.
! 1233: */
! 1234:
! 1235: switch (tok) {
! 1236: case (MDOC_St):
! 1237: ignargs = 1;
! 1238: break;
! 1239: default:
! 1240: ignargs = 0;
! 1241: break;
1.24 kristaps 1242: }
1243:
1.57 ! kristaps 1244: argc = 0;
! 1245:
! 1246: if ( ! ignargs)
! 1247: for ( ; argc < MDOC_LINEARG_MAX; argc++) {
! 1248: lastarg = *pos;
! 1249: c = mdoc_argv(mdoc, line, tok,
! 1250: &argv[argc], pos, buf);
! 1251: if (ARGV_EOLN == c)
! 1252: break;
! 1253: if (ARGV_WORD == c) {
! 1254: *pos = lastarg;
! 1255: break;
! 1256: } else if (ARGV_ARG == c)
! 1257: continue;
! 1258: mdoc_argv_free(argc, argv);
! 1259: return(0);
! 1260: }
! 1261:
1.41 kristaps 1262: if (MDOC_LINEARG_MAX == argc) {
1263: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 1264: return(perr(mdoc, line, ppos, EARGVLIM));
1.41 kristaps 1265: }
1266:
1.54 kristaps 1267: c = mdoc_elem_alloc(mdoc, line, ppos,
1268: tok, (size_t)argc, argv);
1269:
1.28 kristaps 1270: mdoc_argv_free(argc, argv);
1271:
1272: if (0 == c)
1.24 kristaps 1273: return(0);
1274:
1.19 kristaps 1275: mdoc->next = MDOC_NEXT_CHILD;
1.10 kristaps 1276:
1.41 kristaps 1277: for (j = 0; /* No sentinel. */; j++) {
1.19 kristaps 1278: lastarg = *pos;
1.10 kristaps 1279:
1.19 kristaps 1280: if (j == maxargs && ! flushed) {
1.28 kristaps 1281: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 1282: return(0);
1283: flushed = 1;
1284: }
1.11 kristaps 1285:
1.48 kristaps 1286: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1287: assert(ARGS_PHRASE != c);
1288:
1.19 kristaps 1289: if (ARGS_ERROR == c)
1.10 kristaps 1290: return(0);
1.19 kristaps 1291: if (ARGS_PUNCT == c)
1292: break;
1293: if (ARGS_EOLN == c)
1294: break;
1295:
1.30 kristaps 1296: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1297: return(0);
1298: else if (MDOC_MAX != c) {
1.28 kristaps 1299: if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19 kristaps 1300: return(0);
1301: flushed = 1;
1.26 kristaps 1302: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 1303: return(0);
1304: break;
1305: }
1.10 kristaps 1306:
1.50 kristaps 1307: if ( ! flushed && mdoc_isdelim(p) && ! igndelim) {
1.28 kristaps 1308: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 1309: return(0);
1310: flushed = 1;
1311: }
1312:
1.28 kristaps 1313: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1314: return(0);
1.19 kristaps 1315: mdoc->next = MDOC_NEXT_SIBLING;
1.10 kristaps 1316: }
1317:
1.42 kristaps 1318: if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19 kristaps 1319: return(0);
1.11 kristaps 1320:
1.19 kristaps 1321: if (ppos > 1)
1322: return(1);
1.41 kristaps 1323: return(append_delims(mdoc, line, pos, buf));
1.10 kristaps 1324: }
1.11 kristaps 1325:
1326:
1.44 kristaps 1327: /*
1328: * A constant macro is the simplest classification. It spans an entire
1329: * line.
1330: */
1.51 kristaps 1331: static int
1.11 kristaps 1332: macro_constant(MACRO_PROT_ARGS)
1333: {
1.48 kristaps 1334: int c, w, la, argc;
1.43 kristaps 1335: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1336: char *p;
1.44 kristaps 1337:
1338: assert( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.11 kristaps 1339:
1.16 kristaps 1340: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.45 kristaps 1341: la = *pos;
1.28 kristaps 1342: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16 kristaps 1343: if (ARGV_EOLN == c)
1344: break;
1.38 kristaps 1345: if (ARGV_WORD == c) {
1.45 kristaps 1346: *pos = la;
1.38 kristaps 1347: break;
1348: } else if (ARGV_ARG == c)
1.16 kristaps 1349: continue;
1.11 kristaps 1350:
1.16 kristaps 1351: mdoc_argv_free(argc, argv);
1.11 kristaps 1352: return(0);
1353: }
1354:
1.41 kristaps 1355: if (MDOC_LINEARG_MAX == argc) {
1356: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 1357: return(perr(mdoc, line, ppos, EARGVLIM));
1.41 kristaps 1358: }
1359:
1.54 kristaps 1360: c = mdoc_elem_alloc(mdoc, line, ppos,
1361: tok, (size_t)argc, argv);
1362:
1.28 kristaps 1363: mdoc_argv_free(argc, argv);
1364:
1365: if (0 == c)
1366: return(0);
1.11 kristaps 1367:
1.19 kristaps 1368: mdoc->next = MDOC_NEXT_CHILD;
1369:
1.41 kristaps 1370: for (;;) {
1.45 kristaps 1371: la = *pos;
1.48 kristaps 1372: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1373: assert(ARGS_PHRASE != c);
1374:
1.45 kristaps 1375: if (ARGS_ERROR == w)
1.16 kristaps 1376: return(0);
1.45 kristaps 1377: if (ARGS_EOLN == w)
1.13 kristaps 1378: break;
1.19 kristaps 1379:
1.45 kristaps 1380: c = ARGS_QWORD == w ? MDOC_MAX :
1381: lookup(mdoc, line, la, tok, p);
1382:
1383: if (MDOC_MAX != c && -1 != c) {
1.39 kristaps 1384: if ( ! rewind_elem(mdoc, tok))
1385: return(0);
1.45 kristaps 1386: return(mdoc_macro(mdoc, c, line, la, pos, buf));
1387: } else if (-1 == c)
1388: return(0);
1.39 kristaps 1389:
1.45 kristaps 1390: if ( ! mdoc_word_alloc(mdoc, line, la, p))
1.28 kristaps 1391: return(0);
1.21 kristaps 1392: mdoc->next = MDOC_NEXT_SIBLING;
1.13 kristaps 1393: }
1394:
1.44 kristaps 1395: return(rewind_elem(mdoc, tok));
1.13 kristaps 1396: }
1.15 kristaps 1397:
1398:
1.16 kristaps 1399: /* ARGSUSED */
1.51 kristaps 1400: static int
1.15 kristaps 1401: macro_obsolete(MACRO_PROT_ARGS)
1402: {
1403:
1.49 kristaps 1404: return(pwarn(mdoc, line, ppos, WOBS));
1.15 kristaps 1405: }
1.25 kristaps 1406:
1407:
1.44 kristaps 1408: /*
1409: * This is called at the end of parsing. It must traverse up the tree,
1410: * closing out open [implicit] scopes. Obviously, open explicit scopes
1411: * are errors.
1412: */
1.25 kristaps 1413: int
1414: macro_end(struct mdoc *mdoc)
1415: {
1.42 kristaps 1416: struct mdoc_node *n;
1.25 kristaps 1417:
1418: assert(mdoc->first);
1419: assert(mdoc->last);
1.42 kristaps 1420:
1421: /* Scan for open explicit scopes. */
1422:
1423: n = MDOC_VALID & mdoc->last->flags ?
1424: mdoc->last->parent : mdoc->last;
1425:
1426: for ( ; n; n = n->parent) {
1427: if (MDOC_BLOCK != n->type)
1428: continue;
1429: if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
1430: continue;
1.51 kristaps 1431: return(mdoc_nerr(mdoc, n,
1432: "macro scope still open on exit"));
1.42 kristaps 1433: }
1434:
1.41 kristaps 1435: return(rewind_last(mdoc, mdoc->first));
1.25 kristaps 1436: }
CVSweb