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