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