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