]> git.cameronkatri.com Git - mandoc.git/blob - man_macro.c
Removed forgotten printfs.
[mandoc.git] / man_macro.c
1 /* $Id: man_macro.c,v 1.13 2009/04/05 16:34:22 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include <assert.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "libman.h"
25
26 #define FL_NLINE (1 << 0)
27 #define FL_TLINE (1 << 1)
28
29 static int man_args(struct man *, int,
30 int *, char *, char **);
31
32 static int man_flags[MAN_MAX] = {
33 0, /* __ */
34 0, /* TH */
35 0, /* SH */
36 0, /* SS */
37 FL_TLINE, /* TP */
38 0, /* LP */
39 0, /* PP */
40 0, /* P */
41 0, /* IP */
42 0, /* HP */
43 FL_NLINE, /* SM */
44 FL_NLINE, /* SB */
45 FL_NLINE, /* BI */
46 FL_NLINE, /* IB */
47 FL_NLINE, /* BR */
48 FL_NLINE, /* RB */
49 FL_NLINE, /* R */
50 FL_NLINE, /* B */
51 FL_NLINE, /* I */
52 FL_NLINE, /* IR */
53 FL_NLINE, /* RI */
54 0, /* br */
55 0, /* na */
56 FL_NLINE, /* i */
57 };
58
59 int
60 man_macro(struct man *man, int tok, int line,
61 int ppos, int *pos, char *buf)
62 {
63 int w, la;
64 char *p;
65 struct man_node *n;
66
67 if ( ! man_elem_alloc(man, line, ppos, tok))
68 return(0);
69 n = man->last;
70 man->next = MAN_NEXT_CHILD;
71
72 for (;;) {
73 la = *pos;
74 w = man_args(man, line, pos, buf, &p);
75
76 if (-1 == w)
77 return(0);
78 if (0 == w)
79 break;
80
81 if ( ! man_word_alloc(man, line, la, p))
82 return(0);
83 man->next = MAN_NEXT_SIBLING;
84 }
85
86 if (n == man->last && (FL_NLINE & man_flags[tok])) {
87 if (MAN_NLINE & man->flags)
88 return(man_verr(man, line, ppos,
89 "next-line scope already open"));
90 man->flags |= MAN_NLINE;
91 return(1);
92 }
93
94 if (FL_TLINE & man_flags[tok]) {
95 if (MAN_NLINE & man->flags)
96 return(man_verr(man, line, ppos,
97 "next-line scope already open"));
98 man->flags |= MAN_NLINE;
99 return(1);
100 }
101
102 /*
103 * Note that when TH is pruned, we'll be back at the root, so
104 * make sure that we don't clobber as its sibling.
105 */
106
107 for ( ; man->last; man->last = man->last->parent) {
108 if (man->last == n)
109 break;
110 if (man->last->type == MAN_ROOT)
111 break;
112 if ( ! man_valid_post(man))
113 return(0);
114 if ( ! man_action_post(man))
115 return(0);
116 }
117
118 assert(man->last);
119
120 /*
121 * Same here regarding whether we're back at the root.
122 */
123
124 if (man->last->type != MAN_ROOT && ! man_valid_post(man))
125 return(0);
126 if (man->last->type != MAN_ROOT && ! man_action_post(man))
127 return(0);
128 if (man->last->type != MAN_ROOT)
129 man->next = MAN_NEXT_SIBLING;
130
131 return(1);
132 }
133
134
135 int
136 man_macroend(struct man *m)
137 {
138
139 for ( ; m->last && m->last != m->first;
140 m->last = m->last->parent) {
141 if ( ! man_valid_post(m))
142 return(0);
143 if ( ! man_action_post(m))
144 return(0);
145 }
146 assert(m->last == m->first);
147
148 if ( ! man_valid_post(m))
149 return(0);
150 if ( ! man_action_post(m))
151 return(0);
152
153 return(1);
154 }
155
156
157 /* ARGSUSED */
158 static int
159 man_args(struct man *m, int line,
160 int *pos, char *buf, char **v)
161 {
162
163 if (0 == buf[*pos])
164 return(0);
165
166 /* First parse non-quoted strings. */
167
168 if ('\"' != buf[*pos]) {
169 *v = &buf[*pos];
170
171 while (buf[*pos]) {
172 if (' ' == buf[*pos])
173 if ('\\' != buf[*pos - 1])
174 break;
175 (*pos)++;
176 }
177
178 if (0 == buf[*pos])
179 return(1);
180
181 buf[(*pos)++] = 0;
182
183 if (0 == buf[*pos])
184 return(1);
185
186 while (buf[*pos] && ' ' == buf[*pos])
187 (*pos)++;
188
189 if (buf[*pos])
190 return(1);
191
192 if ( ! man_vwarn(m, line, *pos, "trailing spaces"))
193 return(-1);
194
195 return(1);
196 }
197
198 /*
199 * If we're a quoted string (and quoted strings are allowed),
200 * then parse ahead to the next quote. If none's found, it's an
201 * error. After, parse to the next word.
202 */
203
204 *v = &buf[++(*pos)];
205
206 while (buf[*pos] && '\"' != buf[*pos])
207 (*pos)++;
208
209 if (0 == buf[*pos]) {
210 if ( ! man_vwarn(m, line, *pos, "unterminated quote"))
211 return(-1);
212 return(1);
213 }
214
215 buf[(*pos)++] = 0;
216 if (0 == buf[*pos])
217 return(1);
218
219 while (buf[*pos] && ' ' == buf[*pos])
220 (*pos)++;
221
222 if (buf[*pos])
223 return(1);
224
225 if ( ! man_vwarn(m, line, *pos, "trailing spaces"))
226 return(-1);
227 return(1);
228 }