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