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