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