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