Annotation of mandoc/macro.c, Revision 1.39
1.39 ! kristaps 1: /* $Id: macro.c,v 1.38 2009/01/16 11:50:54 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);
1.38 kristaps 43: static int rewind_impblock(struct mdoc *, int, int, int);
44: static int rewind_expblock(struct mdoc *, int, int, 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:
1.38 kristaps 64: if ( ! mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX, "macro-like parameter"))
1.30 kristaps 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.37 kristaps 358: return(mdoc_nerr(mdoc, n, "body scope broken"));
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.38 kristaps 367: rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
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)
1.38 kristaps 374: return(mdoc_perr(mdoc, line, ppos, "closing macro has no context"));
1.36 kristaps 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)
1.38 kristaps 382: return(mdoc_perr(mdoc, line, ppos, "closing macro has no context"));
1.35 kristaps 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.38 kristaps 387: return(mdoc_nerr(mdoc, n, "block scope broken"));
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.38 kristaps 396: rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
1.21 kristaps 397: {
398: struct mdoc_node *n;
1.35 kristaps 399: int c;
1.21 kristaps 400:
1.36 kristaps 401: c = rewind_dohalt(tok, MDOC_BLOCK, mdoc->last);
402: if (REWIND_HALT == c)
403: return(1);
404: if (REWIND_REWIND == c)
405: return(rewind_last(tok, MDOC_BLOCK, mdoc, mdoc->last));
406:
1.21 kristaps 407: /* LINTED */
1.36 kristaps 408: for (n = mdoc->last->parent; n; n = n->parent) {
1.35 kristaps 409: c = rewind_dohalt(tok, MDOC_BLOCK, n);
410: if (REWIND_HALT == c)
411: return(1);
412: else if (REWIND_REWIND == c)
1.21 kristaps 413: break;
1.35 kristaps 414: else if (rewind_dobreak(tok, MDOC_BLOCK, n))
1.21 kristaps 415: continue;
1.38 kristaps 416: return(mdoc_nerr(mdoc, n, "block scope broken"));
1.21 kristaps 417: }
418:
1.35 kristaps 419: assert(n);
1.36 kristaps 420: return(rewind_last(tok, MDOC_BLOCK, mdoc, n));
1.16 kristaps 421: }
422:
423:
1.22 kristaps 424: static int
1.27 kristaps 425: append_delims(struct mdoc *mdoc, int tok,
426: int line, int *pos, char *buf)
1.22 kristaps 427: {
428: int c, lastarg;
429: char *p;
430:
431: if (0 == buf[*pos])
432: return(1);
433:
434: for (;;) {
435: lastarg = *pos;
1.28 kristaps 436: c = mdoc_args(mdoc, line, pos, buf, 0, &p);
1.22 kristaps 437: if (ARGS_ERROR == c)
438: return(0);
439: else if (ARGS_EOLN == c)
440: break;
441: assert(mdoc_isdelim(p));
1.28 kristaps 442: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
443: return(0);
1.22 kristaps 444: mdoc->next = MDOC_NEXT_SIBLING;
445: }
446:
447: return(1);
448: }
449:
450:
1.19 kristaps 451: /* ARGSUSED */
452: int
1.35 kristaps 453: macro_scoped_close(MACRO_PROT_ARGS)
1.19 kristaps 454: {
1.28 kristaps 455: int tt, j, c, lastarg, maxargs, flushed;
1.22 kristaps 456: char *p;
1.19 kristaps 457:
458: switch (tok) {
1.22 kristaps 459: case (MDOC_Ec):
460: maxargs = 1;
461: break;
462: default:
463: maxargs = 0;
464: break;
465: }
466:
1.35 kristaps 467: tt = rewind_alt(tok);
468:
1.36 kristaps 469: mdoc_msg(mdoc, "parse-quiet: %s closing %s",
470: mdoc_macronames[tok], mdoc_macronames[tt]);
471:
1.22 kristaps 472: if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
1.35 kristaps 473: if (0 == buf[*pos]) {
1.36 kristaps 474: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.35 kristaps 475: return(0);
1.38 kristaps 476: return(rewind_expblock(mdoc, tok, line, ppos));
1.35 kristaps 477: }
1.38 kristaps 478: return(mdoc_perr(mdoc, line, ppos, "macro expects no parameters"));
1.22 kristaps 479: }
1.19 kristaps 480:
1.36 kristaps 481: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.22 kristaps 482: return(0);
1.19 kristaps 483:
1.22 kristaps 484: lastarg = ppos;
485: flushed = 0;
1.15 kristaps 486:
1.22 kristaps 487: if (maxargs > 0) {
1.28 kristaps 488: if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
489: return(0);
1.22 kristaps 490: mdoc->next = MDOC_NEXT_CHILD;
491: }
1.15 kristaps 492:
1.22 kristaps 493: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
1.15 kristaps 494: lastarg = *pos;
1.22 kristaps 495:
496: if (j == maxargs && ! flushed) {
1.38 kristaps 497: if ( ! rewind_expblock(mdoc, tok, line, ppos))
1.22 kristaps 498: return(0);
499: flushed = 1;
500: }
501:
1.28 kristaps 502: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.15 kristaps 503: if (ARGS_ERROR == c)
504: return(0);
1.22 kristaps 505: if (ARGS_PUNCT == c)
506: break;
507: if (ARGS_EOLN == c)
508: break;
509:
1.30 kristaps 510: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
511: return(0);
512: else if (MDOC_MAX != c) {
1.22 kristaps 513: if ( ! flushed) {
1.38 kristaps 514: if ( ! rewind_expblock(mdoc, tok, line, ppos))
1.22 kristaps 515: return(0);
516: flushed = 1;
517: }
1.26 kristaps 518: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22 kristaps 519: return(0);
1.15 kristaps 520: break;
1.30 kristaps 521: }
1.22 kristaps 522:
1.28 kristaps 523: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
524: return(0);
1.16 kristaps 525: mdoc->next = MDOC_NEXT_SIBLING;
1.15 kristaps 526: }
1.2 kristaps 527:
1.22 kristaps 528: if (MDOC_LINEARG_MAX == j)
1.38 kristaps 529: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.22 kristaps 530:
1.38 kristaps 531: if ( ! flushed && ! rewind_expblock(mdoc, tok, line, ppos))
1.28 kristaps 532: return(0);
1.22 kristaps 533:
534: if (ppos > 1)
535: return(1);
1.27 kristaps 536: return(append_delims(mdoc, tok, line, pos, buf));
1.1 kristaps 537: }
538:
1.2 kristaps 539:
1.19 kristaps 540: /*
541: * A general text domain macro. When invoked, this opens a scope that
542: * accepts words until either end-of-line, only-punctuation, or a
543: * callable macro. If the word is punctuation (not only-punctuation),
544: * then the scope is closed out, the punctuation appended, then the
545: * scope opened again. If any terminating conditions are met, the scope
546: * is closed out. If this is the first macro in the line and
547: * only-punctuation remains, this punctuation is flushed.
548: */
549: int
550: macro_text(MACRO_PROT_ARGS)
1.13 kristaps 551: {
1.28 kristaps 552: int la, lastpunct, c, sz, fl, argc;
1.19 kristaps 553: struct mdoc_arg argv[MDOC_LINEARG_MAX];
554: char *p;
1.13 kristaps 555:
1.28 kristaps 556: la = ppos;
1.19 kristaps 557: lastpunct = 0;
1.17 kristaps 558:
1.19 kristaps 559: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.28 kristaps 560: la = *pos;
1.17 kristaps 561:
1.28 kristaps 562: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 563: if (ARGV_EOLN == c)
1.19 kristaps 564: break;
1.38 kristaps 565: if (ARGV_WORD == c) {
566: *pos = la;
567: break;
568: } else if (ARGV_ARG == c)
1.19 kristaps 569: continue;
1.38 kristaps 570:
1.19 kristaps 571: mdoc_argv_free(argc, argv);
1.14 kristaps 572: return(0);
1.10 kristaps 573: }
574:
1.28 kristaps 575: if (MDOC_LINEARG_MAX == argc) {
576: mdoc_argv_free(argc, argv);
1.38 kristaps 577: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.28 kristaps 578: }
579:
580: c = mdoc_elem_alloc(mdoc, line, la, tok, argc, argv);
581:
582: if (0 == c) {
1.19 kristaps 583: mdoc_argv_free(argc, argv);
584: return(0);
1.7 kristaps 585: }
586:
1.28 kristaps 587: mdoc->next = MDOC_NEXT_CHILD;
588:
1.15 kristaps 589: fl = ARGS_DELIM;
590: if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
591: fl |= ARGS_QUOTED;
1.7 kristaps 592:
1.19 kristaps 593: for (lastpunct = sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.28 kristaps 594: la = *pos;
1.7 kristaps 595:
1.28 kristaps 596: c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.19 kristaps 597: if (ARGS_ERROR == c) {
598: mdoc_argv_free(argc, argv);
1.7 kristaps 599: return(0);
1.19 kristaps 600: }
601:
602: if (ARGS_EOLN == c)
603: break;
604: if (ARGS_PUNCT == c)
605: break;
1.2 kristaps 606:
1.30 kristaps 607: if (-1 == (c = lookup(mdoc, line, la, tok, p)))
608: return(0);
609: else if (MDOC_MAX != c) {
1.36 kristaps 610: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 611: mdoc_argv_free(argc, argv);
612: return(0);
613: }
614: mdoc_argv_free(argc, argv);
1.28 kristaps 615:
616: c = mdoc_macro(mdoc, c, line, la, pos, buf);
617: if (0 == c)
1.19 kristaps 618: return(0);
619: if (ppos > 1)
620: return(1);
1.27 kristaps 621: return(append_delims(mdoc, tok, line, pos, buf));
1.19 kristaps 622: }
1.2 kristaps 623:
1.19 kristaps 624: if (mdoc_isdelim(p)) {
1.36 kristaps 625: if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19 kristaps 626: mdoc_argv_free(argc, argv);
627: return(0);
628: }
629: lastpunct = 1;
1.36 kristaps 630: } else if (lastpunct) {
631: c = mdoc_elem_alloc(mdoc, line,
632: la, tok, argc, argv);
633: if (0 == c) {
634: mdoc_argv_free(argc, argv);
635: return(0);
636: }
637: mdoc->next = MDOC_NEXT_CHILD;
638: lastpunct = 0;
1.19 kristaps 639: }
1.36 kristaps 640:
1.28 kristaps 641: if ( ! mdoc_word_alloc(mdoc, line, la, p))
642: return(0);
1.19 kristaps 643: mdoc->next = MDOC_NEXT_SIBLING;
1.2 kristaps 644: }
645:
1.19 kristaps 646: mdoc_argv_free(argc, argv);
1.2 kristaps 647:
1.19 kristaps 648: if (sz == MDOC_LINEARG_MAX)
1.38 kristaps 649: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.2 kristaps 650:
1.36 kristaps 651: if (0 == lastpunct && ! rewind_elem(mdoc, tok))
1.7 kristaps 652: return(0);
1.19 kristaps 653: if (ppos > 1)
654: return(1);
1.27 kristaps 655: return(append_delims(mdoc, tok, line, pos, buf));
1.5 kristaps 656: }
657:
658:
1.19 kristaps 659: /*
1.28 kristaps 660: * Implicit- or explicit-end multi-line scoped macro.
1.19 kristaps 661: */
1.5 kristaps 662: int
1.16 kristaps 663: macro_scoped(MACRO_PROT_ARGS)
1.6 kristaps 664: {
1.33 kristaps 665: int c, lastarg, argc, j, fl;
1.6 kristaps 666: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.24 kristaps 667: char *p;
1.6 kristaps 668:
1.16 kristaps 669: assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.6 kristaps 670:
1.35 kristaps 671: if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
1.36 kristaps 672: if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.35 kristaps 673: return(0);
1.38 kristaps 674: if ( ! rewind_impblock(mdoc, tok, line, ppos))
1.16 kristaps 675: return(0);
1.35 kristaps 676: }
1.2 kristaps 677:
1.16 kristaps 678: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
679: lastarg = *pos;
1.28 kristaps 680: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 681: if (ARGV_EOLN == c)
682: break;
683: if (ARGV_WORD == c) {
684: *pos = lastarg;
1.16 kristaps 685: break;
1.38 kristaps 686: } else if (ARGV_ARG == c)
1.16 kristaps 687: continue;
688: mdoc_argv_free(argc, argv);
1.8 kristaps 689: return(0);
1.16 kristaps 690: }
1.2 kristaps 691:
1.28 kristaps 692: if (MDOC_LINEARG_MAX == argc) {
1.16 kristaps 693: mdoc_argv_free(argc, argv);
1.38 kristaps 694: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.28 kristaps 695: }
696:
697: c = mdoc_block_alloc(mdoc, line, ppos,
698: tok, (size_t)argc, argv);
699: mdoc_argv_free(argc, argv);
700:
701: if (0 == c)
1.16 kristaps 702: return(0);
1.8 kristaps 703:
1.19 kristaps 704: mdoc->next = MDOC_NEXT_CHILD;
705:
1.24 kristaps 706: if (0 == buf[*pos]) {
1.28 kristaps 707: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
708: return(0);
1.36 kristaps 709: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28 kristaps 710: return(0);
711: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 712: return(0);
1.19 kristaps 713: mdoc->next = MDOC_NEXT_CHILD;
1.24 kristaps 714: return(1);
715: }
1.19 kristaps 716:
1.28 kristaps 717: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
718: return(0);
1.24 kristaps 719: mdoc->next = MDOC_NEXT_CHILD;
1.7 kristaps 720:
1.33 kristaps 721: fl = ARGS_DELIM;
722: if (MDOC_TABSEP & mdoc_macros[tok].flags)
723: fl |= ARGS_TABSEP;
724:
1.24 kristaps 725: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
726: lastarg = *pos;
1.33 kristaps 727: c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.24 kristaps 728:
729: if (ARGS_ERROR == c)
1.19 kristaps 730: return(0);
1.24 kristaps 731: if (ARGS_PUNCT == c)
732: break;
733: if (ARGS_EOLN == c)
734: break;
735:
1.30 kristaps 736: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
737: return(0);
738: else if (MDOC_MAX == c) {
1.28 kristaps 739: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
740: return(0);
1.24 kristaps 741: mdoc->next = MDOC_NEXT_SIBLING;
742: continue;
1.30 kristaps 743: }
1.2 kristaps 744:
1.26 kristaps 745: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.24 kristaps 746: return(0);
747: break;
1.7 kristaps 748: }
1.1 kristaps 749:
1.24 kristaps 750: if (j == MDOC_LINEARG_MAX)
1.38 kristaps 751: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.24 kristaps 752:
1.36 kristaps 753: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.24 kristaps 754: return(0);
1.27 kristaps 755: if (1 == ppos && ! append_delims(mdoc, tok, line, pos, buf))
1.24 kristaps 756: return(0);
757:
1.28 kristaps 758: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
759: return(0);
1.16 kristaps 760: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 761:
1.16 kristaps 762: return(1);
1.1 kristaps 763: }
1.5 kristaps 764:
1.7 kristaps 765:
1.19 kristaps 766: /*
767: * When scoped to a line, a macro encompasses all of the contents. This
768: * differs from constants or text macros, where a new macro will
769: * terminate the existing context.
770: */
1.7 kristaps 771: int
1.16 kristaps 772: macro_scoped_line(MACRO_PROT_ARGS)
1.7 kristaps 773: {
1.8 kristaps 774: int lastarg, c, j;
775: char *p;
1.7 kristaps 776:
1.28 kristaps 777: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
778: return(0);
1.16 kristaps 779: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 780:
1.28 kristaps 781: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
782: return(0);
1.16 kristaps 783: mdoc->next = MDOC_NEXT_CHILD;
1.8 kristaps 784:
1.19 kristaps 785: /* XXX - no known argument macros. */
786:
787: for (lastarg = ppos, j = 0; j < MDOC_LINEARG_MAX; j++) {
788: lastarg = *pos;
1.28 kristaps 789: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.8 kristaps 790:
1.19 kristaps 791: if (ARGS_ERROR == c)
792: return(0);
793: if (ARGS_PUNCT == c)
794: break;
795: if (ARGS_EOLN == c)
796: break;
1.8 kristaps 797:
1.30 kristaps 798: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
799: return(0);
800: else if (MDOC_MAX == c) {
1.28 kristaps 801: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
802: return(0);
1.19 kristaps 803: mdoc->next = MDOC_NEXT_SIBLING;
804: continue;
1.30 kristaps 805: }
1.8 kristaps 806:
1.26 kristaps 807: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 808: return(0);
1.8 kristaps 809: break;
810: }
811:
1.19 kristaps 812: if (j == MDOC_LINEARG_MAX)
1.38 kristaps 813: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.19 kristaps 814:
815: if (1 == ppos) {
1.36 kristaps 816: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.16 kristaps 817: return(0);
1.27 kristaps 818: if ( ! append_delims(mdoc, tok, line, pos, buf))
1.8 kristaps 819: return(0);
1.36 kristaps 820: } else if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.35 kristaps 821: return(0);
1.38 kristaps 822: return(rewind_impblock(mdoc, tok, line, ppos));
1.22 kristaps 823: }
824:
825:
1.28 kristaps 826: /*
827: * Constant-scope macros accept a fixed number of arguments and behave
828: * like constant macros except that they're scoped across lines.
829: */
1.22 kristaps 830: int
831: macro_constant_scoped(MACRO_PROT_ARGS)
832: {
833: int lastarg, flushed, j, c, maxargs;
834: char *p;
835:
836: lastarg = ppos;
837: flushed = 0;
838:
839: switch (tok) {
840: case (MDOC_Eo):
841: maxargs = 1;
842: break;
843: default:
844: maxargs = 0;
845: break;
846: }
847:
1.28 kristaps 848: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
849: return(0);
1.22 kristaps 850: mdoc->next = MDOC_NEXT_CHILD;
851:
852: if (0 == maxargs) {
1.28 kristaps 853: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
854: return(0);
1.36 kristaps 855: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28 kristaps 856: return(0);
857: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25 kristaps 858: return(0);
1.22 kristaps 859: flushed = 1;
1.28 kristaps 860: } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
861: return(0);
1.22 kristaps 862:
863: mdoc->next = MDOC_NEXT_CHILD;
864:
865: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
866: lastarg = *pos;
867:
868: if (j == maxargs && ! flushed) {
1.36 kristaps 869: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22 kristaps 870: return(0);
871: flushed = 1;
1.28 kristaps 872: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
873: return(0);
1.22 kristaps 874: mdoc->next = MDOC_NEXT_CHILD;
875: }
876:
1.28 kristaps 877: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.22 kristaps 878: if (ARGS_ERROR == c)
879: return(0);
880: if (ARGS_PUNCT == c)
881: break;
882: if (ARGS_EOLN == c)
883: break;
884:
1.30 kristaps 885: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
886: return(0);
887: else if (MDOC_MAX != c) {
1.22 kristaps 888: if ( ! flushed) {
1.36 kristaps 889: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22 kristaps 890: return(0);
891: flushed = 1;
1.28 kristaps 892: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
893: return(0);
1.22 kristaps 894: mdoc->next = MDOC_NEXT_CHILD;
895: }
1.26 kristaps 896: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22 kristaps 897: return(0);
898: break;
899: }
900:
901: if ( ! flushed && mdoc_isdelim(p)) {
1.36 kristaps 902: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22 kristaps 903: return(0);
904: flushed = 1;
1.28 kristaps 905: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
906: return(0);
1.22 kristaps 907: mdoc->next = MDOC_NEXT_CHILD;
908: }
909:
1.28 kristaps 910: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
911: return(0);
1.22 kristaps 912: mdoc->next = MDOC_NEXT_SIBLING;
913: }
914:
915: if (MDOC_LINEARG_MAX == j)
1.38 kristaps 916: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.22 kristaps 917:
918: if ( ! flushed) {
1.36 kristaps 919: if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28 kristaps 920: return(0);
921: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.22 kristaps 922: return(0);
923: mdoc->next = MDOC_NEXT_CHILD;
924: }
925:
926: if (ppos > 1)
927: return(1);
1.27 kristaps 928: return(append_delims(mdoc, tok, line, pos, buf));
1.7 kristaps 929: }
1.8 kristaps 930:
1.10 kristaps 931:
1.19 kristaps 932: /*
933: * Delimited macros are like text macros except that, should punctuation
934: * be encountered, the macro isn't re-started with remaining tokens
935: * (it's only emitted once). Delimited macros can have a maximum number
936: * of arguments.
1.17 kristaps 937: */
1.10 kristaps 938: int
939: macro_constant_delimited(MACRO_PROT_ARGS)
940: {
1.24 kristaps 941: int lastarg, flushed, j, c, maxargs, argc;
942: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.13 kristaps 943: char *p;
1.10 kristaps 944:
945: lastarg = ppos;
946: flushed = 0;
947:
948: switch (tok) {
1.16 kristaps 949: case (MDOC_No):
950: /* FALLTHROUGH */
951: case (MDOC_Ns):
952: /* FALLTHROUGH */
1.39 ! kristaps 953: case (MDOC_Pf):
! 954: /* FALLTHROUGH */
1.10 kristaps 955: case (MDOC_Ux):
1.24 kristaps 956: /* FALLTHROUGH */
957: case (MDOC_St):
1.10 kristaps 958: maxargs = 0;
959: break;
960: default:
961: maxargs = 1;
962: break;
963: }
964:
1.24 kristaps 965: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
966: lastarg = *pos;
1.28 kristaps 967: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.38 kristaps 968: if (ARGV_EOLN == c)
1.24 kristaps 969: break;
1.38 kristaps 970: if (ARGV_WORD == c) {
971: *pos = lastarg;
972: break;
973: } else if (ARGV_ARG == c)
1.24 kristaps 974: continue;
975: mdoc_argv_free(argc, argv);
976: return(0);
977: }
978:
1.28 kristaps 979: c = mdoc_elem_alloc(mdoc, line, lastarg, tok, argc, argv);
980: mdoc_argv_free(argc, argv);
981:
982: if (0 == c)
1.24 kristaps 983: return(0);
984:
1.19 kristaps 985: mdoc->next = MDOC_NEXT_CHILD;
1.10 kristaps 986:
1.19 kristaps 987: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
988: lastarg = *pos;
1.10 kristaps 989:
1.19 kristaps 990: if (j == maxargs && ! flushed) {
1.28 kristaps 991: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 992: return(0);
993: flushed = 1;
994: }
1.11 kristaps 995:
1.28 kristaps 996: c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.19 kristaps 997: if (ARGS_ERROR == c)
1.10 kristaps 998: return(0);
1.19 kristaps 999: if (ARGS_PUNCT == c)
1000: break;
1001: if (ARGS_EOLN == c)
1002: break;
1003:
1.30 kristaps 1004: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1005: return(0);
1006: else if (MDOC_MAX != c) {
1.28 kristaps 1007: if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19 kristaps 1008: return(0);
1009: flushed = 1;
1.26 kristaps 1010: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19 kristaps 1011: return(0);
1012: break;
1013: }
1.10 kristaps 1014:
1.22 kristaps 1015: if ( ! flushed && mdoc_isdelim(p)) {
1.28 kristaps 1016: if ( ! rewind_elem(mdoc, tok))
1.19 kristaps 1017: return(0);
1018: flushed = 1;
1019: }
1020:
1.28 kristaps 1021: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1022: return(0);
1.19 kristaps 1023: mdoc->next = MDOC_NEXT_SIBLING;
1.10 kristaps 1024: }
1025:
1.22 kristaps 1026: if (MDOC_LINEARG_MAX == j)
1.38 kristaps 1027: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.22 kristaps 1028:
1.28 kristaps 1029: if ( ! flushed && rewind_elem(mdoc, tok))
1.19 kristaps 1030: return(0);
1.11 kristaps 1031:
1.19 kristaps 1032: if (ppos > 1)
1033: return(1);
1.27 kristaps 1034: return(append_delims(mdoc, tok, line, pos, buf));
1.10 kristaps 1035: }
1.11 kristaps 1036:
1037:
1.19 kristaps 1038: /*
1039: * Constant macros span an entire line: they constitute a macro and all
1040: * of its arguments and child data.
1041: */
1.11 kristaps 1042: int
1043: macro_constant(MACRO_PROT_ARGS)
1044: {
1.19 kristaps 1045: int c, lastarg, argc, sz, fl;
1046: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1047: char *p;
1.11 kristaps 1048:
1.16 kristaps 1049: fl = 0;
1.15 kristaps 1050: if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
1051: fl = ARGS_QUOTED;
1.11 kristaps 1052:
1.16 kristaps 1053: for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1054: lastarg = *pos;
1.28 kristaps 1055: c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16 kristaps 1056: if (ARGV_EOLN == c)
1057: break;
1.38 kristaps 1058: if (ARGV_WORD == c) {
1059: *pos = lastarg;
1060: break;
1061: } else if (ARGV_ARG == c)
1.16 kristaps 1062: continue;
1.11 kristaps 1063:
1.16 kristaps 1064: mdoc_argv_free(argc, argv);
1.11 kristaps 1065: return(0);
1066: }
1067:
1.28 kristaps 1068: c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
1069: mdoc_argv_free(argc, argv);
1070:
1071: if (0 == c)
1072: return(0);
1.11 kristaps 1073:
1.19 kristaps 1074: mdoc->next = MDOC_NEXT_CHILD;
1075:
1.28 kristaps 1076: if (MDOC_LINEARG_MAX == argc)
1.38 kristaps 1077: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.19 kristaps 1078:
1.16 kristaps 1079: for (sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.13 kristaps 1080: lastarg = *pos;
1.28 kristaps 1081: c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.16 kristaps 1082: if (ARGS_ERROR == c)
1083: return(0);
1084: if (ARGS_EOLN == c)
1.13 kristaps 1085: break;
1.19 kristaps 1086:
1.39 ! kristaps 1087: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
! 1088: return(0);
! 1089: else if (MDOC_MAX != c) {
! 1090: if ( ! rewind_elem(mdoc, tok))
! 1091: return(0);
! 1092: return(mdoc_macro(mdoc, c, line,
! 1093: lastarg, pos, buf));
! 1094: }
! 1095:
1.28 kristaps 1096: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1097: return(0);
1.21 kristaps 1098: mdoc->next = MDOC_NEXT_SIBLING;
1.13 kristaps 1099: }
1100:
1.19 kristaps 1101: if (MDOC_LINEARG_MAX == sz + argc)
1.38 kristaps 1102: return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
1.13 kristaps 1103:
1.28 kristaps 1104: return(rewind_elem(mdoc, tok));
1.13 kristaps 1105: }
1.15 kristaps 1106:
1107:
1.16 kristaps 1108: /* ARGSUSED */
1.15 kristaps 1109: int
1110: macro_obsolete(MACRO_PROT_ARGS)
1111: {
1112:
1.38 kristaps 1113: return(mdoc_pwarn(mdoc, line, ppos, WARN_SYNTAX, "macro is obsolete"));
1.15 kristaps 1114: }
1.25 kristaps 1115:
1116:
1117: int
1118: macro_end(struct mdoc *mdoc)
1119: {
1120:
1121: assert(mdoc->first);
1122: assert(mdoc->last);
1.36 kristaps 1123: return(rewind_last(mdoc->last->tok, mdoc->last->type,
1124: mdoc, mdoc->first));
1.25 kristaps 1125: }
CVSweb