]>
git.cameronkatri.com Git - mandoc.git/blob - mdoc_macro.c
1 /* $Id: mdoc_macro.c,v 1.12 2009/06/12 09:18:00 kristaps Exp $ */
3 * Copyright (c) 2008, 2009 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 above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 /* FIXME: .Fl, .Ar, .Cd handling of `|'. */
41 #define REWIND_REWIND (1 << 0)
42 #define REWIND_NOHALT (1 << 1)
43 #define REWIND_HALT (1 << 2)
45 static int obsolete(MACRO_PROT_ARGS
);
46 static int blk_part_exp(MACRO_PROT_ARGS
);
47 static int in_line_eoln(MACRO_PROT_ARGS
);
48 static int in_line_argn(MACRO_PROT_ARGS
);
49 static int in_line(MACRO_PROT_ARGS
);
50 static int blk_full(MACRO_PROT_ARGS
);
51 static int blk_exp_close(MACRO_PROT_ARGS
);
52 static int blk_part_imp(MACRO_PROT_ARGS
);
54 static int phrase(struct mdoc
*, int, int, char *);
55 static int rew_dohalt(int, enum mdoc_type
,
56 const struct mdoc_node
*);
57 static int rew_alt(int);
58 static int rew_dobreak(int, const struct mdoc_node
*);
59 static int rew_elem(struct mdoc
*, int);
60 static int rew_impblock(struct mdoc
*, int, int, int);
61 static int rew_expblock(struct mdoc
*, int, int, int);
62 static int rew_subblock(enum mdoc_type
,
63 struct mdoc
*, int, int, int);
64 static int rew_last(struct mdoc
*, struct mdoc_node
*);
65 static int append_delims(struct mdoc
*, int, int *, char *);
66 static int lookup(struct mdoc
*, int, int, int, const char *);
67 static int pwarn(struct mdoc
*, int, int, enum mwarn
);
68 static int perr(struct mdoc
*, int, int, enum merr
);
69 static int swarn(struct mdoc
*, enum mdoc_type
, int, int,
70 const struct mdoc_node
*);
72 #define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t))
74 /* Central table of library: who gets parsed how. */
76 const struct mdoc_macro __mdoc_macros
[MDOC_MAX
] = {
78 { in_line_eoln
, MDOC_PROLOGUE
}, /* Dd */
79 { in_line_eoln
, MDOC_PROLOGUE
}, /* Dt */
80 { in_line_eoln
, MDOC_PROLOGUE
}, /* Os */
81 { blk_full
, 0 }, /* Sh */
82 { blk_full
, 0 }, /* Ss */
83 { in_line
, 0 }, /* Pp */
84 { blk_part_imp
, MDOC_PARSED
}, /* D1 */
85 { blk_part_imp
, MDOC_PARSED
}, /* Dl */
86 { blk_full
, MDOC_EXPLICIT
}, /* Bd */
87 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ed */
88 { blk_full
, MDOC_EXPLICIT
}, /* Bl */
89 { blk_exp_close
, MDOC_EXPLICIT
}, /* El */
90 { blk_full
, MDOC_PARSED
}, /* It */
91 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ad */
92 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* An */
93 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ar */
94 { in_line_eoln
, MDOC_CALLABLE
}, /* Cd */
95 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Cm */
96 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dv */
97 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Er */
98 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ev */
99 { in_line_eoln
, 0 }, /* Ex */
100 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fa */
101 { in_line_eoln
, 0 }, /* Fd */
102 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fl */
103 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fn */
104 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ft */
105 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ic */
106 { in_line_eoln
, 0 }, /* In */ /* FIXME: historic usage! */
107 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Li */
108 { in_line_eoln
, 0 }, /* Nd */
109 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nm */
110 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Op */
111 { obsolete
, 0 }, /* Ot */
112 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pa */
113 { in_line_eoln
, 0 }, /* Rv */
114 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* St */
115 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Va */
116 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Vt */
117 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Xr */
118 { in_line_eoln
, 0 }, /* %A */
119 { in_line_eoln
, 0 }, /* %B */
120 { in_line_eoln
, 0 }, /* %D */
121 { in_line_eoln
, 0 }, /* %I */
122 { in_line_eoln
, 0 }, /* %J */
123 { in_line_eoln
, 0 }, /* %N */
124 { in_line_eoln
, 0 }, /* %O */
125 { in_line_eoln
, 0 }, /* %P */
126 { in_line_eoln
, 0 }, /* %R */
127 { in_line_eoln
, 0 }, /* %T */
128 { in_line_eoln
, 0 }, /* %V */
129 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ac */
130 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Ao */
131 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Aq */
132 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* At */
133 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Bc */
134 { blk_full
, MDOC_EXPLICIT
}, /* Bf */
135 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bo */
136 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bq */
137 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bsx */
138 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bx */
139 { in_line_eoln
, 0 }, /* Db */
140 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Dc */
141 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Do */
142 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dq */
143 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ec */
144 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ef */
145 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Em */
146 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Eo */
147 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fx */
148 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ms */
149 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* No */
150 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ns */
151 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nx */
152 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ox */
153 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Pc */
154 { in_line_argn
, MDOC_PARSED
| MDOC_IGNDELIM
}, /* Pf */
155 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Po */
156 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pq */
157 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Qc */
158 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ql */
159 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Qo */
160 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Qq */
161 { blk_exp_close
, MDOC_EXPLICIT
}, /* Re */
162 { blk_full
, MDOC_EXPLICIT
}, /* Rs */
163 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Sc */
164 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* So */
165 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sq */
166 { in_line_eoln
, 0 }, /* Sm */
167 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sx */
168 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sy */
169 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Tn */
170 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ux */
171 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Xc */
172 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Xo */
173 { blk_full
, MDOC_EXPLICIT
| MDOC_CALLABLE
}, /* Fo */
174 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Fc */
175 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Oo */
176 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Oc */
177 { blk_full
, MDOC_EXPLICIT
}, /* Bk */
178 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ek */
179 { in_line_eoln
, 0 }, /* Bt */
180 { in_line_eoln
, 0 }, /* Hf */
181 { obsolete
, 0 }, /* Fr */
182 { in_line_eoln
, 0 }, /* Ud */
183 { in_line_eoln
, 0 }, /* Lb */
184 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ap */
185 { in_line
, 0 }, /* Lp */
186 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Lk */
187 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Mt */
188 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Brq */
189 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bro */
190 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Brc */
191 { in_line_eoln
, 0 }, /* %C */
192 { obsolete
, 0 }, /* Es */
193 { obsolete
, 0 }, /* En */
194 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dx */
195 { in_line_eoln
, 0 }, /* %Q */
198 const struct mdoc_macro
* const mdoc_macros
= __mdoc_macros
;
202 perr(struct mdoc
*mdoc
, int line
, int pos
, enum merr type
)
209 p
= "explicit scope still open on exit";
212 p
= "unterminated quotation";
215 p
= "closure has no prior context";
218 p
= "unexpect line arguments";
222 return(mdoc_perr(mdoc
, line
, pos
, p
));
227 pwarn(struct mdoc
*mdoc
, int line
, int pos
, enum mwarn type
)
234 p
= "ignoring empty element";
237 p
= "crufty end-of-line scope violation";
240 p
= "macro-like parameter";
243 p
= "macro marked obsolete";
247 return(mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
, p
));
252 swarn(struct mdoc
*mdoc
, enum mdoc_type type
,
253 int line
, int pos
, const struct mdoc_node
*p
)
255 const char *n
, *t
, *tt
;
273 n
= mdoc_macronames
[p
->tok
];
277 n
= mdoc_macronames
[p
->tok
];
281 n
= mdoc_macronames
[p
->tok
];
288 if ( ! (MDOC_IGN_SCOPE
& mdoc
->pflags
))
289 return(mdoc_perr(mdoc
, line
, pos
,
290 "%s scope breaks %s scope of %s",
292 return(mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
,
293 "%s scope breaks %s scope of %s",
299 * This is called at the end of parsing. It must traverse up the tree,
300 * closing out open [implicit] scopes. Obviously, open explicit scopes
304 mdoc_macroend(struct mdoc
*mdoc
)
308 /* Scan for open explicit scopes. */
310 n
= MDOC_VALID
& mdoc
->last
->flags
?
311 mdoc
->last
->parent
: mdoc
->last
;
313 for ( ; n
; n
= n
->parent
) {
314 if (MDOC_BLOCK
!= n
->type
)
316 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[n
->tok
].flags
))
318 return(nerr(mdoc
, n
, EOPEN
));
321 return(rew_last(mdoc
, mdoc
->first
));
325 lookup(struct mdoc
*mdoc
, int line
, int pos
, int from
, const char *p
)
329 res
= mdoc_hash_find(mdoc
->htab
, p
);
330 if (MDOC_PARSED
& mdoc_macros
[from
].flags
)
334 if ( ! pwarn(mdoc
, line
, pos
, WMACPARM
))
341 rew_last(struct mdoc
*mdoc
, struct mdoc_node
*to
)
345 mdoc
->next
= MDOC_NEXT_SIBLING
;
348 while (mdoc
->last
!= to
) {
349 if ( ! mdoc_valid_post(mdoc
))
351 if ( ! mdoc_action_post(mdoc
))
353 mdoc
->last
= mdoc
->last
->parent
;
357 if ( ! mdoc_valid_post(mdoc
))
359 return(mdoc_action_post(mdoc
));
408 * Rewind rules. This indicates whether to stop rewinding
409 * (REWIND_HALT) without touching our current scope, stop rewinding and
410 * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
411 * The scope-closing and so on occurs in the various rew_* routines.
414 rew_dohalt(int tok
, enum mdoc_type type
, const struct mdoc_node
*p
)
417 if (MDOC_ROOT
== p
->type
)
419 if (MDOC_VALID
& p
->flags
)
420 return(REWIND_NOHALT
);
444 assert(MDOC_HEAD
!= type
);
445 assert(MDOC_TAIL
!= type
);
446 if (type
== p
->type
&& tok
== p
->tok
)
447 return(REWIND_REWIND
);
450 assert(MDOC_TAIL
!= type
);
451 if (type
== p
->type
&& tok
== p
->tok
)
452 return(REWIND_REWIND
);
453 if (MDOC_BODY
== p
->type
&& MDOC_Bl
== p
->tok
)
457 if (type
== p
->type
&& tok
== p
->tok
)
458 return(REWIND_REWIND
);
461 assert(MDOC_TAIL
!= type
);
462 if (type
== p
->type
&& tok
== p
->tok
)
463 return(REWIND_REWIND
);
464 if (MDOC_BODY
== p
->type
&& MDOC_Sh
== p
->tok
)
498 if (type
== p
->type
&& tok
== p
->tok
)
499 return(REWIND_REWIND
);
502 /* Multi-line explicit scope close. */
534 if (type
== p
->type
&& rew_alt(tok
) == p
->tok
)
535 return(REWIND_REWIND
);
542 return(REWIND_NOHALT
);
547 * See if we can break an encountered scope (the rew_dohalt has returned
551 rew_dobreak(int tok
, const struct mdoc_node
*p
)
554 assert(MDOC_ROOT
!= p
->type
);
555 if (MDOC_ELEM
== p
->type
)
557 if (MDOC_TEXT
== p
->type
)
559 if (MDOC_VALID
& p
->flags
)
564 return(MDOC_It
== p
->tok
);
566 return(MDOC_Ss
== p
->tok
);
568 if (MDOC_Ss
== p
->tok
)
570 return(MDOC_Sh
== p
->tok
);
572 if (MDOC_It
== p
->tok
)
576 /* XXX - experimental! */
577 if (MDOC_Op
== p
->tok
)
584 if (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
)
585 return(p
->tok
== rew_alt(tok
));
586 else if (MDOC_BLOCK
== p
->type
)
589 return(tok
== p
->tok
);
594 rew_elem(struct mdoc
*mdoc
, int tok
)
599 if (MDOC_ELEM
!= n
->type
)
601 assert(MDOC_ELEM
== n
->type
);
602 assert(tok
== n
->tok
);
604 return(rew_last(mdoc
, n
));
609 rew_subblock(enum mdoc_type type
, struct mdoc
*mdoc
,
610 int tok
, int line
, int ppos
)
616 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
617 c
= rew_dohalt(tok
, type
, n
);
618 if (REWIND_HALT
== c
)
620 if (REWIND_REWIND
== c
)
622 else if (rew_dobreak(tok
, n
))
624 if ( ! swarn(mdoc
, type
, line
, ppos
, n
))
629 return(rew_last(mdoc
, n
));
634 rew_expblock(struct mdoc
*mdoc
, int tok
, int line
, int ppos
)
640 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
641 c
= rew_dohalt(tok
, MDOC_BLOCK
, n
);
642 if (REWIND_HALT
== c
)
643 return(perr(mdoc
, line
, ppos
, ENOCTX
));
644 if (REWIND_REWIND
== c
)
646 else if (rew_dobreak(tok
, n
))
648 if ( ! swarn(mdoc
, MDOC_BLOCK
, line
, ppos
, n
))
653 return(rew_last(mdoc
, n
));
658 rew_impblock(struct mdoc
*mdoc
, int tok
, int line
, int ppos
)
664 for (n
= mdoc
->last
; n
; n
= n
->parent
) {
665 c
= rew_dohalt(tok
, MDOC_BLOCK
, n
);
666 if (REWIND_HALT
== c
)
668 else if (REWIND_REWIND
== c
)
670 else if (rew_dobreak(tok
, n
))
672 if ( ! swarn(mdoc
, MDOC_BLOCK
, line
, ppos
, n
))
677 return(rew_last(mdoc
, n
));
682 append_delims(struct mdoc
*mdoc
, int line
, int *pos
, char *buf
)
692 c
= mdoc_args(mdoc
, line
, pos
, buf
, 0, &p
);
693 assert(ARGS_PHRASE
!= c
);
697 else if (ARGS_EOLN
== c
)
699 assert(mdoc_isdelim(p
));
700 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
702 mdoc
->next
= MDOC_NEXT_SIBLING
;
710 * Close out block partial/full explicit.
713 blk_exp_close(MACRO_PROT_ARGS
)
715 int j
, c
, lastarg
, maxargs
, flushed
;
727 if ( ! (MDOC_CALLABLE
& mdoc_macros
[tok
].flags
)) {
728 if (0 == buf
[*pos
]) {
729 if ( ! rew_subblock(MDOC_BODY
, mdoc
,
732 return(rew_expblock(mdoc
, tok
, line
, ppos
));
734 return(perr(mdoc
, line
, ppos
, ENOPARMS
));
737 if ( ! rew_subblock(MDOC_BODY
, mdoc
, tok
, line
, ppos
))
741 if ( ! mdoc_tail_alloc(mdoc
, line
,
744 mdoc
->next
= MDOC_NEXT_CHILD
;
747 for (lastarg
= ppos
, flushed
= j
= 0; ; j
++) {
750 if (j
== maxargs
&& ! flushed
) {
751 if ( ! rew_expblock(mdoc
, tok
, line
, ppos
))
756 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
765 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
767 else if (MDOC_MAX
!= c
) {
769 if ( ! rew_expblock(mdoc
, tok
,
774 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
779 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
781 mdoc
->next
= MDOC_NEXT_SIBLING
;
784 if ( ! flushed
&& ! rew_expblock(mdoc
, tok
, line
, ppos
))
789 return(append_delims(mdoc
, line
, pos
, buf
));
794 * In-line macros where reserved words cause scope close-reopen.
797 in_line(MACRO_PROT_ARGS
)
799 int la
, lastpunct
, c
, w
, cnt
, d
, nc
;
800 struct mdoc_arg
*arg
;
804 * Whether we allow ignored elements (those without content,
805 * usually because of reserved words) to squeak by.
826 for (la
= ppos
, arg
= NULL
;; ) {
828 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
830 if (ARGV_WORD
== c
) {
843 for (cnt
= 0, lastpunct
= 1;; ) {
845 w
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
854 /* Quoted words shouldn't be looked-up. */
856 c
= ARGS_QWORD
== w
? MDOC_MAX
:
857 lookup(mdoc
, line
, la
, tok
, p
);
860 * In this case, we've located a submacro and must
861 * execute it. Close out scope, if open. If no
862 * elements have been generated, either create one (nc)
863 * or raise a warning.
866 if (MDOC_MAX
!= c
&& -1 != c
) {
867 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
869 if (nc
&& 0 == cnt
) {
870 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
,
873 if ( ! rew_last(mdoc
, mdoc
->last
))
875 } else if ( ! nc
&& 0 == cnt
) {
877 if ( ! pwarn(mdoc
, line
, ppos
, WIGNE
))
880 c
= mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
);
885 return(append_delims(mdoc
, line
, pos
, buf
));
890 * Non-quote-enclosed punctuation. Set up our scope, if
891 * a word; rewind the scope, if a delimiter; then append
897 if (ARGS_QWORD
!= w
&& d
) {
898 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
901 } else if (lastpunct
) {
902 c
= mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
);
905 mdoc
->next
= MDOC_NEXT_CHILD
;
911 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
913 mdoc
->next
= MDOC_NEXT_SIBLING
;
916 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
920 * If no elements have been collected and we're allowed to have
921 * empties (nc), open a scope and close it out. Otherwise,
925 if (nc
&& 0 == cnt
) {
926 c
= mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
);
929 if ( ! rew_last(mdoc
, mdoc
->last
))
931 } else if ( ! nc
&& 0 == cnt
) {
933 if ( ! pwarn(mdoc
, line
, ppos
, WIGNE
))
939 return(append_delims(mdoc
, line
, pos
, buf
));
944 * Block full-explicit and full-implicit.
947 blk_full(MACRO_PROT_ARGS
)
949 int c
, lastarg
, reopen
;
950 struct mdoc_arg
*arg
;
953 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
)) {
954 if ( ! rew_subblock(MDOC_BODY
, mdoc
,
957 if ( ! rew_impblock(mdoc
, tok
, line
, ppos
))
961 for (arg
= NULL
;; ) {
963 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
965 if (ARGV_WORD
== c
) {
979 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, arg
))
981 mdoc
->next
= MDOC_NEXT_CHILD
;
983 if (0 == buf
[*pos
]) {
984 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
986 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
989 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
991 mdoc
->next
= MDOC_NEXT_CHILD
;
995 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
997 mdoc
->next
= MDOC_NEXT_CHILD
;
999 for (reopen
= 0;; ) {
1001 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1003 if (ARGS_ERROR
== c
)
1007 if (ARGS_PHRASE
== c
) {
1008 if (reopen
&& ! mdoc_head_alloc
1009 (mdoc
, line
, ppos
, tok
))
1011 mdoc
->next
= MDOC_NEXT_CHILD
;
1013 * Phrases are self-contained macro phrases used
1014 * in the columnar output of a macro. They need
1017 if ( ! phrase(mdoc
, line
, lastarg
, buf
))
1019 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1027 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1030 if (MDOC_MAX
== c
) {
1031 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1033 mdoc
->next
= MDOC_NEXT_SIBLING
;
1037 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1042 if (1 == ppos
&& ! append_delims(mdoc
, line
, pos
, buf
))
1044 if ( ! rew_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1047 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1049 mdoc
->next
= MDOC_NEXT_CHILD
;
1056 * Block partial-imnplicit scope.
1059 blk_part_imp(MACRO_PROT_ARGS
)
1063 struct mdoc_node
*blk
, *body
, *n
;
1065 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, NULL
))
1067 mdoc
->next
= MDOC_NEXT_CHILD
;
1070 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1072 mdoc
->next
= MDOC_NEXT_SIBLING
;
1074 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1076 mdoc
->next
= MDOC_NEXT_CHILD
;
1079 /* XXX - no known argument macros. */
1081 for (lastarg
= ppos
;; ) {
1083 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1084 assert(ARGS_PHRASE
!= c
);
1086 if (ARGS_ERROR
== c
)
1088 if (ARGS_PUNCT
== c
)
1093 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1095 else if (MDOC_MAX
== c
) {
1096 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1098 mdoc
->next
= MDOC_NEXT_SIBLING
;
1102 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1108 * Since we know what our context is, we can rewind directly to
1109 * it. This allows us to accomodate for our scope being
1110 * violated by another token.
1113 for (n
= mdoc
->last
; n
; n
= n
->parent
)
1117 if (NULL
== n
&& ! pwarn(mdoc
, body
->line
, body
->pos
, WIMPBRK
))
1120 if (n
&& ! rew_last(mdoc
, body
))
1123 if (1 == ppos
&& ! append_delims(mdoc
, line
, pos
, buf
))
1126 if (n
&& ! rew_last(mdoc
, blk
))
1134 * Block partial-explicit macros.
1137 blk_part_exp(MACRO_PROT_ARGS
)
1139 int lastarg
, flushed
, j
, c
, maxargs
;
1146 * Number of arguments (head arguments). Only `Eo' has these,
1158 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, NULL
))
1160 mdoc
->next
= MDOC_NEXT_CHILD
;
1163 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1165 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1168 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1171 } else if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1174 mdoc
->next
= MDOC_NEXT_CHILD
;
1176 for (j
= 0; ; j
++) {
1178 if (j
== maxargs
&& ! flushed
) {
1179 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1183 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1185 mdoc
->next
= MDOC_NEXT_CHILD
;
1188 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1189 assert(ARGS_PHRASE
!= c
);
1191 if (ARGS_ERROR
== c
)
1193 if (ARGS_PUNCT
== c
)
1198 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1200 else if (MDOC_MAX
!= c
) {
1202 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1206 if ( ! mdoc_body_alloc(mdoc
, line
,
1209 mdoc
->next
= MDOC_NEXT_CHILD
;
1211 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
,
1217 if ( ! flushed
&& mdoc_isdelim(p
)) {
1218 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1222 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1224 mdoc
->next
= MDOC_NEXT_CHILD
;
1227 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1229 mdoc
->next
= MDOC_NEXT_SIBLING
;
1233 if ( ! rew_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1235 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1237 mdoc
->next
= MDOC_NEXT_CHILD
;
1242 return(append_delims(mdoc
, line
, pos
, buf
));
1247 * In-line macros where reserved words signal closure of the macro.
1248 * Macros also have a fixed number of arguments.
1251 in_line_argn(MACRO_PROT_ARGS
)
1253 int lastarg
, flushed
, j
, c
, maxargs
;
1254 struct mdoc_arg
*arg
;
1259 * Fixed maximum arguments per macro. Some of these have none
1260 * and close as soon as the invocation is parsed.
1278 for (lastarg
= ppos
, arg
= NULL
;; ) {
1280 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
1282 if (ARGV_WORD
== c
) {
1292 mdoc_argv_free(arg
);
1296 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
))
1298 mdoc
->next
= MDOC_NEXT_CHILD
;
1300 for (flushed
= j
= 0; ; j
++) {
1303 if (j
== maxargs
&& ! flushed
) {
1304 if ( ! rew_elem(mdoc
, tok
))
1309 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1311 if (ARGS_ERROR
== c
)
1313 if (ARGS_PUNCT
== c
)
1318 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1320 else if (MDOC_MAX
!= c
) {
1321 if ( ! flushed
&& ! rew_elem(mdoc
, tok
))
1324 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1329 if ( ! (MDOC_IGNDELIM
& mdoc_macros
[tok
].flags
) &&
1330 ! flushed
&& mdoc_isdelim(p
)) {
1331 if ( ! rew_elem(mdoc
, tok
))
1336 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1338 mdoc
->next
= MDOC_NEXT_SIBLING
;
1341 if ( ! flushed
&& ! rew_elem(mdoc
, tok
))
1346 return(append_delims(mdoc
, line
, pos
, buf
));
1351 * In-line macro that spans an entire line. May be callable, but has no
1352 * subsequent parsed arguments.
1355 in_line_eoln(MACRO_PROT_ARGS
)
1358 struct mdoc_arg
*arg
;
1361 assert( ! (MDOC_PARSED
& mdoc_macros
[tok
].flags
));
1367 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
1369 if (ARGV_WORD
== c
) {
1378 mdoc_argv_free(arg
);
1382 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
))
1385 mdoc
->next
= MDOC_NEXT_CHILD
;
1389 w
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1391 if (ARGS_ERROR
== w
)
1396 c
= ARGS_QWORD
== w
? MDOC_MAX
:
1397 lookup(mdoc
, line
, la
, tok
, p
);
1399 if (MDOC_MAX
!= c
&& -1 != c
) {
1400 if ( ! rew_elem(mdoc
, tok
))
1402 return(mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
));
1406 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
1408 mdoc
->next
= MDOC_NEXT_SIBLING
;
1411 return(rew_elem(mdoc
, tok
));
1417 obsolete(MACRO_PROT_ARGS
)
1420 return(pwarn(mdoc
, line
, ppos
, WOBS
));
1425 phrase(struct mdoc
*mdoc
, int line
, int ppos
, char *buf
)
1427 int i
, la
, c
, quoted
;
1430 * Parse over words in a phrase. We have to handle this
1431 * specially because we assume no calling context -- in normal
1432 * circumstances, we switch argument parsing based on whether
1433 * the parent macro accepts quotes, tabs, etc. Here, anything
1437 for (i
= ppos
; buf
[i
]; ) {
1438 assert(' ' != buf
[i
]);
1443 * Read to next token. If quoted (check not escaped),
1444 * scan ahead to next unescaped quote. If not quoted or
1445 * escape-quoted, then scan ahead to next space.
1448 if ((i
&& '\"' == buf
[i
] && '\\' != buf
[i
- 1]) ||
1449 (0 == i
&& '\"' == buf
[i
])) {
1450 for (la
= ++i
; buf
[i
]; i
++)
1453 else if ('\\' != buf
[i
- 1])
1456 return(perr(mdoc
, line
, la
, EQUOT
));
1459 for ( ; buf
[i
]; i
++)
1460 if (i
&& ' ' == buf
[i
]) {
1461 if ('\\' != buf
[i
- 1])
1463 } else if (' ' == buf
[i
])
1466 /* If not end-of-line, terminate argument. */
1471 /* Read to next argument. */
1473 for ( ; buf
[i
] && ' ' == buf
[i
]; i
++)
1477 * If we're a non-quoted string, try to look up the
1478 * value as a macro and execute it, if found.
1481 c
= quoted
? MDOC_MAX
:
1482 mdoc_hash_find(mdoc
->htab
, &buf
[la
]);
1484 if (MDOC_MAX
!= c
) {
1485 if ( ! mdoc_macro(mdoc
, c
, line
, la
, &i
, buf
))
1487 return(append_delims(mdoc
, line
, &i
, buf
));
1490 /* A regular word or quoted string. */
1492 if ( ! mdoc_word_alloc(mdoc
, line
, la
, &buf
[la
]))
1494 mdoc
->next
= MDOC_NEXT_SIBLING
;