]>
git.cameronkatri.com Git - mandoc.git/blob - macro.c
9c15e863c5854931c93f0b4ea6143a95da0d3c7b
1 /* $Id: macro.c,v 1.74 2009/03/21 09:20:15 kristaps Exp $ */
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
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.
28 * This has scanning/parsing routines, each of which extract a macro and
29 * its arguments and parameters, then know how to progress to the next
33 /* FIXME: .Fl, .Ar, .Cd handling of `|'. */
47 #define REWIND_REWIND (1 << 0)
48 #define REWIND_NOHALT (1 << 1)
49 #define REWIND_HALT (1 << 2)
51 static int obsolete(MACRO_PROT_ARGS
);
52 static int blk_part_exp(MACRO_PROT_ARGS
);
53 static int in_line_eoln(MACRO_PROT_ARGS
);
54 static int in_line_argn(MACRO_PROT_ARGS
);
55 static int in_line(MACRO_PROT_ARGS
);
56 static int blk_full(MACRO_PROT_ARGS
);
57 static int blk_exp_close(MACRO_PROT_ARGS
);
58 static int blk_part_imp(MACRO_PROT_ARGS
);
60 static int phrase(struct mdoc
*, int, int, char *);
61 static int rew_dohalt(int, enum mdoc_type
,
62 const struct mdoc_node
*);
63 static int rew_alt(int);
64 static int rew_dobreak(int, const struct mdoc_node
*);
65 static int rew_elem(struct mdoc
*, int);
66 static int rew_impblock(struct mdoc
*, int, int, int);
67 static int rew_expblock(struct mdoc
*, int, int, int);
68 static int rew_subblock(enum mdoc_type
,
69 struct mdoc
*, int, int, int);
70 static int rew_last(struct mdoc
*, struct mdoc_node
*);
71 static int append_delims(struct mdoc
*, int, int *, char *);
72 static int lookup(struct mdoc
*, int, int, int, const char *);
73 static int pwarn(struct mdoc
*, int, int, enum mwarn
);
74 static int perr(struct mdoc
*, int, int, enum merr
);
75 static int swarn(struct mdoc
*, enum mdoc_type
, int, int,
76 const struct mdoc_node
*);
78 #define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t))
80 /* Central table of library: who gets parsed how. */
82 const struct mdoc_macro __mdoc_macros
[MDOC_MAX
] = {
84 { in_line_eoln
, MDOC_PROLOGUE
}, /* Dd */
85 { in_line_eoln
, MDOC_PROLOGUE
}, /* Dt */
86 { in_line_eoln
, MDOC_PROLOGUE
}, /* Os */
87 { blk_full
, 0 }, /* Sh */
88 { blk_full
, 0 }, /* Ss */
89 { in_line
, 0 }, /* Pp */
90 { blk_part_imp
, MDOC_PARSED
}, /* D1 */
91 { blk_part_imp
, MDOC_PARSED
}, /* Dl */
92 { blk_full
, MDOC_EXPLICIT
}, /* Bd */
93 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ed */
94 { blk_full
, MDOC_EXPLICIT
}, /* Bl */
95 { blk_exp_close
, MDOC_EXPLICIT
}, /* El */
96 { blk_full
, MDOC_PARSED
}, /* It */
97 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ad */
98 { in_line
, MDOC_PARSED
}, /* An */
99 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ar */
100 { in_line_eoln
, MDOC_CALLABLE
}, /* Cd */
101 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Cm */
102 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dv */
103 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Er */
104 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ev */
105 { in_line_eoln
, 0 }, /* Ex */
106 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fa */
107 { in_line_eoln
, 0 }, /* Fd */
108 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fl */
109 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fn */
110 { in_line
, MDOC_PARSED
}, /* Ft */
111 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ic */
112 { in_line_eoln
, 0 }, /* In */
113 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Li */
114 { in_line_eoln
, 0 }, /* Nd */
115 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nm */
116 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Op */
117 { obsolete
, 0 }, /* Ot */
118 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pa */
119 { in_line_eoln
, 0 }, /* Rv */
120 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* St */
121 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Va */
122 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Vt */
123 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Xr */
124 { in_line_eoln
, 0 }, /* %A */
125 { in_line_eoln
, 0 }, /* %B */
126 { in_line_eoln
, 0 }, /* %D */
127 { in_line_eoln
, 0 }, /* %I */
128 { in_line_eoln
, 0 }, /* %J */
129 { in_line_eoln
, 0 }, /* %N */
130 { in_line_eoln
, 0 }, /* %O */
131 { in_line_eoln
, 0 }, /* %P */
132 { in_line_eoln
, 0 }, /* %R */
133 { in_line_eoln
, 0 }, /* %T */
134 { in_line_eoln
, 0 }, /* %V */
135 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ac */
136 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Ao */
137 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Aq */
138 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* At */
139 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Bc */
140 { blk_full
, MDOC_EXPLICIT
}, /* Bf */
141 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bo */
142 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bq */
143 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bsx */
144 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bx */
145 { in_line_eoln
, 0 }, /* Db */
146 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Dc */
147 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Do */
148 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dq */
149 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ec */
150 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ef */
151 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Em */
152 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Eo */
153 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fx */
154 { in_line
, MDOC_PARSED
}, /* Ms */
155 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* No */
156 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ns */
157 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nx */
158 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ox */
159 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Pc */
160 { in_line_argn
, MDOC_PARSED
| MDOC_IGNDELIM
}, /* Pf */
161 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Po */
162 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pq */
163 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Qc */
164 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ql */
165 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Qo */
166 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Qq */
167 { blk_exp_close
, MDOC_EXPLICIT
}, /* Re */
168 { blk_full
, MDOC_EXPLICIT
}, /* Rs */
169 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Sc */
170 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* So */
171 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sq */
172 { in_line_eoln
, 0 }, /* Sm */
173 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sx */
174 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sy */
175 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Tn */
176 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ux */
177 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Xc */
178 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Xo */
179 { blk_full
, MDOC_EXPLICIT
| MDOC_CALLABLE
}, /* Fo */
180 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Fc */
181 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Oo */
182 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Oc */
183 { blk_full
, MDOC_EXPLICIT
}, /* Bk */
184 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ek */
185 { in_line_eoln
, 0 }, /* Bt */
186 { in_line_eoln
, 0 }, /* Hf */
187 { obsolete
, 0 }, /* Fr */
188 { in_line_eoln
, 0 }, /* Ud */
189 { in_line_eoln
, 0 }, /* Lb */
190 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ap */
191 { in_line
, 0 }, /* Lp */
192 { in_line
, MDOC_PARSED
}, /* Lk */
193 { in_line
, MDOC_PARSED
}, /* Mt */
194 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Brq */
195 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bro */
196 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Brc */
197 { in_line_eoln
, 0 }, /* %C */
198 { obsolete
, 0 }, /* Es */
199 { obsolete
, 0 }, /* En */
200 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dx */
203 const struct mdoc_macro
* const mdoc_macros
= __mdoc_macros
;
207 perr(struct mdoc
*mdoc
, int line
, int pos
, enum merr type
)
214 p
= "explicit scope still open on exit";
217 p
= "unterminated quotation";
220 p
= "closure has no prior context";
223 p
= "unexpect line arguments";
227 return(mdoc_perr(mdoc
, line
, pos
, p
));
232 pwarn(struct mdoc
*mdoc
, int line
, int pos
, enum mwarn type
)
239 p
= "macro-like parameter";
242 p
= "macro marked obsolete";
246 return(mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
, p
));
251 swarn(struct mdoc
*mdoc
, enum mdoc_type type
,
252 int line
, int pos
, const struct mdoc_node
*p
)
254 const char *n
, *t
, *tt
;
272 n
= mdoc_macronames
[p
->tok
];
276 n
= mdoc_macronames
[p
->tok
];
280 n
= mdoc_macronames
[p
->tok
];
287 if ( ! (MDOC_IGN_SCOPE
& mdoc
->pflags
))
288 return(mdoc_perr(mdoc
, line
, pos
,
289 "%s scope breaks %s scope of %s",
291 return(mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
,
292 "%s scope breaks %s scope of %s",
298 * This is called at the end of parsing. It must traverse up the tree,
299 * closing out open [implicit] scopes. Obviously, open explicit scopes
303 macro_end(struct mdoc
*mdoc
)
310 /* Scan for open explicit scopes. */
312 n
= MDOC_VALID
& mdoc
->last
->flags
?
313 mdoc
->last
->parent
: mdoc
->last
;
315 for ( ; n
; n
= n
->parent
) {
316 if (MDOC_BLOCK
!= n
->type
)
318 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[n
->tok
].flags
))
320 return(nerr(mdoc
, n
, EOPEN
));
323 return(rew_last(mdoc
, mdoc
->first
));
327 lookup(struct mdoc
*mdoc
, int line
, int pos
, int from
, const char *p
)
331 res
= mdoc_tokhash_find(mdoc
->htab
, p
);
332 if (MDOC_PARSED
& mdoc_macros
[from
].flags
)
336 if ( ! pwarn(mdoc
, line
, pos
, WMACPARM
))
343 rew_last(struct mdoc
*mdoc
, struct mdoc_node
*to
)
347 mdoc
->next
= MDOC_NEXT_SIBLING
;
350 while (mdoc
->last
!= to
) {
351 if ( ! mdoc_valid_post(mdoc
))
353 if ( ! mdoc_action_post(mdoc
))
355 mdoc
->last
= mdoc
->last
->parent
;
359 if ( ! mdoc_valid_post(mdoc
))
361 return(mdoc_action_post(mdoc
));
410 * Rewind rules. This indicates whether to stop rewinding
411 * (REWIND_HALT) without touching our current scope, stop rewinding and
412 * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
413 * The scope-closing and so on occurs in the various rew_* routines.
416 rew_dohalt(int tok
, enum mdoc_type type
, const struct mdoc_node
*p
)
419 if (MDOC_ROOT
== p
->type
)
421 if (MDOC_VALID
& p
->flags
)
422 return(REWIND_NOHALT
);
446 assert(MDOC_HEAD
!= type
);
447 assert(MDOC_TAIL
!= type
);
448 if (type
== p
->type
&& tok
== p
->tok
)
449 return(REWIND_REWIND
);
452 assert(MDOC_TAIL
!= type
);
453 if (type
== p
->type
&& tok
== p
->tok
)
454 return(REWIND_REWIND
);
455 if (MDOC_BODY
== p
->type
&& MDOC_Bl
== p
->tok
)
459 if (type
== p
->type
&& tok
== p
->tok
)
460 return(REWIND_REWIND
);
463 assert(MDOC_TAIL
!= type
);
464 if (type
== p
->type
&& tok
== p
->tok
)
465 return(REWIND_REWIND
);
466 if (MDOC_BODY
== p
->type
&& MDOC_Sh
== p
->tok
)
500 if (type
== p
->type
&& tok
== p
->tok
)
501 return(REWIND_REWIND
);
504 /* Multi-line explicit scope close. */
536 if (type
== p
->type
&& rew_alt(tok
) == p
->tok
)
537 return(REWIND_REWIND
);
544 return(REWIND_NOHALT
);
549 * See if we can break an encountered scope (the rew_dohalt has returned
553 rew_dobreak(int tok
, const struct mdoc_node
*p
)
556 assert(MDOC_ROOT
!= p
->type
);
557 if (MDOC_ELEM
== p
->type
)
559 if (MDOC_TEXT
== p
->type
)
561 if (MDOC_VALID
& p
->flags
)
566 return(MDOC_It
== p
->tok
);
568 return(MDOC_Ss
== p
->tok
);
570 if (MDOC_Ss
== p
->tok
)
572 return(MDOC_Sh
== p
->tok
);
574 if (MDOC_It
== p
->tok
)
578 /* XXX - experimental! */
579 if (MDOC_Op
== p
->tok
)
586 if (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
)
587 return(p
->tok
== rew_alt(tok
));
588 else if (MDOC_BLOCK
== p
->type
)
591 return(tok
== p
->tok
);
596 rew_elem(struct mdoc
*mdoc
, int tok
)
601 if (MDOC_ELEM
!= n
->type
)
603 assert(MDOC_ELEM
== n
->type
);
604 assert(tok
== n
->tok
);
606 return(rew_last(mdoc
, n
));
611 rew_subblock(enum mdoc_type type
, struct mdoc
*mdoc
,
612 int tok
, int line
, int ppos
)
618 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
619 c
= rew_dohalt(tok
, type
, n
);
620 if (REWIND_HALT
== c
)
622 if (REWIND_REWIND
== c
)
624 else if (rew_dobreak(tok
, n
))
626 if ( ! swarn(mdoc
, type
, line
, ppos
, n
))
631 return(rew_last(mdoc
, n
));
636 rew_expblock(struct mdoc
*mdoc
, int tok
, int line
, int ppos
)
642 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
643 c
= rew_dohalt(tok
, MDOC_BLOCK
, n
);
644 if (REWIND_HALT
== c
)
645 return(perr(mdoc
, line
, ppos
, ENOCTX
));
646 if (REWIND_REWIND
== c
)
648 else if (rew_dobreak(tok
, n
))
650 if ( ! swarn(mdoc
, MDOC_BLOCK
, line
, ppos
, n
))
655 return(rew_last(mdoc
, n
));
660 rew_impblock(struct mdoc
*mdoc
, int tok
, int line
, int ppos
)
666 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
667 c
= rew_dohalt(tok
, MDOC_BLOCK
, n
);
668 if (REWIND_HALT
== c
)
670 else if (REWIND_REWIND
== c
)
672 else if (rew_dobreak(tok
, n
))
674 if ( ! swarn(mdoc
, MDOC_BLOCK
, line
, ppos
, n
))
679 return(rew_last(mdoc
, n
));
684 append_delims(struct mdoc
*mdoc
, int line
, int *pos
, char *buf
)
694 c
= mdoc_args(mdoc
, line
, pos
, buf
, 0, &p
);
695 assert(ARGS_PHRASE
!= c
);
699 else if (ARGS_EOLN
== c
)
701 assert(mdoc_isdelim(p
));
702 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
704 mdoc
->next
= MDOC_NEXT_SIBLING
;
712 * Close out block partial/full explicit.
715 blk_exp_close(MACRO_PROT_ARGS
)
717 int j
, c
, lastarg
, maxargs
, flushed
;
729 if ( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
)) {
730 if (0 == buf
[*pos
]) {
731 if ( ! rew_subblock(MDOC_BODY
, mdoc
,
734 return(rew_expblock(mdoc
, tok
, line
, ppos
));
736 return(perr(mdoc
, line
, ppos
, ENOPARMS
));
739 if ( ! rew_subblock(MDOC_BODY
, mdoc
, tok
, line
, ppos
))
743 if ( ! mdoc_tail_alloc(mdoc
, line
,
746 mdoc
->next
= MDOC_NEXT_CHILD
;
749 for (lastarg
= ppos
, flushed
= j
= 0; ; j
++) {
752 if (j
== maxargs
&& ! flushed
) {
753 if ( ! rew_expblock(mdoc
, tok
, line
, ppos
))
758 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
767 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
769 else if (MDOC_MAX
!= c
) {
771 if ( ! rew_expblock(mdoc
, tok
,
776 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
781 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
783 mdoc
->next
= MDOC_NEXT_SIBLING
;
786 if ( ! flushed
&& ! rew_expblock(mdoc
, tok
, line
, ppos
))
791 return(append_delims(mdoc
, line
, pos
, buf
));
796 * In-line macros where reserved words cause scope close-reopen.
799 in_line(MACRO_PROT_ARGS
)
801 int la
, lastpunct
, c
, w
;
802 struct mdoc_arg
*arg
;
805 for (la
= ppos
, arg
= NULL
;; ) {
807 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
809 if (ARGV_WORD
== c
) {
823 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
))
825 mdoc
->next
= MDOC_NEXT_CHILD
;
827 for (lastpunct
= 0;; ) {
829 w
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
838 /* Quoted words shouldn't be looked-up. */
840 c
= ARGS_QWORD
== w
? MDOC_MAX
:
841 lookup(mdoc
, line
, la
, tok
, p
);
843 /* MDOC_MAX (not a macro) or -1 (error). */
845 if (MDOC_MAX
!= c
&& -1 != c
) {
846 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
848 c
= mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
);
853 return(append_delims(mdoc
, line
, pos
, buf
));
857 /* Non-quote-enclosed punctuation. */
859 if (ARGS_QWORD
!= w
&& mdoc_isdelim(p
)) {
860 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
863 } else if (lastpunct
) {
864 c
= mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
);
869 mdoc
->next
= MDOC_NEXT_CHILD
;
873 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
875 mdoc
->next
= MDOC_NEXT_SIBLING
;
878 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
882 return(append_delims(mdoc
, line
, pos
, buf
));
887 * Block full-explicit and full-implicit.
890 blk_full(MACRO_PROT_ARGS
)
892 int c
, lastarg
, reopen
;
893 struct mdoc_arg
*arg
;
896 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
)) {
897 if ( ! rew_subblock(MDOC_BODY
, mdoc
,
900 if ( ! rew_impblock(mdoc
, tok
, line
, ppos
))
904 for (arg
= NULL
;; ) {
906 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
908 if (ARGV_WORD
== c
) {
922 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, arg
))
924 mdoc
->next
= MDOC_NEXT_CHILD
;
926 if (0 == buf
[*pos
]) {
927 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
929 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
932 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
934 mdoc
->next
= MDOC_NEXT_CHILD
;
938 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
940 mdoc
->next
= MDOC_NEXT_CHILD
;
942 for (reopen
= 0;; ) {
944 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
950 if (ARGS_PHRASE
== c
) {
951 if (reopen
&& ! mdoc_head_alloc
952 (mdoc
, line
, ppos
, tok
))
954 mdoc
->next
= MDOC_NEXT_CHILD
;
956 * Phrases are self-contained macro phrases used
957 * in the columnar output of a macro. They need
960 if ( ! phrase(mdoc
, line
, lastarg
, buf
))
962 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
970 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
974 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
976 mdoc
->next
= MDOC_NEXT_SIBLING
;
980 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
985 if (1 == ppos
&& ! append_delims(mdoc
, line
, pos
, buf
))
987 if ( ! rew_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
990 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
992 mdoc
->next
= MDOC_NEXT_CHILD
;
999 * Block partial-imnplicit scope.
1002 blk_part_imp(MACRO_PROT_ARGS
)
1006 struct mdoc_node
*blk
, *body
, *n
;
1008 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, NULL
))
1010 mdoc
->next
= MDOC_NEXT_CHILD
;
1013 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1015 mdoc
->next
= MDOC_NEXT_SIBLING
;
1017 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1019 mdoc
->next
= MDOC_NEXT_CHILD
;
1022 /* XXX - no known argument macros. */
1024 for (lastarg
= ppos
;; ) {
1026 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1027 assert(ARGS_PHRASE
!= c
);
1029 if (ARGS_ERROR
== c
)
1031 if (ARGS_PUNCT
== c
)
1036 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1038 else if (MDOC_MAX
== c
) {
1039 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1041 mdoc
->next
= MDOC_NEXT_SIBLING
;
1045 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1051 * Since we know what our context is, we can rewind directly to
1052 * it. This allows us to accomodate for our scope being
1053 * violated by another token.
1056 for (n
= mdoc
->last
; n
; n
= n
->parent
)
1062 mdoc
->next
= MDOC_NEXT_SIBLING
;
1065 if (1 == ppos
&& ! append_delims(mdoc
, line
, pos
, buf
))
1069 mdoc
->last
= mdoc
->last
->parent
;
1070 assert(mdoc
->last
== blk
);
1071 mdoc
->next
= MDOC_NEXT_SIBLING
;
1078 * Block partial-explicit macros.
1081 blk_part_exp(MACRO_PROT_ARGS
)
1083 int lastarg
, flushed
, j
, c
, maxargs
;
1090 * Number of arguments (head arguments). Only `Eo' has these,
1102 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, NULL
))
1104 mdoc
->next
= MDOC_NEXT_CHILD
;
1107 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1109 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1112 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1115 } else if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1118 mdoc
->next
= MDOC_NEXT_CHILD
;
1120 for (j
= 0; ; j
++) {
1122 if (j
== maxargs
&& ! flushed
) {
1123 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1127 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1129 mdoc
->next
= MDOC_NEXT_CHILD
;
1132 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1133 assert(ARGS_PHRASE
!= c
);
1135 if (ARGS_ERROR
== c
)
1137 if (ARGS_PUNCT
== c
)
1142 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1144 else if (MDOC_MAX
!= c
) {
1146 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1150 if ( ! mdoc_body_alloc(mdoc
, line
,
1153 mdoc
->next
= MDOC_NEXT_CHILD
;
1155 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
,
1161 if ( ! flushed
&& mdoc_isdelim(p
)) {
1162 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1166 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1168 mdoc
->next
= MDOC_NEXT_CHILD
;
1171 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1173 mdoc
->next
= MDOC_NEXT_SIBLING
;
1177 if ( ! rew_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1179 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1181 mdoc
->next
= MDOC_NEXT_CHILD
;
1186 return(append_delims(mdoc
, line
, pos
, buf
));
1191 * In-line macros where reserved words signal closure of the macro.
1192 * Macros also have a fixed number of arguments.
1195 in_line_argn(MACRO_PROT_ARGS
)
1197 int lastarg
, flushed
, j
, c
, maxargs
;
1198 struct mdoc_arg
*arg
;
1203 * Fixed maximum arguments per macro. Some of these have none
1204 * and close as soon as the invocation is parsed.
1222 for (lastarg
= ppos
, arg
= NULL
;; ) {
1224 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
1226 if (ARGV_WORD
== c
) {
1236 mdoc_argv_free(arg
);
1240 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
))
1242 mdoc
->next
= MDOC_NEXT_CHILD
;
1244 for (flushed
= j
= 0; ; j
++) {
1247 if (j
== maxargs
&& ! flushed
) {
1248 if ( ! rew_elem(mdoc
, tok
))
1253 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1255 if (ARGS_ERROR
== c
)
1257 if (ARGS_PUNCT
== c
)
1262 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1264 else if (MDOC_MAX
!= c
) {
1265 if ( ! flushed
&& ! rew_elem(mdoc
, tok
))
1268 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1273 if ( ! (MDOC_IGNDELIM
& mdoc_macros
[tok
].flags
) &&
1274 ! flushed
&& mdoc_isdelim(p
)) {
1275 if ( ! rew_elem(mdoc
, tok
))
1280 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1282 mdoc
->next
= MDOC_NEXT_SIBLING
;
1285 if ( ! flushed
&& ! rew_elem(mdoc
, tok
))
1290 return(append_delims(mdoc
, line
, pos
, buf
));
1295 * In-line macro that spans an entire line. May be callable, but has no
1296 * subsequent parsed arguments.
1299 in_line_eoln(MACRO_PROT_ARGS
)
1302 struct mdoc_arg
*arg
;
1305 assert( ! (MDOC_PARSED
& mdoc_macros
[tok
].flags
));
1311 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
1313 if (ARGV_WORD
== c
) {
1322 mdoc_argv_free(arg
);
1326 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
))
1329 mdoc
->next
= MDOC_NEXT_CHILD
;
1333 w
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1335 if (ARGS_ERROR
== w
)
1340 c
= ARGS_QWORD
== w
? MDOC_MAX
:
1341 lookup(mdoc
, line
, la
, tok
, p
);
1343 if (MDOC_MAX
!= c
&& -1 != c
) {
1344 if ( ! rew_elem(mdoc
, tok
))
1346 return(mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
));
1350 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
1352 mdoc
->next
= MDOC_NEXT_SIBLING
;
1355 return(rew_elem(mdoc
, tok
));
1361 obsolete(MACRO_PROT_ARGS
)
1364 return(pwarn(mdoc
, line
, ppos
, WOBS
));
1369 phrase(struct mdoc
*mdoc
, int line
, int ppos
, char *buf
)
1371 int i
, la
, c
, quoted
;
1374 * Parse over words in a phrase. We have to handle this
1375 * specially because we assume no calling context -- in normal
1376 * circumstances, we switch argument parsing based on whether
1377 * the parent macro accepts quotes, tabs, etc. Here, anything
1381 for (i
= ppos
; buf
[i
]; ) {
1382 assert(' ' != buf
[i
]);
1387 * Read to next token. If quoted (check not escaped),
1388 * scan ahead to next unescaped quote. If not quoted or
1389 * escape-quoted, then scan ahead to next space.
1392 if ((i
&& '\"' == buf
[i
] && '\\' != buf
[i
- 1]) ||
1393 (0 == i
&& '\"' == buf
[i
])) {
1394 for (la
= ++i
; buf
[i
]; i
++)
1397 else if ('\\' != buf
[i
- 1])
1400 return(perr(mdoc
, line
, la
, EQUOT
));
1403 for ( ; buf
[i
]; i
++)
1404 if (i
&& ' ' == buf
[i
]) {
1405 if ('\\' != buf
[i
- 1])
1407 } else if (' ' == buf
[i
])
1410 /* If not end-of-line, terminate argument. */
1415 /* Read to next argument. */
1417 for ( ; buf
[i
] && ' ' == buf
[i
]; i
++)
1421 * If we're a non-quoted string, try to look up the
1422 * value as a macro and execute it, if found.
1425 c
= quoted
? MDOC_MAX
:
1426 mdoc_tokhash_find(mdoc
->htab
, &buf
[la
]);
1428 if (MDOC_MAX
!= c
) {
1429 if ( ! mdoc_macro(mdoc
, c
, line
, la
, &i
, buf
))
1431 return(append_delims(mdoc
, line
, &i
, buf
));
1434 /* A regular word or quoted string. */
1436 if ( ! mdoc_word_alloc(mdoc
, line
, la
, &buf
[la
]))
1438 mdoc
->next
= MDOC_NEXT_SIBLING
;