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