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