]>
git.cameronkatri.com Git - mandoc.git/blob - macro.c
1 /* $Id: macro.c,v 1.57 2009/03/06 14:13:47 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
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
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.
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
35 * FIXME: don't use static mdoc_argv values, as they require us to do a
36 * complicated copy-over when actually assigning them to dynamic memory.
41 static int macro_obsolete(MACRO_PROT_ARGS
);
42 static int macro_constant(MACRO_PROT_ARGS
);
43 static int macro_constant_scoped(MACRO_PROT_ARGS
);
44 static int macro_constant_delimited(MACRO_PROT_ARGS
);
45 static int macro_text(MACRO_PROT_ARGS
);
46 static int macro_scoped(MACRO_PROT_ARGS
);
47 static int macro_scoped_close(MACRO_PROT_ARGS
);
48 static int macro_scoped_line(MACRO_PROT_ARGS
);
50 #define REWIND_REWIND (1 << 0)
51 #define REWIND_NOHALT (1 << 1)
52 #define REWIND_HALT (1 << 2)
54 static int rewind_dohalt(int, enum mdoc_type
,
55 const struct mdoc_node
*);
56 static int rewind_alt(int);
57 static int rewind_dobreak(int, const struct mdoc_node
*);
58 static int rewind_elem(struct mdoc
*, int);
59 static int rewind_impblock(struct mdoc
*, int, int, int);
60 static int rewind_expblock(struct mdoc
*, int, int, int);
61 static int rewind_subblock(enum mdoc_type
,
62 struct mdoc
*, int, int, int);
63 static int rewind_last(struct mdoc
*, struct mdoc_node
*);
64 static int append_delims(struct mdoc
*, int, int *, char *);
65 static int lookup(struct mdoc
*, int, int, int, const char *);
66 static int pwarn(struct mdoc
*, int, int, int);
67 static int perr(struct mdoc
*, int, int, int);
76 /* Central table of library: who gets parsed how. */
78 const struct mdoc_macro __mdoc_macros
[MDOC_MAX
] = {
80 { macro_constant
, MDOC_PROLOGUE
}, /* Dd */
81 { macro_constant
, MDOC_PROLOGUE
}, /* Dt */
82 { macro_constant
, MDOC_PROLOGUE
}, /* Os */
83 { macro_scoped
, 0 }, /* Sh */
84 { macro_scoped
, 0 }, /* Ss */
85 { macro_text
, 0 }, /* Pp */
86 { macro_scoped_line
, MDOC_PARSED
}, /* D1 */
87 { macro_scoped_line
, MDOC_PARSED
}, /* Dl */
88 { macro_scoped
, MDOC_EXPLICIT
}, /* Bd */
89 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Ed */
90 { macro_scoped
, MDOC_EXPLICIT
}, /* Bl */
91 { macro_scoped_close
, MDOC_EXPLICIT
}, /* El */
92 { macro_scoped
, MDOC_PARSED
}, /* It */
93 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ad */
94 { macro_text
, MDOC_PARSED
}, /* An */
95 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ar */
96 { macro_constant
, 0 }, /* Cd */
97 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Cm */
98 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dv */
99 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Er */
100 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ev */
101 { macro_constant
, 0 }, /* Ex */
102 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fa */
103 { macro_constant
, 0 }, /* Fd */
104 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fl */
105 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fn */
106 { macro_text
, MDOC_PARSED
}, /* Ft */
107 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ic */
108 { macro_constant
, 0 }, /* In */
109 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Li */
110 { macro_constant
, 0 }, /* Nd */
111 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nm */
112 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Op */
113 { macro_obsolete
, 0 }, /* Ot */
114 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pa */
115 { macro_constant
, 0 }, /* Rv */
116 /* XXX - .St supposed to be (but isn't) callable. */
117 { macro_constant_delimited
, MDOC_PARSED
}, /* St */
118 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Va */
119 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Vt */
120 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Xr */
121 { macro_constant
, 0 }, /* %A */
122 { macro_constant
, 0 }, /* %B */
123 { macro_constant
, 0 }, /* %D */
124 { macro_constant
, 0 }, /* %I */
125 { macro_constant
, 0 }, /* %J */
126 { macro_constant
, 0 }, /* %N */
127 { macro_constant
, 0 }, /* %O */
128 { macro_constant
, 0 }, /* %P */
129 { macro_constant
, 0 }, /* %R */
130 { macro_constant
, 0 }, /* %T */
131 { macro_constant
, 0 }, /* %V */
132 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ac */
133 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Ao */
134 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Aq */
135 { macro_constant_delimited
, 0 }, /* At */
136 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Bc */
137 { macro_scoped
, MDOC_EXPLICIT
}, /* Bf */
138 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bo */
139 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bq */
140 { macro_constant_delimited
, MDOC_PARSED
}, /* Bsx */
141 { macro_constant_delimited
, MDOC_PARSED
}, /* Bx */
142 { macro_constant
, 0 }, /* Db */
143 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Dc */
144 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Do */
145 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dq */
146 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ec */
147 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Ef */
148 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Em */
149 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Eo */
150 { macro_constant_delimited
, MDOC_PARSED
}, /* Fx */
151 { macro_text
, MDOC_PARSED
}, /* Ms */
152 { macro_constant_delimited
, MDOC_CALLABLE
| MDOC_PARSED
}, /* No */
153 { macro_constant_delimited
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ns */
154 { macro_constant_delimited
, MDOC_PARSED
}, /* Nx */
155 { macro_constant_delimited
, MDOC_PARSED
}, /* Ox */
156 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Pc */
157 { macro_constant_delimited
, MDOC_PARSED
}, /* Pf */
158 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Po */
159 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pq */
160 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Qc */
161 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ql */
162 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Qo */
163 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Qq */
164 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Re */
165 { macro_scoped
, MDOC_EXPLICIT
}, /* Rs */
166 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Sc */
167 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* So */
168 { macro_scoped_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sq */
169 { macro_constant
, 0 }, /* Sm */
170 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sx */
171 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sy */
172 { macro_text
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Tn */
173 { macro_constant_delimited
, MDOC_PARSED
}, /* Ux */
174 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Xc */
175 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Xo */
176 /* XXX - .Fo supposed to be (but isn't) callable. */
177 { macro_scoped
, MDOC_EXPLICIT
}, /* Fo */
178 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Fc */
179 { macro_constant_scoped
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Oo */
180 { macro_scoped_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Oc */
181 { macro_scoped
, MDOC_EXPLICIT
}, /* Bk */
182 { macro_scoped_close
, MDOC_EXPLICIT
}, /* Ek */
183 { macro_constant
, 0 }, /* Bt */
184 { macro_constant
, 0 }, /* Hf */
185 { macro_obsolete
, 0 }, /* Fr */
186 { macro_constant
, 0 }, /* Ud */
187 { macro_constant
, 0 }, /* Lb */
190 const struct mdoc_macro
* const mdoc_macros
= __mdoc_macros
;
194 perr(struct mdoc
*mdoc
, int line
, int pos
, int type
)
200 c
= mdoc_perr(mdoc
, line
, pos
,
201 "closing macro has prior context");
204 c
= mdoc_perr(mdoc
, line
, pos
,
205 "macro doesn't expect parameters");
208 c
= mdoc_perr(mdoc
, line
, pos
,
209 "argument hard-limit %d reached",
220 pwarn(struct mdoc
*mdoc
, int line
, int pos
, int type
)
226 c
= mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
,
227 "macro-like parameter");
230 c
= mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
,
231 "macro is marked obsolete");
242 lookup(struct mdoc
*mdoc
, int line
, int pos
, int from
, const char *p
)
246 res
= mdoc_find(mdoc
, p
);
247 if (MDOC_PARSED
& mdoc_macros
[from
].flags
)
251 if ( ! pwarn(mdoc
, line
, pos
, WMACPARM
))
258 rewind_last(struct mdoc
*mdoc
, struct mdoc_node
*to
)
262 mdoc
->next
= MDOC_NEXT_SIBLING
;
265 while (mdoc
->last
!= to
) {
266 if ( ! mdoc_valid_post(mdoc
))
268 if ( ! mdoc_action_post(mdoc
))
270 mdoc
->last
= mdoc
->last
->parent
;
274 if ( ! mdoc_valid_post(mdoc
))
276 return(mdoc_action_post(mdoc
));
323 rewind_dohalt(int tok
, enum mdoc_type type
, const struct mdoc_node
*p
)
326 if (MDOC_ROOT
== p
->type
)
328 if (MDOC_VALID
& p
->flags
)
329 return(REWIND_NOHALT
);
332 /* One-liner implicit-scope. */
352 assert(MDOC_HEAD
!= type
);
353 assert(MDOC_TAIL
!= type
);
354 if (type
== p
->type
&& tok
== p
->tok
)
355 return(REWIND_REWIND
);
358 /* Multi-line implicit-scope. */
360 assert(MDOC_TAIL
!= type
);
361 if (type
== p
->type
&& tok
== p
->tok
)
362 return(REWIND_REWIND
);
363 if (MDOC_BODY
== p
->type
&& MDOC_Bl
== p
->tok
)
367 if (type
== p
->type
&& tok
== p
->tok
)
368 return(REWIND_REWIND
);
371 assert(MDOC_TAIL
!= type
);
372 if (type
== p
->type
&& tok
== p
->tok
)
373 return(REWIND_REWIND
);
374 if (MDOC_BODY
== p
->type
&& MDOC_Sh
== p
->tok
)
378 /* Multi-line explicit scope start. */
408 if (type
== p
->type
&& tok
== p
->tok
)
409 return(REWIND_REWIND
);
412 /* Multi-line explicit scope close. */
442 if (type
== p
->type
&& rewind_alt(tok
) == p
->tok
)
443 return(REWIND_REWIND
);
450 return(REWIND_NOHALT
);
455 rewind_dobreak(int tok
, const struct mdoc_node
*p
)
458 assert(MDOC_ROOT
!= p
->type
);
459 if (MDOC_ELEM
== p
->type
)
461 if (MDOC_TEXT
== p
->type
)
463 if (MDOC_VALID
& p
->flags
)
467 /* Implicit rules. */
469 return(MDOC_It
== p
->tok
);
471 return(MDOC_Ss
== p
->tok
);
473 if (MDOC_Ss
== p
->tok
)
475 return(MDOC_Sh
== p
->tok
);
477 /* Extra scope rules. */
479 if (MDOC_It
== p
->tok
)
486 if (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
)
487 return(p
->tok
== rewind_alt(tok
));
488 else if (MDOC_BLOCK
== p
->type
)
491 return(tok
== p
->tok
);
496 rewind_elem(struct mdoc
*mdoc
, int tok
)
501 if (MDOC_ELEM
!= n
->type
)
503 assert(MDOC_ELEM
== n
->type
);
504 assert(tok
== n
->tok
);
506 return(rewind_last(mdoc
, n
));
511 rewind_subblock(enum mdoc_type type
, struct mdoc
*mdoc
,
512 int tok
, int line
, int ppos
)
518 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
519 c
= rewind_dohalt(tok
, type
, n
);
520 if (REWIND_HALT
== c
)
522 if (REWIND_REWIND
== c
)
524 else if (rewind_dobreak(tok
, n
))
526 return(mdoc_perr(mdoc
, line
, ppos
,
527 "scope breaks %s", MDOC_ROOT
== n
->type
?
528 "<root>" : mdoc_macronames
[n
->tok
]));
532 return(rewind_last(mdoc
, n
));
537 rewind_expblock(struct mdoc
*mdoc
, int tok
, int line
, int ppos
)
543 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
544 c
= rewind_dohalt(tok
, MDOC_BLOCK
, n
);
545 if (REWIND_HALT
== c
)
546 return(perr(mdoc
, line
, ppos
, ENOCTX
));
547 if (REWIND_REWIND
== c
)
549 else if (rewind_dobreak(tok
, n
))
551 return(mdoc_perr(mdoc
, line
, ppos
,
552 "scope breaks %s", MDOC_ROOT
== n
->type
?
553 "<root>" : mdoc_macronames
[n
->tok
]));
557 return(rewind_last(mdoc
, n
));
562 rewind_impblock(struct mdoc
*mdoc
, int tok
, int line
, int ppos
)
568 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
569 c
= rewind_dohalt(tok
, MDOC_BLOCK
, n
);
570 if (REWIND_HALT
== c
)
572 else if (REWIND_REWIND
== c
)
574 else if (rewind_dobreak(tok
, n
))
576 return(mdoc_perr(mdoc
, line
, ppos
,
577 "scope breaks %s", MDOC_ROOT
== n
->type
?
578 "<root>" : mdoc_macronames
[n
->tok
]));
582 return(rewind_last(mdoc
, n
));
587 append_delims(struct mdoc
*mdoc
, int line
, int *pos
, char *buf
)
597 c
= mdoc_args(mdoc
, line
, pos
, buf
, 0, &p
);
598 assert(ARGS_PHRASE
!= c
);
602 else if (ARGS_EOLN
== c
)
604 assert(mdoc_isdelim(p
));
605 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
607 mdoc
->next
= MDOC_NEXT_SIBLING
;
615 * Close out an explicit scope. This optionally parses a TAIL type with
616 * a set number of TEXT children.
619 macro_scoped_close(MACRO_PROT_ARGS
)
621 int tt
, j
, c
, lastarg
, maxargs
, flushed
;
633 tt
= rewind_alt(tok
);
635 mdoc_msg(mdoc
, "parse: %s closing %s",
636 mdoc_macronames
[tok
], mdoc_macronames
[tt
]);
638 if ( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
)) {
639 if (0 == buf
[*pos
]) {
640 if ( ! rewind_subblock(MDOC_BODY
, mdoc
,
643 return(rewind_expblock(mdoc
, tok
, line
, ppos
));
645 return(perr(mdoc
, line
, ppos
, ENOPARMS
));
648 if ( ! rewind_subblock(MDOC_BODY
, mdoc
, tok
, line
, ppos
))
655 if ( ! mdoc_tail_alloc(mdoc
, line
, ppos
, tt
))
657 mdoc
->next
= MDOC_NEXT_CHILD
;
660 for (j
= 0; /* No sentinel. */; j
++) {
663 if (j
== maxargs
&& ! flushed
) {
664 if ( ! rewind_expblock(mdoc
, tok
, line
, ppos
))
669 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
670 assert(ARGS_PHRASE
!= c
);
679 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
681 else if (MDOC_MAX
!= c
) {
683 if ( ! rewind_expblock(mdoc
, tok
,
688 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
693 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
695 mdoc
->next
= MDOC_NEXT_SIBLING
;
698 if ( ! flushed
&& ! rewind_expblock(mdoc
, tok
, line
, ppos
))
703 return(append_delims(mdoc
, line
, pos
, buf
));
708 * A general text macro. This is a complex case because of punctuation.
709 * If a text macro is followed by words, then punctuation, the macro is
710 * "stopped" and "reopened" following the punctuation. Thus, the
721 * This must handle the following situations:
732 macro_text(MACRO_PROT_ARGS
)
734 int la
, lastpunct
, c
, w
, argc
;
735 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
741 for (argc
= 0; argc
< MDOC_LINEARG_MAX
; argc
++) {
743 c
= mdoc_argv(mdoc
, line
, tok
, &argv
[argc
], pos
, buf
);
746 if (ARGV_WORD
== c
) {
749 } else if (ARGV_ARG
== c
)
752 mdoc_argv_free(argc
, argv
);
756 if (MDOC_LINEARG_MAX
== argc
) {
757 mdoc_argv_free(argc
- 1, argv
);
758 return(perr(mdoc
, line
, ppos
, EARGVLIM
));
761 c
= mdoc_elem_alloc(mdoc
, line
, ppos
,
762 tok
, (size_t)argc
, argv
);
765 mdoc_argv_free(argc
, argv
);
769 mdoc
->next
= MDOC_NEXT_CHILD
;
774 w
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
775 assert(ARGS_PHRASE
!= c
);
777 if (ARGS_ERROR
== w
) {
778 mdoc_argv_free(argc
, argv
);
787 c
= ARGS_QWORD
== w
? MDOC_MAX
:
788 lookup(mdoc
, line
, la
, tok
, p
);
790 if (MDOC_MAX
!= c
&& -1 != c
) {
791 if (0 == lastpunct
&& ! rewind_elem(mdoc
, tok
)) {
792 mdoc_argv_free(argc
, argv
);
795 mdoc_argv_free(argc
, argv
);
796 c
= mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
);
801 return(append_delims(mdoc
, line
, pos
, buf
));
802 } else if (-1 == c
) {
803 mdoc_argv_free(argc
, argv
);
807 /* FIXME: .Fl and .Ar handling of `|'. */
809 if (ARGS_QWORD
!= w
&& mdoc_isdelim(p
)) {
810 if (0 == lastpunct
&& ! rewind_elem(mdoc
, tok
)) {
811 mdoc_argv_free(argc
, argv
);
815 } else if (lastpunct
) {
816 c
= mdoc_elem_alloc(mdoc
, line
, ppos
,
817 tok
, (size_t)argc
, argv
);
819 mdoc_argv_free(argc
, argv
);
822 mdoc
->next
= MDOC_NEXT_CHILD
;
826 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
828 mdoc
->next
= MDOC_NEXT_SIBLING
;
831 mdoc_argv_free(argc
, argv
);
833 if (0 == lastpunct
&& ! rewind_elem(mdoc
, tok
))
837 return(append_delims(mdoc
, line
, pos
, buf
));
842 * Handle explicit-scope (having a different closure token) and implicit
843 * scope (closing out prior scopes when re-invoked) macros. These
844 * constitute the BLOCK type and usually span multiple lines. These
845 * always have HEAD and sometimes have BODY types. In the multi-line
862 * Note that the `.It' macro, possibly the most difficult (as it has
863 * embedded scope, etc.) is handled by this routine.
866 macro_scoped(MACRO_PROT_ARGS
)
868 int c
, lastarg
, argc
;
869 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
872 assert ( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
));
874 /* First rewind extant implicit scope. */
876 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
)) {
877 if ( ! rewind_subblock(MDOC_BODY
, mdoc
, tok
, line
, ppos
))
879 if ( ! rewind_impblock(mdoc
, tok
, line
, ppos
))
883 /* Parse arguments. */
885 for (argc
= 0; argc
< MDOC_LINEARG_MAX
; argc
++) {
887 c
= mdoc_argv(mdoc
, line
, tok
, &argv
[argc
], pos
, buf
);
890 if (ARGV_WORD
== c
) {
893 } else if (ARGV_ARG
== c
)
895 mdoc_argv_free(argc
, argv
);
899 if (MDOC_LINEARG_MAX
== argc
) {
900 mdoc_argv_free(argc
- 1, argv
);
901 return(perr(mdoc
, line
, ppos
, EARGVLIM
));
904 c
= mdoc_block_alloc(mdoc
, line
, ppos
,
905 tok
, (size_t)argc
, argv
);
906 mdoc_argv_free(argc
, argv
);
911 mdoc
->next
= MDOC_NEXT_CHILD
;
913 if (0 == buf
[*pos
]) {
914 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
916 if ( ! rewind_subblock(MDOC_HEAD
, mdoc
,
919 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
921 mdoc
->next
= MDOC_NEXT_CHILD
;
925 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
927 mdoc
->next
= MDOC_NEXT_CHILD
;
931 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
937 if (ARGS_PHRASE
== c
) {
939 if ( ! mdoc_phrase(mdoc, line, lastarg, buf))
945 /* FIXME: if .It -column, the lookup must be for a
946 * sub-line component. BLAH. */
948 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
952 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
954 mdoc
->next
= MDOC_NEXT_SIBLING
;
958 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
963 if (1 == ppos
&& ! append_delims(mdoc
, line
, pos
, buf
))
965 if ( ! rewind_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
968 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
970 mdoc
->next
= MDOC_NEXT_CHILD
;
977 * This handles a case of implicitly-scoped macro (BLOCK) limited to a
978 * single line. Instead of being closed out by a subsequent call to
979 * another macro, the scope is closed at the end of line. These don't
980 * have BODY or TAIL types. Notice that the punctuation falls outside
983 * .Qq a Fl b Ar d ; ;
996 macro_scoped_line(MACRO_PROT_ARGS
)
1001 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, 0, NULL
))
1003 mdoc
->next
= MDOC_NEXT_CHILD
;
1005 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1007 mdoc
->next
= MDOC_NEXT_SIBLING
;
1008 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1010 mdoc
->next
= MDOC_NEXT_CHILD
;
1012 /* XXX - no known argument macros. */
1017 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1018 assert(ARGS_PHRASE
!= c
);
1020 if (ARGS_ERROR
== c
)
1022 if (ARGS_PUNCT
== c
)
1027 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1029 else if (MDOC_MAX
== c
) {
1030 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1032 mdoc
->next
= MDOC_NEXT_SIBLING
;
1036 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1042 if ( ! rewind_subblock(MDOC_BODY
, mdoc
, tok
, line
, ppos
))
1044 if ( ! append_delims(mdoc
, line
, pos
, buf
))
1046 } else if ( ! rewind_subblock(MDOC_BODY
, mdoc
, tok
, line
, ppos
))
1048 return(rewind_impblock(mdoc
, tok
, line
, ppos
));
1053 * A constant-scoped macro is like a simple-scoped macro (mdoc_scoped)
1054 * except that it doesn't handle implicit scopes and explicit ones have
1055 * a fixed number of TEXT children to the BODY.
1068 macro_constant_scoped(MACRO_PROT_ARGS
)
1070 int lastarg
, flushed
, j
, c
, maxargs
;
1085 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, 0, NULL
))
1087 mdoc
->next
= MDOC_NEXT_CHILD
;
1090 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1092 if ( ! rewind_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1094 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1097 } else if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1100 mdoc
->next
= MDOC_NEXT_CHILD
;
1102 for (j
= 0; /* No sentinel. */; j
++) {
1105 if (j
== maxargs
&& ! flushed
) {
1106 if ( ! rewind_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1109 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1111 mdoc
->next
= MDOC_NEXT_CHILD
;
1114 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1115 assert(ARGS_PHRASE
!= c
);
1117 if (ARGS_ERROR
== c
)
1119 if (ARGS_PUNCT
== c
)
1124 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1126 else if (MDOC_MAX
!= c
) {
1128 if ( ! rewind_subblock(MDOC_HEAD
, mdoc
,
1132 if ( ! mdoc_body_alloc(mdoc
, line
,
1135 mdoc
->next
= MDOC_NEXT_CHILD
;
1137 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
,
1143 if ( ! flushed
&& mdoc_isdelim(p
)) {
1144 if ( ! rewind_subblock(MDOC_HEAD
, mdoc
,
1148 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1150 mdoc
->next
= MDOC_NEXT_CHILD
;
1153 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1155 mdoc
->next
= MDOC_NEXT_SIBLING
;
1159 if ( ! rewind_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1161 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1163 mdoc
->next
= MDOC_NEXT_CHILD
;
1168 return(append_delims(mdoc
, line
, pos
, buf
));
1173 * A delimited constant is very similar to the macros parsed by
1174 * macro_text except that, in the event of punctuation, the macro isn't
1175 * "re-opened" as it is in macro_text. Also, these macros have a fixed
1176 * number of parameters.
1186 macro_constant_delimited(MACRO_PROT_ARGS
)
1188 int lastarg
, flushed
, j
, c
, maxargs
, argc
,
1190 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
1198 * Maximum arguments per macro. Some of these have none and
1199 * exit as soon as they're parsed.
1216 * Whether to ignore delimiter characters. `Pf' accepts its
1217 * first token as a parameter no matter what it looks like (if
1231 * Whether to ignore arguments: `St', for example, handles its
1232 * argument-like parameters as regular parameters.
1247 for ( ; argc
< MDOC_LINEARG_MAX
; argc
++) {
1249 c
= mdoc_argv(mdoc
, line
, tok
,
1250 &argv
[argc
], pos
, buf
);
1253 if (ARGV_WORD
== c
) {
1256 } else if (ARGV_ARG
== c
)
1258 mdoc_argv_free(argc
, argv
);
1262 if (MDOC_LINEARG_MAX
== argc
) {
1263 mdoc_argv_free(argc
- 1, argv
);
1264 return(perr(mdoc
, line
, ppos
, EARGVLIM
));
1267 c
= mdoc_elem_alloc(mdoc
, line
, ppos
,
1268 tok
, (size_t)argc
, argv
);
1270 mdoc_argv_free(argc
, argv
);
1275 mdoc
->next
= MDOC_NEXT_CHILD
;
1277 for (j
= 0; /* No sentinel. */; j
++) {
1280 if (j
== maxargs
&& ! flushed
) {
1281 if ( ! rewind_elem(mdoc
, tok
))
1286 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1287 assert(ARGS_PHRASE
!= c
);
1289 if (ARGS_ERROR
== c
)
1291 if (ARGS_PUNCT
== c
)
1296 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1298 else if (MDOC_MAX
!= c
) {
1299 if ( ! flushed
&& ! rewind_elem(mdoc
, tok
))
1302 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1307 if ( ! flushed
&& mdoc_isdelim(p
) && ! igndelim
) {
1308 if ( ! rewind_elem(mdoc
, tok
))
1313 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1315 mdoc
->next
= MDOC_NEXT_SIBLING
;
1318 if ( ! flushed
&& ! rewind_elem(mdoc
, tok
))
1323 return(append_delims(mdoc
, line
, pos
, buf
));
1328 * A constant macro is the simplest classification. It spans an entire
1332 macro_constant(MACRO_PROT_ARGS
)
1335 struct mdoc_arg argv
[MDOC_LINEARG_MAX
];
1338 assert( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
));
1340 for (argc
= 0; argc
< MDOC_LINEARG_MAX
; argc
++) {
1342 c
= mdoc_argv(mdoc
, line
, tok
, &argv
[argc
], pos
, buf
);
1345 if (ARGV_WORD
== c
) {
1348 } else if (ARGV_ARG
== c
)
1351 mdoc_argv_free(argc
, argv
);
1355 if (MDOC_LINEARG_MAX
== argc
) {
1356 mdoc_argv_free(argc
- 1, argv
);
1357 return(perr(mdoc
, line
, ppos
, EARGVLIM
));
1360 c
= mdoc_elem_alloc(mdoc
, line
, ppos
,
1361 tok
, (size_t)argc
, argv
);
1363 mdoc_argv_free(argc
, argv
);
1368 mdoc
->next
= MDOC_NEXT_CHILD
;
1372 w
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1373 assert(ARGS_PHRASE
!= c
);
1375 if (ARGS_ERROR
== w
)
1380 c
= ARGS_QWORD
== w
? MDOC_MAX
:
1381 lookup(mdoc
, line
, la
, tok
, p
);
1383 if (MDOC_MAX
!= c
&& -1 != c
) {
1384 if ( ! rewind_elem(mdoc
, tok
))
1386 return(mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
));
1390 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
1392 mdoc
->next
= MDOC_NEXT_SIBLING
;
1395 return(rewind_elem(mdoc
, tok
));
1401 macro_obsolete(MACRO_PROT_ARGS
)
1404 return(pwarn(mdoc
, line
, ppos
, WOBS
));
1409 * This is called at the end of parsing. It must traverse up the tree,
1410 * closing out open [implicit] scopes. Obviously, open explicit scopes
1414 macro_end(struct mdoc
*mdoc
)
1416 struct mdoc_node
*n
;
1418 assert(mdoc
->first
);
1421 /* Scan for open explicit scopes. */
1423 n
= MDOC_VALID
& mdoc
->last
->flags
?
1424 mdoc
->last
->parent
: mdoc
->last
;
1426 for ( ; n
; n
= n
->parent
) {
1427 if (MDOC_BLOCK
!= n
->type
)
1429 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[n
->tok
].flags
))
1431 return(mdoc_nerr(mdoc
, n
,
1432 "macro scope still open on exit"));
1435 return(rewind_last(mdoc
, mdoc
->first
));