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