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