]> git.cameronkatri.com Git - mandoc.git/blob - macro.c
In-progress migration to ARGV separation.
[mandoc.git] / macro.c
1 /* $Id: macro.c,v 1.48 2009/01/20 20:56:21 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 /*
29 * This has scanning/parsing routines, each of which extract a macro and
30 * its arguments and parameters, then know how to progress to the next
31 * macro. Macros are parsed according as follows:
32 *
33 * ELEMENT: TEXT | epsilon
34 * BLOCK: HEAD PUNCT BODY PUNCT BLOCK_TAIL PUNCT
35 * BLOCK_TAIL: TAIL | epsilon
36 * HEAD: ELEMENT | TEXT | BLOCK | epsilon
37 * BODY: ELEMENT | TEXT | BLOCK | epsilon
38 * TAIL: TEXT | epsilon
39 * PUNCT: TEXT (delimiters) | epsilon
40 *
41 * These are arranged into a parse tree, an example of which follows:
42 *
43 * ROOT
44 * BLOCK (.Sh)
45 * HEAD
46 * TEXT (`NAME')
47 * BODY
48 * ELEMENT (.Nm)
49 * TEXT (`mdocml')
50 * ELEMENT (.Nd)
51 * TEXT (`mdoc macro compiler')
52 * BLOCK (.Op)
53 * HEAD
54 * ELEMENT (.Fl)
55 * TEXT (`v')
56 * BLOCK (.Op)
57 * HEAD
58 * ELEMENT (.Fl)
59 * TEXT (`v')
60 * ELEMENT (.Fl)
61 * TEXT (`W')
62 * ELEMENT (.Ns)
63 * ELEMENT (.Ar)
64 * TEXT (`err...')
65 *
66 * These types are always per-line except for block bodies, which may
67 * span multiple lines. Macros are assigned a parsing routine, which
68 * corresponds to the type, in the mdoc_macros table.
69 *
70 * Note that types are general: there can be several parsing routines
71 * corresponding to a single type. The macro_text function, for
72 * example, parses an ELEMENT type (see the function definition for
73 * details) that may be interrupted by further macros; the
74 * macro_constant function, on the other hand, parses an ELEMENT type
75 * spanning a single line.
76 */
77
78 #include "private.h"
79
80 #define REWIND_REWIND (1 << 0)
81 #define REWIND_NOHALT (1 << 1)
82 #define REWIND_HALT (1 << 2)
83 static int rewind_dohalt(int, enum mdoc_type,
84 const struct mdoc_node *);
85 static int rewind_alt(int);
86 static int rewind_dobreak(int, const struct mdoc_node *);
87 static int rewind_elem(struct mdoc *, int);
88 static int rewind_impblock(struct mdoc *, int, int, int);
89 static int rewind_expblock(struct mdoc *, int, int, int);
90 static int rewind_subblock(enum mdoc_type,
91 struct mdoc *, int, int, int);
92 static int rewind_last(struct mdoc *, struct mdoc_node *);
93 static int append_delims(struct mdoc *, int, int *, char *);
94 static int lookup(struct mdoc *, int, int, int, const char *);
95
96
97 static int
98 lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
99 {
100 int res;
101
102 res = mdoc_find(mdoc, p);
103 if (MDOC_PARSED & mdoc_macros[from].flags)
104 return(res);
105 if (MDOC_MAX == res)
106 return(res);
107 if ( ! mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX, "macro-like parameter"))
108 return(-1);
109 return(MDOC_MAX);
110 }
111
112
113 static int
114 rewind_last(struct mdoc *mdoc, struct mdoc_node *to)
115 {
116
117 assert(to);
118 mdoc->next = MDOC_NEXT_SIBLING;
119
120 while (mdoc->last != to) {
121 if ( ! mdoc_valid_post(mdoc))
122 return(0);
123 if ( ! mdoc_action_post(mdoc))
124 return(0);
125 mdoc->last = mdoc->last->parent;
126 assert(mdoc->last);
127 }
128
129 if ( ! mdoc_valid_post(mdoc))
130 return(0);
131 return(mdoc_action_post(mdoc));
132 }
133
134
135 static int
136 rewind_alt(int tok)
137 {
138 switch (tok) {
139 case (MDOC_Ac):
140 return(MDOC_Ao);
141 case (MDOC_Bc):
142 return(MDOC_Bo);
143 case (MDOC_Dc):
144 return(MDOC_Do);
145 case (MDOC_Ec):
146 return(MDOC_Eo);
147 case (MDOC_Ed):
148 return(MDOC_Bd);
149 case (MDOC_Ef):
150 return(MDOC_Bf);
151 case (MDOC_Ek):
152 return(MDOC_Bk);
153 case (MDOC_El):
154 return(MDOC_Bl);
155 case (MDOC_Fc):
156 return(MDOC_Fo);
157 case (MDOC_Oc):
158 return(MDOC_Oo);
159 case (MDOC_Pc):
160 return(MDOC_Po);
161 case (MDOC_Qc):
162 return(MDOC_Qo);
163 case (MDOC_Re):
164 return(MDOC_Rs);
165 case (MDOC_Sc):
166 return(MDOC_So);
167 case (MDOC_Xc):
168 return(MDOC_Xo);
169 default:
170 break;
171 }
172 abort();
173 /* NOTREACHED */
174 }
175
176
177 static int
178 rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
179 {
180
181 if (MDOC_ROOT == p->type)
182 return(REWIND_HALT);
183 if (MDOC_VALID & p->flags)
184 return(REWIND_NOHALT);
185
186 switch (tok) {
187 /* One-liner implicit-scope. */
188 case (MDOC_Aq):
189 /* FALLTHROUGH */
190 case (MDOC_Bq):
191 /* FALLTHROUGH */
192 case (MDOC_D1):
193 /* FALLTHROUGH */
194 case (MDOC_Dl):
195 /* FALLTHROUGH */
196 case (MDOC_Dq):
197 /* FALLTHROUGH */
198 case (MDOC_Op):
199 /* FALLTHROUGH */
200 case (MDOC_Pq):
201 /* FALLTHROUGH */
202 case (MDOC_Ql):
203 /* FALLTHROUGH */
204 case (MDOC_Qq):
205 /* FALLTHROUGH */
206 case (MDOC_Sq):
207 assert(MDOC_HEAD != type);
208 assert(MDOC_TAIL != type);
209 if (type == p->type && tok == p->tok)
210 return(REWIND_REWIND);
211 break;
212
213 /* Multi-line implicit-scope. */
214 case (MDOC_It):
215 assert(MDOC_TAIL != type);
216 if (type == p->type && tok == p->tok)
217 return(REWIND_REWIND);
218 if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
219 return(REWIND_HALT);
220 break;
221 case (MDOC_Sh):
222 if (type == p->type && tok == p->tok)
223 return(REWIND_REWIND);
224 break;
225 case (MDOC_Ss):
226 assert(MDOC_TAIL != type);
227 if (type == p->type && tok == p->tok)
228 return(REWIND_REWIND);
229 if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
230 return(REWIND_HALT);
231 break;
232
233 /* Multi-line explicit scope start. */
234 case (MDOC_Ao):
235 /* FALLTHROUGH */
236 case (MDOC_Bd):
237 /* FALLTHROUGH */
238 case (MDOC_Bf):
239 /* FALLTHROUGH */
240 case (MDOC_Bk):
241 /* FALLTHROUGH */
242 case (MDOC_Bl):
243 /* FALLTHROUGH */
244 case (MDOC_Bo):
245 /* FALLTHROUGH */
246 case (MDOC_Do):
247 /* FALLTHROUGH */
248 case (MDOC_Eo):
249 /* FALLTHROUGH */
250 case (MDOC_Fo):
251 /* FALLTHROUGH */
252 case (MDOC_Oo):
253 /* FALLTHROUGH */
254 case (MDOC_Po):
255 /* FALLTHROUGH */
256 case (MDOC_Qo):
257 /* FALLTHROUGH */
258 case (MDOC_Rs):
259 /* FALLTHROUGH */
260 case (MDOC_So):
261 /* FALLTHROUGH */
262 case (MDOC_Xo):
263 if (type == p->type && tok == p->tok)
264 return(REWIND_REWIND);
265 break;
266
267 /* Multi-line explicit scope close. */
268 case (MDOC_Ac):
269 /* FALLTHROUGH */
270 case (MDOC_Bc):
271 /* FALLTHROUGH */
272 case (MDOC_Dc):
273 /* FALLTHROUGH */
274 case (MDOC_Ec):
275 /* FALLTHROUGH */
276 case (MDOC_Ed):
277 /* FALLTHROUGH */
278 case (MDOC_Ek):
279 /* FALLTHROUGH */
280 case (MDOC_El):
281 /* FALLTHROUGH */
282 case (MDOC_Fc):
283 /* FALLTHROUGH */
284 case (MDOC_Ef):
285 /* FALLTHROUGH */
286 case (MDOC_Oc):
287 /* FALLTHROUGH */
288 case (MDOC_Pc):
289 /* FALLTHROUGH */
290 case (MDOC_Qc):
291 /* FALLTHROUGH */
292 case (MDOC_Re):
293 /* FALLTHROUGH */
294 case (MDOC_Sc):
295 /* FALLTHROUGH */
296 case (MDOC_Xc):
297 if (type == p->type && rewind_alt(tok) == p->tok)
298 return(REWIND_REWIND);
299 break;
300 default:
301 abort();
302 /* NOTREACHED */
303 }
304
305 return(REWIND_NOHALT);
306 }
307
308
309 static int
310 rewind_dobreak(int tok, const struct mdoc_node *p)
311 {
312
313 assert(MDOC_ROOT != p->type);
314 if (MDOC_ELEM == p->type)
315 return(1);
316 if (MDOC_TEXT == p->type)
317 return(1);
318 if (MDOC_VALID & p->flags)
319 return(1);
320
321 switch (tok) {
322 /* Implicit rules. */
323 case (MDOC_It):
324 return(MDOC_It == p->tok);
325 case (MDOC_Ss):
326 return(MDOC_Ss == p->tok);
327 case (MDOC_Sh):
328 if (MDOC_Ss == p->tok)
329 return(1);
330 return(MDOC_Sh == p->tok);
331
332 /* Extra scope rules. */
333 case (MDOC_El):
334 if (MDOC_It == p->tok)
335 return(1);
336 break;
337 default:
338 break;
339 }
340
341 if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
342 return(p->tok == rewind_alt(tok));
343 else if (MDOC_BLOCK == p->type)
344 return(1);
345
346 return(tok == p->tok);
347 }
348
349
350 static int
351 rewind_elem(struct mdoc *mdoc, int tok)
352 {
353 struct mdoc_node *n;
354
355 n = mdoc->last;
356 if (MDOC_ELEM != n->type)
357 n = n->parent;
358 assert(MDOC_ELEM == n->type);
359 assert(tok == n->tok);
360
361 return(rewind_last(mdoc, n));
362 }
363
364
365 static int
366 rewind_subblock(enum mdoc_type type, struct mdoc *mdoc,
367 int tok, int line, int ppos)
368 {
369 struct mdoc_node *n;
370 int c;
371
372 /* LINTED */
373 for (n = mdoc->last; n; n = n->parent) {
374 c = rewind_dohalt(tok, type, n);
375 if (REWIND_HALT == c)
376 return(1);
377 if (REWIND_REWIND == c)
378 break;
379 else if (rewind_dobreak(tok, n))
380 continue;
381 return(mdoc_perr(mdoc, line, ppos, "scope breaks prior %s", mdoc_node2a(n)));
382 }
383
384 assert(n);
385 return(rewind_last(mdoc, n));
386 }
387
388
389 static int
390 rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
391 {
392 struct mdoc_node *n;
393 int c;
394
395 /* LINTED */
396 for (n = mdoc->last; n; n = n->parent) {
397 c = rewind_dohalt(tok, MDOC_BLOCK, n);
398 if (REWIND_HALT == c)
399 return(mdoc_perr(mdoc, line, ppos, "closing macro has no context"));
400 if (REWIND_REWIND == c)
401 break;
402 else if (rewind_dobreak(tok, n))
403 continue;
404 return(mdoc_perr(mdoc, line, ppos, "scope breaks prior %s", mdoc_node2a(n)));
405 }
406
407 assert(n);
408 return(rewind_last(mdoc, n));
409 }
410
411
412 static int
413 rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
414 {
415 struct mdoc_node *n;
416 int c;
417
418 /* LINTED */
419 for (n = mdoc->last; n; n = n->parent) {
420 c = rewind_dohalt(tok, MDOC_BLOCK, n);
421 if (REWIND_HALT == c)
422 return(1);
423 else if (REWIND_REWIND == c)
424 break;
425 else if (rewind_dobreak(tok, n))
426 continue;
427 return(mdoc_perr(mdoc, line, ppos, "scope breaks prior %s", mdoc_node2a(n)));
428 }
429
430 assert(n);
431 return(rewind_last(mdoc, n));
432 }
433
434
435 static int
436 append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
437 {
438 int c, lastarg;
439 char *p;
440
441 if (0 == buf[*pos])
442 return(1);
443
444 for (;;) {
445 lastarg = *pos;
446 c = mdoc_args(mdoc, line, pos, buf, 0, &p);
447 if (ARGS_ERROR == c)
448 return(0);
449 else if (ARGS_EOLN == c)
450 break;
451 assert(mdoc_isdelim(p));
452 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
453 return(0);
454 mdoc->next = MDOC_NEXT_SIBLING;
455 }
456
457 return(1);
458 }
459
460
461 /*
462 * Close out an explicit scope. This optionally parses a TAIL type with
463 * a set number of TEXT children.
464 */
465 int
466 macro_scoped_close(MACRO_PROT_ARGS)
467 {
468 int tt, j, c, lastarg, maxargs, flushed;
469 char *p;
470
471 switch (tok) {
472 case (MDOC_Ec):
473 maxargs = 1;
474 break;
475 default:
476 maxargs = 0;
477 break;
478 }
479
480 tt = rewind_alt(tok);
481
482 mdoc_msg(mdoc, "parse: %s closing %s",
483 mdoc_macronames[tok], mdoc_macronames[tt]);
484
485 if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
486 if (0 == buf[*pos]) {
487 if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
488 return(0);
489 return(rewind_expblock(mdoc, tok, line, ppos));
490 }
491 return(mdoc_perr(mdoc, line, ppos, "macro expects no parameters"));
492 }
493
494 if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
495 return(0);
496
497 lastarg = ppos;
498 flushed = 0;
499
500 if (maxargs > 0) {
501 if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
502 return(0);
503 mdoc->next = MDOC_NEXT_CHILD;
504 }
505
506 for (j = 0; /* No sentinel. */; j++) {
507 lastarg = *pos;
508
509 if (j == maxargs && ! flushed) {
510 if ( ! rewind_expblock(mdoc, tok, line, ppos))
511 return(0);
512 flushed = 1;
513 }
514
515 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
516 if (ARGS_ERROR == c)
517 return(0);
518 if (ARGS_PUNCT == c)
519 break;
520 if (ARGS_EOLN == c)
521 break;
522
523 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
524 return(0);
525 else if (MDOC_MAX != c) {
526 if ( ! flushed) {
527 if ( ! rewind_expblock(mdoc, tok, line, ppos))
528 return(0);
529 flushed = 1;
530 }
531 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
532 return(0);
533 break;
534 }
535
536 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
537 return(0);
538 mdoc->next = MDOC_NEXT_SIBLING;
539 }
540
541 if ( ! flushed && ! rewind_expblock(mdoc, tok, line, ppos))
542 return(0);
543
544 if (ppos > 1)
545 return(1);
546 return(append_delims(mdoc, line, pos, buf));
547 }
548
549
550 /*
551 * A general text macro. This is a complex case because of punctuation.
552 * If a text macro is followed by words, then punctuation, the macro is
553 * "stopped" and "reopened" following the punctuation. Thus, the
554 * following arises:
555 *
556 * .Fl a ; b
557 *
558 * ELEMENT (.Fl)
559 * TEXT (`a')
560 * TEXT (`;')
561 * ELEMENT (.Fl)
562 * TEXT (`b')
563 *
564 * This must handle the following situations:
565 *
566 * .Fl Ar b ; ;
567 *
568 * ELEMENT (.Fl)
569 * ELEMENT (.Ar)
570 * TEXT (`b')
571 * TEXT (`;')
572 * TEXT (`;')
573 */
574 int
575 macro_text(MACRO_PROT_ARGS)
576 {
577 int la, lastpunct, c, w, argc;
578 struct mdoc_arg argv[MDOC_LINEARG_MAX];
579 char *p;
580
581 la = ppos;
582 lastpunct = 0;
583
584 for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
585 la = *pos;
586 c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
587 if (ARGV_EOLN == c)
588 break;
589 if (ARGV_WORD == c) {
590 *pos = la;
591 break;
592 } else if (ARGV_ARG == c)
593 continue;
594
595 mdoc_argv_free(argc, argv);
596 return(0);
597 }
598
599 if (MDOC_LINEARG_MAX == argc) {
600 mdoc_argv_free(argc - 1, argv);
601 return(mdoc_perr(mdoc, line, ppos, "parameter hard-limit exceeded"));
602 }
603
604 c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
605
606 if (0 == c) {
607 mdoc_argv_free(argc, argv);
608 return(0);
609 }
610
611 mdoc->next = MDOC_NEXT_CHILD;
612
613 lastpunct = 0;
614 for (;;) {
615 la = *pos;
616 w = mdoc_args(mdoc, line, pos, buf, tok, &p);
617 if (ARGS_ERROR == w) {
618 mdoc_argv_free(argc, argv);
619 return(0);
620 }
621
622 if (ARGS_EOLN == w)
623 break;
624 if (ARGS_PUNCT == w)
625 break;
626
627 c = ARGS_QWORD == w ? MDOC_MAX :
628 lookup(mdoc, line, la, tok, p);
629
630 if (MDOC_MAX != c && -1 != c) {
631 if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
632 mdoc_argv_free(argc, argv);
633 return(0);
634 }
635 mdoc_argv_free(argc, argv);
636 c = mdoc_macro(mdoc, c, line, la, pos, buf);
637 if (0 == c)
638 return(0);
639 if (ppos > 1)
640 return(1);
641 return(append_delims(mdoc, line, pos, buf));
642 } else if (-1 == c) {
643 mdoc_argv_free(argc, argv);
644 return(0);
645 }
646
647 if (ARGS_QWORD != w && mdoc_isdelim(p)) {
648 if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
649 mdoc_argv_free(argc, argv);
650 return(0);
651 }
652 lastpunct = 1;
653 } else if (lastpunct) {
654 c = mdoc_elem_alloc(mdoc, line,
655 ppos, tok, argc, argv);
656 if (0 == c) {
657 mdoc_argv_free(argc, argv);
658 return(0);
659 }
660 mdoc->next = MDOC_NEXT_CHILD;
661 lastpunct = 0;
662 }
663
664 if ( ! mdoc_word_alloc(mdoc, line, la, p))
665 return(0);
666 mdoc->next = MDOC_NEXT_SIBLING;
667 }
668
669 mdoc_argv_free(argc, argv);
670
671 if (0 == lastpunct && ! rewind_elem(mdoc, tok))
672 return(0);
673 if (ppos > 1)
674 return(1);
675 return(append_delims(mdoc, line, pos, buf));
676 }
677
678
679 /*
680 * Handle explicit-scope (having a different closure token) and implicit
681 * scope (closing out prior scopes when re-invoked) macros. These
682 * constitute the BLOCK type and usually span multiple lines. These
683 * always have HEAD and sometimes have BODY types. In the multi-line
684 * case:
685 *
686 * .Bd -ragged
687 * Text.
688 * .Fl macro
689 * Another.
690 * .Ed
691 *
692 * BLOCK (.Bd)
693 * HEAD
694 * BODY
695 * TEXT (`Text.')
696 * ELEMENT (.Fl)
697 * TEXT (`macro')
698 * TEXT (`Another.')
699 *
700 * Note that the `.It' macro, possibly the most difficult (as it has
701 * embedded scope, etc.) is handled by this routine.
702 */
703 int
704 macro_scoped(MACRO_PROT_ARGS)
705 {
706 int c, lastarg, argc;
707 struct mdoc_arg argv[MDOC_LINEARG_MAX];
708 char *p;
709
710 assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
711
712 /* First rewind extant implicit scope. */
713
714 if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
715 if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
716 return(0);
717 if ( ! rewind_impblock(mdoc, tok, line, ppos))
718 return(0);
719 }
720
721 /* Parse arguments. */
722
723 for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
724 lastarg = *pos;
725 c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
726 if (ARGV_EOLN == c)
727 break;
728 if (ARGV_WORD == c) {
729 *pos = lastarg;
730 break;
731 } else if (ARGV_ARG == c)
732 continue;
733 mdoc_argv_free(argc, argv);
734 return(0);
735 }
736
737 if (MDOC_LINEARG_MAX == argc) {
738 mdoc_argv_free(argc - 1, argv);
739 return(mdoc_perr(mdoc, line, ppos, "parameter hard-limit exceeded"));
740 }
741
742 c = mdoc_block_alloc(mdoc, line, ppos,
743 tok, (size_t)argc, argv);
744 mdoc_argv_free(argc, argv);
745
746 if (0 == c)
747 return(0);
748
749 mdoc->next = MDOC_NEXT_CHILD;
750
751 if (0 == buf[*pos]) {
752 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
753 return(0);
754 if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
755 return(0);
756 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
757 return(0);
758 mdoc->next = MDOC_NEXT_CHILD;
759 return(1);
760 }
761
762 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
763 return(0);
764 mdoc->next = MDOC_NEXT_CHILD;
765
766 for (;;) {
767 lastarg = *pos;
768 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
769
770 if (ARGS_ERROR == c)
771 return(0);
772 if (ARGS_PUNCT == c)
773 break;
774 if (ARGS_EOLN == c)
775 break;
776
777 /* FIXME: if .It -column, the lookup must be for a
778 * sub-line component. BLAH. */
779
780 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
781 return(0);
782
783 if (MDOC_MAX == c) {
784 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
785 return(0);
786 mdoc->next = MDOC_NEXT_SIBLING;
787 continue;
788 }
789
790 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
791 return(0);
792 break;
793 }
794
795 if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
796 return(0);
797 if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
798 return(0);
799
800 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
801 return(0);
802 mdoc->next = MDOC_NEXT_CHILD;
803
804 return(1);
805 }
806
807
808 /*
809 * This handles a case of implicitly-scoped macro (BLOCK) limited to a
810 * single line. Instead of being closed out by a subsequent call to
811 * another macro, the scope is closed at the end of line. These don't
812 * have BODY or TAIL types. Notice that the punctuation falls outside
813 * of the HEAD type.
814 *
815 * .Qq a Fl b Ar d ; ;
816 *
817 * BLOCK (Qq)
818 * HEAD
819 * TEXT (`a')
820 * ELEMENT (.Fl)
821 * TEXT (`b')
822 * ELEMENT (.Ar)
823 * TEXT (`d')
824 * TEXT (`;')
825 * TEXT (`;')
826 */
827 int
828 macro_scoped_line(MACRO_PROT_ARGS)
829 {
830 int lastarg, c;
831 char *p;
832
833 if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
834 return(0);
835 mdoc->next = MDOC_NEXT_CHILD;
836
837 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
838 return(0);
839 mdoc->next = MDOC_NEXT_SIBLING;
840 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
841 return(0);
842 mdoc->next = MDOC_NEXT_CHILD;
843
844 /* XXX - no known argument macros. */
845
846 lastarg = ppos;
847 for (;;) {
848 lastarg = *pos;
849 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
850
851 if (ARGS_ERROR == c)
852 return(0);
853 if (ARGS_PUNCT == c)
854 break;
855 if (ARGS_EOLN == c)
856 break;
857
858 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
859 return(0);
860 else if (MDOC_MAX == c) {
861 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
862 return(0);
863 mdoc->next = MDOC_NEXT_SIBLING;
864 continue;
865 }
866
867 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
868 return(0);
869 break;
870 }
871
872 if (1 == ppos) {
873 if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
874 return(0);
875 if ( ! append_delims(mdoc, line, pos, buf))
876 return(0);
877 } else if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
878 return(0);
879 return(rewind_impblock(mdoc, tok, line, ppos));
880 }
881
882
883 /*
884 * A constant-scoped macro is like a simple-scoped macro (mdoc_scoped)
885 * except that it doesn't handle implicit scopes and explicit ones have
886 * a fixed number of TEXT children to the BODY.
887 *
888 * .Fl a So b Sc ;
889 *
890 * ELEMENT (.Fl)
891 * TEXT (`a')
892 * BLOCK (.So)
893 * HEAD
894 * BODY
895 * TEXT (`b')
896 * TEXT (';')
897 */
898 int
899 macro_constant_scoped(MACRO_PROT_ARGS)
900 {
901 int lastarg, flushed, j, c, maxargs;
902 char *p;
903
904 lastarg = ppos;
905 flushed = 0;
906
907 switch (tok) {
908 case (MDOC_Eo):
909 maxargs = 1;
910 break;
911 default:
912 maxargs = 0;
913 break;
914 }
915
916 if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
917 return(0);
918 mdoc->next = MDOC_NEXT_CHILD;
919
920 if (0 == maxargs) {
921 if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
922 return(0);
923 if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
924 return(0);
925 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
926 return(0);
927 flushed = 1;
928 } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
929 return(0);
930
931 mdoc->next = MDOC_NEXT_CHILD;
932
933 for (j = 0; /* No sentinel. */; j++) {
934 lastarg = *pos;
935
936 if (j == maxargs && ! flushed) {
937 if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
938 return(0);
939 flushed = 1;
940 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
941 return(0);
942 mdoc->next = MDOC_NEXT_CHILD;
943 }
944
945 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
946 if (ARGS_ERROR == c)
947 return(0);
948 if (ARGS_PUNCT == c)
949 break;
950 if (ARGS_EOLN == c)
951 break;
952
953 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
954 return(0);
955 else if (MDOC_MAX != c) {
956 if ( ! flushed) {
957 if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
958 return(0);
959 flushed = 1;
960 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
961 return(0);
962 mdoc->next = MDOC_NEXT_CHILD;
963 }
964 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
965 return(0);
966 break;
967 }
968
969 if ( ! flushed && mdoc_isdelim(p)) {
970 if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
971 return(0);
972 flushed = 1;
973 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
974 return(0);
975 mdoc->next = MDOC_NEXT_CHILD;
976 }
977
978 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
979 return(0);
980 mdoc->next = MDOC_NEXT_SIBLING;
981 }
982
983 if ( ! flushed) {
984 if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
985 return(0);
986 if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
987 return(0);
988 mdoc->next = MDOC_NEXT_CHILD;
989 }
990
991 if (ppos > 1)
992 return(1);
993 return(append_delims(mdoc, line, pos, buf));
994 }
995
996
997 /*
998 * A delimited constant is very similar to the macros parsed by
999 * macro_text except that, in the event of punctuation, the macro isn't
1000 * "re-opened" as it is in macro_text. Also, these macros have a fixed
1001 * number of parameters.
1002 *
1003 * .Fl a No b
1004 *
1005 * ELEMENT (.Fl)
1006 * TEXT (`a')
1007 * ELEMENT (.No)
1008 * TEXT (`b')
1009 */
1010 int
1011 macro_constant_delimited(MACRO_PROT_ARGS)
1012 {
1013 int lastarg, flushed, j, c, maxargs, argc;
1014 struct mdoc_arg argv[MDOC_LINEARG_MAX];
1015 char *p;
1016
1017 lastarg = ppos;
1018 flushed = 0;
1019
1020 switch (tok) {
1021 case (MDOC_No):
1022 /* FALLTHROUGH */
1023 case (MDOC_Ns):
1024 /* FALLTHROUGH */
1025 case (MDOC_Pf):
1026 /* FALLTHROUGH */
1027 case (MDOC_Ux):
1028 /* FALLTHROUGH */
1029 case (MDOC_St):
1030 maxargs = 0;
1031 break;
1032 default:
1033 maxargs = 1;
1034 break;
1035 }
1036
1037 for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1038 lastarg = *pos;
1039 c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1040 if (ARGV_EOLN == c)
1041 break;
1042 if (ARGV_WORD == c) {
1043 *pos = lastarg;
1044 break;
1045 } else if (ARGV_ARG == c)
1046 continue;
1047 mdoc_argv_free(argc, argv);
1048 return(0);
1049 }
1050
1051 if (MDOC_LINEARG_MAX == argc) {
1052 mdoc_argv_free(argc - 1, argv);
1053 return(mdoc_perr(mdoc, line, ppos, "parameter hard-limit exceeded"));
1054 }
1055
1056 c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
1057 mdoc_argv_free(argc, argv);
1058
1059 if (0 == c)
1060 return(0);
1061
1062 mdoc->next = MDOC_NEXT_CHILD;
1063
1064 for (j = 0; /* No sentinel. */; j++) {
1065 lastarg = *pos;
1066
1067 if (j == maxargs && ! flushed) {
1068 if ( ! rewind_elem(mdoc, tok))
1069 return(0);
1070 flushed = 1;
1071 }
1072
1073 c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1074 if (ARGS_ERROR == c)
1075 return(0);
1076 if (ARGS_PUNCT == c)
1077 break;
1078 if (ARGS_EOLN == c)
1079 break;
1080
1081 if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1082 return(0);
1083 else if (MDOC_MAX != c) {
1084 if ( ! flushed && ! rewind_elem(mdoc, tok))
1085 return(0);
1086 flushed = 1;
1087 if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1088 return(0);
1089 break;
1090 }
1091
1092 if ( ! flushed && mdoc_isdelim(p)) {
1093 if ( ! rewind_elem(mdoc, tok))
1094 return(0);
1095 flushed = 1;
1096 }
1097
1098 if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1099 return(0);
1100 mdoc->next = MDOC_NEXT_SIBLING;
1101 }
1102
1103 if ( ! flushed && ! rewind_elem(mdoc, tok))
1104 return(0);
1105
1106 if (ppos > 1)
1107 return(1);
1108 return(append_delims(mdoc, line, pos, buf));
1109 }
1110
1111
1112 /*
1113 * A constant macro is the simplest classification. It spans an entire
1114 * line.
1115 */
1116 int
1117 macro_constant(MACRO_PROT_ARGS)
1118 {
1119 int c, w, la, argc;
1120 struct mdoc_arg argv[MDOC_LINEARG_MAX];
1121 char *p;
1122
1123 assert( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1124
1125 for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1126 la = *pos;
1127 c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1128 if (ARGV_EOLN == c)
1129 break;
1130 if (ARGV_WORD == c) {
1131 *pos = la;
1132 break;
1133 } else if (ARGV_ARG == c)
1134 continue;
1135
1136 mdoc_argv_free(argc, argv);
1137 return(0);
1138 }
1139
1140 if (MDOC_LINEARG_MAX == argc) {
1141 mdoc_argv_free(argc - 1, argv);
1142 return(mdoc_perr(mdoc, line, ppos, "parameter hard-limit exceeded"));
1143 }
1144
1145 c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
1146 mdoc_argv_free(argc, argv);
1147
1148 if (0 == c)
1149 return(0);
1150
1151 mdoc->next = MDOC_NEXT_CHILD;
1152
1153 for (;;) {
1154 la = *pos;
1155 w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1156 if (ARGS_ERROR == w)
1157 return(0);
1158 if (ARGS_EOLN == w)
1159 break;
1160
1161 c = ARGS_QWORD == w ? MDOC_MAX :
1162 lookup(mdoc, line, la, tok, p);
1163
1164 if (MDOC_MAX != c && -1 != c) {
1165 if ( ! rewind_elem(mdoc, tok))
1166 return(0);
1167 return(mdoc_macro(mdoc, c, line, la, pos, buf));
1168 } else if (-1 == c)
1169 return(0);
1170
1171 if ( ! mdoc_word_alloc(mdoc, line, la, p))
1172 return(0);
1173 mdoc->next = MDOC_NEXT_SIBLING;
1174 }
1175
1176 return(rewind_elem(mdoc, tok));
1177 }
1178
1179
1180 /* ARGSUSED */
1181 int
1182 macro_obsolete(MACRO_PROT_ARGS)
1183 {
1184
1185 return(mdoc_pwarn(mdoc, line, ppos, WARN_SYNTAX, "macro is obsolete"));
1186 }
1187
1188
1189 /*
1190 * This is called at the end of parsing. It must traverse up the tree,
1191 * closing out open [implicit] scopes. Obviously, open explicit scopes
1192 * are errors.
1193 */
1194 int
1195 macro_end(struct mdoc *mdoc)
1196 {
1197 struct mdoc_node *n;
1198
1199 assert(mdoc->first);
1200 assert(mdoc->last);
1201
1202 /* Scan for open explicit scopes. */
1203
1204 n = MDOC_VALID & mdoc->last->flags ?
1205 mdoc->last->parent : mdoc->last;
1206
1207 for ( ; n; n = n->parent) {
1208 if (MDOC_BLOCK != n->type)
1209 continue;
1210 if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
1211 continue;
1212 return(mdoc_nerr(mdoc, n, "macro scope still open on exit"));
1213 }
1214
1215 return(rewind_last(mdoc, mdoc->first));
1216 }