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