Annotation of mandoc/macro.c, Revision 1.56
1.56 ! kristaps 1: /* $Id: macro.c,v 1.55 2009/02/28 20:13:06 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 */
187: };
188:
189: const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
190:
1.49 kristaps 191:
192: static int
193: perr(struct mdoc *mdoc, int line, int pos, int type)
194: {
195: int c;
196:
197: switch (type) {
198: case (ENOCTX):
199: c = mdoc_perr(mdoc, line, pos,
200: "closing macro has prior context");
201: break;
202: case (ENOPARMS):
203: c = mdoc_perr(mdoc, line, pos,
204: "macro doesn't expect parameters");
205: break;
206: case (EARGVLIM):
207: c = mdoc_perr(mdoc, line, pos,
208: "argument hard-limit %d reached",
209: MDOC_LINEARG_MAX);
210: break;
211: default:
212: abort();
213: /* NOTREACHED */
214: }
215: return(c);
216: }
217:
218: static int
219: pwarn(struct mdoc *mdoc, int line, int pos, int type)
220: {
221: int c;
222:
223: switch (type) {
224: case (WMACPARM):
225: c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX,
226: "macro-like parameter");
227: break;
228: case (WOBS):
229: c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX,
230: "macro is marked obsolete");
231: break;
232: default:
233: abort();
234: /* NOTREACHED */
235: }
236: return(c);
237: }
1.24 kristaps 238:
239:
240: static int
1.30 kristaps 241: lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
1.24 kristaps 242: {
1.30 kristaps 243: int res;
1.24 kristaps 244:
1.30 kristaps 245: res = mdoc_find(mdoc, p);
246: if (MDOC_PARSED & mdoc_macros[from].flags)
247: return(res);
248: if (MDOC_MAX == res)
249: return(res);
1.49 kristaps 250: if ( ! pwarn(mdoc, line, pos, WMACPARM))
1.30 kristaps 251: return(-1);
252: return(MDOC_MAX);
1.24 kristaps 253: }
1.19 kristaps 254:
255:
256: static int
1.41 kristaps 257: rewind_last(struct mdoc *mdoc, struct mdoc_node *to)
1.25 kristaps 258: {
259:
260: assert(to);
1.30 kristaps 261: mdoc->next = MDOC_NEXT_SIBLING;
1.42 kristaps 262:
1.49 kristaps 263: /* LINTED */
1.42 kristaps 264: while (mdoc->last != to) {
1.30 kristaps 265: if ( ! mdoc_valid_post(mdoc))
266: return(0);
267: if ( ! mdoc_action_post(mdoc))
268: return(0);
1.29 kristaps 269: mdoc->last = mdoc->last->parent;
270: assert(mdoc->last);
1.42 kristaps 271: }
1.28 kristaps 272:
1.42 kristaps 273: if ( ! mdoc_valid_post(mdoc))
274: return(0);
275: return(mdoc_action_post(mdoc));
1.25 kristaps 276: }
277:
278:
279: static int
1.35 kristaps 280: rewind_alt(int tok)
281: {
282: switch (tok) {
283: case (MDOC_Ac):
284: return(MDOC_Ao);
285: case (MDOC_Bc):
286: return(MDOC_Bo);
287: case (MDOC_Dc):
288: return(MDOC_Do);
289: case (MDOC_Ec):
290: return(MDOC_Eo);
291: case (MDOC_Ed):
292: return(MDOC_Bd);
293: case (MDOC_Ef):
294: return(MDOC_Bf);
295: case (MDOC_Ek):
296: return(MDOC_Bk);
297: case (MDOC_El):
298: return(MDOC_Bl);
299: case (MDOC_Fc):
300: return(MDOC_Fo);
301: case (MDOC_Oc):
302: return(MDOC_Oo);
303: case (MDOC_Pc):
304: return(MDOC_Po);
305: case (MDOC_Qc):
306: return(MDOC_Qo);
307: case (MDOC_Re):
308: return(MDOC_Rs);
309: case (MDOC_Sc):
310: return(MDOC_So);
311: case (MDOC_Xc):
312: return(MDOC_Xo);
313: default:
314: break;
315: }
316: abort();
317: /* NOTREACHED */
318: }
319:
320:
321: static int
322: rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
323: {
324:
325: if (MDOC_ROOT == p->type)
326: return(REWIND_HALT);
1.42 kristaps 327: if (MDOC_VALID & p->flags)
1.35 kristaps 328: return(REWIND_NOHALT);
329:
330: switch (tok) {
331: /* One-liner implicit-scope. */
332: case (MDOC_Aq):
333: /* FALLTHROUGH */
334: case (MDOC_Bq):
335: /* FALLTHROUGH */
336: case (MDOC_D1):
337: /* FALLTHROUGH */
338: case (MDOC_Dl):
339: /* FALLTHROUGH */
340: case (MDOC_Dq):
341: /* FALLTHROUGH */
342: case (MDOC_Op):
343: /* FALLTHROUGH */
344: case (MDOC_Pq):
345: /* FALLTHROUGH */
346: case (MDOC_Ql):
347: /* FALLTHROUGH */
348: case (MDOC_Qq):
349: /* FALLTHROUGH */
350: case (MDOC_Sq):
1.44 kristaps 351: assert(MDOC_HEAD != type);
1.35 kristaps 352: assert(MDOC_TAIL != type);
353: if (type == p->type && tok == p->tok)
354: return(REWIND_REWIND);
355: break;
356:
357: /* Multi-line implicit-scope. */
358: case (MDOC_It):
359: assert(MDOC_TAIL != type);
360: if (type == p->type && tok == p->tok)
361: return(REWIND_REWIND);
1.36 kristaps 362: if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
1.35 kristaps 363: return(REWIND_HALT);
364: break;
365: case (MDOC_Sh):
1.36 kristaps 366: if (type == p->type && tok == p->tok)
367: return(REWIND_REWIND);
368: break;
1.35 kristaps 369: case (MDOC_Ss):
1.36 kristaps 370: assert(MDOC_TAIL != type);
1.35 kristaps 371: if (type == p->type && tok == p->tok)
372: return(REWIND_REWIND);
1.36 kristaps 373: if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
374: return(REWIND_HALT);
1.35 kristaps 375: break;
376:
377: /* Multi-line explicit scope start. */
378: case (MDOC_Ao):
379: /* FALLTHROUGH */
380: case (MDOC_Bd):
381: /* FALLTHROUGH */
382: case (MDOC_Bf):
383: /* FALLTHROUGH */
384: case (MDOC_Bk):
385: /* FALLTHROUGH */
386: case (MDOC_Bl):
387: /* FALLTHROUGH */
388: case (MDOC_Bo):
389: /* FALLTHROUGH */
390: case (MDOC_Do):
391: /* FALLTHROUGH */
392: case (MDOC_Eo):
393: /* FALLTHROUGH */
394: case (MDOC_Fo):
395: /* FALLTHROUGH */
396: case (MDOC_Oo):
397: /* FALLTHROUGH */
398: case (MDOC_Po):
399: /* FALLTHROUGH */
400: case (MDOC_Qo):
401: /* FALLTHROUGH */
402: case (MDOC_Rs):
403: /* FALLTHROUGH */
404: case (MDOC_So):
405: /* FALLTHROUGH */
406: case (MDOC_Xo):
407: if (type == p->type && tok == p->tok)
408: return(REWIND_REWIND);
409: break;
410:
411: /* Multi-line explicit scope close. */
412: case (MDOC_Ac):
413: /* FALLTHROUGH */
414: case (MDOC_Bc):
415: /* FALLTHROUGH */
416: case (MDOC_Dc):
417: /* FALLTHROUGH */
418: case (MDOC_Ec):
419: /* FALLTHROUGH */
420: case (MDOC_Ed):
421: /* FALLTHROUGH */
422: case (MDOC_Ek):
423: /* FALLTHROUGH */
424: case (MDOC_El):
425: /* FALLTHROUGH */
426: case (MDOC_Fc):
427: /* FALLTHROUGH */
428: case (MDOC_Ef):
429: /* FALLTHROUGH */
430: case (MDOC_Oc):
431: /* FALLTHROUGH */
432: case (MDOC_Pc):
433: /* FALLTHROUGH */
434: case (MDOC_Qc):
435: /* FALLTHROUGH */
436: case (MDOC_Re):
437: /* FALLTHROUGH */
438: case (MDOC_Sc):
439: /* FALLTHROUGH */
440: case (MDOC_Xc):
441: if (type == p->type && rewind_alt(tok) == p->tok)
442: return(REWIND_REWIND);
443: break;
444: default:
445: abort();
446: /* NOTREACHED */
447: }
448:
449: return(REWIND_NOHALT);
450: }
451:
452:
453: static int
1.41 kristaps 454: rewind_dobreak(int tok, const struct mdoc_node *p)
1.35 kristaps 455: {
456:
457: assert(MDOC_ROOT != p->type);
458: if (MDOC_ELEM == p->type)
459: return(1);
460: if (MDOC_TEXT == p->type)
461: return(1);
1.42 kristaps 462: if (MDOC_VALID & p->flags)
463: return(1);
1.35 kristaps 464:
465: switch (tok) {
1.36 kristaps 466: /* Implicit rules. */
1.35 kristaps 467: case (MDOC_It):
468: return(MDOC_It == p->tok);
469: case (MDOC_Ss):
470: return(MDOC_Ss == p->tok);
471: case (MDOC_Sh):
472: if (MDOC_Ss == p->tok)
473: return(1);
474: return(MDOC_Sh == p->tok);
1.36 kristaps 475:
476: /* Extra scope rules. */
477: case (MDOC_El):
478: if (MDOC_It == p->tok)
479: return(1);
480: break;
481: default:
482: break;
1.35 kristaps 483: }
484:
485: if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
486: return(p->tok == rewind_alt(tok));
487: else if (MDOC_BLOCK == p->type)
488: return(1);
489:
490: return(tok == p->tok);
491: }
492:
493:
494: static int
1.28 kristaps 495: rewind_elem(struct mdoc *mdoc, int tok)
1.19 kristaps 496: {
497: struct mdoc_node *n;
1.2 kristaps 498:
1.19 kristaps 499: n = mdoc->last;
500: if (MDOC_ELEM != n->type)
501: n = n->parent;
502: assert(MDOC_ELEM == n->type);
1.32 kristaps 503: assert(tok == n->tok);
1.19 kristaps 504:
1.41 kristaps 505: return(rewind_last(mdoc, n));
1.19 kristaps 506: }
1.6 kristaps 507:
508:
509: static int
1.41 kristaps 510: rewind_subblock(enum mdoc_type type, struct mdoc *mdoc,
511: int tok, int line, int ppos)
1.22 kristaps 512: {
513: struct mdoc_node *n;
1.35 kristaps 514: int c;
1.28 kristaps 515:
1.6 kristaps 516: /* LINTED */
1.42 kristaps 517: for (n = mdoc->last; n; n = n->parent) {
1.36 kristaps 518: c = rewind_dohalt(tok, type, n);
1.35 kristaps 519: if (REWIND_HALT == c)
520: return(1);
521: if (REWIND_REWIND == c)
1.6 kristaps 522: break;
1.41 kristaps 523: else if (rewind_dobreak(tok, n))
1.7 kristaps 524: continue;
1.41 kristaps 525: return(mdoc_perr(mdoc, line, ppos, "scope breaks prior %s", mdoc_node2a(n)));
1.6 kristaps 526: }
527:
1.25 kristaps 528: assert(n);
1.41 kristaps 529: return(rewind_last(mdoc, n));
1.6 kristaps 530: }
531:
532:
533: static int
1.38 kristaps 534: rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
1.6 kristaps 535: {
1.7 kristaps 536: struct mdoc_node *n;
1.35 kristaps 537: int c;
1.6 kristaps 538:
1.7 kristaps 539: /* LINTED */
1.42 kristaps 540: for (n = mdoc->last; n; n = n->parent) {
1.35 kristaps 541: c = rewind_dohalt(tok, MDOC_BLOCK, n);
542: if (REWIND_HALT == c)
1.49 kristaps 543: return(perr(mdoc, line, ppos, ENOCTX));
1.35 kristaps 544: if (REWIND_REWIND == c)
1.16 kristaps 545: break;
1.41 kristaps 546: else if (rewind_dobreak(tok, n))
1.22 kristaps 547: continue;
1.51 kristaps 548: return(mdoc_perr(mdoc, line, ppos,
549: "scope breaks prior %s",
550: mdoc_node2a(n)));
1.16 kristaps 551: }
552:
1.28 kristaps 553: assert(n);
1.41 kristaps 554: return(rewind_last(mdoc, n));
1.21 kristaps 555: }
556:
557:
558: static int
1.38 kristaps 559: rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
1.21 kristaps 560: {
561: struct mdoc_node *n;
1.35 kristaps 562: int c;
1.21 kristaps 563:
564: /* LINTED */
1.42 kristaps 565: for (n = mdoc->last; n; n = n->parent) {
1.35 kristaps 566: c = rewind_dohalt(tok, MDOC_BLOCK, n);
567: if (REWIND_HALT == c)
568: return(1);
569: else if (REWIND_REWIND == c)
1.21 kristaps 570: break;
1.41 kristaps 571: else if (rewind_dobreak(tok, n))
1.21 kristaps 572: continue;
1.51 kristaps 573: return(mdoc_perr(mdoc, line, ppos,
574: "scope breaks prior %s",
575: mdoc_node2a(n)));
1.21 kristaps 576: }
577:
1.35 kristaps 578: assert(n);
1.41 kristaps 579: return(rewind_last(mdoc, n));
1.16 kristaps 580: }
581:
582:
1.22 kristaps 583: static int
1.41 kristaps 584: append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
1.22 kristaps 585: {
586: int c, lastarg;
587: char *p;
588:
589: if (0 == buf[*pos])
590: return(1);
591:
592: for (;;) {
593: lastarg = *pos;
1.28 kristaps 594: c = mdoc_args(mdoc, line, pos, buf, 0, &p);
1.49 kristaps 595: assert(ARGS_PHRASE != c);
596:
1.22 kristaps 597: if (ARGS_ERROR == c)
598: return(0);
599: else if (ARGS_EOLN == c)
600: break;
601: assert(mdoc_isdelim(p));
1.28 kristaps 602: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
603: return(0);
1.22 kristaps 604: mdoc->next = MDOC_NEXT_SIBLING;
605: }
606:
607: return(1);
608: }
609:
610:
1.44 kristaps 611: /*
612: * Close out an explicit scope. This optionally parses a TAIL type with
613: * a set number of TEXT children.
614: */
1.51 kristaps 615: static int
1.35 kristaps 616: macro_scoped_close(MACRO_PROT_ARGS)
1.19 kristaps 617: {
1.28 kristaps 618: int tt, j, c, lastarg, maxargs, flushed;
1.22 kristaps 619: char *p;
1.19 kristaps 620:
621: switch (tok) {
1.22 kristaps 622: case (MDOC_Ec):
623: maxargs = 1;
624: break;
625: default:
626: maxargs = 0;
627: break;
628: }
629:
1.35 kristaps 630: tt = rewind_alt(tok);
631:
1.41 kristaps 632: mdoc_msg(mdoc, "parse: %s closing %s",
1.36 kristaps 633: mdoc_macronames[tok], mdoc_macronames[tt]);
634:
1.22 kristaps 635: if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
1.35 kristaps 636: if (0 == buf[*pos]) {
1.51 kristaps 637: if ( ! rewind_subblock(MDOC_BODY, mdoc,
638: tok, line, ppos))
1.35 kristaps 639: return(0);
1.38 kristaps 640: return(rewind_expblock(mdoc, tok, line, ppos));
1.35 kristaps 641: }
1.49 kristaps 642: return(perr(mdoc, line, ppos, ENOPARMS));
1.22 kristaps 643: }
1.19 kristaps 644:
1.41 kristaps 645: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.22 kristaps 646: return(0);
1.19 kristaps 647:
1.22 kristaps 648: lastarg = ppos;
649: flushed = 0;
1.15 kristaps 650:
1.22 kristaps 651: if (maxargs > 0) {
1.28 kristaps 652: if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
653: return(0);
1.22 kristaps 654: mdoc->next = MDOC_NEXT_CHILD;
655: }
1.15 kristaps 656:
1.41 kristaps 657: for (j = 0; /* No sentinel. */; j++) {
1.15 kristaps 658: lastarg = *pos;
1.22 kristaps 659:
660: if (j == maxargs && ! flushed) {
1.38 kristaps 661: if ( ! rewind_expblock(mdoc, tok, line, ppos))
1.22 kristaps 662: return(0);
663: flushed = 1;
664: }
665:
1.48 kristaps 666: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 667: assert(ARGS_PHRASE != c);
668:
1.15 kristaps 669: if (ARGS_ERROR == c)
670: return(0);
1.22 kristaps 671: if (ARGS_PUNCT == c)
672: break;
673: if (ARGS_EOLN == c)
674: break;
675:
1.30 kristaps 676: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
677: return(0);
678: else if (MDOC_MAX != c) {
1.22 kristaps 679: if ( ! flushed) {
1.51 kristaps 680: if ( ! rewind_expblock(mdoc, tok,
681: line, ppos))
1.22 kristaps 682: return(0);
683: flushed = 1;
684: }
1.26 kristaps 685: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22 kristaps 686: return(0);
1.15 kristaps 687: break;
1.30 kristaps 688: }
1.22 kristaps 689:
1.28 kristaps 690: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
691: return(0);
1.16 kristaps 692: mdoc->next = MDOC_NEXT_SIBLING;
1.15 kristaps 693: }
1.2 kristaps 694:
1.38 kristaps 695: if ( ! flushed && ! rewind_expblock(mdoc, tok, line, ppos))
1.28 kristaps 696: return(0);
1.22 kristaps 697:
698: if (ppos > 1)
699: return(1);
1.41 kristaps 700: return(append_delims(mdoc, line, pos, buf));
1.1 kristaps 701: }
702:
1.2 kristaps 703:
1.44 kristaps 704: /*
705: * A general text macro. This is a complex case because of punctuation.
706: * If a text macro is followed by words, then punctuation, the macro is
707: * "stopped" and "reopened" following the punctuation. Thus, the
708: * following arises:
709: *
710: * .Fl a ; b
711: *
712: * ELEMENT (.Fl)
713: * TEXT (`a')
714: * TEXT (`;')
715: * ELEMENT (.Fl)
716: * TEXT (`b')
717: *
718: * This must handle the following situations:
719: *
720: * .Fl Ar b ; ;
721: *
722: * ELEMENT (.Fl)
723: * ELEMENT (.Ar)
724: * TEXT (`b')
725: * TEXT (`;')
726: * TEXT (`;')
727: */
1.51 kristaps 728: static int
1.19 kristaps 729: macro_text(MACRO_PROT_ARGS)
1.13 kristaps 730: {
1.48 kristaps 731: int la, lastpunct, c, w, argc;
1.19 kristaps 732: struct mdoc_arg argv[MDOC_LINEARG_MAX];
733: char *p;
1.13 kristaps 734:
1.28 kristaps 735: la = ppos;
1.19 kristaps 736: lastpunct = 0;
1.17 kristaps 737:
1.19 kristaps 738: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.28 kristaps 739: la = *pos;
740: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 741: if (ARGV_EOLN == c)
1.19 kristaps 742: break;
1.38 kristaps 743: if (ARGV_WORD == c) {
744: *pos = la;
745: break;
746: } else if (ARGV_ARG == c)
1.19 kristaps 747: continue;
1.38 kristaps 748:
1.19 kristaps 749: mdoc_argv_free(argc, argv);
1.14 kristaps 750: return(0);
1.10 kristaps 751: }
752:
1.28 kristaps 753: if (MDOC_LINEARG_MAX == argc) {
1.41 kristaps 754: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 755: return(perr(mdoc, line, ppos, EARGVLIM));
1.28 kristaps 756: }
757:
1.54 kristaps 758: c = mdoc_elem_alloc(mdoc, line, ppos,
759: tok, (size_t)argc, argv);
1.28 kristaps 760:
761: if (0 == c) {
1.19 kristaps 762: mdoc_argv_free(argc, argv);
763: return(0);
1.7 kristaps 764: }
765:
1.28 kristaps 766: mdoc->next = MDOC_NEXT_CHILD;
767:
1.41 kristaps 768: lastpunct = 0;
769: for (;;) {
1.28 kristaps 770: la = *pos;
1.48 kristaps 771: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 772: assert(ARGS_PHRASE != c);
773:
1.45 kristaps 774: if (ARGS_ERROR == w) {
1.19 kristaps 775: mdoc_argv_free(argc, argv);
1.7 kristaps 776: return(0);
1.19 kristaps 777: }
778:
1.45 kristaps 779: if (ARGS_EOLN == w)
1.19 kristaps 780: break;
1.45 kristaps 781: if (ARGS_PUNCT == w)
1.19 kristaps 782: break;
1.2 kristaps 783:
1.45 kristaps 784: c = ARGS_QWORD == w ? MDOC_MAX :
785: lookup(mdoc, line, la, tok, p);
786:
787: if (MDOC_MAX != c && -1 != c) {
1.36 kristaps 788: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 789: mdoc_argv_free(argc, argv);
790: return(0);
791: }
792: mdoc_argv_free(argc, argv);
1.28 kristaps 793: c = mdoc_macro(mdoc, c, line, la, pos, buf);
794: if (0 == c)
1.19 kristaps 795: return(0);
796: if (ppos > 1)
797: return(1);
1.41 kristaps 798: return(append_delims(mdoc, line, pos, buf));
1.45 kristaps 799: } else if (-1 == c) {
800: mdoc_argv_free(argc, argv);
801: return(0);
1.19 kristaps 802: }
1.2 kristaps 803:
1.55 kristaps 804: /* FIXME: .Fl and .Ar handling of `|'. */
805:
1.45 kristaps 806: if (ARGS_QWORD != w && mdoc_isdelim(p)) {
1.36 kristaps 807: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 808: mdoc_argv_free(argc, argv);
809: return(0);
810: }
811: lastpunct = 1;
1.36 kristaps 812: } else if (lastpunct) {
1.54 kristaps 813: c = mdoc_elem_alloc(mdoc, line, ppos,
814: tok, (size_t)argc, argv);
1.36 kristaps 815: if (0 == c) {
816: mdoc_argv_free(argc, argv);
817: return(0);
818: }
819: mdoc->next = MDOC_NEXT_CHILD;
820: lastpunct = 0;
1.19 kristaps 821: }
1.36 kristaps 822:
1.28 kristaps 823: if ( ! mdoc_word_alloc(mdoc, line, la, p))
824: return(0);
1.19 kristaps 825: mdoc->next = MDOC_NEXT_SIBLING;
1.2 kristaps 826: }
827:
1.19 kristaps 828: mdoc_argv_free(argc, argv);
1.2 kristaps 829:
1.36 kristaps 830: if (0 == lastpunct && ! rewind_elem(mdoc, tok))
1.7 kristaps 831: return(0);
1.19 kristaps 832: if (ppos > 1)
833: return(1);
1.41 kristaps 834: return(append_delims(mdoc, line, pos, buf));
1.5 kristaps 835: }
836:
837:
1.44 kristaps 838: /*
839: * Handle explicit-scope (having a different closure token) and implicit
840: * scope (closing out prior scopes when re-invoked) macros. These
841: * constitute the BLOCK type and usually span multiple lines. These
842: * always have HEAD and sometimes have BODY types. In the multi-line
843: * case:
844: *
845: * .Bd -ragged
846: * Text.
847: * .Fl macro
848: * Another.
849: * .Ed
850: *
851: * BLOCK (.Bd)
852: * HEAD
853: * BODY
854: * TEXT (`Text.')
855: * ELEMENT (.Fl)
856: * TEXT (`macro')
857: * TEXT (`Another.')
858: *
859: * Note that the `.It' macro, possibly the most difficult (as it has
860: * embedded scope, etc.) is handled by this routine.
861: */
1.51 kristaps 862: static int
1.16 kristaps 863: macro_scoped(MACRO_PROT_ARGS)
1.6 kristaps 864: {
1.48 kristaps 865: int c, lastarg, argc;
1.6 kristaps 866: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.24 kristaps 867: char *p;
1.6 kristaps 868:
1.16 kristaps 869: assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.6 kristaps 870:
1.47 kristaps 871: /* First rewind extant implicit scope. */
872:
1.35 kristaps 873: if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
1.41 kristaps 874: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.35 kristaps 875: return(0);
1.38 kristaps 876: if ( ! rewind_impblock(mdoc, tok, line, ppos))
1.16 kristaps 877: return(0);
1.35 kristaps 878: }
1.2 kristaps 879:
1.47 kristaps 880: /* Parse arguments. */
881:
1.16 kristaps 882: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
883: lastarg = *pos;
1.28 kristaps 884: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 885: if (ARGV_EOLN == c)
886: break;
887: if (ARGV_WORD == c) {
888: *pos = lastarg;
1.16 kristaps 889: break;
1.38 kristaps 890: } else if (ARGV_ARG == c)
1.16 kristaps 891: continue;
892: mdoc_argv_free(argc, argv);
1.8 kristaps 893: return(0);
1.16 kristaps 894: }
1.2 kristaps 895:
1.28 kristaps 896: if (MDOC_LINEARG_MAX == argc) {
1.41 kristaps 897: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 898: return(perr(mdoc, line, ppos, EARGVLIM));
1.28 kristaps 899: }
900:
901: c = mdoc_block_alloc(mdoc, line, ppos,
902: tok, (size_t)argc, argv);
903: mdoc_argv_free(argc, argv);
904:
905: if (0 == c)
1.16 kristaps 906: return(0);
1.8 kristaps 907:
1.19 kristaps 908: mdoc->next = MDOC_NEXT_CHILD;
909:
1.24 kristaps 910: if (0 == buf[*pos]) {
1.28 kristaps 911: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
912: return(0);
1.51 kristaps 913: if ( ! rewind_subblock(MDOC_HEAD, mdoc,
914: tok, line, ppos))
1.28 kristaps 915: return(0);
916: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 917: return(0);
1.19 kristaps 918: mdoc->next = MDOC_NEXT_CHILD;
1.24 kristaps 919: return(1);
920: }
1.19 kristaps 921:
1.28 kristaps 922: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
923: return(0);
1.24 kristaps 924: mdoc->next = MDOC_NEXT_CHILD;
1.7 kristaps 925:
1.41 kristaps 926: for (;;) {
1.24 kristaps 927: lastarg = *pos;
1.48 kristaps 928: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 929:
1.24 kristaps 930: if (ARGS_ERROR == c)
1.19 kristaps 931: return(0);
1.24 kristaps 932: if (ARGS_EOLN == c)
933: break;
1.49 kristaps 934: if (ARGS_PHRASE == c) {
935: /*
936: if ( ! mdoc_phrase(mdoc, line, lastarg, buf))
937: return(0);
938: */
939: continue;
940: }
941:
1.48 kristaps 942: /* FIXME: if .It -column, the lookup must be for a
943: * sub-line component. BLAH. */
1.24 kristaps 944:
1.30 kristaps 945: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
946: return(0);
1.48 kristaps 947:
948: if (MDOC_MAX == c) {
1.28 kristaps 949: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
950: return(0);
1.24 kristaps 951: mdoc->next = MDOC_NEXT_SIBLING;
952: continue;
1.30 kristaps 953: }
1.2 kristaps 954:
1.26 kristaps 955: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.24 kristaps 956: return(0);
957: break;
1.7 kristaps 958: }
1.48 kristaps 959:
1.53 kristaps 960: if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
961: return(0);
1.41 kristaps 962: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.24 kristaps 963: return(0);
964:
1.28 kristaps 965: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
966: return(0);
1.16 kristaps 967: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 968:
1.16 kristaps 969: return(1);
1.1 kristaps 970: }
1.5 kristaps 971:
1.7 kristaps 972:
1.44 kristaps 973: /*
974: * This handles a case of implicitly-scoped macro (BLOCK) limited to a
975: * single line. Instead of being closed out by a subsequent call to
976: * another macro, the scope is closed at the end of line. These don't
977: * have BODY or TAIL types. Notice that the punctuation falls outside
978: * of the HEAD type.
979: *
980: * .Qq a Fl b Ar d ; ;
981: *
982: * BLOCK (Qq)
983: * HEAD
984: * TEXT (`a')
985: * ELEMENT (.Fl)
986: * TEXT (`b')
987: * ELEMENT (.Ar)
988: * TEXT (`d')
989: * TEXT (`;')
990: * TEXT (`;')
991: */
1.51 kristaps 992: static int
1.16 kristaps 993: macro_scoped_line(MACRO_PROT_ARGS)
1.7 kristaps 994: {
1.41 kristaps 995: int lastarg, c;
1.8 kristaps 996: char *p;
1.7 kristaps 997:
1.28 kristaps 998: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
999: return(0);
1.16 kristaps 1000: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 1001:
1.28 kristaps 1002: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1003: return(0);
1.44 kristaps 1004: mdoc->next = MDOC_NEXT_SIBLING;
1005: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1006: return(0);
1.16 kristaps 1007: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 1008:
1.19 kristaps 1009: /* XXX - no known argument macros. */
1010:
1.41 kristaps 1011: lastarg = ppos;
1012: for (;;) {
1.19 kristaps 1013: lastarg = *pos;
1.48 kristaps 1014: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1015: assert(ARGS_PHRASE != c);
1.8 kristaps 1016:
1.19 kristaps 1017: if (ARGS_ERROR == c)
1018: return(0);
1019: if (ARGS_PUNCT == c)
1020: break;
1021: if (ARGS_EOLN == c)
1022: break;
1.8 kristaps 1023:
1.30 kristaps 1024: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1025: return(0);
1026: else if (MDOC_MAX == c) {
1.28 kristaps 1027: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1028: return(0);
1.19 kristaps 1029: mdoc->next = MDOC_NEXT_SIBLING;
1030: continue;
1.30 kristaps 1031: }
1.8 kristaps 1032:
1.26 kristaps 1033: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 1034: return(0);
1.8 kristaps 1035: break;
1036: }
1037:
1.19 kristaps 1038: if (1 == ppos) {
1.44 kristaps 1039: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.16 kristaps 1040: return(0);
1.41 kristaps 1041: if ( ! append_delims(mdoc, line, pos, buf))
1.8 kristaps 1042: return(0);
1.44 kristaps 1043: } else if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
1.35 kristaps 1044: return(0);
1.38 kristaps 1045: return(rewind_impblock(mdoc, tok, line, ppos));
1.22 kristaps 1046: }
1047:
1048:
1.44 kristaps 1049: /*
1050: * A constant-scoped macro is like a simple-scoped macro (mdoc_scoped)
1051: * except that it doesn't handle implicit scopes and explicit ones have
1052: * a fixed number of TEXT children to the BODY.
1053: *
1054: * .Fl a So b Sc ;
1055: *
1056: * ELEMENT (.Fl)
1057: * TEXT (`a')
1058: * BLOCK (.So)
1059: * HEAD
1060: * BODY
1061: * TEXT (`b')
1062: * TEXT (';')
1063: */
1.51 kristaps 1064: static int
1.22 kristaps 1065: macro_constant_scoped(MACRO_PROT_ARGS)
1066: {
1067: int lastarg, flushed, j, c, maxargs;
1068: char *p;
1069:
1070: lastarg = ppos;
1071: flushed = 0;
1072:
1073: switch (tok) {
1074: case (MDOC_Eo):
1075: maxargs = 1;
1076: break;
1077: default:
1078: maxargs = 0;
1079: break;
1080: }
1081:
1.28 kristaps 1082: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
1083: return(0);
1.22 kristaps 1084: mdoc->next = MDOC_NEXT_CHILD;
1085:
1086: if (0 == maxargs) {
1.28 kristaps 1087: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1088: return(0);
1.41 kristaps 1089: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.28 kristaps 1090: return(0);
1091: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 1092: return(0);
1.22 kristaps 1093: flushed = 1;
1.28 kristaps 1094: } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1095: return(0);
1.22 kristaps 1096:
1097: mdoc->next = MDOC_NEXT_CHILD;
1098:
1.41 kristaps 1099: for (j = 0; /* No sentinel. */; j++) {
1.22 kristaps 1100: lastarg = *pos;
1101:
1102: if (j == maxargs && ! flushed) {
1.41 kristaps 1103: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.22 kristaps 1104: return(0);
1105: flushed = 1;
1.28 kristaps 1106: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1107: return(0);
1.22 kristaps 1108: mdoc->next = MDOC_NEXT_CHILD;
1109: }
1110:
1.48 kristaps 1111: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1112: assert(ARGS_PHRASE != c);
1113:
1.22 kristaps 1114: if (ARGS_ERROR == c)
1115: return(0);
1116: if (ARGS_PUNCT == c)
1117: break;
1118: if (ARGS_EOLN == c)
1119: break;
1120:
1.30 kristaps 1121: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1122: return(0);
1123: else if (MDOC_MAX != c) {
1.22 kristaps 1124: if ( ! flushed) {
1.51 kristaps 1125: if ( ! rewind_subblock(MDOC_HEAD, mdoc,
1126: tok, line, ppos))
1.22 kristaps 1127: return(0);
1128: flushed = 1;
1.51 kristaps 1129: if ( ! mdoc_body_alloc(mdoc, line,
1130: ppos, tok))
1.28 kristaps 1131: return(0);
1.22 kristaps 1132: mdoc->next = MDOC_NEXT_CHILD;
1133: }
1.51 kristaps 1134: if ( ! mdoc_macro(mdoc, c, line, lastarg,
1135: pos, buf))
1.22 kristaps 1136: return(0);
1137: break;
1138: }
1139:
1140: if ( ! flushed && mdoc_isdelim(p)) {
1.51 kristaps 1141: if ( ! rewind_subblock(MDOC_HEAD, mdoc,
1142: tok, line, ppos))
1.22 kristaps 1143: return(0);
1144: flushed = 1;
1.28 kristaps 1145: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1146: return(0);
1.22 kristaps 1147: mdoc->next = MDOC_NEXT_CHILD;
1148: }
1149:
1.28 kristaps 1150: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1151: return(0);
1.22 kristaps 1152: mdoc->next = MDOC_NEXT_SIBLING;
1153: }
1154:
1155: if ( ! flushed) {
1.41 kristaps 1156: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1.28 kristaps 1157: return(0);
1158: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.22 kristaps 1159: return(0);
1160: mdoc->next = MDOC_NEXT_CHILD;
1161: }
1162:
1163: if (ppos > 1)
1164: return(1);
1.41 kristaps 1165: return(append_delims(mdoc, line, pos, buf));
1.7 kristaps 1166: }
1.8 kristaps 1167:
1.10 kristaps 1168:
1.44 kristaps 1169: /*
1170: * A delimited constant is very similar to the macros parsed by
1171: * macro_text except that, in the event of punctuation, the macro isn't
1172: * "re-opened" as it is in macro_text. Also, these macros have a fixed
1173: * number of parameters.
1174: *
1175: * .Fl a No b
1176: *
1177: * ELEMENT (.Fl)
1178: * TEXT (`a')
1179: * ELEMENT (.No)
1180: * TEXT (`b')
1181: */
1.51 kristaps 1182: static int
1.10 kristaps 1183: macro_constant_delimited(MACRO_PROT_ARGS)
1184: {
1.50 kristaps 1185: int lastarg, flushed, j, c, maxargs, argc,
1186: igndelim;
1.24 kristaps 1187: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.13 kristaps 1188: char *p;
1.10 kristaps 1189:
1190: lastarg = ppos;
1191: flushed = 0;
1192:
1193: switch (tok) {
1.16 kristaps 1194: case (MDOC_No):
1195: /* FALLTHROUGH */
1196: case (MDOC_Ns):
1197: /* FALLTHROUGH */
1.10 kristaps 1198: case (MDOC_Ux):
1.24 kristaps 1199: /* FALLTHROUGH */
1200: case (MDOC_St):
1.10 kristaps 1201: maxargs = 0;
1202: break;
1203: default:
1204: maxargs = 1;
1205: break;
1206: }
1207:
1.50 kristaps 1208: switch (tok) {
1209: case (MDOC_Pf):
1210: igndelim = 1;
1211: break;
1212: default:
1213: igndelim = 0;
1214: break;
1215: }
1216:
1.24 kristaps 1217: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1218: lastarg = *pos;
1.28 kristaps 1219: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 1220: if (ARGV_EOLN == c)
1.24 kristaps 1221: break;
1.38 kristaps 1222: if (ARGV_WORD == c) {
1223: *pos = lastarg;
1224: break;
1225: } else if (ARGV_ARG == c)
1.24 kristaps 1226: continue;
1227: mdoc_argv_free(argc, argv);
1228: return(0);
1229: }
1230:
1.41 kristaps 1231: if (MDOC_LINEARG_MAX == argc) {
1232: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 1233: return(perr(mdoc, line, ppos, EARGVLIM));
1.41 kristaps 1234: }
1235:
1.54 kristaps 1236: c = mdoc_elem_alloc(mdoc, line, ppos,
1237: tok, (size_t)argc, argv);
1238:
1.28 kristaps 1239: mdoc_argv_free(argc, argv);
1240:
1241: if (0 == c)
1.24 kristaps 1242: return(0);
1243:
1.19 kristaps 1244: mdoc->next = MDOC_NEXT_CHILD;
1.10 kristaps 1245:
1.41 kristaps 1246: for (j = 0; /* No sentinel. */; j++) {
1.19 kristaps 1247: lastarg = *pos;
1.10 kristaps 1248:
1.19 kristaps 1249: if (j == maxargs && ! flushed) {
1.28 kristaps 1250: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 1251: return(0);
1252: flushed = 1;
1253: }
1.11 kristaps 1254:
1.48 kristaps 1255: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1256: assert(ARGS_PHRASE != c);
1257:
1.19 kristaps 1258: if (ARGS_ERROR == c)
1.10 kristaps 1259: return(0);
1.19 kristaps 1260: if (ARGS_PUNCT == c)
1261: break;
1262: if (ARGS_EOLN == c)
1263: break;
1264:
1.30 kristaps 1265: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1266: return(0);
1267: else if (MDOC_MAX != c) {
1.28 kristaps 1268: if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19 kristaps 1269: return(0);
1270: flushed = 1;
1.26 kristaps 1271: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 1272: return(0);
1273: break;
1274: }
1.10 kristaps 1275:
1.50 kristaps 1276: if ( ! flushed && mdoc_isdelim(p) && ! igndelim) {
1.28 kristaps 1277: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 1278: return(0);
1279: flushed = 1;
1280: }
1281:
1.28 kristaps 1282: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1283: return(0);
1.19 kristaps 1284: mdoc->next = MDOC_NEXT_SIBLING;
1.10 kristaps 1285: }
1286:
1.42 kristaps 1287: if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19 kristaps 1288: return(0);
1.11 kristaps 1289:
1.19 kristaps 1290: if (ppos > 1)
1291: return(1);
1.41 kristaps 1292: return(append_delims(mdoc, line, pos, buf));
1.10 kristaps 1293: }
1.11 kristaps 1294:
1295:
1.44 kristaps 1296: /*
1297: * A constant macro is the simplest classification. It spans an entire
1298: * line.
1299: */
1.51 kristaps 1300: static int
1.11 kristaps 1301: macro_constant(MACRO_PROT_ARGS)
1302: {
1.48 kristaps 1303: int c, w, la, argc;
1.43 kristaps 1304: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1305: char *p;
1.44 kristaps 1306:
1307: assert( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.11 kristaps 1308:
1.16 kristaps 1309: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.45 kristaps 1310: la = *pos;
1.28 kristaps 1311: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16 kristaps 1312: if (ARGV_EOLN == c)
1313: break;
1.38 kristaps 1314: if (ARGV_WORD == c) {
1.45 kristaps 1315: *pos = la;
1.38 kristaps 1316: break;
1317: } else if (ARGV_ARG == c)
1.16 kristaps 1318: continue;
1.11 kristaps 1319:
1.16 kristaps 1320: mdoc_argv_free(argc, argv);
1.11 kristaps 1321: return(0);
1322: }
1323:
1.41 kristaps 1324: if (MDOC_LINEARG_MAX == argc) {
1325: mdoc_argv_free(argc - 1, argv);
1.49 kristaps 1326: return(perr(mdoc, line, ppos, EARGVLIM));
1.41 kristaps 1327: }
1328:
1.54 kristaps 1329: c = mdoc_elem_alloc(mdoc, line, ppos,
1330: tok, (size_t)argc, argv);
1331:
1.28 kristaps 1332: mdoc_argv_free(argc, argv);
1333:
1334: if (0 == c)
1335: return(0);
1.11 kristaps 1336:
1.19 kristaps 1337: mdoc->next = MDOC_NEXT_CHILD;
1338:
1.41 kristaps 1339: for (;;) {
1.45 kristaps 1340: la = *pos;
1.48 kristaps 1341: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1.49 kristaps 1342: assert(ARGS_PHRASE != c);
1343:
1.45 kristaps 1344: if (ARGS_ERROR == w)
1.16 kristaps 1345: return(0);
1.45 kristaps 1346: if (ARGS_EOLN == w)
1.13 kristaps 1347: break;
1.19 kristaps 1348:
1.45 kristaps 1349: c = ARGS_QWORD == w ? MDOC_MAX :
1350: lookup(mdoc, line, la, tok, p);
1351:
1352: if (MDOC_MAX != c && -1 != c) {
1.39 kristaps 1353: if ( ! rewind_elem(mdoc, tok))
1354: return(0);
1.45 kristaps 1355: return(mdoc_macro(mdoc, c, line, la, pos, buf));
1356: } else if (-1 == c)
1357: return(0);
1.39 kristaps 1358:
1.45 kristaps 1359: if ( ! mdoc_word_alloc(mdoc, line, la, p))
1.28 kristaps 1360: return(0);
1.21 kristaps 1361: mdoc->next = MDOC_NEXT_SIBLING;
1.13 kristaps 1362: }
1363:
1.44 kristaps 1364: return(rewind_elem(mdoc, tok));
1.13 kristaps 1365: }
1.15 kristaps 1366:
1367:
1.16 kristaps 1368: /* ARGSUSED */
1.51 kristaps 1369: static int
1.15 kristaps 1370: macro_obsolete(MACRO_PROT_ARGS)
1371: {
1372:
1.49 kristaps 1373: return(pwarn(mdoc, line, ppos, WOBS));
1.15 kristaps 1374: }
1.25 kristaps 1375:
1376:
1.44 kristaps 1377: /*
1378: * This is called at the end of parsing. It must traverse up the tree,
1379: * closing out open [implicit] scopes. Obviously, open explicit scopes
1380: * are errors.
1381: */
1.25 kristaps 1382: int
1383: macro_end(struct mdoc *mdoc)
1384: {
1.42 kristaps 1385: struct mdoc_node *n;
1.25 kristaps 1386:
1387: assert(mdoc->first);
1388: assert(mdoc->last);
1.42 kristaps 1389:
1390: /* Scan for open explicit scopes. */
1391:
1392: n = MDOC_VALID & mdoc->last->flags ?
1393: mdoc->last->parent : mdoc->last;
1394:
1395: for ( ; n; n = n->parent) {
1396: if (MDOC_BLOCK != n->type)
1397: continue;
1398: if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
1399: continue;
1.51 kristaps 1400: return(mdoc_nerr(mdoc, n,
1401: "macro scope still open on exit"));
1.42 kristaps 1402: }
1403:
1.41 kristaps 1404: return(rewind_last(mdoc, mdoc->first));
1.25 kristaps 1405: }
CVSweb