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