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