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