Mercurial > ~dholland > hg > tradcpp > index.cgi
annotate directive.c @ 136:59680a727e9d
Improve previous.
Just in case we ever crash and reach cleanup() while processing an
-include foo option, take the array entry for it out of the array to
make sure it doesn't get freed twice. This case shouldn't be
reachable, but it's better to be safe.
author | David A. Holland |
---|---|
date | Tue, 09 Jul 2013 13:38:43 -0400 (2013-07-09) |
parents | 1cda505ddc78 |
children | a2c2fe8dbea3 d6e6b3940780 |
rev | line source |
---|---|
30 | 1 /*- |
99
60184aa42604
add 2013 to copyrights where it seems warranted
David A. Holland
parents:
90
diff
changeset
|
2 * Copyright (c) 2010, 2013 The NetBSD Foundation, Inc. |
30 | 3 * All rights reserved. |
4 * | |
5 * This code is derived from software contributed to The NetBSD Foundation | |
6 * by David A. Holland. | |
7 * | |
8 * Redistribution and use in source and binary forms, with or without | |
9 * modification, are permitted provided that the following conditions | |
10 * are met: | |
11 * 1. Redistributions of source code must retain the above copyright | |
12 * notice, this list of conditions and the following disclaimer. | |
13 * 2. Redistributions in binary form must reproduce the above copyright | |
14 * notice, this list of conditions and the following disclaimer in the | |
15 * documentation and/or other materials provided with the distribution. | |
16 * | |
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
27 * POSSIBILITY OF SUCH DAMAGE. | |
28 */ | |
29 | |
15 | 30 #include <assert.h> |
31 #include <stdbool.h> | |
32 #include <stdlib.h> | |
33 #include <string.h> | |
34 | |
35 #include "utils.h" | |
36 #include "mode.h" | |
37 #include "place.h" | |
38 #include "files.h" | |
39 #include "directive.h" | |
40 #include "macro.h" | |
41 #include "eval.h" | |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
42 #include "output.h" |
15 | 43 |
44 struct ifstate { | |
45 struct ifstate *prev; | |
46 struct place startplace; | |
47 bool curtrue; | |
48 bool evertrue; | |
49 bool seenelse; | |
50 }; | |
51 | |
52 static struct ifstate *ifstate; | |
53 | |
54 //////////////////////////////////////////////////////////// | |
55 // common parsing bits | |
56 | |
57 static | |
58 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
59 uncomment(char *buf) |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
60 { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
61 char *s, *t, *u = NULL; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
62 bool incomment = false; |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
63 bool inesc = false; |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
64 bool inquote = false; |
128
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
127
diff
changeset
|
65 char quote = '\0'; |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
66 |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
67 for (s = t = buf; *s; s++) { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
68 if (incomment) { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
69 if (s[0] == '*' && s[1] == '/') { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
70 s++; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
71 incomment = false; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
72 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
73 } else { |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
74 if (!inquote && s[0] == '/' && s[1] == '*') { |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
75 incomment = true; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
76 } else { |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
77 if (inesc) { |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
78 inesc = false; |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
79 } else if (s[0] == '\\') { |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
80 inesc = true; |
128
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
127
diff
changeset
|
81 } else if (!inquote && |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
127
diff
changeset
|
82 (s[0] == '"' || s[0] == '\'')) { |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
127
diff
changeset
|
83 inquote = true; |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
127
diff
changeset
|
84 quote = s[0]; |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
127
diff
changeset
|
85 } else if (inquote && s[0] == quote) { |
1cda505ddc78
Don't expand macros within character constants.
David A. Holland
parents:
127
diff
changeset
|
86 inquote = false; |
81
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
87 } |
27c9aafcaca1
Don't recognize comments within double-quote strings.
David A. Holland
parents:
77
diff
changeset
|
88 |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
89 if (t != s) { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
90 *t = *s; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
91 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
92 if (!strchr(ws, *t)) { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
93 u = t; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
94 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
95 t++; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
96 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
97 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
98 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
99 if (u) { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
100 /* end string after last non-whitespace char */ |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
101 u[1] = '\0'; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
102 } else { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
103 *t = '\0'; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
104 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
105 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
106 |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
107 static |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
108 void |
15 | 109 oneword(const char *what, struct place *p2, char *line) |
110 { | |
111 size_t pos; | |
112 | |
113 pos = strcspn(line, ws); | |
114 if (line[pos] != '\0') { | |
115 p2->column += pos; | |
116 complain(p2, "Garbage after %s argument", what); | |
117 complain_fail(); | |
118 line[pos] = '\0'; | |
119 } | |
120 } | |
121 | |
122 //////////////////////////////////////////////////////////// | |
123 // if handling | |
124 | |
125 static | |
126 struct ifstate * | |
127 ifstate_create(struct ifstate *prev, struct place *p, bool startstate) | |
128 { | |
129 struct ifstate *is; | |
130 | |
131 is = domalloc(sizeof(*is)); | |
132 is->prev = prev; | |
133 if (p != NULL) { | |
134 is->startplace = *p; | |
135 } else { | |
136 place_setbuiltin(&is->startplace, 1); | |
137 } | |
138 is->curtrue = startstate; | |
139 is->evertrue = is->curtrue; | |
140 is->seenelse = false; | |
141 return is; | |
142 } | |
143 | |
144 static | |
145 void | |
146 ifstate_destroy(struct ifstate *is) | |
147 { | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
148 dofree(is, sizeof(*is)); |
15 | 149 } |
150 | |
151 static | |
152 void | |
153 ifstate_push(struct place *p, bool startstate) | |
154 { | |
72 | 155 struct ifstate *newstate; |
156 | |
157 newstate = ifstate_create(ifstate, p, startstate); | |
158 if (!ifstate->curtrue) { | |
159 newstate->curtrue = false; | |
160 newstate->evertrue = true; | |
161 } | |
162 ifstate = newstate; | |
15 | 163 } |
164 | |
165 static | |
166 void | |
167 ifstate_pop(void) | |
168 { | |
169 struct ifstate *is; | |
170 | |
171 is = ifstate; | |
172 ifstate = ifstate->prev; | |
173 ifstate_destroy(is); | |
174 } | |
175 | |
176 static | |
177 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
178 d_if(struct place *p, struct place *p2, char *line) |
15 | 179 { |
180 char *expr; | |
181 bool val; | |
16 | 182 struct place p3 = *p2; |
82
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
183 size_t oldlen; |
15 | 184 |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
185 expr = macroexpand(p2, line, strlen(line), true); |
82
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
186 |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
187 oldlen = strlen(expr); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
188 uncomment(expr); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
189 /* trim to fit, so the malloc debugging won't complain */ |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
190 expr = dorealloc(expr, oldlen + 1, strlen(expr) + 1); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
191 |
127 | 192 if (ifstate->curtrue) { |
193 val = eval(&p3, expr); | |
194 } else { | |
195 val = 0; | |
196 } | |
15 | 197 ifstate_push(p, val); |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
198 dostrfree(expr); |
15 | 199 } |
200 | |
201 static | |
202 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
203 d_ifdef(struct place *p, struct place *p2, char *line) |
15 | 204 { |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
205 uncomment(line); |
15 | 206 oneword("#ifdef", p2, line); |
207 ifstate_push(p, macro_isdefined(line)); | |
208 } | |
209 | |
210 static | |
211 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
212 d_ifndef(struct place *p, struct place *p2, char *line) |
15 | 213 { |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
214 uncomment(line); |
15 | 215 oneword("#ifndef", p2, line); |
216 ifstate_push(p, !macro_isdefined(line)); | |
217 } | |
218 | |
219 static | |
220 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
221 d_elif(struct place *p, struct place *p2, char *line) |
15 | 222 { |
223 char *expr; | |
16 | 224 struct place p3 = *p2; |
82
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
225 size_t oldlen; |
15 | 226 |
227 if (ifstate->seenelse) { | |
228 complain(p, "#elif after #else"); | |
229 complain_fail(); | |
230 } | |
231 | |
232 if (ifstate->evertrue) { | |
233 ifstate->curtrue = false; | |
234 } else { | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
235 expr = macroexpand(p2, line, strlen(line), true); |
82
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
236 |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
237 oldlen = strlen(expr); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
238 uncomment(expr); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
239 /* trim to fit, so the malloc debugging won't complain */ |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
240 expr = dorealloc(expr, oldlen + 1, strlen(expr) + 1); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
241 |
16 | 242 ifstate->curtrue = eval(&p3, expr); |
15 | 243 ifstate->evertrue = ifstate->curtrue; |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
244 dostrfree(expr); |
15 | 245 } |
246 } | |
247 | |
248 static | |
249 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
250 d_else(struct place *p, struct place *p2, char *line) |
15 | 251 { |
103 | 252 (void)p2; |
253 (void)line; | |
254 | |
15 | 255 if (ifstate->seenelse) { |
256 complain(p, "Multiple #else directives in one conditional"); | |
257 complain_fail(); | |
258 } | |
259 | |
260 ifstate->curtrue = !ifstate->evertrue; | |
261 ifstate->evertrue = true; | |
262 ifstate->seenelse = true; | |
263 } | |
264 | |
265 static | |
266 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
267 d_endif(struct place *p, struct place *p2, char *line) |
15 | 268 { |
103 | 269 (void)p2; |
270 (void)line; | |
271 | |
15 | 272 if (ifstate->prev == NULL) { |
273 complain(p, "Unmatched #endif"); | |
274 complain_fail(); | |
275 } else { | |
276 ifstate_pop(); | |
277 } | |
278 } | |
279 | |
280 //////////////////////////////////////////////////////////// | |
281 // macros | |
282 | |
283 static | |
284 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
285 d_define(struct place *p, struct place *p2, char *line) |
15 | 286 { |
18 | 287 size_t pos, argpos; |
288 struct place p3, p4; | |
15 | 289 |
103 | 290 (void)p; |
291 | |
15 | 292 /* |
293 * line may be: | |
294 * macro expansion | |
295 * macro(arg, arg, ...) expansion | |
296 */ | |
297 | |
298 pos = strcspn(line, " \t\f\v("); | |
299 if (line[pos] == '(') { | |
18 | 300 line[pos++] = '\0'; |
301 argpos = pos; | |
15 | 302 pos = pos + strcspn(line+pos, "()"); |
303 if (line[pos] == '(') { | |
304 p2->column += pos; | |
305 complain(p2, "Left parenthesis in macro parameters"); | |
306 complain_fail(); | |
307 return; | |
308 } | |
309 if (line[pos] != ')') { | |
310 p2->column += pos; | |
311 complain(p2, "Unclosed macro parameter list"); | |
312 complain_fail(); | |
313 return; | |
314 } | |
18 | 315 line[pos++] = '\0'; |
36
a489cc223483
Don't demand space after the macro argument parenthesis.
David A. Holland
parents:
30
diff
changeset
|
316 #if 0 |
15 | 317 if (!strchr(ws, line[pos])) { |
318 p2->column += pos; | |
319 complain(p2, "Trash after macro parameter list"); | |
320 complain_fail(); | |
321 return; | |
322 } | |
36
a489cc223483
Don't demand space after the macro argument parenthesis.
David A. Holland
parents:
30
diff
changeset
|
323 #endif |
15 | 324 } else if (line[pos] == '\0') { |
18 | 325 argpos = 0; |
15 | 326 } else { |
327 line[pos++] = '\0'; | |
18 | 328 argpos = 0; |
15 | 329 } |
330 | |
331 pos += strspn(line+pos, ws); | |
332 | |
333 p3 = *p2; | |
18 | 334 p3.column += argpos; |
335 | |
336 p4 = *p2; | |
337 p4.column += pos; | |
338 | |
339 if (argpos) { | |
340 macro_define_params(p2, line, &p3, | |
341 line + argpos, &p4, | |
342 line + pos); | |
343 } else { | |
344 macro_define_plain(p2, line, &p4, line + pos); | |
345 } | |
15 | 346 } |
347 | |
348 static | |
349 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
350 d_undef(struct place *p, struct place *p2, char *line) |
15 | 351 { |
103 | 352 (void)p; |
353 | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
354 uncomment(line); |
15 | 355 oneword("#undef", p2, line); |
356 macro_undef(line); | |
357 } | |
358 | |
359 //////////////////////////////////////////////////////////// | |
360 // includes | |
361 | |
362 static | |
363 bool | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
364 tryinclude(struct place *p, char *line) |
15 | 365 { |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
366 size_t len; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
367 |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
368 len = strlen(line); |
15 | 369 if (len > 2 && line[0] == '"' && line[len-1] == '"') { |
370 line[len-1] = '\0'; | |
371 file_readquote(p, line+1); | |
62
90c6052410ce
Don't truncate the candidate include path strings.
David A. Holland
parents:
49
diff
changeset
|
372 line[len-1] = '"'; |
15 | 373 return true; |
374 } | |
375 if (len > 2 && line[0] == '<' && line[len-1] == '>') { | |
376 line[len-1] = '\0'; | |
377 file_readbracket(p, line+1); | |
62
90c6052410ce
Don't truncate the candidate include path strings.
David A. Holland
parents:
49
diff
changeset
|
378 line[len-1] = '>'; |
15 | 379 return true; |
380 } | |
381 return false; | |
382 } | |
383 | |
384 static | |
385 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
386 d_include(struct place *p, struct place *p2, char *line) |
15 | 387 { |
388 char *text; | |
82
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
389 size_t oldlen; |
15 | 390 |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
391 uncomment(line); |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
392 if (tryinclude(p, line)) { |
15 | 393 return; |
394 } | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
395 text = macroexpand(p2, line, strlen(line), false); |
82
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
396 |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
397 oldlen = strlen(text); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
398 uncomment(text); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
399 /* trim to fit, so the malloc debugging won't complain */ |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
400 text = dorealloc(text, oldlen + 1, strlen(text) + 1); |
05a94332f08b
In #if/#elif, prune comments *after* macro expansion.
David A. Holland
parents:
81
diff
changeset
|
401 |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
402 if (tryinclude(p, text)) { |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
403 dostrfree(text); |
15 | 404 return; |
405 } | |
90 | 406 complain(p, "Illegal #include directive"); |
407 complain(p, "Before macro expansion: #include %s", line); | |
408 complain(p, "After macro expansion: #include %s", text); | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
409 dostrfree(text); |
15 | 410 complain_fail(); |
411 } | |
412 | |
413 static | |
414 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
415 d_line(struct place *p, struct place *p2, char *line) |
15 | 416 { |
103 | 417 (void)p2; |
418 (void)line; | |
419 | |
15 | 420 /* XXX */ |
421 complain(p, "Sorry, no #line yet"); | |
422 } | |
423 | |
424 //////////////////////////////////////////////////////////// | |
425 // messages | |
426 | |
427 static | |
428 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
429 d_warning(struct place *p, struct place *p2, char *line) |
15 | 430 { |
431 char *msg; | |
432 | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
433 msg = macroexpand(p2, line, strlen(line), false); |
15 | 434 complain(p, "#warning: %s", msg); |
435 if (mode.werror) { | |
436 complain_fail(); | |
437 } | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
438 dostrfree(msg); |
15 | 439 } |
440 | |
441 static | |
442 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
443 d_error(struct place *p, struct place *p2, char *line) |
15 | 444 { |
445 char *msg; | |
446 | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
447 msg = macroexpand(p2, line, strlen(line), false); |
15 | 448 complain(p, "#error: %s", msg); |
449 complain_fail(); | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
450 dostrfree(msg); |
15 | 451 } |
452 | |
453 //////////////////////////////////////////////////////////// | |
454 // other | |
455 | |
456 static | |
457 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
458 d_pragma(struct place *p, struct place *p2, char *line) |
15 | 459 { |
103 | 460 (void)p2; |
461 | |
15 | 462 complain(p, "#pragma %s", line); |
463 complain_fail(); | |
464 } | |
465 | |
466 //////////////////////////////////////////////////////////// | |
467 // directive table | |
468 | |
469 static const struct { | |
470 const char *name; | |
471 bool ifskip; | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
472 void (*func)(struct place *, struct place *, char *line); |
15 | 473 } directives[] = { |
474 { "define", true, d_define }, | |
475 { "elif", false, d_elif }, | |
476 { "else", false, d_else }, | |
477 { "endif", false, d_endif }, | |
478 { "error", true, d_error }, | |
479 { "if", false, d_if }, | |
480 { "ifdef", false, d_ifdef }, | |
481 { "ifndef", false, d_ifndef }, | |
482 { "include", true, d_include }, | |
483 { "line", true, d_line }, | |
484 { "pragma", true, d_pragma }, | |
485 { "undef", true, d_undef }, | |
486 { "warning", true, d_warning }, | |
487 }; | |
488 static const unsigned numdirectives = HOWMANY(directives); | |
489 | |
490 static | |
491 void | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
492 directive_gotdirective(struct place *p, char *line) |
15 | 493 { |
494 struct place p2; | |
495 size_t len, skip; | |
496 unsigned i; | |
497 | |
498 p2 = *p; | |
499 for (i=0; i<numdirectives; i++) { | |
500 len = strlen(directives[i].name); | |
501 if (!strncmp(line, directives[i].name, len) && | |
502 strchr(ws, line[len])) { | |
503 if (directives[i].ifskip && !ifstate->curtrue) { | |
504 return; | |
505 } | |
506 skip = len + strspn(line+len, ws); | |
507 p2.column += skip; | |
508 line += skip; | |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
509 |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
510 len = strlen(line); |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
511 len = notrailingws(line, len); |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
512 if (len < strlen(line)) { |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
513 line[len] = '\0'; |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
514 } |
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
515 directives[i].func(p, &p2, line); |
15 | 516 return; |
517 } | |
518 } | |
83
3e505c16b0b0
Accept # by itself, including with a comment after it.
David A. Holland
parents:
82
diff
changeset
|
519 /* ugh. allow # by itself, including with a comment after it */ |
3e505c16b0b0
Accept # by itself, including with a comment after it.
David A. Holland
parents:
82
diff
changeset
|
520 uncomment(line); |
3e505c16b0b0
Accept # by itself, including with a comment after it.
David A. Holland
parents:
82
diff
changeset
|
521 if (line[0] == '\0') { |
3e505c16b0b0
Accept # by itself, including with a comment after it.
David A. Holland
parents:
82
diff
changeset
|
522 return; |
3e505c16b0b0
Accept # by itself, including with a comment after it.
David A. Holland
parents:
82
diff
changeset
|
523 } |
3e505c16b0b0
Accept # by itself, including with a comment after it.
David A. Holland
parents:
82
diff
changeset
|
524 |
15 | 525 skip = strcspn(line, ws); |
526 complain(p, "Unknown directive #%.*s", (int)skip, line); | |
527 complain_fail(); | |
528 } | |
529 | |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
530 /* |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
531 * Check for nested comment delimiters in LINE. |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
532 */ |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
533 static |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
534 size_t |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
535 directive_scancomments(const struct place *p, char *line, size_t len) |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
536 { |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
537 size_t pos; |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
538 bool incomment; |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
539 struct place p2; |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
540 |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
541 p2 = *p; |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
542 incomment = 0; |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
543 for (pos = 0; pos+1 < len; pos++) { |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
544 if (line[pos] == '/' && line[pos+1] == '*') { |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
545 if (incomment) { |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
546 complain(&p2, "Warning: %c%c within comment", |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
547 '/', '*'); |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
548 if (mode.werror) { |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
549 complain_failed(); |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
550 } |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
551 } else { |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
552 incomment = true; |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
553 } |
109 | 554 pos++; |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
555 } else if (line[pos] == '*' && line[pos+1] == '/') { |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
556 if (incomment) { |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
557 incomment = false; |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
558 } else { |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
559 /* stray end-comment; should we care? */ |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
560 } |
109 | 561 pos++; |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
562 } |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
563 if (line[pos] == '\n') { |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
564 p2.line++; |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
565 p2.column = 0; |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
566 } else { |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
567 p2.column++; |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
568 } |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
569 } |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
570 |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
571 /* multiline comments are supposed to arrive in a single buffer */ |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
572 assert(!incomment); |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
573 return len; |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
574 } |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
575 |
15 | 576 void |
577 directive_gotline(struct place *p, char *line, size_t len) | |
578 { | |
579 size_t skip; | |
580 | |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
581 if (warns.nestcomment) { |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
582 directive_scancomments(p, line, len); |
49
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
583 } |
8a204d153398
Intercept multiline comments earlier. Leave same-line comments alone.
David A. Holland
parents:
39
diff
changeset
|
584 |
66
f8507e5ed84c
Recognize directive lines only when the # is exactly in column 0.
David A. Holland
parents:
64
diff
changeset
|
585 /* check if we have a directive line (# exactly in column 0) */ |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
586 if (line[0] == '#') { |
66
f8507e5ed84c
Recognize directive lines only when the # is exactly in column 0.
David A. Holland
parents:
64
diff
changeset
|
587 skip = 1 + strspn(line + 1, ws); |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
588 assert(skip <= len); |
15 | 589 p->column += skip; |
64
f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
David A. Holland
parents:
62
diff
changeset
|
590 assert(line[len] == '\0'); |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
591 directive_gotdirective(p, line+skip /*, length = len-skip */); |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
592 p->column += len-skip; |
15 | 593 } else if (ifstate->curtrue) { |
77
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
594 macro_sendline(p, line, len); |
123168887da8
Clean out old not-really-working nested comment handling.
David A. Holland
parents:
72
diff
changeset
|
595 p->column += len; |
15 | 596 } |
597 } | |
598 | |
599 void | |
600 directive_goteof(struct place *p) | |
601 { | |
602 while (ifstate->prev != NULL) { | |
603 complain(p, "Missing #endif"); | |
604 complain(&ifstate->startplace, "...opened at this point"); | |
605 complain_failed(); | |
606 ifstate_pop(); | |
607 } | |
608 macro_sendeof(p); | |
609 } | |
610 | |
611 //////////////////////////////////////////////////////////// | |
612 // module initialization | |
613 | |
614 void | |
615 directive_init(void) | |
616 { | |
617 ifstate = ifstate_create(NULL, NULL, true); | |
618 } | |
619 | |
620 void | |
621 directive_cleanup(void) | |
622 { | |
623 assert(ifstate->prev == NULL); | |
624 ifstate_destroy(ifstate); | |
625 ifstate = NULL; | |
626 } |