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