1 |
|
|
/*- |
2 |
|
|
* Copyright (c) 2010 The NetBSD Foundation, Inc. |
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 |
|
|
|
30 |
|
|
#include <stdbool.h> |
31 |
|
|
#include <stdio.h> |
32 |
|
|
#include <stdarg.h> |
33 |
|
|
#include <stdlib.h> |
34 |
|
|
#include <unistd.h> |
35 |
|
|
#include <string.h> |
36 |
|
|
#include <errno.h> |
37 |
|
|
|
38 |
|
|
#include "version.h" |
39 |
|
|
#include "config.h" |
40 |
|
|
#include "utils.h" |
41 |
|
|
#include "array.h" |
42 |
|
|
#include "mode.h" |
43 |
|
|
#include "place.h" |
44 |
|
|
#include "files.h" |
45 |
|
|
#include "directive.h" |
46 |
|
|
#include "macro.h" |
47 |
|
|
|
48 |
|
|
struct mode mode = { |
49 |
|
|
.werror = false, |
50 |
|
|
|
51 |
|
|
.input_allow_dollars = false, |
52 |
|
|
.input_tabstop = 8, |
53 |
|
|
|
54 |
|
|
.do_stdinc = true, |
55 |
|
|
.do_stddef = true, |
56 |
|
|
|
57 |
|
|
.do_output = true, |
58 |
|
|
.output_linenumbers = true, |
59 |
|
|
.output_retain_comments = false, |
60 |
|
|
.output_file = NULL, |
61 |
|
|
|
62 |
|
|
.do_depend = false, |
63 |
|
|
.depend_report_system = false, |
64 |
|
|
.depend_assume_generated = false, |
65 |
|
|
.depend_issue_fakerules = false, |
66 |
|
|
.depend_quote_target = true, |
67 |
|
|
.depend_target = NULL, |
68 |
|
|
.depend_file = NULL, |
69 |
|
|
|
70 |
|
|
.do_macrolist = false, |
71 |
|
|
.macrolist_include_stddef = false, |
72 |
|
|
.macrolist_include_expansions = false, |
73 |
|
|
|
74 |
|
|
.do_trace = false, |
75 |
|
|
.trace_namesonly = false, |
76 |
|
|
.trace_indented = false, |
77 |
|
|
}; |
78 |
|
|
|
79 |
|
|
struct warns warns = { |
80 |
|
|
.endiflabels = true, |
81 |
|
|
.nestcomment = false, |
82 |
|
|
.undef = false, |
83 |
|
|
.unused = false, |
84 |
|
|
}; |
85 |
|
|
|
86 |
|
|
//////////////////////////////////////////////////////////// |
87 |
|
|
// commandline macros |
88 |
|
|
|
89 |
|
|
struct commandline_macro { |
90 |
|
|
struct place where; |
91 |
|
|
struct place where2; |
92 |
|
|
const char *macro; |
93 |
|
|
const char *expansion; |
94 |
|
|
}; |
95 |
|
|
|
96 |
|
|
static struct array commandline_macros; |
97 |
|
|
|
98 |
|
|
static |
99 |
|
|
void |
100 |
|
|
commandline_macros_init(void) |
101 |
|
|
{ |
102 |
|
|
array_init(&commandline_macros); |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
static |
106 |
|
|
void |
107 |
|
|
commandline_macros_cleanup(void) |
108 |
|
|
{ |
109 |
|
|
unsigned i, num; |
110 |
|
|
struct commandline_macro *cm; |
111 |
|
|
|
112 |
|
|
num = array_num(&commandline_macros); |
113 |
|
|
for (i=0; i<num; i++) { |
114 |
|
|
cm = array_get(&commandline_macros, i); |
115 |
|
|
dofree(cm, sizeof(*cm)); |
116 |
|
|
} |
117 |
|
|
array_setsize(&commandline_macros, 0); |
118 |
|
|
|
119 |
|
|
array_cleanup(&commandline_macros); |
120 |
|
|
} |
121 |
|
|
|
122 |
|
|
static |
123 |
|
|
void |
124 |
|
|
commandline_macro_add(const struct place *p, const char *macro, |
125 |
|
|
const struct place *p2, const char *expansion) |
126 |
|
|
{ |
127 |
|
|
struct commandline_macro *cm; |
128 |
|
|
|
129 |
|
|
cm = domalloc(sizeof(*cm)); |
130 |
|
|
cm->where = *p; |
131 |
|
|
cm->where2 = *p2; |
132 |
|
|
cm->macro = macro; |
133 |
|
|
cm->expansion = expansion; |
134 |
|
|
|
135 |
|
|
array_add(&commandline_macros, cm, NULL); |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
static |
139 |
|
|
void |
140 |
|
|
commandline_def(const struct place *p, char *str) |
141 |
|
|
{ |
142 |
|
|
struct place p2; |
143 |
|
|
char *val; |
144 |
|
|
|
145 |
|
|
if (*str == '\0') { |
146 |
|
|
complain(NULL, "-D: macro name expected"); |
147 |
|
|
die(); |
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
val = strchr(str, '='); |
151 |
|
|
if (val != NULL) { |
152 |
|
|
*val = '\0'; |
153 |
|
|
val++; |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
if (val) { |
157 |
|
|
p2 = *p; |
158 |
|
|
p2.column += strlen(str); |
159 |
|
|
} else { |
160 |
|
|
place_setbuiltin(&p2, 1); |
161 |
|
|
} |
162 |
|
|
commandline_macro_add(p, str, &p2, val ? val : "1"); |
163 |
|
|
} |
164 |
|
|
|
165 |
|
|
static |
166 |
|
|
void |
167 |
|
|
commandline_undef(const struct place *p, char *str) |
168 |
|
|
{ |
169 |
|
|
if (*str == '\0') { |
170 |
|
|
complain(NULL, "-D: macro name expected"); |
171 |
|
|
die(); |
172 |
|
|
} |
173 |
|
|
commandline_macro_add(p, str, p, NULL); |
174 |
|
|
} |
175 |
|
|
|
176 |
|
|
static |
177 |
|
|
void |
178 |
|
|
apply_commandline_macros(void) |
179 |
|
|
{ |
180 |
|
|
struct commandline_macro *cm; |
181 |
|
|
unsigned i, num; |
182 |
|
|
|
183 |
|
|
num = array_num(&commandline_macros); |
184 |
|
|
for (i=0; i<num; i++) { |
185 |
|
|
cm = array_get(&commandline_macros, i); |
186 |
|
|
if (cm->expansion != NULL) { |
187 |
|
|
macro_define_plain(&cm->where, cm->macro, |
188 |
|
|
&cm->where2, cm->expansion); |
189 |
|
|
} else { |
190 |
|
|
macro_undef(cm->macro); |
191 |
|
|
} |
192 |
|
|
dofree(cm, sizeof(*cm)); |
193 |
|
|
} |
194 |
|
|
array_setsize(&commandline_macros, 0); |
195 |
|
|
} |
196 |
|
|
|
197 |
|
|
static |
198 |
|
|
void |
199 |
|
|
apply_builtin_macro(unsigned num, const char *name, const char *val) |
200 |
|
|
{ |
201 |
|
|
struct place p; |
202 |
|
|
|
203 |
|
|
place_setbuiltin(&p, num); |
204 |
|
|
macro_define_plain(&p, name, &p, val); |
205 |
|
|
} |
206 |
|
|
|
207 |
|
|
static |
208 |
|
|
void |
209 |
|
|
apply_builtin_macros(void) |
210 |
|
|
{ |
211 |
|
|
unsigned n = 1; |
212 |
|
|
|
213 |
|
|
#ifdef CONFIG_OS |
214 |
|
|
apply_builtin_macro(n++, CONFIG_OS, "1"); |
215 |
|
|
#endif |
216 |
|
|
#ifdef CONFIG_OS_2 |
217 |
|
|
apply_builtin_macro(n++, CONFIG_OS_2, "1"); |
218 |
|
|
#endif |
219 |
|
|
|
220 |
|
|
#ifdef CONFIG_CPU |
221 |
|
|
apply_builtin_macro(n++, CONFIG_CPU, "1"); |
222 |
|
|
#endif |
223 |
|
|
#ifdef CONFIG_CPU_2 |
224 |
|
|
apply_builtin_macro(n++, CONFIG_CPU_2, "1"); |
225 |
|
|
#endif |
226 |
|
|
|
227 |
|
|
#ifdef CONFIG_SIZE |
228 |
|
|
apply_builtin_macro(n++, CONFIG_SIZE, "1"); |
229 |
|
|
#endif |
230 |
|
|
#ifdef CONFIG_BINFMT |
231 |
|
|
apply_builtin_macro(n++, CONFIG_BINFMT, "1"); |
232 |
|
|
#endif |
233 |
|
|
|
234 |
|
|
#ifdef CONFIG_COMPILER |
235 |
|
|
apply_builtin_macro(n++, CONFIG_COMPILER, VERSION_MAJOR); |
236 |
|
|
apply_builtin_macro(n++, CONFIG_COMPILER_MINOR, VERSION_MINOR); |
237 |
|
|
apply_builtin_macro(n++, "__VERSION__", VERSION_LONG); |
238 |
|
|
#endif |
239 |
|
|
} |
240 |
|
|
|
241 |
|
|
//////////////////////////////////////////////////////////// |
242 |
|
|
// extra included files |
243 |
|
|
|
244 |
|
|
struct commandline_file { |
245 |
|
|
struct place where; |
246 |
|
|
char *name; |
247 |
|
|
bool suppress_output; |
248 |
|
|
}; |
249 |
|
|
|
250 |
|
|
static struct array commandline_files; |
251 |
|
|
|
252 |
|
|
static |
253 |
|
|
void |
254 |
|
|
commandline_files_init(void) |
255 |
|
|
{ |
256 |
|
|
array_init(&commandline_files); |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
static |
260 |
|
|
void |
261 |
|
|
commandline_files_cleanup(void) |
262 |
|
|
{ |
263 |
|
|
unsigned i, num; |
264 |
|
|
struct commandline_file *cf; |
265 |
|
|
|
266 |
|
|
num = array_num(&commandline_files); |
267 |
|
|
for (i=0; i<num; i++) { |
268 |
|
|
cf = array_get(&commandline_files, i); |
269 |
|
|
if (cf != NULL) { |
270 |
|
|
dofree(cf, sizeof(*cf)); |
271 |
|
|
} |
272 |
|
|
} |
273 |
|
|
array_setsize(&commandline_files, 0); |
274 |
|
|
|
275 |
|
|
array_cleanup(&commandline_files); |
276 |
|
|
} |
277 |
|
|
|
278 |
|
|
static |
279 |
|
|
void |
280 |
|
|
commandline_addfile(const struct place *p, char *name, bool suppress_output) |
281 |
|
|
{ |
282 |
|
|
struct commandline_file *cf; |
283 |
|
|
|
284 |
|
|
cf = domalloc(sizeof(*cf)); |
285 |
|
|
cf->where = *p; |
286 |
|
|
cf->name = name; |
287 |
|
|
cf->suppress_output = suppress_output; |
288 |
|
|
array_add(&commandline_files, cf, NULL); |
289 |
|
|
} |
290 |
|
|
|
291 |
|
|
static |
292 |
|
|
void |
293 |
|
|
commandline_addfile_output(const struct place *p, char *name) |
294 |
|
|
{ |
295 |
|
|
commandline_addfile(p, name, false); |
296 |
|
|
} |
297 |
|
|
|
298 |
|
|
static |
299 |
|
|
void |
300 |
|
|
commandline_addfile_nooutput(const struct place *p, char *name) |
301 |
|
|
{ |
302 |
|
|
commandline_addfile(p, name, true); |
303 |
|
|
} |
304 |
|
|
|
305 |
|
|
static |
306 |
|
|
void |
307 |
|
|
read_commandline_files(void) |
308 |
|
|
{ |
309 |
|
|
struct commandline_file *cf; |
310 |
|
|
unsigned i, num; |
311 |
|
|
bool save = false; |
312 |
|
|
|
313 |
|
|
num = array_num(&commandline_files); |
314 |
|
|
for (i=0; i<num; i++) { |
315 |
|
|
cf = array_get(&commandline_files, i); |
316 |
|
|
array_set(&commandline_files, i, NULL); |
317 |
|
|
if (cf->suppress_output) { |
318 |
|
|
save = mode.do_output; |
319 |
|
|
mode.do_output = false; |
320 |
|
|
file_readquote(&cf->where, cf->name); |
321 |
|
|
mode.do_output = save; |
322 |
|
|
} else { |
323 |
|
|
file_readquote(&cf->where, cf->name); |
324 |
|
|
} |
325 |
|
|
dofree(cf, sizeof(*cf)); |
326 |
|
|
} |
327 |
|
|
array_setsize(&commandline_files, 0); |
328 |
|
|
} |
329 |
|
|
|
330 |
|
|
//////////////////////////////////////////////////////////// |
331 |
|
|
// include path accumulation |
332 |
|
|
|
333 |
|
|
static struct stringarray incpath_quote; |
334 |
|
|
static struct stringarray incpath_user; |
335 |
|
|
static struct stringarray incpath_system; |
336 |
|
|
static struct stringarray incpath_late; |
337 |
|
|
static const char *sysroot; |
338 |
|
|
|
339 |
|
|
static |
340 |
|
|
void |
341 |
|
|
incpath_init(void) |
342 |
|
|
{ |
343 |
|
|
stringarray_init(&incpath_quote); |
344 |
|
|
stringarray_init(&incpath_user); |
345 |
|
|
stringarray_init(&incpath_system); |
346 |
|
|
stringarray_init(&incpath_late); |
347 |
|
|
} |
348 |
|
|
|
349 |
|
|
static |
350 |
|
|
void |
351 |
|
|
incpath_cleanup(void) |
352 |
|
|
{ |
353 |
|
|
stringarray_setsize(&incpath_quote, 0); |
354 |
|
|
stringarray_setsize(&incpath_user, 0); |
355 |
|
|
stringarray_setsize(&incpath_system, 0); |
356 |
|
|
stringarray_setsize(&incpath_late, 0); |
357 |
|
|
|
358 |
|
|
stringarray_cleanup(&incpath_quote); |
359 |
|
|
stringarray_cleanup(&incpath_user); |
360 |
|
|
stringarray_cleanup(&incpath_system); |
361 |
|
|
stringarray_cleanup(&incpath_late); |
362 |
|
|
} |
363 |
|
|
|
364 |
|
|
static |
365 |
|
|
void |
366 |
|
|
commandline_isysroot(const struct place *p, char *dir) |
367 |
|
|
{ |
368 |
|
|
(void)p; |
369 |
|
|
sysroot = dir; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
static |
373 |
|
|
void |
374 |
|
|
commandline_addincpath(struct stringarray *arr, char *s) |
375 |
|
|
{ |
376 |
|
|
if (*s == '\0') { |
377 |
|
|
complain(NULL, "Empty include directory"); |
378 |
|
|
die(); |
379 |
|
|
} |
380 |
|
|
stringarray_add(arr, s, NULL); |
381 |
|
|
} |
382 |
|
|
|
383 |
|
|
static |
384 |
|
|
void |
385 |
|
|
commandline_addincpath_quote(const struct place *p, char *dir) |
386 |
|
|
{ |
387 |
|
|
(void)p; |
388 |
|
|
commandline_addincpath(&incpath_quote, dir); |
389 |
|
|
} |
390 |
|
|
|
391 |
|
|
static |
392 |
|
|
void |
393 |
|
|
commandline_addincpath_user(const struct place *p, char *dir) |
394 |
|
|
{ |
395 |
|
|
(void)p; |
396 |
|
|
commandline_addincpath(&incpath_user, dir); |
397 |
|
|
} |
398 |
|
|
|
399 |
|
|
static |
400 |
|
|
void |
401 |
|
|
commandline_addincpath_system(const struct place *p, char *dir) |
402 |
|
|
{ |
403 |
|
|
(void)p; |
404 |
|
|
commandline_addincpath(&incpath_system, dir); |
405 |
|
|
} |
406 |
|
|
|
407 |
|
|
static |
408 |
|
|
void |
409 |
|
|
commandline_addincpath_late(const struct place *p, char *dir) |
410 |
|
|
{ |
411 |
|
|
(void)p; |
412 |
|
|
commandline_addincpath(&incpath_late, dir); |
413 |
|
|
} |
414 |
|
|
|
415 |
|
|
static |
416 |
|
|
void |
417 |
|
|
loadincludepath(void) |
418 |
|
|
{ |
419 |
|
|
unsigned i, num; |
420 |
|
|
const char *dir; |
421 |
|
|
char *t; |
422 |
|
|
|
423 |
|
|
num = stringarray_num(&incpath_quote); |
424 |
|
|
for (i=0; i<num; i++) { |
425 |
|
|
dir = stringarray_get(&incpath_quote, i); |
426 |
|
|
files_addquotepath(dir, false); |
427 |
|
|
} |
428 |
|
|
files_addquotepath(NULL, false); |
429 |
|
|
|
430 |
|
|
num = stringarray_num(&incpath_user); |
431 |
|
|
for (i=0; i<num; i++) { |
432 |
|
|
dir = stringarray_get(&incpath_user, i); |
433 |
|
|
files_addquotepath(dir, false); |
434 |
|
|
files_addbracketpath(dir, false); |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
if (mode.do_stdinc) { |
438 |
|
|
if (sysroot != NULL) { |
439 |
|
|
t = dostrdup3(sysroot, "/", CONFIG_LOCALINCLUDE); |
440 |
|
|
freestringlater(t); |
441 |
|
|
dir = t; |
442 |
|
|
} else { |
443 |
|
|
dir = CONFIG_LOCALINCLUDE; |
444 |
|
|
} |
445 |
|
|
files_addquotepath(dir, true); |
446 |
|
|
files_addbracketpath(dir, true); |
447 |
|
|
|
448 |
|
|
if (sysroot != NULL) { |
449 |
|
|
t = dostrdup3(sysroot, "/", CONFIG_SYSTEMINCLUDE); |
450 |
|
|
freestringlater(t); |
451 |
|
|
dir = t; |
452 |
|
|
} else { |
453 |
|
|
dir = CONFIG_SYSTEMINCLUDE; |
454 |
|
|
} |
455 |
|
|
files_addquotepath(dir, true); |
456 |
|
|
files_addbracketpath(dir, true); |
457 |
|
|
} |
458 |
|
|
|
459 |
|
|
num = stringarray_num(&incpath_system); |
460 |
|
|
for (i=0; i<num; i++) { |
461 |
|
|
dir = stringarray_get(&incpath_system, i); |
462 |
|
|
files_addquotepath(dir, true); |
463 |
|
|
files_addbracketpath(dir, true); |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
num = stringarray_num(&incpath_late); |
467 |
|
|
for (i=0; i<num; i++) { |
468 |
|
|
dir = stringarray_get(&incpath_late, i); |
469 |
|
|
files_addquotepath(dir, false); |
470 |
|
|
files_addbracketpath(dir, false); |
471 |
|
|
} |
472 |
|
|
} |
473 |
|
|
|
474 |
|
|
//////////////////////////////////////////////////////////// |
475 |
|
|
// silly commandline stuff |
476 |
|
|
|
477 |
|
|
static const char *commandline_prefix; |
478 |
|
|
|
479 |
|
|
static |
480 |
|
|
void |
481 |
|
|
commandline_setprefix(const struct place *p, char *prefix) |
482 |
|
|
{ |
483 |
|
|
(void)p; |
484 |
|
|
commandline_prefix = prefix; |
485 |
|
|
} |
486 |
|
|
|
487 |
|
|
static |
488 |
|
|
void |
489 |
|
|
commandline_addincpath_user_withprefix(const struct place *p, char *dir) |
490 |
|
|
{ |
491 |
|
|
char *s; |
492 |
|
|
|
493 |
|
|
if (commandline_prefix == NULL) { |
494 |
|
|
complain(NULL, "-iprefix needed"); |
495 |
|
|
die(); |
496 |
|
|
} |
497 |
|
|
s = dostrdup3(commandline_prefix, "/", dir); |
498 |
|
|
freestringlater(s); |
499 |
|
|
commandline_addincpath_user(p, s); |
500 |
|
|
} |
501 |
|
|
|
502 |
|
|
static |
503 |
|
|
void |
504 |
|
|
commandline_addincpath_late_withprefix(const struct place *p, char *dir) |
505 |
|
|
{ |
506 |
|
|
char *s; |
507 |
|
|
|
508 |
|
|
if (commandline_prefix == NULL) { |
509 |
|
|
complain(NULL, "-iprefix needed"); |
510 |
|
|
die(); |
511 |
|
|
} |
512 |
|
|
s = dostrdup3(commandline_prefix, "/", dir); |
513 |
|
|
freestringlater(s); |
514 |
|
|
commandline_addincpath_late(p, s); |
515 |
|
|
} |
516 |
|
|
|
517 |
|
|
static |
518 |
|
|
void |
519 |
|
|
commandline_setstd(const struct place *p, char *std) |
520 |
|
|
{ |
521 |
|
|
(void)p; |
522 |
|
|
|
523 |
|
|
if (!strcmp(std, "krc")) { |
524 |
|
|
return; |
525 |
|
|
} |
526 |
|
|
complain(NULL, "Standard %s not supported by this preprocessor", std); |
527 |
|
|
die(); |
528 |
|
|
} |
529 |
|
|
|
530 |
|
|
static |
531 |
|
|
void |
532 |
|
|
commandline_setlang(const struct place *p, char *lang) |
533 |
|
|
{ |
534 |
|
|
(void)p; |
535 |
|
|
|
536 |
|
|
if (!strcmp(lang, "c") || !strcmp(lang, "assembler-with-cpp")) { |
537 |
|
|
return; |
538 |
|
|
} |
539 |
|
|
complain(NULL, "Language %s not supported by this preprocessor", lang); |
540 |
|
|
die(); |
541 |
|
|
} |
542 |
|
|
|
543 |
|
|
//////////////////////////////////////////////////////////// |
544 |
|
|
// complex modes |
545 |
|
|
|
546 |
|
|
DEAD static |
547 |
|
|
void |
548 |
|
|
commandline_iremap(const struct place *p, char *str) |
549 |
|
|
{ |
550 |
|
|
(void)p; |
551 |
|
|
/* XXX */ |
552 |
|
|
(void)str; |
553 |
|
|
complain(NULL, "-iremap not supported"); |
554 |
|
|
die(); |
555 |
|
|
} |
556 |
|
|
|
557 |
|
|
static |
558 |
|
|
void |
559 |
|
|
commandline_tabstop(const struct place *p, char *s) |
560 |
|
|
{ |
561 |
|
|
char *t; |
562 |
|
|
unsigned long val; |
563 |
|
|
|
564 |
|
|
(void)p; |
565 |
|
|
|
566 |
|
|
t = strchr(s, '='); |
567 |
|
|
if (t == NULL) { |
568 |
|
|
/* should not happen */ |
569 |
|
|
complain(NULL, "Invalid tabstop"); |
570 |
|
|
die(); |
571 |
|
|
} |
572 |
|
|
t++; |
573 |
|
|
errno = 0; |
574 |
|
|
val = strtoul(t, &t, 10); |
575 |
|
|
if (errno || *t != '\0') { |
576 |
|
|
complain(NULL, "Invalid tabstop"); |
577 |
|
|
die(); |
578 |
|
|
} |
579 |
|
|
if (val > 64) { |
580 |
|
|
complain(NULL, "Preposterously large tabstop"); |
581 |
|
|
die(); |
582 |
|
|
} |
583 |
|
|
mode.input_tabstop = val; |
584 |
|
|
} |
585 |
|
|
|
586 |
|
|
/* |
587 |
|
|
* macrolist |
588 |
|
|
*/ |
589 |
|
|
|
590 |
|
|
static |
591 |
|
|
void |
592 |
|
|
commandline_dD(void) |
593 |
|
|
{ |
594 |
|
|
mode.do_macrolist = true; |
595 |
|
|
mode.macrolist_include_stddef = false; |
596 |
|
|
mode.macrolist_include_expansions = true; |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
static |
600 |
|
|
void |
601 |
|
|
commandline_dM(void) |
602 |
|
|
{ |
603 |
|
|
mode.do_macrolist = true; |
604 |
|
|
mode.macrolist_include_stddef = true; |
605 |
|
|
mode.macrolist_include_expansions = true; |
606 |
|
|
mode.do_output = false; |
607 |
|
|
} |
608 |
|
|
|
609 |
|
|
static |
610 |
|
|
void |
611 |
|
|
commandline_dN(void) |
612 |
|
|
{ |
613 |
|
|
mode.do_macrolist = true; |
614 |
|
|
mode.macrolist_include_stddef = false; |
615 |
|
|
mode.macrolist_include_expansions = false; |
616 |
|
|
} |
617 |
|
|
|
618 |
|
|
/* |
619 |
|
|
* include trace |
620 |
|
|
*/ |
621 |
|
|
|
622 |
|
|
static |
623 |
|
|
void |
624 |
|
|
commandline_dI(void) |
625 |
|
|
{ |
626 |
|
|
mode.do_trace = true; |
627 |
|
|
mode.trace_namesonly = false; |
628 |
|
|
mode.trace_indented = false; |
629 |
|
|
} |
630 |
|
|
|
631 |
|
|
static |
632 |
|
|
void |
633 |
|
|
commandline_H(void) |
634 |
|
|
{ |
635 |
|
|
mode.do_trace = true; |
636 |
|
|
mode.trace_namesonly = true; |
637 |
|
|
mode.trace_indented = true; |
638 |
|
|
} |
639 |
|
|
|
640 |
|
|
/* |
641 |
|
|
* depend |
642 |
|
|
*/ |
643 |
|
|
|
644 |
|
|
static |
645 |
|
|
void |
646 |
|
|
commandline_setdependtarget(const struct place *p, char *str) |
647 |
|
|
{ |
648 |
|
|
(void)p; |
649 |
|
|
mode.depend_target = str; |
650 |
|
|
mode.depend_quote_target = false; |
651 |
|
|
} |
652 |
|
|
|
653 |
|
|
static |
654 |
|
|
void |
655 |
|
|
commandline_setdependtarget_quoted(const struct place *p, char *str) |
656 |
|
|
{ |
657 |
|
|
(void)p; |
658 |
|
|
mode.depend_target = str; |
659 |
|
|
mode.depend_quote_target = true; |
660 |
|
|
} |
661 |
|
|
|
662 |
|
|
static |
663 |
|
|
void |
664 |
|
|
commandline_setdependoutput(const struct place *p, char *str) |
665 |
|
|
{ |
666 |
|
|
(void)p; |
667 |
|
|
mode.depend_file = str; |
668 |
|
|
} |
669 |
|
|
|
670 |
|
|
static |
671 |
|
|
void |
672 |
|
|
commandline_M(void) |
673 |
|
|
{ |
674 |
|
|
mode.do_depend = true; |
675 |
|
|
mode.depend_report_system = true; |
676 |
|
|
mode.do_output = false; |
677 |
|
|
} |
678 |
|
|
|
679 |
|
|
static |
680 |
|
|
void |
681 |
|
|
commandline_MM(void) |
682 |
|
|
{ |
683 |
|
|
mode.do_depend = true; |
684 |
|
|
mode.depend_report_system = false; |
685 |
|
|
mode.do_output = false; |
686 |
|
|
} |
687 |
|
|
|
688 |
|
|
static |
689 |
|
|
void |
690 |
|
|
commandline_MD(void) |
691 |
|
|
{ |
692 |
|
|
mode.do_depend = true; |
693 |
|
|
mode.depend_report_system = true; |
694 |
|
|
} |
695 |
|
|
|
696 |
|
|
static |
697 |
|
|
void |
698 |
|
|
commandline_MMD(void) |
699 |
|
|
{ |
700 |
|
|
mode.do_depend = true; |
701 |
|
|
mode.depend_report_system = false; |
702 |
|
|
} |
703 |
|
|
|
704 |
|
|
static |
705 |
|
|
void |
706 |
|
|
commandline_wall(void) |
707 |
|
|
{ |
708 |
|
|
warns.nestcomment = true; |
709 |
|
|
warns.undef = true; |
710 |
|
|
warns.unused = true; |
711 |
|
|
} |
712 |
|
|
|
713 |
|
|
static |
714 |
|
|
void |
715 |
|
|
commandline_wnoall(void) |
716 |
|
|
{ |
717 |
|
|
warns.nestcomment = false; |
718 |
|
|
warns.undef = false; |
719 |
|
|
warns.unused = false; |
720 |
|
|
} |
721 |
|
|
|
722 |
|
|
static |
723 |
|
|
void |
724 |
|
|
commandline_wnone(void) |
725 |
|
|
{ |
726 |
|
|
warns.nestcomment = false; |
727 |
|
|
warns.endiflabels = false; |
728 |
|
|
warns.undef = false; |
729 |
|
|
warns.unused = false; |
730 |
|
|
} |
731 |
|
|
|
732 |
|
|
//////////////////////////////////////////////////////////// |
733 |
|
|
// options |
734 |
|
|
|
735 |
|
|
struct ignore_option { |
736 |
|
|
const char *string; |
737 |
|
|
}; |
738 |
|
|
|
739 |
|
|
struct flag_option { |
740 |
|
|
const char *string; |
741 |
|
|
bool *flag; |
742 |
|
|
bool setto; |
743 |
|
|
}; |
744 |
|
|
|
745 |
|
|
struct act_option { |
746 |
|
|
const char *string; |
747 |
|
|
void (*func)(void); |
748 |
|
|
}; |
749 |
|
|
|
750 |
|
|
struct prefix_option { |
751 |
|
|
const char *string; |
752 |
|
|
void (*func)(const struct place *, char *); |
753 |
|
|
}; |
754 |
|
|
|
755 |
|
|
struct arg_option { |
756 |
|
|
const char *string; |
757 |
|
|
void (*func)(const struct place *, char *); |
758 |
|
|
}; |
759 |
|
|
|
760 |
|
|
static const struct ignore_option ignore_options[] = { |
761 |
|
|
{ "m32" }, |
762 |
|
|
{ "traditional" }, |
763 |
|
|
}; |
764 |
|
|
static const unsigned num_ignore_options = HOWMANY(ignore_options); |
765 |
|
|
|
766 |
|
|
static const struct flag_option flag_options[] = { |
767 |
|
|
{ "C", &mode.output_retain_comments, true }, |
768 |
|
|
{ "CC", &mode.output_retain_comments, true }, |
769 |
|
|
{ "MG", &mode.depend_assume_generated, true }, |
770 |
|
|
{ "MP", &mode.depend_issue_fakerules, true }, |
771 |
|
|
{ "P", &mode.output_linenumbers, false }, |
772 |
|
|
{ "Wcomment", &warns.nestcomment, true }, |
773 |
|
|
{ "Wendif-labels", &warns.endiflabels, true }, |
774 |
|
|
{ "Werror", &mode.werror, true }, |
775 |
|
|
{ "Wno-comment", &warns.nestcomment, false }, |
776 |
|
|
{ "Wno-endif-labels", &warns.endiflabels, false }, |
777 |
|
|
{ "Wno-error", &mode.werror, false }, |
778 |
|
|
{ "Wno-undef", &warns.undef, false }, |
779 |
|
|
{ "Wno-unused-macros", &warns.unused, false }, |
780 |
|
|
{ "Wundef", &warns.undef, true }, |
781 |
|
|
{ "Wunused-macros", &warns.unused, true }, |
782 |
|
|
{ "fdollars-in-identifiers", &mode.input_allow_dollars, true }, |
783 |
|
|
{ "fno-dollars-in-identifiers", &mode.input_allow_dollars, false }, |
784 |
|
|
{ "nostdinc", &mode.do_stdinc, false }, |
785 |
|
|
{ "undef", &mode.do_stddef, false }, |
786 |
|
|
}; |
787 |
|
|
static const unsigned num_flag_options = HOWMANY(flag_options); |
788 |
|
|
|
789 |
|
|
static const struct act_option act_options[] = { |
790 |
|
|
{ "H", commandline_H }, |
791 |
|
|
{ "M", commandline_M }, |
792 |
|
|
{ "MD", commandline_MD }, |
793 |
|
|
{ "MM", commandline_MM }, |
794 |
|
|
{ "MMD", commandline_MMD }, |
795 |
|
|
{ "Wall", commandline_wall }, |
796 |
|
|
{ "Wno-all", commandline_wnoall }, |
797 |
|
|
{ "dD", commandline_dD }, |
798 |
|
|
{ "dI", commandline_dI }, |
799 |
|
|
{ "dM", commandline_dM }, |
800 |
|
|
{ "dN", commandline_dN }, |
801 |
|
|
{ "w", commandline_wnone }, |
802 |
|
|
}; |
803 |
|
|
static const unsigned num_act_options = HOWMANY(act_options); |
804 |
|
|
|
805 |
|
|
static const struct prefix_option prefix_options[] = { |
806 |
|
|
{ "D", commandline_def }, |
807 |
|
|
{ "I", commandline_addincpath_user }, |
808 |
|
|
{ "U", commandline_undef }, |
809 |
|
|
{ "ftabstop=", commandline_tabstop }, |
810 |
|
|
{ "std=", commandline_setstd }, |
811 |
|
|
}; |
812 |
|
|
static const unsigned num_prefix_options = HOWMANY(prefix_options); |
813 |
|
|
|
814 |
|
|
static const struct arg_option arg_options[] = { |
815 |
|
|
{ "MF", commandline_setdependoutput }, |
816 |
|
|
{ "MQ", commandline_setdependtarget_quoted }, |
817 |
|
|
{ "MT", commandline_setdependtarget }, |
818 |
|
|
{ "idirafter", commandline_addincpath_late }, |
819 |
|
|
{ "imacros", commandline_addfile_nooutput }, |
820 |
|
|
{ "include", commandline_addfile_output }, |
821 |
|
|
{ "iprefix", commandline_setprefix }, |
822 |
|
|
{ "iquote", commandline_addincpath_quote }, |
823 |
|
|
{ "iremap", commandline_iremap }, |
824 |
|
|
{ "isysroot", commandline_isysroot }, |
825 |
|
|
{ "isystem", commandline_addincpath_system }, |
826 |
|
|
{ "iwithprefix", commandline_addincpath_late_withprefix }, |
827 |
|
|
{ "iwithprefixbefore", commandline_addincpath_user_withprefix }, |
828 |
|
|
{ "x", commandline_setlang }, |
829 |
|
|
}; |
830 |
|
|
static const unsigned num_arg_options = HOWMANY(arg_options); |
831 |
|
|
|
832 |
|
|
static |
833 |
|
|
bool |
834 |
|
|
check_ignore_option(const char *opt) |
835 |
|
|
{ |
836 |
|
|
unsigned i; |
837 |
|
|
int r; |
838 |
|
|
|
839 |
|
|
for (i=0; i<num_ignore_options; i++) { |
840 |
|
|
r = strcmp(opt, ignore_options[i].string); |
841 |
|
|
if (r == 0) { |
842 |
|
|
return true; |
843 |
|
|
} |
844 |
|
|
if (r < 0) { |
845 |
|
|
break; |
846 |
|
|
} |
847 |
|
|
} |
848 |
|
|
return false; |
849 |
|
|
} |
850 |
|
|
|
851 |
|
|
static |
852 |
|
|
bool |
853 |
|
|
check_flag_option(const char *opt) |
854 |
|
|
{ |
855 |
|
|
unsigned i; |
856 |
|
|
int r; |
857 |
|
|
|
858 |
|
|
for (i=0; i<num_flag_options; i++) { |
859 |
|
|
r = strcmp(opt, flag_options[i].string); |
860 |
|
|
if (r == 0) { |
861 |
|
|
*flag_options[i].flag = flag_options[i].setto; |
862 |
|
|
return true; |
863 |
|
|
} |
864 |
|
|
if (r < 0) { |
865 |
|
|
break; |
866 |
|
|
} |
867 |
|
|
} |
868 |
|
|
return false; |
869 |
|
|
} |
870 |
|
|
|
871 |
|
|
static |
872 |
|
|
bool |
873 |
|
|
check_act_option(const char *opt) |
874 |
|
|
{ |
875 |
|
|
unsigned i; |
876 |
|
|
int r; |
877 |
|
|
|
878 |
|
|
for (i=0; i<num_act_options; i++) { |
879 |
|
|
r = strcmp(opt, act_options[i].string); |
880 |
|
|
if (r == 0) { |
881 |
|
|
act_options[i].func(); |
882 |
|
|
return true; |
883 |
|
|
} |
884 |
|
|
if (r < 0) { |
885 |
|
|
break; |
886 |
|
|
} |
887 |
|
|
} |
888 |
|
|
return false; |
889 |
|
|
} |
890 |
|
|
|
891 |
|
|
static |
892 |
|
|
bool |
893 |
|
|
check_prefix_option(const struct place *p, char *opt) |
894 |
|
|
{ |
895 |
|
|
unsigned i, len; |
896 |
|
|
int r; |
897 |
|
|
|
898 |
|
|
for (i=0; i<num_prefix_options; i++) { |
899 |
|
|
len = strlen(prefix_options[i].string); |
900 |
|
|
r = strncmp(opt, prefix_options[i].string, len); |
901 |
|
|
if (r == 0) { |
902 |
|
|
prefix_options[i].func(p, opt + len); |
903 |
|
|
return true; |
904 |
|
|
} |
905 |
|
|
if (r < 0) { |
906 |
|
|
break; |
907 |
|
|
} |
908 |
|
|
} |
909 |
|
|
return false; |
910 |
|
|
} |
911 |
|
|
|
912 |
|
|
static |
913 |
|
|
bool |
914 |
|
|
check_arg_option(const char *opt, const struct place *argplace, char *arg) |
915 |
|
|
{ |
916 |
|
|
unsigned i; |
917 |
|
|
int r; |
918 |
|
|
|
919 |
|
|
for (i=0; i<num_arg_options; i++) { |
920 |
|
|
r = strcmp(opt, arg_options[i].string); |
921 |
|
|
if (r == 0) { |
922 |
|
|
if (arg == NULL) { |
923 |
|
|
complain(NULL, |
924 |
|
|
"Option -%s requires an argument", |
925 |
|
|
opt); |
926 |
|
|
die(); |
927 |
|
|
} |
928 |
|
|
arg_options[i].func(argplace, arg); |
929 |
|
|
return true; |
930 |
|
|
} |
931 |
|
|
if (r < 0) { |
932 |
|
|
break; |
933 |
|
|
} |
934 |
|
|
} |
935 |
|
|
return false; |
936 |
|
|
} |
937 |
|
|
|
938 |
|
|
DEAD static |
939 |
|
|
void |
940 |
|
|
usage(const char *progname, const char *fmt, ...) |
941 |
|
|
{ |
942 |
|
|
va_list ap; |
943 |
|
|
|
944 |
|
|
fprintf(stderr, "%s: ", progname); |
945 |
|
|
va_start(ap, fmt); |
946 |
|
|
vfprintf(stderr, fmt, ap); |
947 |
|
|
va_end(ap); |
948 |
|
|
fprintf(stderr, "\n"); |
949 |
|
|
|
950 |
|
|
fprintf(stderr, "Usage: %s [options] [infile [outfile]]\n", progname); |
951 |
|
|
fprintf(stderr, "Common options:\n"); |
952 |
|
|
fprintf(stderr, " -C Retain comments\n"); |
953 |
|
|
fprintf(stderr, " -Dmacro[=def] Predefine macro\n"); |
954 |
|
|
fprintf(stderr, " -Idir Add to include path\n"); |
955 |
|
|
fprintf(stderr, " -M Issue depend info\n"); |
956 |
|
|
fprintf(stderr, " -MD Issue depend info and output\n"); |
957 |
|
|
fprintf(stderr, " -MM -M w/o system headers\n"); |
958 |
|
|
fprintf(stderr, " -MMD -MD w/o system headers\n"); |
959 |
|
|
fprintf(stderr, " -nostdinc Drop default include path\n"); |
960 |
|
|
fprintf(stderr, " -Umacro Undefine macro\n"); |
961 |
|
|
fprintf(stderr, " -undef Undefine everything\n"); |
962 |
|
|
fprintf(stderr, " -Wall Enable all warnings\n"); |
963 |
|
|
fprintf(stderr, " -Werror Make warnings into errors\n"); |
964 |
|
|
fprintf(stderr, " -w Disable all warnings\n"); |
965 |
|
|
die(); |
966 |
|
|
} |
967 |
|
|
|
968 |
|
|
//////////////////////////////////////////////////////////// |
969 |
|
|
// exit and cleanup |
970 |
|
|
|
971 |
|
|
static struct stringarray freestrings; |
972 |
|
|
|
973 |
|
|
static |
974 |
|
|
void |
975 |
|
|
init(void) |
976 |
|
|
{ |
977 |
|
|
stringarray_init(&freestrings); |
978 |
|
|
|
979 |
|
|
incpath_init(); |
980 |
|
|
commandline_macros_init(); |
981 |
|
|
commandline_files_init(); |
982 |
|
|
|
983 |
|
|
place_init(); |
984 |
|
|
files_init(); |
985 |
|
|
directive_init(); |
986 |
|
|
macros_init(); |
987 |
|
|
} |
988 |
|
|
|
989 |
|
|
static |
990 |
|
|
void |
991 |
|
|
cleanup(void) |
992 |
|
|
{ |
993 |
|
|
unsigned i, num; |
994 |
|
|
|
995 |
|
|
macros_cleanup(); |
996 |
|
|
directive_cleanup(); |
997 |
|
|
files_cleanup(); |
998 |
|
|
place_cleanup(); |
999 |
|
|
|
1000 |
|
|
commandline_files_cleanup(); |
1001 |
|
|
commandline_macros_cleanup(); |
1002 |
|
|
incpath_cleanup(); |
1003 |
|
|
|
1004 |
|
|
num = stringarray_num(&freestrings); |
1005 |
|
|
for (i=0; i<num; i++) { |
1006 |
|
|
dostrfree(stringarray_get(&freestrings, i)); |
1007 |
|
|
} |
1008 |
|
|
stringarray_setsize(&freestrings, 0); |
1009 |
|
|
stringarray_cleanup(&freestrings); |
1010 |
|
|
} |
1011 |
|
|
|
1012 |
|
|
void |
1013 |
|
|
die(void) |
1014 |
|
|
{ |
1015 |
|
|
cleanup(); |
1016 |
|
|
exit(EXIT_FAILURE); |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
void |
1020 |
|
|
freestringlater(char *s) |
1021 |
|
|
{ |
1022 |
|
|
stringarray_add(&freestrings, s, NULL); |
1023 |
|
|
} |
1024 |
|
|
|
1025 |
|
|
//////////////////////////////////////////////////////////// |
1026 |
|
|
// main |
1027 |
|
|
|
1028 |
|
|
int |
1029 |
|
|
main(int argc, char *argv[]) |
1030 |
|
|
{ |
1031 |
|
|
const char *progname; |
1032 |
|
|
const char *inputfile = NULL; |
1033 |
|
|
const char *outputfile = NULL; |
1034 |
|
|
struct place cmdplace; |
1035 |
|
|
int i; |
1036 |
|
|
|
1037 |
|
|
progname = strrchr(argv[0], '/'); |
1038 |
|
|
progname = progname == NULL ? argv[0] : progname + 1; |
1039 |
|
|
complain_init(progname); |
1040 |
|
|
|
1041 |
|
|
if (pledge("stdio rpath wpath cpath", NULL) == -1) { |
1042 |
|
|
fprintf(stderr, "%s: pledge: %s", progname, strerror(errno)); |
1043 |
|
|
exit(1); |
1044 |
|
|
} |
1045 |
|
|
|
1046 |
|
|
init(); |
1047 |
|
|
|
1048 |
|
|
for (i=1; i<argc; i++) { |
1049 |
|
|
if ((argv[i][0] != '-') || !strcmp(argv[i], "-")) { |
1050 |
|
|
break; |
1051 |
|
|
} |
1052 |
|
|
place_setcommandline(&cmdplace, i, 1); |
1053 |
|
|
if (check_ignore_option(argv[i]+1)) { |
1054 |
|
|
continue; |
1055 |
|
|
} |
1056 |
|
|
if (check_flag_option(argv[i]+1)) { |
1057 |
|
|
continue; |
1058 |
|
|
} |
1059 |
|
|
if (check_act_option(argv[i]+1)) { |
1060 |
|
|
continue; |
1061 |
|
|
} |
1062 |
|
|
if (check_prefix_option(&cmdplace, argv[i]+1)) { |
1063 |
|
|
continue; |
1064 |
|
|
} |
1065 |
|
|
place_setcommandline(&cmdplace, i+1, 1); |
1066 |
|
|
if (check_arg_option(argv[i]+1, &cmdplace, argv[i+1])) { |
1067 |
|
|
i++; |
1068 |
|
|
continue; |
1069 |
|
|
} |
1070 |
|
|
usage(progname, "Invalid option %s", argv[i]); |
1071 |
|
|
} |
1072 |
|
|
if (i < argc) { |
1073 |
|
|
inputfile = argv[i++]; |
1074 |
|
|
} |
1075 |
|
|
if (i < argc) { |
1076 |
|
|
outputfile = argv[i++]; |
1077 |
|
|
} |
1078 |
|
|
if (i < argc) { |
1079 |
|
|
usage(progname, "Extra non-option argument %s", argv[i]); |
1080 |
|
|
} |
1081 |
|
|
|
1082 |
|
|
mode.output_file = outputfile; |
1083 |
|
|
|
1084 |
|
|
loadincludepath(); |
1085 |
|
|
apply_builtin_macros(); |
1086 |
|
|
apply_commandline_macros(); |
1087 |
|
|
read_commandline_files(); |
1088 |
|
|
place_setnowhere(&cmdplace); |
1089 |
|
|
file_readabsolute(&cmdplace, inputfile); |
1090 |
|
|
|
1091 |
|
|
cleanup(); |
1092 |
|
|
if (complain_failed()) { |
1093 |
|
|
return EXIT_FAILURE; |
1094 |
|
|
} |
1095 |
|
|
return EXIT_SUCCESS; |
1096 |
|
|
} |