]>
git.cameronkatri.com Git - mandoc.git/blob - mdoc_macro.c
1 /* $Id: mdoc_macro.c,v 1.6 2009/04/02 06:51:44 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.
27 /* FIXME: .Fl, .Ar, .Cd handling of `|'. */
43 #define REWIND_REWIND (1 << 0)
44 #define REWIND_NOHALT (1 << 1)
45 #define REWIND_HALT (1 << 2)
47 static int obsolete(MACRO_PROT_ARGS
);
48 static int blk_part_exp(MACRO_PROT_ARGS
);
49 static int in_line_eoln(MACRO_PROT_ARGS
);
50 static int in_line_argn(MACRO_PROT_ARGS
);
51 static int in_line(MACRO_PROT_ARGS
);
52 static int blk_full(MACRO_PROT_ARGS
);
53 static int blk_exp_close(MACRO_PROT_ARGS
);
54 static int blk_part_imp(MACRO_PROT_ARGS
);
56 static int phrase(struct mdoc
*, int, int, char *);
57 static int rew_dohalt(int, enum mdoc_type
,
58 const struct mdoc_node
*);
59 static int rew_alt(int);
60 static int rew_dobreak(int, const struct mdoc_node
*);
61 static int rew_elem(struct mdoc
*, int);
62 static int rew_impblock(struct mdoc
*, int, int, int);
63 static int rew_expblock(struct mdoc
*, int, int, int);
64 static int rew_subblock(enum mdoc_type
,
65 struct mdoc
*, int, int, int);
66 static int rew_last(struct mdoc
*, struct mdoc_node
*);
67 static int append_delims(struct mdoc
*, int, int *, char *);
68 static int lookup(struct mdoc
*, int, int, int, const char *);
69 static int pwarn(struct mdoc
*, int, int, enum mwarn
);
70 static int perr(struct mdoc
*, int, int, enum merr
);
71 static int swarn(struct mdoc
*, enum mdoc_type
, int, int,
72 const struct mdoc_node
*);
74 #define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t))
76 /* Central table of library: who gets parsed how. */
78 const struct mdoc_macro __mdoc_macros
[MDOC_MAX
] = {
80 { in_line_eoln
, MDOC_PROLOGUE
}, /* Dd */
81 { in_line_eoln
, MDOC_PROLOGUE
}, /* Dt */
82 { in_line_eoln
, MDOC_PROLOGUE
}, /* Os */
83 { blk_full
, 0 }, /* Sh */
84 { blk_full
, 0 }, /* Ss */
85 { in_line
, 0 }, /* Pp */
86 { blk_part_imp
, MDOC_PARSED
}, /* D1 */
87 { blk_part_imp
, MDOC_PARSED
}, /* Dl */
88 { blk_full
, MDOC_EXPLICIT
}, /* Bd */
89 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ed */
90 { blk_full
, MDOC_EXPLICIT
}, /* Bl */
91 { blk_exp_close
, MDOC_EXPLICIT
}, /* El */
92 { blk_full
, MDOC_PARSED
}, /* It */
93 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ad */
94 { in_line
, MDOC_PARSED
}, /* An */
95 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ar */
96 { in_line_eoln
, MDOC_CALLABLE
}, /* Cd */
97 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Cm */
98 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dv */
99 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Er */
100 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ev */
101 { in_line_eoln
, 0 }, /* Ex */
102 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fa */
103 { in_line_eoln
, 0 }, /* Fd */
104 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fl */
105 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fn */
106 { in_line
, MDOC_PARSED
}, /* Ft */
107 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ic */
108 { in_line_eoln
, 0 }, /* In */
109 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Li */
110 { in_line_eoln
, 0 }, /* Nd */
111 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nm */
112 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Op */
113 { obsolete
, 0 }, /* Ot */
114 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pa */
115 { in_line_eoln
, 0 }, /* Rv */
116 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* St */
117 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Va */
118 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Vt */
119 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Xr */
120 { in_line_eoln
, 0 }, /* %A */
121 { in_line_eoln
, 0 }, /* %B */
122 { in_line_eoln
, 0 }, /* %D */
123 { in_line_eoln
, 0 }, /* %I */
124 { in_line_eoln
, 0 }, /* %J */
125 { in_line_eoln
, 0 }, /* %N */
126 { in_line_eoln
, 0 }, /* %O */
127 { in_line_eoln
, 0 }, /* %P */
128 { in_line_eoln
, 0 }, /* %R */
129 { in_line_eoln
, 0 }, /* %T */
130 { in_line_eoln
, 0 }, /* %V */
131 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ac */
132 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Ao */
133 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Aq */
134 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* At */
135 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Bc */
136 { blk_full
, MDOC_EXPLICIT
}, /* Bf */
137 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bo */
138 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bq */
139 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bsx */
140 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Bx */
141 { in_line_eoln
, 0 }, /* Db */
142 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Dc */
143 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Do */
144 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dq */
145 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Ec */
146 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ef */
147 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Em */
148 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Eo */
149 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Fx */
150 { in_line
, MDOC_PARSED
}, /* Ms */
151 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* No */
152 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ns */
153 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Nx */
154 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ox */
155 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Pc */
156 { in_line_argn
, MDOC_PARSED
| MDOC_IGNDELIM
}, /* Pf */
157 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Po */
158 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Pq */
159 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Qc */
160 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ql */
161 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Qo */
162 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Qq */
163 { blk_exp_close
, MDOC_EXPLICIT
}, /* Re */
164 { blk_full
, MDOC_EXPLICIT
}, /* Rs */
165 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Sc */
166 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* So */
167 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sq */
168 { in_line_eoln
, 0 }, /* Sm */
169 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sx */
170 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Sy */
171 { in_line
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Tn */
172 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ux */
173 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Xc */
174 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Xo */
175 { blk_full
, MDOC_EXPLICIT
| MDOC_CALLABLE
}, /* Fo */
176 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Fc */
177 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Oo */
178 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Oc */
179 { blk_full
, MDOC_EXPLICIT
}, /* Bk */
180 { blk_exp_close
, MDOC_EXPLICIT
}, /* Ek */
181 { in_line_eoln
, 0 }, /* Bt */
182 { in_line_eoln
, 0 }, /* Hf */
183 { obsolete
, 0 }, /* Fr */
184 { in_line_eoln
, 0 }, /* Ud */
185 { in_line_eoln
, 0 }, /* Lb */
186 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Ap */
187 { in_line
, 0 }, /* Lp */
188 { in_line
, MDOC_PARSED
}, /* Lk */
189 { in_line
, MDOC_PARSED
}, /* Mt */
190 { blk_part_imp
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Brq */
191 { blk_part_exp
, MDOC_CALLABLE
| MDOC_PARSED
| MDOC_EXPLICIT
}, /* Bro */
192 { blk_exp_close
, MDOC_EXPLICIT
| MDOC_CALLABLE
| MDOC_PARSED
}, /* Brc */
193 { in_line_eoln
, 0 }, /* %C */
194 { obsolete
, 0 }, /* Es */
195 { obsolete
, 0 }, /* En */
196 { in_line_argn
, MDOC_CALLABLE
| MDOC_PARSED
}, /* Dx */
197 { in_line_eoln
, 0 }, /* %Q */
200 const struct mdoc_macro
* const mdoc_macros
= __mdoc_macros
;
204 perr(struct mdoc
*mdoc
, int line
, int pos
, enum merr type
)
211 p
= "explicit scope still open on exit";
214 p
= "unterminated quotation";
217 p
= "closure has no prior context";
220 p
= "unexpect line arguments";
224 return(mdoc_perr(mdoc
, line
, pos
, p
));
229 pwarn(struct mdoc
*mdoc
, int line
, int pos
, enum mwarn type
)
236 p
= "ignoring empty element";
239 p
= "crufty end-of-line scope violation";
242 p
= "macro-like parameter";
245 p
= "macro marked obsolete";
249 return(mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
, p
));
254 swarn(struct mdoc
*mdoc
, enum mdoc_type type
,
255 int line
, int pos
, const struct mdoc_node
*p
)
257 const char *n
, *t
, *tt
;
275 n
= mdoc_macronames
[p
->tok
];
279 n
= mdoc_macronames
[p
->tok
];
283 n
= mdoc_macronames
[p
->tok
];
290 if ( ! (MDOC_IGN_SCOPE
& mdoc
->pflags
))
291 return(mdoc_perr(mdoc
, line
, pos
,
292 "%s scope breaks %s scope of %s",
294 return(mdoc_pwarn(mdoc
, line
, pos
, WARN_SYNTAX
,
295 "%s scope breaks %s scope of %s",
301 * This is called at the end of parsing. It must traverse up the tree,
302 * closing out open [implicit] scopes. Obviously, open explicit scopes
306 mdoc_macroend(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_hash_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
, cnt
, d
, nc
;
802 struct mdoc_arg
*arg
;
806 * Whether we allow ignored elements (those without content,
807 * 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 mdoc
->next
= MDOC_NEXT_SIBLING
;
874 } else if ( ! nc
&& 0 == cnt
)
875 if ( ! pwarn(mdoc
, line
, ppos
, WIGNE
))
877 c
= mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
);
882 return(append_delims(mdoc
, line
, pos
, buf
));
887 * Non-quote-enclosed punctuation. Set up our scope, if
888 * a word; rewind the scope, if a delimiter; then append
894 if (ARGS_QWORD
!= w
&& d
) {
895 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
898 } else if (lastpunct
) {
899 c
= mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
);
902 mdoc
->next
= MDOC_NEXT_CHILD
;
908 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
910 mdoc
->next
= MDOC_NEXT_SIBLING
;
913 if (0 == lastpunct
&& ! rew_elem(mdoc
, tok
))
917 * If no elements have been collected and we're allowed to have
918 * empties (nc), open a scope and close it out. Otherwise,
922 if (nc
&& 0 == cnt
) {
923 c
= mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
);
926 mdoc
->next
= MDOC_NEXT_SIBLING
;
927 } else if ( ! nc
&& 0 == cnt
)
928 if ( ! pwarn(mdoc
, line
, ppos
, WIGNE
))
933 return(append_delims(mdoc
, line
, pos
, buf
));
938 * Block full-explicit and full-implicit.
941 blk_full(MACRO_PROT_ARGS
)
943 int c
, lastarg
, reopen
;
944 struct mdoc_arg
*arg
;
947 if ( ! (MDOC_EXPLICIT
& mdoc_macros
[tok
].flags
)) {
948 if ( ! rew_subblock(MDOC_BODY
, mdoc
,
951 if ( ! rew_impblock(mdoc
, tok
, line
, ppos
))
955 for (arg
= NULL
;; ) {
957 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
959 if (ARGV_WORD
== c
) {
973 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, arg
))
975 mdoc
->next
= MDOC_NEXT_CHILD
;
977 if (0 == buf
[*pos
]) {
978 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
980 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
983 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
985 mdoc
->next
= MDOC_NEXT_CHILD
;
989 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
991 mdoc
->next
= MDOC_NEXT_CHILD
;
993 for (reopen
= 0;; ) {
995 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1001 if (ARGS_PHRASE
== c
) {
1002 if (reopen
&& ! mdoc_head_alloc
1003 (mdoc
, line
, ppos
, tok
))
1005 mdoc
->next
= MDOC_NEXT_CHILD
;
1007 * Phrases are self-contained macro phrases used
1008 * in the columnar output of a macro. They need
1011 if ( ! phrase(mdoc
, line
, lastarg
, buf
))
1013 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1021 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1024 if (MDOC_MAX
== c
) {
1025 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1027 mdoc
->next
= MDOC_NEXT_SIBLING
;
1031 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1036 if (1 == ppos
&& ! append_delims(mdoc
, line
, pos
, buf
))
1038 if ( ! rew_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1041 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1043 mdoc
->next
= MDOC_NEXT_CHILD
;
1050 * Block partial-imnplicit scope.
1053 blk_part_imp(MACRO_PROT_ARGS
)
1057 struct mdoc_node
*blk
, *body
, *n
;
1059 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, NULL
))
1061 mdoc
->next
= MDOC_NEXT_CHILD
;
1064 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1066 mdoc
->next
= MDOC_NEXT_SIBLING
;
1068 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1070 mdoc
->next
= MDOC_NEXT_CHILD
;
1073 /* XXX - no known argument macros. */
1075 for (lastarg
= ppos
;; ) {
1077 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1078 assert(ARGS_PHRASE
!= c
);
1080 if (ARGS_ERROR
== c
)
1082 if (ARGS_PUNCT
== c
)
1087 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1089 else if (MDOC_MAX
== c
) {
1090 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1092 mdoc
->next
= MDOC_NEXT_SIBLING
;
1096 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1102 * Since we know what our context is, we can rewind directly to
1103 * it. This allows us to accomodate for our scope being
1104 * violated by another token.
1107 for (n
= mdoc
->last
; n
; n
= n
->parent
)
1111 if (NULL
== n
&& ! pwarn(mdoc
, body
->line
, body
->pos
, WIMPBRK
))
1114 if (n
&& ! rew_last(mdoc
, body
))
1117 if (1 == ppos
&& ! append_delims(mdoc
, line
, pos
, buf
))
1120 if (n
&& ! rew_last(mdoc
, blk
))
1128 * Block partial-explicit macros.
1131 blk_part_exp(MACRO_PROT_ARGS
)
1133 int lastarg
, flushed
, j
, c
, maxargs
;
1140 * Number of arguments (head arguments). Only `Eo' has these,
1152 if ( ! mdoc_block_alloc(mdoc
, line
, ppos
, tok
, NULL
))
1154 mdoc
->next
= MDOC_NEXT_CHILD
;
1157 if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1159 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1162 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1165 } else if ( ! mdoc_head_alloc(mdoc
, line
, ppos
, tok
))
1168 mdoc
->next
= MDOC_NEXT_CHILD
;
1170 for (j
= 0; ; j
++) {
1172 if (j
== maxargs
&& ! flushed
) {
1173 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1177 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1179 mdoc
->next
= MDOC_NEXT_CHILD
;
1182 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1183 assert(ARGS_PHRASE
!= c
);
1185 if (ARGS_ERROR
== c
)
1187 if (ARGS_PUNCT
== c
)
1192 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1194 else if (MDOC_MAX
!= c
) {
1196 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1200 if ( ! mdoc_body_alloc(mdoc
, line
,
1203 mdoc
->next
= MDOC_NEXT_CHILD
;
1205 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
,
1211 if ( ! flushed
&& mdoc_isdelim(p
)) {
1212 if ( ! rew_subblock(MDOC_HEAD
, mdoc
,
1216 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1218 mdoc
->next
= MDOC_NEXT_CHILD
;
1221 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1223 mdoc
->next
= MDOC_NEXT_SIBLING
;
1227 if ( ! rew_subblock(MDOC_HEAD
, mdoc
, tok
, line
, ppos
))
1229 if ( ! mdoc_body_alloc(mdoc
, line
, ppos
, tok
))
1231 mdoc
->next
= MDOC_NEXT_CHILD
;
1236 return(append_delims(mdoc
, line
, pos
, buf
));
1241 * In-line macros where reserved words signal closure of the macro.
1242 * Macros also have a fixed number of arguments.
1245 in_line_argn(MACRO_PROT_ARGS
)
1247 int lastarg
, flushed
, j
, c
, maxargs
;
1248 struct mdoc_arg
*arg
;
1253 * Fixed maximum arguments per macro. Some of these have none
1254 * and close as soon as the invocation is parsed.
1272 for (lastarg
= ppos
, arg
= NULL
;; ) {
1274 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
1276 if (ARGV_WORD
== c
) {
1286 mdoc_argv_free(arg
);
1290 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
))
1292 mdoc
->next
= MDOC_NEXT_CHILD
;
1294 for (flushed
= j
= 0; ; j
++) {
1297 if (j
== maxargs
&& ! flushed
) {
1298 if ( ! rew_elem(mdoc
, tok
))
1303 c
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1305 if (ARGS_ERROR
== c
)
1307 if (ARGS_PUNCT
== c
)
1312 if (-1 == (c
= lookup(mdoc
, line
, lastarg
, tok
, p
)))
1314 else if (MDOC_MAX
!= c
) {
1315 if ( ! flushed
&& ! rew_elem(mdoc
, tok
))
1318 if ( ! mdoc_macro(mdoc
, c
, line
, lastarg
, pos
, buf
))
1323 if ( ! (MDOC_IGNDELIM
& mdoc_macros
[tok
].flags
) &&
1324 ! flushed
&& mdoc_isdelim(p
)) {
1325 if ( ! rew_elem(mdoc
, tok
))
1330 if ( ! mdoc_word_alloc(mdoc
, line
, lastarg
, p
))
1332 mdoc
->next
= MDOC_NEXT_SIBLING
;
1335 if ( ! flushed
&& ! rew_elem(mdoc
, tok
))
1340 return(append_delims(mdoc
, line
, pos
, buf
));
1345 * In-line macro that spans an entire line. May be callable, but has no
1346 * subsequent parsed arguments.
1349 in_line_eoln(MACRO_PROT_ARGS
)
1352 struct mdoc_arg
*arg
;
1355 assert( ! (MDOC_PARSED
& mdoc_macros
[tok
].flags
));
1361 c
= mdoc_argv(mdoc
, line
, tok
, &arg
, pos
, buf
);
1363 if (ARGV_WORD
== c
) {
1372 mdoc_argv_free(arg
);
1376 if ( ! mdoc_elem_alloc(mdoc
, line
, ppos
, tok
, arg
))
1379 mdoc
->next
= MDOC_NEXT_CHILD
;
1383 w
= mdoc_args(mdoc
, line
, pos
, buf
, tok
, &p
);
1385 if (ARGS_ERROR
== w
)
1390 c
= ARGS_QWORD
== w
? MDOC_MAX
:
1391 lookup(mdoc
, line
, la
, tok
, p
);
1393 if (MDOC_MAX
!= c
&& -1 != c
) {
1394 if ( ! rew_elem(mdoc
, tok
))
1396 return(mdoc_macro(mdoc
, c
, line
, la
, pos
, buf
));
1400 if ( ! mdoc_word_alloc(mdoc
, line
, la
, p
))
1402 mdoc
->next
= MDOC_NEXT_SIBLING
;
1405 return(rew_elem(mdoc
, tok
));
1411 obsolete(MACRO_PROT_ARGS
)
1414 return(pwarn(mdoc
, line
, ppos
, WOBS
));
1419 phrase(struct mdoc
*mdoc
, int line
, int ppos
, char *buf
)
1421 int i
, la
, c
, quoted
;
1424 * Parse over words in a phrase. We have to handle this
1425 * specially because we assume no calling context -- in normal
1426 * circumstances, we switch argument parsing based on whether
1427 * the parent macro accepts quotes, tabs, etc. Here, anything
1431 for (i
= ppos
; buf
[i
]; ) {
1432 assert(' ' != buf
[i
]);
1437 * Read to next token. If quoted (check not escaped),
1438 * scan ahead to next unescaped quote. If not quoted or
1439 * escape-quoted, then scan ahead to next space.
1442 if ((i
&& '\"' == buf
[i
] && '\\' != buf
[i
- 1]) ||
1443 (0 == i
&& '\"' == buf
[i
])) {
1444 for (la
= ++i
; buf
[i
]; i
++)
1447 else if ('\\' != buf
[i
- 1])
1450 return(perr(mdoc
, line
, la
, EQUOT
));
1453 for ( ; buf
[i
]; i
++)
1454 if (i
&& ' ' == buf
[i
]) {
1455 if ('\\' != buf
[i
- 1])
1457 } else if (' ' == buf
[i
])
1460 /* If not end-of-line, terminate argument. */
1465 /* Read to next argument. */
1467 for ( ; buf
[i
] && ' ' == buf
[i
]; i
++)
1471 * If we're a non-quoted string, try to look up the
1472 * value as a macro and execute it, if found.
1475 c
= quoted
? MDOC_MAX
:
1476 mdoc_hash_find(mdoc
->htab
, &buf
[la
]);
1478 if (MDOC_MAX
!= c
) {
1479 if ( ! mdoc_macro(mdoc
, c
, line
, la
, &i
, buf
))
1481 return(append_delims(mdoc
, line
, &i
, buf
));
1484 /* A regular word or quoted string. */
1486 if ( ! mdoc_word_alloc(mdoc
, line
, la
, &buf
[la
]))
1488 mdoc
->next
= MDOC_NEXT_SIBLING
;