Annotation of mandoc/macro.c, Revision 1.36
1.36 ! kristaps 1: /* $Id: macro.c,v 1.35 2009/01/14 11:58:24 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:
28: #include "private.h"
29:
1.10 kristaps 30: /* FIXME: maxlineargs should be per LINE, no per TOKEN. */
31:
1.35 kristaps 32: static int rewind_alt(int);
33: static int rewind_dohalt(int, enum mdoc_type,
34: const struct mdoc_node *);
35: #define REWIND_REWIND (1 << 0)
36: #define REWIND_NOHALT (1 << 1)
37: #define REWIND_HALT (1 << 2)
38: static int rewind_dobreak(int, enum mdoc_type,
39: const struct mdoc_node *);
40:
41:
1.28 kristaps 42: static int rewind_elem(struct mdoc *, int);
43: static int rewind_impblock(struct mdoc *, int);
44: static int rewind_expblock(struct mdoc *, int);
1.36 ! kristaps 45: static int rewind_subblock(enum mdoc_type, struct mdoc *, int);
! 46: static int rewind_last(int, int,
! 47: struct mdoc *, struct mdoc_node *);
1.27 kristaps 48: static int append_delims(struct mdoc *,
49: int, int, int *, char *);
1.30 kristaps 50: static int lookup(struct mdoc *, int, int, int, const char *);
1.24 kristaps 51:
52:
53: static int
1.30 kristaps 54: lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
1.24 kristaps 55: {
1.30 kristaps 56: int res;
1.24 kristaps 57:
1.30 kristaps 58: res = mdoc_find(mdoc, p);
59: if (MDOC_PARSED & mdoc_macros[from].flags)
60: return(res);
61: if (MDOC_MAX == res)
62: return(res);
63:
64: if ( ! mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX_MACLIKE))
65: return(-1);
66: return(MDOC_MAX);
1.24 kristaps 67: }
1.19 kristaps 68:
69:
70: static int
1.36 ! kristaps 71: rewind_last(int tok, int type, struct mdoc *mdoc, struct mdoc_node *to)
1.25 kristaps 72: {
73:
74: assert(to);
1.30 kristaps 75: mdoc->next = MDOC_NEXT_SIBLING;
76: if (mdoc->last == to) {
77: if ( ! mdoc_valid_post(mdoc))
78: return(0);
79: if ( ! mdoc_action_post(mdoc))
80: return(0);
1.36 ! kristaps 81: mdoc_msg(mdoc, "rewound %s %s to %s %s",
! 82: mdoc_type2a(type),
! 83: mdoc_macronames[tok],
1.35 kristaps 84: mdoc_type2a(mdoc->last->type),
1.34 kristaps 85: mdoc_macronames[mdoc->last->tok]);
1.29 kristaps 86: return(1);
1.30 kristaps 87: }
1.29 kristaps 88:
89: do {
90: mdoc->last = mdoc->last->parent;
91: assert(mdoc->last);
1.28 kristaps 92: if ( ! mdoc_valid_post(mdoc))
1.25 kristaps 93: return(0);
1.28 kristaps 94: if ( ! mdoc_action_post(mdoc))
1.25 kristaps 95: return(0);
1.36 ! kristaps 96: mdoc_msg(mdoc, "rewound %s %s to %s %s",
! 97: mdoc_type2a(type),
! 98: mdoc_macronames[tok],
1.35 kristaps 99: mdoc_type2a(mdoc->last->type),
1.34 kristaps 100: mdoc_macronames[mdoc->last->tok]);
1.29 kristaps 101: } while (mdoc->last != to);
1.28 kristaps 102:
1.29 kristaps 103: return(1);
1.25 kristaps 104: }
105:
106:
107: static int
1.35 kristaps 108: rewind_alt(int tok)
109: {
110: switch (tok) {
111: case (MDOC_Ac):
112: return(MDOC_Ao);
113: case (MDOC_Bc):
114: return(MDOC_Bo);
115: case (MDOC_Dc):
116: return(MDOC_Do);
117: case (MDOC_Ec):
118: return(MDOC_Eo);
119: case (MDOC_Ed):
120: return(MDOC_Bd);
121: case (MDOC_Ef):
122: return(MDOC_Bf);
123: case (MDOC_Ek):
124: return(MDOC_Bk);
125: case (MDOC_El):
126: return(MDOC_Bl);
127: case (MDOC_Fc):
128: return(MDOC_Fo);
129: case (MDOC_Oc):
130: return(MDOC_Oo);
131: case (MDOC_Pc):
132: return(MDOC_Po);
133: case (MDOC_Qc):
134: return(MDOC_Qo);
135: case (MDOC_Re):
136: return(MDOC_Rs);
137: case (MDOC_Sc):
138: return(MDOC_So);
139: case (MDOC_Xc):
140: return(MDOC_Xo);
141: default:
142: break;
143: }
144: abort();
145: /* NOTREACHED */
146: }
147:
148:
149: static int
150: rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
151: {
152:
153: if (MDOC_ROOT == p->type)
154: return(REWIND_HALT);
155: if (MDOC_TEXT == p->type)
156: return(REWIND_NOHALT);
157: if (MDOC_ELEM == p->type)
158: return(REWIND_NOHALT);
159:
160: switch (tok) {
161: /* One-liner implicit-scope. */
162: case (MDOC_Aq):
163: /* FALLTHROUGH */
164: case (MDOC_Bq):
165: /* FALLTHROUGH */
166: case (MDOC_D1):
167: /* FALLTHROUGH */
168: case (MDOC_Dl):
169: /* FALLTHROUGH */
170: case (MDOC_Dq):
171: /* FALLTHROUGH */
172: case (MDOC_Op):
173: /* FALLTHROUGH */
174: case (MDOC_Pq):
175: /* FALLTHROUGH */
176: case (MDOC_Ql):
177: /* FALLTHROUGH */
178: case (MDOC_Qq):
179: /* FALLTHROUGH */
180: case (MDOC_Sq):
181: assert(MDOC_BODY != type);
182: assert(MDOC_TAIL != type);
183: if (type == p->type && tok == p->tok)
184: return(REWIND_REWIND);
185: break;
186:
187: /* Multi-line implicit-scope. */
188: case (MDOC_It):
189: assert(MDOC_TAIL != type);
190: if (type == p->type && tok == p->tok)
191: return(REWIND_REWIND);
1.36 ! kristaps 192: if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
1.35 kristaps 193: return(REWIND_HALT);
194: break;
195: case (MDOC_Sh):
1.36 ! kristaps 196: if (type == p->type && tok == p->tok)
! 197: return(REWIND_REWIND);
! 198: break;
1.35 kristaps 199: case (MDOC_Ss):
1.36 ! kristaps 200: assert(MDOC_TAIL != type);
1.35 kristaps 201: if (type == p->type && tok == p->tok)
202: return(REWIND_REWIND);
1.36 ! kristaps 203: if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
! 204: return(REWIND_HALT);
1.35 kristaps 205: break;
206:
207: /* Multi-line explicit scope start. */
208: case (MDOC_Ao):
209: /* FALLTHROUGH */
210: case (MDOC_Bd):
211: /* FALLTHROUGH */
212: case (MDOC_Bf):
213: /* FALLTHROUGH */
214: case (MDOC_Bk):
215: /* FALLTHROUGH */
216: case (MDOC_Bl):
217: /* FALLTHROUGH */
218: case (MDOC_Bo):
219: /* FALLTHROUGH */
220: case (MDOC_Do):
221: /* FALLTHROUGH */
222: case (MDOC_Eo):
223: /* FALLTHROUGH */
224: case (MDOC_Fo):
225: /* FALLTHROUGH */
226: case (MDOC_Oo):
227: /* FALLTHROUGH */
228: case (MDOC_Po):
229: /* FALLTHROUGH */
230: case (MDOC_Qo):
231: /* FALLTHROUGH */
232: case (MDOC_Rs):
233: /* FALLTHROUGH */
234: case (MDOC_So):
235: /* FALLTHROUGH */
236: case (MDOC_Xo):
237: if (type == p->type && tok == p->tok)
238: return(REWIND_REWIND);
239: break;
240:
241: /* Multi-line explicit scope close. */
242: case (MDOC_Ac):
243: /* FALLTHROUGH */
244: case (MDOC_Bc):
245: /* FALLTHROUGH */
246: case (MDOC_Dc):
247: /* FALLTHROUGH */
248: case (MDOC_Ec):
249: /* FALLTHROUGH */
250: case (MDOC_Ed):
251: /* FALLTHROUGH */
252: case (MDOC_Ek):
253: /* FALLTHROUGH */
254: case (MDOC_El):
255: /* FALLTHROUGH */
256: case (MDOC_Fc):
257: /* FALLTHROUGH */
258: case (MDOC_Ef):
259: /* FALLTHROUGH */
260: case (MDOC_Oc):
261: /* FALLTHROUGH */
262: case (MDOC_Pc):
263: /* FALLTHROUGH */
264: case (MDOC_Qc):
265: /* FALLTHROUGH */
266: case (MDOC_Re):
267: /* FALLTHROUGH */
268: case (MDOC_Sc):
269: /* FALLTHROUGH */
270: case (MDOC_Xc):
271: if (type == p->type && rewind_alt(tok) == p->tok)
272: return(REWIND_REWIND);
273: break;
274: default:
275: abort();
276: /* NOTREACHED */
277: }
278:
279: return(REWIND_NOHALT);
280: }
281:
282:
283: static int
284: rewind_dobreak(int tok, enum mdoc_type type, const struct mdoc_node *p)
285: {
286:
287: assert(MDOC_ROOT != p->type);
288: if (MDOC_ELEM == p->type)
289: return(1);
290: if (MDOC_TEXT == p->type)
291: return(1);
292:
293: switch (tok) {
1.36 ! kristaps 294: /* Implicit rules. */
1.35 kristaps 295: case (MDOC_It):
296: return(MDOC_It == p->tok);
297: case (MDOC_Ss):
298: return(MDOC_Ss == p->tok);
299: case (MDOC_Sh):
300: if (MDOC_Ss == p->tok)
301: return(1);
302: return(MDOC_Sh == p->tok);
1.36 ! kristaps 303:
! 304: /* Extra scope rules. */
! 305: case (MDOC_El):
! 306: if (MDOC_It == p->tok)
! 307: return(1);
! 308: break;
! 309: default:
! 310: break;
1.35 kristaps 311: }
312:
313: if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
314: return(p->tok == rewind_alt(tok));
315: else if (MDOC_BLOCK == p->type)
316: return(1);
317:
318: return(tok == p->tok);
319: }
320:
321:
322: static int
1.28 kristaps 323: rewind_elem(struct mdoc *mdoc, int tok)
1.19 kristaps 324: {
325: struct mdoc_node *n;
1.2 kristaps 326:
1.19 kristaps 327: n = mdoc->last;
328: if (MDOC_ELEM != n->type)
329: n = n->parent;
330: assert(MDOC_ELEM == n->type);
1.32 kristaps 331: assert(tok == n->tok);
1.19 kristaps 332:
1.36 ! kristaps 333: return(rewind_last(tok, MDOC_ELEM, mdoc, n));
1.19 kristaps 334: }
1.6 kristaps 335:
336:
337: static int
1.36 ! kristaps 338: rewind_subblock(enum mdoc_type type, struct mdoc *mdoc, int tok)
1.22 kristaps 339: {
340: struct mdoc_node *n;
1.35 kristaps 341: int c;
1.28 kristaps 342:
1.36 ! kristaps 343: c = rewind_dohalt(tok, type, mdoc->last);
! 344: if (REWIND_HALT == c)
! 345: return(1);
! 346: if (REWIND_REWIND == c)
! 347: return(rewind_last(tok, type, mdoc, mdoc->last));
1.28 kristaps 348:
1.6 kristaps 349: /* LINTED */
1.36 ! kristaps 350: for (n = mdoc->last->parent; n; n = n->parent) {
! 351: c = rewind_dohalt(tok, type, n);
1.35 kristaps 352: if (REWIND_HALT == c)
353: return(1);
354: if (REWIND_REWIND == c)
1.6 kristaps 355: break;
1.36 ! kristaps 356: else if (rewind_dobreak(tok, type, n))
1.7 kristaps 357: continue;
1.28 kristaps 358: return(mdoc_verr(mdoc, n, ERR_SCOPE_BREAK));
1.6 kristaps 359: }
360:
1.25 kristaps 361: assert(n);
1.36 ! kristaps 362: return(rewind_last(tok, type, mdoc, n));
1.6 kristaps 363: }
364:
365:
366: static int
1.28 kristaps 367: rewind_expblock(struct mdoc *mdoc, int tok)
1.6 kristaps 368: {
1.7 kristaps 369: struct mdoc_node *n;
1.35 kristaps 370: int c;
1.6 kristaps 371:
1.36 ! kristaps 372: c = rewind_dohalt(tok, MDOC_BLOCK, mdoc->last);
! 373: if (REWIND_HALT == c)
! 374: return(mdoc_err(mdoc, ERR_SCOPE_NOCTX));
! 375: if (REWIND_REWIND == c)
! 376: return(rewind_last(tok, MDOC_BLOCK, mdoc, mdoc->last));
! 377:
1.7 kristaps 378: /* LINTED */
1.36 ! kristaps 379: for (n = mdoc->last->parent; n; n = n->parent) {
1.35 kristaps 380: c = rewind_dohalt(tok, MDOC_BLOCK, n);
381: if (REWIND_HALT == c)
382: return(mdoc_err(mdoc, ERR_SCOPE_NOCTX));
383: if (REWIND_REWIND == c)
1.16 kristaps 384: break;
1.35 kristaps 385: else if (rewind_dobreak(tok, MDOC_BLOCK, n))
1.22 kristaps 386: continue;
1.28 kristaps 387: return(mdoc_verr(mdoc, n, ERR_SCOPE_BREAK));
1.16 kristaps 388: }
389:
1.28 kristaps 390: assert(n);
1.36 ! kristaps 391: return(rewind_last(tok, MDOC_BLOCK, mdoc, n));
1.21 kristaps 392: }
393:
394:
395: static int
1.28 kristaps 396: rewind_impblock(struct mdoc *mdoc, int tok)
1.21 kristaps 397: {
398: struct mdoc_node *n;
1.35 kristaps 399: int c;
1.21 kristaps 400:
1.36 ! kristaps 401: printf("1\n");
! 402: c = rewind_dohalt(tok, MDOC_BLOCK, mdoc->last);
! 403: if (REWIND_HALT == c)
! 404: return(1);
! 405: if (REWIND_REWIND == c)
! 406: return(rewind_last(tok, MDOC_BLOCK, mdoc, mdoc->last));
! 407:
1.21 kristaps 408: /* LINTED */
1.36 ! kristaps 409: for (n = mdoc->last->parent; n; n = n->parent) {
1.35 kristaps 410: c = rewind_dohalt(tok, MDOC_BLOCK, n);
411: if (REWIND_HALT == c)
412: return(1);
413: else if (REWIND_REWIND == c)
1.21 kristaps 414: break;
1.35 kristaps 415: else if (rewind_dobreak(tok, MDOC_BLOCK, n))
1.21 kristaps 416: continue;
1.28 kristaps 417: return(mdoc_verr(mdoc, n, ERR_SCOPE_BREAK));
1.21 kristaps 418: }
419:
1.35 kristaps 420: assert(n);
1.36 ! kristaps 421: return(rewind_last(tok, MDOC_BLOCK, mdoc, n));
1.16 kristaps 422: }
423:
424:
1.22 kristaps 425: static int
1.27 kristaps 426: append_delims(struct mdoc *mdoc, int tok,
427: int line, int *pos, char *buf)
1.22 kristaps 428: {
429: int c, lastarg;
430: char *p;
431:
432: if (0 == buf[*pos])
433: return(1);
434:
435: for (;;) {
436: lastarg = *pos;
1.28 kristaps 437: c = mdoc_args(mdoc, line, pos, buf, 0, &p);
1.22 kristaps 438: if (ARGS_ERROR == c)
439: return(0);
440: else if (ARGS_EOLN == c)
441: break;
442: assert(mdoc_isdelim(p));
1.28 kristaps 443: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
444: return(0);
1.22 kristaps 445: mdoc->next = MDOC_NEXT_SIBLING;
446: }
447:
448: return(1);
449: }
450:
451:
1.19 kristaps 452: /* ARGSUSED */
453: int
1.35 kristaps 454: macro_scoped_close(MACRO_PROT_ARGS)
1.19 kristaps 455: {
1.28 kristaps 456: int tt, j, c, lastarg, maxargs, flushed;
1.22 kristaps 457: char *p;
1.19 kristaps 458:
459: switch (tok) {
1.22 kristaps 460: case (MDOC_Ec):
461: maxargs = 1;
462: break;
463: default:
464: maxargs = 0;
465: break;
466: }
467:
1.35 kristaps 468: tt = rewind_alt(tok);
469:
1.36 ! kristaps 470: mdoc_msg(mdoc, "parse-quiet: %s closing %s",
! 471: mdoc_macronames[tok], mdoc_macronames[tt]);
! 472:
1.22 kristaps 473: if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
1.35 kristaps 474: if (0 == buf[*pos]) {
1.36 ! kristaps 475: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.35 kristaps 476: return(0);
477: return(rewind_expblock(mdoc, tok));
478: }
1.28 kristaps 479: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_EQ0));
1.22 kristaps 480: }
1.19 kristaps 481:
1.36 ! kristaps 482: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.22 kristaps 483: return(0);
1.19 kristaps 484:
1.22 kristaps 485: lastarg = ppos;
486: flushed = 0;
1.15 kristaps 487:
1.22 kristaps 488: if (maxargs > 0) {
1.28 kristaps 489: if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
490: return(0);
1.22 kristaps 491: mdoc->next = MDOC_NEXT_CHILD;
492: }
1.15 kristaps 493:
1.22 kristaps 494: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
1.15 kristaps 495: lastarg = *pos;
1.22 kristaps 496:
497: if (j == maxargs && ! flushed) {
1.35 kristaps 498: if ( ! rewind_expblock(mdoc, tok))
1.22 kristaps 499: return(0);
500: flushed = 1;
501: }
502:
1.28 kristaps 503: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.15 kristaps 504: if (ARGS_ERROR == c)
505: return(0);
1.22 kristaps 506: if (ARGS_PUNCT == c)
507: break;
508: if (ARGS_EOLN == c)
509: break;
510:
1.30 kristaps 511: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
512: return(0);
513: else if (MDOC_MAX != c) {
1.22 kristaps 514: if ( ! flushed) {
1.35 kristaps 515: if ( ! rewind_expblock(mdoc, tok))
1.22 kristaps 516: return(0);
517: flushed = 1;
518: }
1.26 kristaps 519: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22 kristaps 520: return(0);
1.15 kristaps 521: break;
1.30 kristaps 522: }
1.22 kristaps 523:
1.28 kristaps 524: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
525: return(0);
1.16 kristaps 526: mdoc->next = MDOC_NEXT_SIBLING;
1.15 kristaps 527: }
1.2 kristaps 528:
1.22 kristaps 529: if (MDOC_LINEARG_MAX == j)
1.28 kristaps 530: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22 kristaps 531:
1.35 kristaps 532: if ( ! flushed && ! rewind_expblock(mdoc, tok))
1.28 kristaps 533: return(0);
1.22 kristaps 534:
535: if (ppos > 1)
536: return(1);
1.27 kristaps 537: return(append_delims(mdoc, tok, line, pos, buf));
1.1 kristaps 538: }
539:
1.2 kristaps 540:
1.19 kristaps 541: /*
542: * A general text domain macro. When invoked, this opens a scope that
543: * accepts words until either end-of-line, only-punctuation, or a
544: * callable macro. If the word is punctuation (not only-punctuation),
545: * then the scope is closed out, the punctuation appended, then the
546: * scope opened again. If any terminating conditions are met, the scope
547: * is closed out. If this is the first macro in the line and
548: * only-punctuation remains, this punctuation is flushed.
549: */
550: int
551: macro_text(MACRO_PROT_ARGS)
1.13 kristaps 552: {
1.28 kristaps 553: int la, lastpunct, c, sz, fl, argc;
1.19 kristaps 554: struct mdoc_arg argv[MDOC_LINEARG_MAX];
555: char *p;
1.13 kristaps 556:
1.28 kristaps 557: la = ppos;
1.19 kristaps 558: lastpunct = 0;
1.17 kristaps 559:
1.19 kristaps 560: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.28 kristaps 561: la = *pos;
1.17 kristaps 562:
1.28 kristaps 563: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.19 kristaps 564: if (ARGV_EOLN == c || ARGV_WORD == c)
565: break;
566: else if (ARGV_ARG == c)
567: continue;
568: mdoc_argv_free(argc, argv);
1.14 kristaps 569: return(0);
1.10 kristaps 570: }
571:
1.28 kristaps 572: if (MDOC_LINEARG_MAX == argc) {
573: mdoc_argv_free(argc, argv);
574: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
575: }
576:
577: c = mdoc_elem_alloc(mdoc, line, la, tok, argc, argv);
578:
579: if (0 == c) {
1.19 kristaps 580: mdoc_argv_free(argc, argv);
581: return(0);
1.7 kristaps 582: }
583:
1.28 kristaps 584: mdoc->next = MDOC_NEXT_CHILD;
585:
1.15 kristaps 586: fl = ARGS_DELIM;
587: if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
588: fl |= ARGS_QUOTED;
1.7 kristaps 589:
1.19 kristaps 590: for (lastpunct = sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.28 kristaps 591: la = *pos;
1.7 kristaps 592:
1.28 kristaps 593: c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.19 kristaps 594: if (ARGS_ERROR == c) {
595: mdoc_argv_free(argc, argv);
1.7 kristaps 596: return(0);
1.19 kristaps 597: }
598:
599: if (ARGS_EOLN == c)
600: break;
601: if (ARGS_PUNCT == c)
602: break;
1.2 kristaps 603:
1.30 kristaps 604: if (-1 == (c = lookup(mdoc, line, la, tok, p)))
605: return(0);
606: else if (MDOC_MAX != c) {
1.36 ! kristaps 607: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 608: mdoc_argv_free(argc, argv);
609: return(0);
610: }
611: mdoc_argv_free(argc, argv);
1.28 kristaps 612:
613: c = mdoc_macro(mdoc, c, line, la, pos, buf);
614: if (0 == c)
1.19 kristaps 615: return(0);
616: if (ppos > 1)
617: return(1);
1.27 kristaps 618: return(append_delims(mdoc, tok, line, pos, buf));
1.19 kristaps 619: }
1.2 kristaps 620:
1.19 kristaps 621: if (mdoc_isdelim(p)) {
1.36 ! kristaps 622: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 623: mdoc_argv_free(argc, argv);
624: return(0);
625: }
626: lastpunct = 1;
1.36 ! kristaps 627: } else if (lastpunct) {
! 628: c = mdoc_elem_alloc(mdoc, line,
! 629: la, tok, argc, argv);
! 630: if (0 == c) {
! 631: mdoc_argv_free(argc, argv);
! 632: return(0);
! 633: }
! 634: mdoc->next = MDOC_NEXT_CHILD;
! 635: lastpunct = 0;
1.19 kristaps 636: }
1.36 ! kristaps 637:
1.28 kristaps 638: if ( ! mdoc_word_alloc(mdoc, line, la, p))
639: return(0);
1.19 kristaps 640: mdoc->next = MDOC_NEXT_SIBLING;
1.2 kristaps 641: }
642:
1.19 kristaps 643: mdoc_argv_free(argc, argv);
1.2 kristaps 644:
1.19 kristaps 645: if (sz == MDOC_LINEARG_MAX)
1.28 kristaps 646: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.2 kristaps 647:
1.36 ! kristaps 648: if (0 == lastpunct && ! rewind_elem(mdoc, tok))
1.7 kristaps 649: return(0);
1.19 kristaps 650: if (ppos > 1)
651: return(1);
1.27 kristaps 652: return(append_delims(mdoc, tok, line, pos, buf));
1.5 kristaps 653: }
654:
655:
1.19 kristaps 656: /*
1.28 kristaps 657: * Implicit- or explicit-end multi-line scoped macro.
1.19 kristaps 658: */
1.5 kristaps 659: int
1.16 kristaps 660: macro_scoped(MACRO_PROT_ARGS)
1.6 kristaps 661: {
1.33 kristaps 662: int c, lastarg, argc, j, fl;
1.6 kristaps 663: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.24 kristaps 664: char *p;
1.6 kristaps 665:
1.16 kristaps 666: assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.6 kristaps 667:
1.35 kristaps 668: if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
1.36 ! kristaps 669: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.35 kristaps 670: return(0);
1.28 kristaps 671: if ( ! rewind_impblock(mdoc, tok))
1.16 kristaps 672: return(0);
1.35 kristaps 673: }
1.2 kristaps 674:
1.16 kristaps 675: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
676: lastarg = *pos;
1.28 kristaps 677: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16 kristaps 678: if (ARGV_EOLN == c || ARGV_WORD == c)
679: break;
680: else if (ARGV_ARG == c)
681: continue;
682: mdoc_argv_free(argc, argv);
1.8 kristaps 683: return(0);
1.16 kristaps 684: }
1.2 kristaps 685:
1.28 kristaps 686: if (MDOC_LINEARG_MAX == argc) {
1.16 kristaps 687: mdoc_argv_free(argc, argv);
1.28 kristaps 688: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
689: }
690:
691: c = mdoc_block_alloc(mdoc, line, ppos,
692: tok, (size_t)argc, argv);
693: mdoc_argv_free(argc, argv);
694:
695: if (0 == c)
1.16 kristaps 696: return(0);
1.8 kristaps 697:
1.19 kristaps 698: mdoc->next = MDOC_NEXT_CHILD;
699:
1.24 kristaps 700: if (0 == buf[*pos]) {
1.28 kristaps 701: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
702: return(0);
1.36 ! kristaps 703: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28 kristaps 704: return(0);
705: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 706: return(0);
1.19 kristaps 707: mdoc->next = MDOC_NEXT_CHILD;
1.24 kristaps 708: return(1);
709: }
1.19 kristaps 710:
1.28 kristaps 711: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
712: return(0);
1.24 kristaps 713: mdoc->next = MDOC_NEXT_CHILD;
1.7 kristaps 714:
1.33 kristaps 715: fl = ARGS_DELIM;
716: if (MDOC_TABSEP & mdoc_macros[tok].flags)
717: fl |= ARGS_TABSEP;
718:
1.24 kristaps 719: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
720: lastarg = *pos;
1.33 kristaps 721: c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.24 kristaps 722:
723: if (ARGS_ERROR == c)
1.19 kristaps 724: return(0);
1.24 kristaps 725: if (ARGS_PUNCT == c)
726: break;
727: if (ARGS_EOLN == c)
728: break;
729:
1.30 kristaps 730: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
731: return(0);
732: else if (MDOC_MAX == c) {
1.28 kristaps 733: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
734: return(0);
1.24 kristaps 735: mdoc->next = MDOC_NEXT_SIBLING;
736: continue;
1.30 kristaps 737: }
1.2 kristaps 738:
1.26 kristaps 739: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.24 kristaps 740: return(0);
741: break;
1.7 kristaps 742: }
1.1 kristaps 743:
1.24 kristaps 744: if (j == MDOC_LINEARG_MAX)
1.28 kristaps 745: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.24 kristaps 746:
1.36 ! kristaps 747: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.24 kristaps 748: return(0);
1.27 kristaps 749: if (1 == ppos && ! append_delims(mdoc, tok, line, pos, buf))
1.24 kristaps 750: return(0);
751:
1.28 kristaps 752: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
753: return(0);
1.16 kristaps 754: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 755:
1.16 kristaps 756: return(1);
1.1 kristaps 757: }
1.5 kristaps 758:
1.7 kristaps 759:
1.19 kristaps 760: /*
761: * When scoped to a line, a macro encompasses all of the contents. This
762: * differs from constants or text macros, where a new macro will
763: * terminate the existing context.
764: */
1.7 kristaps 765: int
1.16 kristaps 766: macro_scoped_line(MACRO_PROT_ARGS)
1.7 kristaps 767: {
1.8 kristaps 768: int lastarg, c, j;
769: char *p;
1.7 kristaps 770:
1.28 kristaps 771: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
772: return(0);
1.16 kristaps 773: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 774:
1.28 kristaps 775: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
776: return(0);
1.16 kristaps 777: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 778:
1.19 kristaps 779: /* XXX - no known argument macros. */
780:
781: for (lastarg = ppos, j = 0; j < MDOC_LINEARG_MAX; j++) {
782: lastarg = *pos;
1.28 kristaps 783: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.8 kristaps 784:
1.19 kristaps 785: if (ARGS_ERROR == c)
786: return(0);
787: if (ARGS_PUNCT == c)
788: break;
789: if (ARGS_EOLN == c)
790: break;
1.8 kristaps 791:
1.30 kristaps 792: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
793: return(0);
794: else if (MDOC_MAX == c) {
1.28 kristaps 795: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
796: return(0);
1.19 kristaps 797: mdoc->next = MDOC_NEXT_SIBLING;
798: continue;
1.30 kristaps 799: }
1.8 kristaps 800:
1.26 kristaps 801: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 802: return(0);
1.8 kristaps 803: break;
804: }
805:
1.19 kristaps 806: if (j == MDOC_LINEARG_MAX)
1.28 kristaps 807: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.19 kristaps 808:
809: if (1 == ppos) {
1.36 ! kristaps 810: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.16 kristaps 811: return(0);
1.27 kristaps 812: if ( ! append_delims(mdoc, tok, line, pos, buf))
1.8 kristaps 813: return(0);
1.36 ! kristaps 814: } else if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.35 kristaps 815: return(0);
1.28 kristaps 816: return(rewind_impblock(mdoc, tok));
1.22 kristaps 817: }
818:
819:
1.28 kristaps 820: /*
821: * Constant-scope macros accept a fixed number of arguments and behave
822: * like constant macros except that they're scoped across lines.
823: */
1.22 kristaps 824: int
825: macro_constant_scoped(MACRO_PROT_ARGS)
826: {
827: int lastarg, flushed, j, c, maxargs;
828: char *p;
829:
830: lastarg = ppos;
831: flushed = 0;
832:
833: switch (tok) {
834: case (MDOC_Eo):
835: maxargs = 1;
836: break;
837: default:
838: maxargs = 0;
839: break;
840: }
841:
1.28 kristaps 842: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
843: return(0);
1.22 kristaps 844: mdoc->next = MDOC_NEXT_CHILD;
845:
846: if (0 == maxargs) {
1.28 kristaps 847: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
848: return(0);
1.36 ! kristaps 849: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28 kristaps 850: return(0);
851: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 852: return(0);
1.22 kristaps 853: flushed = 1;
1.28 kristaps 854: } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
855: return(0);
1.22 kristaps 856:
857: mdoc->next = MDOC_NEXT_CHILD;
858:
859: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
860: lastarg = *pos;
861:
862: if (j == maxargs && ! flushed) {
1.36 ! kristaps 863: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22 kristaps 864: return(0);
865: flushed = 1;
1.28 kristaps 866: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
867: return(0);
1.22 kristaps 868: mdoc->next = MDOC_NEXT_CHILD;
869: }
870:
1.28 kristaps 871: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.22 kristaps 872: if (ARGS_ERROR == c)
873: return(0);
874: if (ARGS_PUNCT == c)
875: break;
876: if (ARGS_EOLN == c)
877: break;
878:
1.30 kristaps 879: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
880: return(0);
881: else if (MDOC_MAX != c) {
1.22 kristaps 882: if ( ! flushed) {
1.36 ! kristaps 883: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22 kristaps 884: return(0);
885: flushed = 1;
1.28 kristaps 886: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
887: return(0);
1.22 kristaps 888: mdoc->next = MDOC_NEXT_CHILD;
889: }
1.26 kristaps 890: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22 kristaps 891: return(0);
892: break;
893: }
894:
895: if ( ! flushed && mdoc_isdelim(p)) {
1.36 ! kristaps 896: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22 kristaps 897: return(0);
898: flushed = 1;
1.28 kristaps 899: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
900: return(0);
1.22 kristaps 901: mdoc->next = MDOC_NEXT_CHILD;
902: }
903:
1.28 kristaps 904: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
905: return(0);
1.22 kristaps 906: mdoc->next = MDOC_NEXT_SIBLING;
907: }
908:
909: if (MDOC_LINEARG_MAX == j)
1.28 kristaps 910: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22 kristaps 911:
912: if ( ! flushed) {
1.36 ! kristaps 913: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28 kristaps 914: return(0);
915: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.22 kristaps 916: return(0);
917: mdoc->next = MDOC_NEXT_CHILD;
918: }
919:
920: if (ppos > 1)
921: return(1);
1.27 kristaps 922: return(append_delims(mdoc, tok, line, pos, buf));
1.7 kristaps 923: }
1.8 kristaps 924:
1.10 kristaps 925:
1.19 kristaps 926: /*
927: * Delimited macros are like text macros except that, should punctuation
928: * be encountered, the macro isn't re-started with remaining tokens
929: * (it's only emitted once). Delimited macros can have a maximum number
930: * of arguments.
1.17 kristaps 931: */
1.10 kristaps 932: int
933: macro_constant_delimited(MACRO_PROT_ARGS)
934: {
1.24 kristaps 935: int lastarg, flushed, j, c, maxargs, argc;
936: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.13 kristaps 937: char *p;
1.10 kristaps 938:
939: lastarg = ppos;
940: flushed = 0;
941:
942: switch (tok) {
1.16 kristaps 943: case (MDOC_No):
944: /* FALLTHROUGH */
945: case (MDOC_Ns):
946: /* FALLTHROUGH */
1.10 kristaps 947: case (MDOC_Ux):
1.24 kristaps 948: /* FALLTHROUGH */
949: case (MDOC_St):
1.10 kristaps 950: maxargs = 0;
951: break;
952: default:
953: maxargs = 1;
954: break;
955: }
956:
1.24 kristaps 957: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
958: lastarg = *pos;
1.28 kristaps 959: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.24 kristaps 960: if (ARGV_EOLN == c || ARGV_WORD == c)
961: break;
962: else if (ARGV_ARG == c)
963: continue;
964: mdoc_argv_free(argc, argv);
965: return(0);
966: }
967:
1.28 kristaps 968: c = mdoc_elem_alloc(mdoc, line, lastarg, tok, argc, argv);
969: mdoc_argv_free(argc, argv);
970:
971: if (0 == c)
1.24 kristaps 972: return(0);
973:
1.19 kristaps 974: mdoc->next = MDOC_NEXT_CHILD;
1.10 kristaps 975:
1.19 kristaps 976: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
977: lastarg = *pos;
1.10 kristaps 978:
1.19 kristaps 979: if (j == maxargs && ! flushed) {
1.28 kristaps 980: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 981: return(0);
982: flushed = 1;
983: }
1.11 kristaps 984:
1.28 kristaps 985: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.19 kristaps 986: if (ARGS_ERROR == c)
1.10 kristaps 987: return(0);
1.19 kristaps 988: if (ARGS_PUNCT == c)
989: break;
990: if (ARGS_EOLN == c)
991: break;
992:
1.30 kristaps 993: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
994: return(0);
995: else if (MDOC_MAX != c) {
1.28 kristaps 996: if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19 kristaps 997: return(0);
998: flushed = 1;
1.26 kristaps 999: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 1000: return(0);
1001: break;
1002: }
1.10 kristaps 1003:
1.22 kristaps 1004: if ( ! flushed && mdoc_isdelim(p)) {
1.28 kristaps 1005: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 1006: return(0);
1007: flushed = 1;
1008: }
1009:
1.28 kristaps 1010: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1011: return(0);
1.19 kristaps 1012: mdoc->next = MDOC_NEXT_SIBLING;
1.10 kristaps 1013: }
1014:
1.22 kristaps 1015: if (MDOC_LINEARG_MAX == j)
1.28 kristaps 1016: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22 kristaps 1017:
1.28 kristaps 1018: if ( ! flushed && rewind_elem(mdoc, tok))
1.19 kristaps 1019: return(0);
1.11 kristaps 1020:
1.19 kristaps 1021: if (ppos > 1)
1022: return(1);
1.27 kristaps 1023: return(append_delims(mdoc, tok, line, pos, buf));
1.10 kristaps 1024: }
1.11 kristaps 1025:
1026:
1.19 kristaps 1027: /*
1028: * Constant macros span an entire line: they constitute a macro and all
1029: * of its arguments and child data.
1030: */
1.11 kristaps 1031: int
1032: macro_constant(MACRO_PROT_ARGS)
1033: {
1.19 kristaps 1034: int c, lastarg, argc, sz, fl;
1035: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1036: char *p;
1.11 kristaps 1037:
1.28 kristaps 1038: /* FIXME: parsing macros! */
1.24 kristaps 1039:
1.16 kristaps 1040: fl = 0;
1.15 kristaps 1041: if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
1042: fl = ARGS_QUOTED;
1.11 kristaps 1043:
1.16 kristaps 1044: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1045: lastarg = *pos;
1.28 kristaps 1046: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16 kristaps 1047: if (ARGV_EOLN == c)
1048: break;
1049: else if (ARGV_ARG == c)
1050: continue;
1051: else if (ARGV_WORD == c)
1052: break;
1.11 kristaps 1053:
1.16 kristaps 1054: mdoc_argv_free(argc, argv);
1.11 kristaps 1055: return(0);
1056: }
1057:
1.28 kristaps 1058: c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
1059: mdoc_argv_free(argc, argv);
1060:
1061: if (0 == c)
1062: return(0);
1.11 kristaps 1063:
1.19 kristaps 1064: mdoc->next = MDOC_NEXT_CHILD;
1065:
1.28 kristaps 1066: if (MDOC_LINEARG_MAX == argc)
1067: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.19 kristaps 1068:
1.16 kristaps 1069: for (sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.13 kristaps 1070: lastarg = *pos;
1.28 kristaps 1071: c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.16 kristaps 1072: if (ARGS_ERROR == c)
1073: return(0);
1074: if (ARGS_EOLN == c)
1.13 kristaps 1075: break;
1.19 kristaps 1076:
1.28 kristaps 1077: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1078: return(0);
1.21 kristaps 1079: mdoc->next = MDOC_NEXT_SIBLING;
1.13 kristaps 1080: }
1081:
1.19 kristaps 1082: if (MDOC_LINEARG_MAX == sz + argc)
1.28 kristaps 1083: return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.13 kristaps 1084:
1.28 kristaps 1085: return(rewind_elem(mdoc, tok));
1.13 kristaps 1086: }
1.15 kristaps 1087:
1088:
1.16 kristaps 1089: /* ARGSUSED */
1.15 kristaps 1090: int
1091: macro_obsolete(MACRO_PROT_ARGS)
1092: {
1093:
1.28 kristaps 1094: return(mdoc_pwarn(mdoc, line, ppos, WARN_IGN_OBSOLETE));
1.15 kristaps 1095: }
1.25 kristaps 1096:
1097:
1098: int
1099: macro_end(struct mdoc *mdoc)
1100: {
1101:
1102: assert(mdoc->first);
1103: assert(mdoc->last);
1.36 ! kristaps 1104: return(rewind_last(mdoc->last->tok, mdoc->last->type,
! 1105: mdoc, mdoc->first));
1.25 kristaps 1106: }
CVSweb