1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: MIT
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * 'sparse' library helper routines.
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * Copyright (C) 2003 Transmeta Corp.
6f08c3bdfSopenharmony_ci *               2003-2004 Linus Torvalds
7f08c3bdfSopenharmony_ci *               2017-2020 Luc Van Oostenryck
8f08c3bdfSopenharmony_ci */
9f08c3bdfSopenharmony_ci
10f08c3bdfSopenharmony_ci#include "options.h"
11f08c3bdfSopenharmony_ci#include "lib.h"
12f08c3bdfSopenharmony_ci#include "machine.h"
13f08c3bdfSopenharmony_ci#include "target.h"
14f08c3bdfSopenharmony_ci#include <ctype.h>
15f08c3bdfSopenharmony_ci#include <stdio.h>
16f08c3bdfSopenharmony_ci#include <stdlib.h>
17f08c3bdfSopenharmony_ci#include <string.h>
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci#ifndef __GNUC__
21f08c3bdfSopenharmony_ci# define __GNUC__ 2
22f08c3bdfSopenharmony_ci# define __GNUC_MINOR__ 95
23f08c3bdfSopenharmony_ci# define __GNUC_PATCHLEVEL__ 0
24f08c3bdfSopenharmony_ci#endif
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_cienum flag_type {
27f08c3bdfSopenharmony_ci	FLAG_OFF,
28f08c3bdfSopenharmony_ci	FLAG_ON,
29f08c3bdfSopenharmony_ci	FLAG_FORCE_OFF
30f08c3bdfSopenharmony_ci};
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_ciint die_if_error = 0;
33f08c3bdfSopenharmony_ciint do_output = 1;
34f08c3bdfSopenharmony_ciint gcc_major = __GNUC__;
35f08c3bdfSopenharmony_ciint gcc_minor = __GNUC_MINOR__;
36f08c3bdfSopenharmony_ciint gcc_patchlevel = __GNUC_PATCHLEVEL__;
37f08c3bdfSopenharmony_ciint has_error = 0;
38f08c3bdfSopenharmony_ciint optimize_level;
39f08c3bdfSopenharmony_ciint optimize_size;
40f08c3bdfSopenharmony_ciint preprocess_only;
41f08c3bdfSopenharmony_ciint preprocessing;
42f08c3bdfSopenharmony_ciint verbose;
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci#define CMDLINE_INCLUDE 20
45f08c3bdfSopenharmony_ciint cmdline_include_nr = 0;
46f08c3bdfSopenharmony_cichar *cmdline_include[CMDLINE_INCLUDE];
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ciconst char *base_filename;
49f08c3bdfSopenharmony_ciconst char *diag_prefix = "";
50f08c3bdfSopenharmony_ciconst char *gcc_base_dir = GCC_BASE;
51f08c3bdfSopenharmony_ciconst char *multiarch_dir = MULTIARCH_TRIPLET;
52f08c3bdfSopenharmony_ciconst char *outfile = NULL;
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cienum standard standard = STANDARD_GNU89;
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ciint arch_big_endian = ARCH_BIG_ENDIAN;
57f08c3bdfSopenharmony_ciint arch_cmodel = CMODEL_UNKNOWN;
58f08c3bdfSopenharmony_ciint arch_fp_abi = FP_ABI_NATIVE;
59f08c3bdfSopenharmony_ciint arch_m64 = ARCH_M64_DEFAULT;
60f08c3bdfSopenharmony_ciint arch_msize_long = 0;
61f08c3bdfSopenharmony_ciint arch_os = OS_NATIVE;
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_ciint dbg_compound = 0;
64f08c3bdfSopenharmony_ciint dbg_dead = 0;
65f08c3bdfSopenharmony_ciint dbg_domtree = 0;
66f08c3bdfSopenharmony_ciint dbg_entry = 0;
67f08c3bdfSopenharmony_ciint dbg_ir = 0;
68f08c3bdfSopenharmony_ciint dbg_postorder = 0;
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ciint dump_macro_defs = 0;
71f08c3bdfSopenharmony_ciint dump_macros_only = 0;
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ciunsigned long fdump_ir;
74f08c3bdfSopenharmony_ciint fhosted = 1;
75f08c3bdfSopenharmony_ciunsigned int fmax_errors = 100;
76f08c3bdfSopenharmony_ciunsigned int fmax_warnings = 100;
77f08c3bdfSopenharmony_ciint fmem_report = 0;
78f08c3bdfSopenharmony_ciunsigned long long fmemcpy_max_count = 100000;
79f08c3bdfSopenharmony_ciunsigned long fpasses = ~0UL;
80f08c3bdfSopenharmony_ciint fpic = 0;
81f08c3bdfSopenharmony_ciint fpie = 0;
82f08c3bdfSopenharmony_ciint fshort_wchar = 0;
83f08c3bdfSopenharmony_ciint funsigned_bitfields = 0;
84f08c3bdfSopenharmony_ciint funsigned_char = 0;
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ciint Waddress = 0;
87f08c3bdfSopenharmony_ciint Waddress_space = 1;
88f08c3bdfSopenharmony_ciint Wbitwise = 1;
89f08c3bdfSopenharmony_ciint Wbitwise_pointer = 0;
90f08c3bdfSopenharmony_ciint Wcast_from_as = 0;
91f08c3bdfSopenharmony_ciint Wcast_to_as = 0;
92f08c3bdfSopenharmony_ciint Wcast_truncate = 1;
93f08c3bdfSopenharmony_ciint Wconstant_suffix = 0;
94f08c3bdfSopenharmony_ciint Wconstexpr_not_const = 0;
95f08c3bdfSopenharmony_ciint Wcontext = 1;
96f08c3bdfSopenharmony_ciint Wdecl = 1;
97f08c3bdfSopenharmony_ciint Wdeclarationafterstatement = -1;
98f08c3bdfSopenharmony_ciint Wdefault_bitfield_sign = 0;
99f08c3bdfSopenharmony_ciint Wdesignated_init = 1;
100f08c3bdfSopenharmony_ciint Wdo_while = 0;
101f08c3bdfSopenharmony_ciint Wenum_mismatch = 1;
102f08c3bdfSopenharmony_ciint Wexternal_function_has_definition = 1;
103f08c3bdfSopenharmony_ciint Wflexible_array_array = 1;
104f08c3bdfSopenharmony_ciint Wflexible_array_nested = 0;
105f08c3bdfSopenharmony_ciint Wflexible_array_sizeof = 0;
106f08c3bdfSopenharmony_ciint Wflexible_array_union = 0;
107f08c3bdfSopenharmony_ciint Wimplicit_int = 1;
108f08c3bdfSopenharmony_ciint Winit_cstring = 0;
109f08c3bdfSopenharmony_ciint Wint_to_pointer_cast = 1;
110f08c3bdfSopenharmony_ciint Wmemcpy_max_count = 1;
111f08c3bdfSopenharmony_ciint Wnewline_eof = 1;
112f08c3bdfSopenharmony_ciint Wnon_pointer_null = 1;
113f08c3bdfSopenharmony_ciint Wold_initializer = 1;
114f08c3bdfSopenharmony_ciint Wold_style_definition = 1;
115f08c3bdfSopenharmony_ciint Wone_bit_signed_bitfield = 1;
116f08c3bdfSopenharmony_ciint Woverride_init = 1;
117f08c3bdfSopenharmony_ciint Woverride_init_all = 0;
118f08c3bdfSopenharmony_ciint Woverride_init_whole_range = 0;
119f08c3bdfSopenharmony_ciint Wparen_string = 0;
120f08c3bdfSopenharmony_ciint Wpast_deep_designator = 0;
121f08c3bdfSopenharmony_ciint Wpedantic = 0;
122f08c3bdfSopenharmony_ciint Wpointer_arith = 0;
123f08c3bdfSopenharmony_ciint Wpointer_to_int_cast = 1;
124f08c3bdfSopenharmony_ciint Wptr_subtraction_blows = 0;
125f08c3bdfSopenharmony_ciint Wreturn_void = 0;
126f08c3bdfSopenharmony_ciint Wshadow = 0;
127f08c3bdfSopenharmony_ciint Wshift_count_negative = 1;
128f08c3bdfSopenharmony_ciint Wshift_count_overflow = 1;
129f08c3bdfSopenharmony_ciint Wsizeof_bool = 0;
130f08c3bdfSopenharmony_ciint Wsparse_error = FLAG_FORCE_OFF;
131f08c3bdfSopenharmony_ciint Wstrict_prototypes = 1;
132f08c3bdfSopenharmony_ciint Wtautological_compare = 0;
133f08c3bdfSopenharmony_ciint Wtransparent_union = 0;
134f08c3bdfSopenharmony_ciint Wtypesign = 0;
135f08c3bdfSopenharmony_ciint Wundef = 0;
136f08c3bdfSopenharmony_ciint Wuninitialized = 1;
137f08c3bdfSopenharmony_ciint Wunion_cast = 0;
138f08c3bdfSopenharmony_ciint Wuniversal_initializer = 0;
139f08c3bdfSopenharmony_ciint Wunknown_attribute = 0;
140f08c3bdfSopenharmony_ciint Wvla = 1;
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ci////////////////////////////////////////////////////////////////////////////////
143f08c3bdfSopenharmony_ci// Helpers for option parsing
144f08c3bdfSopenharmony_ci
145f08c3bdfSopenharmony_cistatic const char *match_option(const char *arg, const char *prefix)
146f08c3bdfSopenharmony_ci{
147f08c3bdfSopenharmony_ci	unsigned int n = strlen(prefix);
148f08c3bdfSopenharmony_ci	if (strncmp(arg, prefix, n) == 0)
149f08c3bdfSopenharmony_ci		return arg + n;
150f08c3bdfSopenharmony_ci	return NULL;
151f08c3bdfSopenharmony_ci}
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_ci
154f08c3bdfSopenharmony_cistruct val_map {
155f08c3bdfSopenharmony_ci	const char *name;
156f08c3bdfSopenharmony_ci	int val;
157f08c3bdfSopenharmony_ci};
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_cistatic int handle_subopt_val(const char *opt, const char *arg, const struct val_map *map, int *flag)
160f08c3bdfSopenharmony_ci{
161f08c3bdfSopenharmony_ci	const char *name;
162f08c3bdfSopenharmony_ci
163f08c3bdfSopenharmony_ci	if (*arg++ != '=')
164f08c3bdfSopenharmony_ci		die("missing argument for option '%s'", opt);
165f08c3bdfSopenharmony_ci	for (;(name = map->name); map++) {
166f08c3bdfSopenharmony_ci		if (strcmp(name, arg) == 0 || strcmp(name, "*") == 0) {
167f08c3bdfSopenharmony_ci			*flag = map->val;
168f08c3bdfSopenharmony_ci			return 1;
169f08c3bdfSopenharmony_ci		}
170f08c3bdfSopenharmony_ci		if (strcmp(name, "?") == 0)
171f08c3bdfSopenharmony_ci			die("invalid argument '%s' in option '%s'", arg, opt);
172f08c3bdfSopenharmony_ci	}
173f08c3bdfSopenharmony_ci	return 0;
174f08c3bdfSopenharmony_ci}
175f08c3bdfSopenharmony_ci
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_cistruct mask_map {
178f08c3bdfSopenharmony_ci	const char *name;
179f08c3bdfSopenharmony_ci	unsigned long mask;
180f08c3bdfSopenharmony_ci};
181f08c3bdfSopenharmony_ci
182f08c3bdfSopenharmony_cistatic int apply_mask(unsigned long *val, const char *str, unsigned len, const struct mask_map *map, int neg)
183f08c3bdfSopenharmony_ci{
184f08c3bdfSopenharmony_ci	const char *name;
185f08c3bdfSopenharmony_ci
186f08c3bdfSopenharmony_ci	for (;(name = map->name); map++) {
187f08c3bdfSopenharmony_ci		if (!strncmp(name, str, len) && !name[len]) {
188f08c3bdfSopenharmony_ci			if (neg == 0)
189f08c3bdfSopenharmony_ci				*val |= map->mask;
190f08c3bdfSopenharmony_ci			else
191f08c3bdfSopenharmony_ci				*val &= ~map->mask;
192f08c3bdfSopenharmony_ci			return 0;
193f08c3bdfSopenharmony_ci		}
194f08c3bdfSopenharmony_ci	}
195f08c3bdfSopenharmony_ci	return 1;
196f08c3bdfSopenharmony_ci}
197f08c3bdfSopenharmony_ci
198f08c3bdfSopenharmony_cistatic int handle_suboption_mask(const char *arg, const char *opt, const struct mask_map *map, unsigned long *flag)
199f08c3bdfSopenharmony_ci{
200f08c3bdfSopenharmony_ci	if (*opt == '\0') {
201f08c3bdfSopenharmony_ci		apply_mask(flag, "", 0, map, 0);
202f08c3bdfSopenharmony_ci		return 1;
203f08c3bdfSopenharmony_ci	}
204f08c3bdfSopenharmony_ci	if (*opt++ != '=')
205f08c3bdfSopenharmony_ci		return 0;
206f08c3bdfSopenharmony_ci	while (1) {
207f08c3bdfSopenharmony_ci		unsigned int len = strcspn(opt, ",+");
208f08c3bdfSopenharmony_ci		int neg = 0;
209f08c3bdfSopenharmony_ci		if (len == 0)
210f08c3bdfSopenharmony_ci			goto end;
211f08c3bdfSopenharmony_ci		if (!strncmp(opt, "no-", 3)) {
212f08c3bdfSopenharmony_ci			opt += 3;
213f08c3bdfSopenharmony_ci			len -= 3;
214f08c3bdfSopenharmony_ci			neg = 1;
215f08c3bdfSopenharmony_ci		}
216f08c3bdfSopenharmony_ci		if (apply_mask(flag, opt, len, map, neg))
217f08c3bdfSopenharmony_ci			die("error: wrong option '%.*s' for \'%s\'", len, opt, arg);
218f08c3bdfSopenharmony_ci
219f08c3bdfSopenharmony_ciend:
220f08c3bdfSopenharmony_ci		opt += len;
221f08c3bdfSopenharmony_ci		if (*opt++ == '\0')
222f08c3bdfSopenharmony_ci			break;
223f08c3bdfSopenharmony_ci	}
224f08c3bdfSopenharmony_ci	return 1;
225f08c3bdfSopenharmony_ci}
226f08c3bdfSopenharmony_ci
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci#define OPT_INVERSE	1
229f08c3bdfSopenharmony_ci#define OPT_VAL		2
230f08c3bdfSopenharmony_cistruct flag {
231f08c3bdfSopenharmony_ci	const char *name;
232f08c3bdfSopenharmony_ci	int *flag;
233f08c3bdfSopenharmony_ci	int (*fun)(const char *arg, const char *opt, const struct flag *, int options);
234f08c3bdfSopenharmony_ci	unsigned long mask;
235f08c3bdfSopenharmony_ci	int val;
236f08c3bdfSopenharmony_ci};
237f08c3bdfSopenharmony_ci
238f08c3bdfSopenharmony_cistatic int handle_switches(const char *ori, const char *opt, const struct flag *flags)
239f08c3bdfSopenharmony_ci{
240f08c3bdfSopenharmony_ci	const char *arg = opt;
241f08c3bdfSopenharmony_ci	int val = 1;
242f08c3bdfSopenharmony_ci
243f08c3bdfSopenharmony_ci	// Prefixe "no-" mean to turn flag off.
244f08c3bdfSopenharmony_ci	if (strncmp(arg, "no-", 3) == 0) {
245f08c3bdfSopenharmony_ci		arg += 3;
246f08c3bdfSopenharmony_ci		val = 0;
247f08c3bdfSopenharmony_ci	}
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_ci	for (; flags->name; flags++) {
250f08c3bdfSopenharmony_ci		const char *opt = match_option(arg, flags->name);
251f08c3bdfSopenharmony_ci		int rc;
252f08c3bdfSopenharmony_ci
253f08c3bdfSopenharmony_ci		if (!opt)
254f08c3bdfSopenharmony_ci			continue;
255f08c3bdfSopenharmony_ci
256f08c3bdfSopenharmony_ci		if (flags->fun) {
257f08c3bdfSopenharmony_ci			int options = 0;
258f08c3bdfSopenharmony_ci			if (!val)
259f08c3bdfSopenharmony_ci				options |= OPT_INVERSE;
260f08c3bdfSopenharmony_ci			if ((rc = flags->fun(ori, opt, flags, options)))
261f08c3bdfSopenharmony_ci				return rc;
262f08c3bdfSopenharmony_ci		}
263f08c3bdfSopenharmony_ci
264f08c3bdfSopenharmony_ci		// boolean flag
265f08c3bdfSopenharmony_ci		if (opt[0] == '\0' && flags->flag) {
266f08c3bdfSopenharmony_ci			if (flags->mask & OPT_VAL)
267f08c3bdfSopenharmony_ci				val = flags->val;
268f08c3bdfSopenharmony_ci			if (flags->mask & OPT_INVERSE)
269f08c3bdfSopenharmony_ci				val = !val;
270f08c3bdfSopenharmony_ci			*flags->flag = val;
271f08c3bdfSopenharmony_ci			return 1;
272f08c3bdfSopenharmony_ci		}
273f08c3bdfSopenharmony_ci	}
274f08c3bdfSopenharmony_ci
275f08c3bdfSopenharmony_ci	// not handled
276f08c3bdfSopenharmony_ci	return 0;
277f08c3bdfSopenharmony_ci}
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_cistatic char **handle_onoff_switch(char *arg, char **next, const struct flag flags[])
280f08c3bdfSopenharmony_ci{
281f08c3bdfSopenharmony_ci	int flag = FLAG_ON;
282f08c3bdfSopenharmony_ci	char *p = arg + 1;
283f08c3bdfSopenharmony_ci	unsigned i;
284f08c3bdfSopenharmony_ci
285f08c3bdfSopenharmony_ci	// Prefixes "no" and "no-" mean to turn warning off.
286f08c3bdfSopenharmony_ci	if (p[0] == 'n' && p[1] == 'o') {
287f08c3bdfSopenharmony_ci		p += 2;
288f08c3bdfSopenharmony_ci		if (p[0] == '-')
289f08c3bdfSopenharmony_ci			p++;
290f08c3bdfSopenharmony_ci		flag = FLAG_FORCE_OFF;
291f08c3bdfSopenharmony_ci	}
292f08c3bdfSopenharmony_ci
293f08c3bdfSopenharmony_ci	for (i = 0; flags[i].name; i++) {
294f08c3bdfSopenharmony_ci		if (!strcmp(p,flags[i].name)) {
295f08c3bdfSopenharmony_ci			*flags[i].flag = flag;
296f08c3bdfSopenharmony_ci			return next;
297f08c3bdfSopenharmony_ci		}
298f08c3bdfSopenharmony_ci	}
299f08c3bdfSopenharmony_ci
300f08c3bdfSopenharmony_ci	// Unknown.
301f08c3bdfSopenharmony_ci	return NULL;
302f08c3bdfSopenharmony_ci}
303f08c3bdfSopenharmony_ci
304f08c3bdfSopenharmony_cistatic void handle_onoff_switch_finalize(const struct flag flags[])
305f08c3bdfSopenharmony_ci{
306f08c3bdfSopenharmony_ci	unsigned i;
307f08c3bdfSopenharmony_ci
308f08c3bdfSopenharmony_ci	for (i = 0; flags[i].name; i++) {
309f08c3bdfSopenharmony_ci		if (*flags[i].flag == FLAG_FORCE_OFF)
310f08c3bdfSopenharmony_ci			*flags[i].flag = FLAG_OFF;
311f08c3bdfSopenharmony_ci	}
312f08c3bdfSopenharmony_ci}
313f08c3bdfSopenharmony_ci
314f08c3bdfSopenharmony_cistatic int handle_switch_setval(const char *arg, const char *opt, const struct flag *flag, int options)
315f08c3bdfSopenharmony_ci{
316f08c3bdfSopenharmony_ci	*(flag->flag) = flag->mask;
317f08c3bdfSopenharmony_ci	return 1;
318f08c3bdfSopenharmony_ci}
319f08c3bdfSopenharmony_ci
320f08c3bdfSopenharmony_ci
321f08c3bdfSopenharmony_ci#define	OPTNUM_ZERO_IS_INF		1
322f08c3bdfSopenharmony_ci#define	OPTNUM_UNLIMITED		2
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ci#define OPT_NUMERIC(NAME, TYPE, FUNCTION)	\
325f08c3bdfSopenharmony_cistatic int opt_##NAME(const char *arg, const char *opt, TYPE *ptr, int flag)	\
326f08c3bdfSopenharmony_ci{									\
327f08c3bdfSopenharmony_ci	char *end;							\
328f08c3bdfSopenharmony_ci	TYPE val;							\
329f08c3bdfSopenharmony_ci									\
330f08c3bdfSopenharmony_ci	val = FUNCTION(opt, &end, 0);					\
331f08c3bdfSopenharmony_ci	if (*end != '\0' || end == opt) {				\
332f08c3bdfSopenharmony_ci		if ((flag & OPTNUM_UNLIMITED) && !strcmp(opt, "unlimited"))	\
333f08c3bdfSopenharmony_ci			val = ~val;					\
334f08c3bdfSopenharmony_ci		else							\
335f08c3bdfSopenharmony_ci			die("error: wrong argument to \'%s\'", arg);	\
336f08c3bdfSopenharmony_ci	}								\
337f08c3bdfSopenharmony_ci	if ((flag & OPTNUM_ZERO_IS_INF) && val == 0)			\
338f08c3bdfSopenharmony_ci		val = ~val;						\
339f08c3bdfSopenharmony_ci	*ptr = val;							\
340f08c3bdfSopenharmony_ci	return 1;							\
341f08c3bdfSopenharmony_ci}
342f08c3bdfSopenharmony_ci
343f08c3bdfSopenharmony_ciOPT_NUMERIC(ullong, unsigned long long, strtoull)
344f08c3bdfSopenharmony_ciOPT_NUMERIC(uint, unsigned int, strtoul)
345f08c3bdfSopenharmony_ci
346f08c3bdfSopenharmony_ci////////////////////////////////////////////////////////////////////////////////
347f08c3bdfSopenharmony_ci// Option parsing
348f08c3bdfSopenharmony_ci
349f08c3bdfSopenharmony_cistatic char **handle_switch_a(char *arg, char **next)
350f08c3bdfSopenharmony_ci{
351f08c3bdfSopenharmony_ci	if (!strcmp(arg, "ansi"))
352f08c3bdfSopenharmony_ci		standard = STANDARD_C89;
353f08c3bdfSopenharmony_ci
354f08c3bdfSopenharmony_ci	return next;
355f08c3bdfSopenharmony_ci}
356f08c3bdfSopenharmony_ci
357f08c3bdfSopenharmony_cistatic char **handle_switch_D(char *arg, char **next)
358f08c3bdfSopenharmony_ci{
359f08c3bdfSopenharmony_ci	const char *name = arg + 1;
360f08c3bdfSopenharmony_ci	const char *value = "1";
361f08c3bdfSopenharmony_ci
362f08c3bdfSopenharmony_ci	if (!*name) {
363f08c3bdfSopenharmony_ci		arg = *++next;
364f08c3bdfSopenharmony_ci		if (!arg)
365f08c3bdfSopenharmony_ci			die("argument to `-D' is missing");
366f08c3bdfSopenharmony_ci		name = arg;
367f08c3bdfSopenharmony_ci	}
368f08c3bdfSopenharmony_ci
369f08c3bdfSopenharmony_ci	for (;;arg++) {
370f08c3bdfSopenharmony_ci		char c;
371f08c3bdfSopenharmony_ci		c = *arg;
372f08c3bdfSopenharmony_ci		if (!c)
373f08c3bdfSopenharmony_ci			break;
374f08c3bdfSopenharmony_ci		if (c == '=') {
375f08c3bdfSopenharmony_ci			*arg = '\0';
376f08c3bdfSopenharmony_ci			value = arg + 1;
377f08c3bdfSopenharmony_ci			break;
378f08c3bdfSopenharmony_ci		}
379f08c3bdfSopenharmony_ci	}
380f08c3bdfSopenharmony_ci	add_pre_buffer("#define %s %s\n", name, value);
381f08c3bdfSopenharmony_ci	return next;
382f08c3bdfSopenharmony_ci}
383f08c3bdfSopenharmony_ci
384f08c3bdfSopenharmony_cistatic char **handle_switch_d(char *arg, char **next)
385f08c3bdfSopenharmony_ci{
386f08c3bdfSopenharmony_ci	char *arg_char = arg + 1;
387f08c3bdfSopenharmony_ci
388f08c3bdfSopenharmony_ci	/*
389f08c3bdfSopenharmony_ci	 * -d<CHARS>, where <CHARS> is a sequence of characters, not preceded
390f08c3bdfSopenharmony_ci	 * by a space. If you specify characters whose behaviour conflicts,
391f08c3bdfSopenharmony_ci	 * the result is undefined.
392f08c3bdfSopenharmony_ci	 */
393f08c3bdfSopenharmony_ci	while (*arg_char) {
394f08c3bdfSopenharmony_ci		switch (*arg_char) {
395f08c3bdfSopenharmony_ci		case 'M': /* dump just the macro definitions */
396f08c3bdfSopenharmony_ci			dump_macros_only = 1;
397f08c3bdfSopenharmony_ci			dump_macro_defs = 0;
398f08c3bdfSopenharmony_ci			break;
399f08c3bdfSopenharmony_ci		case 'D': /* like 'M', but also output pre-processed text */
400f08c3bdfSopenharmony_ci			dump_macro_defs = 1;
401f08c3bdfSopenharmony_ci			dump_macros_only = 0;
402f08c3bdfSopenharmony_ci			break;
403f08c3bdfSopenharmony_ci		case 'N': /* like 'D', but only output macro names not bodies */
404f08c3bdfSopenharmony_ci			break;
405f08c3bdfSopenharmony_ci		case 'I': /* like 'D', but also output #include directives */
406f08c3bdfSopenharmony_ci			break;
407f08c3bdfSopenharmony_ci		case 'U': /* like 'D', but only output expanded macros */
408f08c3bdfSopenharmony_ci			break;
409f08c3bdfSopenharmony_ci		}
410f08c3bdfSopenharmony_ci		arg_char++;
411f08c3bdfSopenharmony_ci	}
412f08c3bdfSopenharmony_ci	return next;
413f08c3bdfSopenharmony_ci}
414f08c3bdfSopenharmony_ci
415f08c3bdfSopenharmony_cistatic char **handle_switch_E(char *arg, char **next)
416f08c3bdfSopenharmony_ci{
417f08c3bdfSopenharmony_ci	if (arg[1] == '\0')
418f08c3bdfSopenharmony_ci		preprocess_only = 1;
419f08c3bdfSopenharmony_ci	return next;
420f08c3bdfSopenharmony_ci}
421f08c3bdfSopenharmony_ci
422f08c3bdfSopenharmony_cistatic int handle_ftabstop(const char *arg, const char *opt, const struct flag *flag, int options)
423f08c3bdfSopenharmony_ci{
424f08c3bdfSopenharmony_ci	unsigned long val;
425f08c3bdfSopenharmony_ci	char *end;
426f08c3bdfSopenharmony_ci
427f08c3bdfSopenharmony_ci	if (*opt == '\0')
428f08c3bdfSopenharmony_ci		die("error: missing argument to \"%s\"", arg);
429f08c3bdfSopenharmony_ci
430f08c3bdfSopenharmony_ci	/* we silently ignore silly values */
431f08c3bdfSopenharmony_ci	val = strtoul(opt, &end, 10);
432f08c3bdfSopenharmony_ci	if (*end == '\0' && 1 <= val && val <= 100)
433f08c3bdfSopenharmony_ci		tabstop = val;
434f08c3bdfSopenharmony_ci
435f08c3bdfSopenharmony_ci	return 1;
436f08c3bdfSopenharmony_ci}
437f08c3bdfSopenharmony_ci
438f08c3bdfSopenharmony_cistatic int handle_fpasses(const char *arg, const char *opt, const struct flag *flag, int options)
439f08c3bdfSopenharmony_ci{
440f08c3bdfSopenharmony_ci	unsigned long mask;
441f08c3bdfSopenharmony_ci
442f08c3bdfSopenharmony_ci	mask = flag->mask;
443f08c3bdfSopenharmony_ci	if (*opt == '\0') {
444f08c3bdfSopenharmony_ci		if (options & OPT_INVERSE)
445f08c3bdfSopenharmony_ci			fpasses &= ~mask;
446f08c3bdfSopenharmony_ci		else
447f08c3bdfSopenharmony_ci			fpasses |=  mask;
448f08c3bdfSopenharmony_ci		return 1;
449f08c3bdfSopenharmony_ci	}
450f08c3bdfSopenharmony_ci	if (options & OPT_INVERSE)
451f08c3bdfSopenharmony_ci		return 0;
452f08c3bdfSopenharmony_ci	if (!strcmp(opt, "-enable")) {
453f08c3bdfSopenharmony_ci		fpasses |= mask;
454f08c3bdfSopenharmony_ci		return 1;
455f08c3bdfSopenharmony_ci	}
456f08c3bdfSopenharmony_ci	if (!strcmp(opt, "-disable")) {
457f08c3bdfSopenharmony_ci		fpasses &= ~mask;
458f08c3bdfSopenharmony_ci		return 1;
459f08c3bdfSopenharmony_ci	}
460f08c3bdfSopenharmony_ci	if (!strcmp(opt, "=last")) {
461f08c3bdfSopenharmony_ci		// clear everything above
462f08c3bdfSopenharmony_ci		mask |= mask - 1;
463f08c3bdfSopenharmony_ci		fpasses &= mask;
464f08c3bdfSopenharmony_ci		return 1;
465f08c3bdfSopenharmony_ci	}
466f08c3bdfSopenharmony_ci	return 0;
467f08c3bdfSopenharmony_ci}
468f08c3bdfSopenharmony_ci
469f08c3bdfSopenharmony_cistatic int handle_fdiagnostic_prefix(const char *arg, const char *opt, const struct flag *flag, int options)
470f08c3bdfSopenharmony_ci{
471f08c3bdfSopenharmony_ci	switch (*opt) {
472f08c3bdfSopenharmony_ci	case '\0':
473f08c3bdfSopenharmony_ci		diag_prefix = "sparse: ";
474f08c3bdfSopenharmony_ci		return 1;
475f08c3bdfSopenharmony_ci	case '=':
476f08c3bdfSopenharmony_ci		diag_prefix = xasprintf("%s: ", opt+1);
477f08c3bdfSopenharmony_ci		return 1;
478f08c3bdfSopenharmony_ci	default:
479f08c3bdfSopenharmony_ci		return 0;
480f08c3bdfSopenharmony_ci	}
481f08c3bdfSopenharmony_ci}
482f08c3bdfSopenharmony_ci
483f08c3bdfSopenharmony_cistatic int handle_fdump_ir(const char *arg, const char *opt, const struct flag *flag, int options)
484f08c3bdfSopenharmony_ci{
485f08c3bdfSopenharmony_ci	static const struct mask_map dump_ir_options[] = {
486f08c3bdfSopenharmony_ci		{ "",			PASS_LINEARIZE },
487f08c3bdfSopenharmony_ci		{ "linearize",		PASS_LINEARIZE },
488f08c3bdfSopenharmony_ci		{ "mem2reg",		PASS_MEM2REG },
489f08c3bdfSopenharmony_ci		{ "final",		PASS_FINAL },
490f08c3bdfSopenharmony_ci		{ },
491f08c3bdfSopenharmony_ci	};
492f08c3bdfSopenharmony_ci
493f08c3bdfSopenharmony_ci	return handle_suboption_mask(arg, opt, dump_ir_options, &fdump_ir);
494f08c3bdfSopenharmony_ci}
495f08c3bdfSopenharmony_ci
496f08c3bdfSopenharmony_cistatic int handle_fmemcpy_max_count(const char *arg, const char *opt, const struct flag *flag, int options)
497f08c3bdfSopenharmony_ci{
498f08c3bdfSopenharmony_ci	opt_ullong(arg, opt, &fmemcpy_max_count, OPTNUM_ZERO_IS_INF|OPTNUM_UNLIMITED);
499f08c3bdfSopenharmony_ci	return 1;
500f08c3bdfSopenharmony_ci}
501f08c3bdfSopenharmony_ci
502f08c3bdfSopenharmony_cistatic int handle_fmax_errors(const char *arg, const char *opt, const struct flag *flag, int options)
503f08c3bdfSopenharmony_ci{
504f08c3bdfSopenharmony_ci	opt_uint(arg, opt, &fmax_errors, OPTNUM_UNLIMITED);
505f08c3bdfSopenharmony_ci	return 1;
506f08c3bdfSopenharmony_ci}
507f08c3bdfSopenharmony_ci
508f08c3bdfSopenharmony_cistatic int handle_fmax_warnings(const char *arg, const char *opt, const struct flag *flag, int options)
509f08c3bdfSopenharmony_ci{
510f08c3bdfSopenharmony_ci	opt_uint(arg, opt, &fmax_warnings, OPTNUM_UNLIMITED);
511f08c3bdfSopenharmony_ci	return 1;
512f08c3bdfSopenharmony_ci}
513f08c3bdfSopenharmony_ci
514f08c3bdfSopenharmony_cistatic struct flag fflags[] = {
515f08c3bdfSopenharmony_ci	{ "diagnostic-prefix",	NULL,	handle_fdiagnostic_prefix },
516f08c3bdfSopenharmony_ci	{ "dump-ir",		NULL,	handle_fdump_ir },
517f08c3bdfSopenharmony_ci	{ "freestanding",	&fhosted, NULL, OPT_INVERSE },
518f08c3bdfSopenharmony_ci	{ "hosted",		&fhosted },
519f08c3bdfSopenharmony_ci	{ "linearize",		NULL,	handle_fpasses,	PASS_LINEARIZE },
520f08c3bdfSopenharmony_ci	{ "max-errors=",	NULL,	handle_fmax_errors },
521f08c3bdfSopenharmony_ci	{ "max-warnings=",	NULL,	handle_fmax_warnings },
522f08c3bdfSopenharmony_ci	{ "mem-report",		&fmem_report },
523f08c3bdfSopenharmony_ci	{ "memcpy-max-count=",	NULL,	handle_fmemcpy_max_count },
524f08c3bdfSopenharmony_ci	{ "tabstop=",		NULL,	handle_ftabstop },
525f08c3bdfSopenharmony_ci	{ "mem2reg",		NULL,	handle_fpasses,	PASS_MEM2REG },
526f08c3bdfSopenharmony_ci	{ "optim",		NULL,	handle_fpasses,	PASS_OPTIM },
527f08c3bdfSopenharmony_ci	{ "pic",		&fpic,	handle_switch_setval, 1 },
528f08c3bdfSopenharmony_ci	{ "PIC",		&fpic,	handle_switch_setval, 2 },
529f08c3bdfSopenharmony_ci	{ "pie",		&fpie,	handle_switch_setval, 1 },
530f08c3bdfSopenharmony_ci	{ "PIE",		&fpie,	handle_switch_setval, 2 },
531f08c3bdfSopenharmony_ci	{ "signed-bitfields",	&funsigned_bitfields, NULL, OPT_INVERSE },
532f08c3bdfSopenharmony_ci	{ "unsigned-bitfields",	&funsigned_bitfields, NULL, },
533f08c3bdfSopenharmony_ci	{ "signed-char",	&funsigned_char, NULL,	OPT_INVERSE },
534f08c3bdfSopenharmony_ci	{ "short-wchar",	&fshort_wchar },
535f08c3bdfSopenharmony_ci	{ "unsigned-char",	&funsigned_char, NULL, },
536f08c3bdfSopenharmony_ci	{ },
537f08c3bdfSopenharmony_ci};
538f08c3bdfSopenharmony_ci
539f08c3bdfSopenharmony_cistatic char **handle_switch_f(char *arg, char **next)
540f08c3bdfSopenharmony_ci{
541f08c3bdfSopenharmony_ci	if (handle_switches(arg-1, arg+1, fflags))
542f08c3bdfSopenharmony_ci		return next;
543f08c3bdfSopenharmony_ci
544f08c3bdfSopenharmony_ci	return next;
545f08c3bdfSopenharmony_ci}
546f08c3bdfSopenharmony_ci
547f08c3bdfSopenharmony_cistatic char **handle_switch_G(char *arg, char **next)
548f08c3bdfSopenharmony_ci{
549f08c3bdfSopenharmony_ci	if (!strcmp(arg, "G") && *next)
550f08c3bdfSopenharmony_ci		return next + 1; // "-G 0"
551f08c3bdfSopenharmony_ci	else
552f08c3bdfSopenharmony_ci		return next;     // "-G0" or (bogus) terminal "-G"
553f08c3bdfSopenharmony_ci}
554f08c3bdfSopenharmony_ci
555f08c3bdfSopenharmony_cistatic char **handle_base_dir(char *arg, char **next)
556f08c3bdfSopenharmony_ci{
557f08c3bdfSopenharmony_ci	gcc_base_dir = *++next;
558f08c3bdfSopenharmony_ci	if (!gcc_base_dir)
559f08c3bdfSopenharmony_ci		die("missing argument for -gcc-base-dir option");
560f08c3bdfSopenharmony_ci	return next;
561f08c3bdfSopenharmony_ci}
562f08c3bdfSopenharmony_ci
563f08c3bdfSopenharmony_cistatic char **handle_switch_g(char *arg, char **next)
564f08c3bdfSopenharmony_ci{
565f08c3bdfSopenharmony_ci	if (!strcmp(arg, "gcc-base-dir"))
566f08c3bdfSopenharmony_ci		return handle_base_dir(arg, next);
567f08c3bdfSopenharmony_ci
568f08c3bdfSopenharmony_ci	return next;
569f08c3bdfSopenharmony_ci}
570f08c3bdfSopenharmony_ci
571f08c3bdfSopenharmony_cistatic char **handle_switch_I(char *arg, char **next)
572f08c3bdfSopenharmony_ci{
573f08c3bdfSopenharmony_ci	char *path = arg+1;
574f08c3bdfSopenharmony_ci
575f08c3bdfSopenharmony_ci	switch (arg[1]) {
576f08c3bdfSopenharmony_ci	case '-':
577f08c3bdfSopenharmony_ci		add_pre_buffer("#split_include\n");
578f08c3bdfSopenharmony_ci		break;
579f08c3bdfSopenharmony_ci
580f08c3bdfSopenharmony_ci	case '\0':	/* Plain "-I" */
581f08c3bdfSopenharmony_ci		path = *++next;
582f08c3bdfSopenharmony_ci		if (!path)
583f08c3bdfSopenharmony_ci			die("missing argument for -I option");
584f08c3bdfSopenharmony_ci		/* Fall through */
585f08c3bdfSopenharmony_ci	default:
586f08c3bdfSopenharmony_ci		add_pre_buffer("#add_include \"%s/\"\n", path);
587f08c3bdfSopenharmony_ci	}
588f08c3bdfSopenharmony_ci	return next;
589f08c3bdfSopenharmony_ci}
590f08c3bdfSopenharmony_ci
591f08c3bdfSopenharmony_cistatic void add_cmdline_include(char *filename)
592f08c3bdfSopenharmony_ci{
593f08c3bdfSopenharmony_ci	if (cmdline_include_nr >= CMDLINE_INCLUDE)
594f08c3bdfSopenharmony_ci		die("too many include files for %s\n", filename);
595f08c3bdfSopenharmony_ci	cmdline_include[cmdline_include_nr++] = filename;
596f08c3bdfSopenharmony_ci}
597f08c3bdfSopenharmony_ci
598f08c3bdfSopenharmony_cistatic char **handle_switch_i(char *arg, char **next)
599f08c3bdfSopenharmony_ci{
600f08c3bdfSopenharmony_ci	if (*next && !strcmp(arg, "include"))
601f08c3bdfSopenharmony_ci		add_cmdline_include(*++next);
602f08c3bdfSopenharmony_ci	else if (*next && !strcmp(arg, "imacros"))
603f08c3bdfSopenharmony_ci		add_cmdline_include(*++next);
604f08c3bdfSopenharmony_ci	else if (*next && !strcmp(arg, "isystem")) {
605f08c3bdfSopenharmony_ci		char *path = *++next;
606f08c3bdfSopenharmony_ci		if (!path)
607f08c3bdfSopenharmony_ci			die("missing argument for -isystem option");
608f08c3bdfSopenharmony_ci		add_pre_buffer("#add_isystem \"%s/\"\n", path);
609f08c3bdfSopenharmony_ci	} else if (*next && !strcmp(arg, "idirafter")) {
610f08c3bdfSopenharmony_ci		char *path = *++next;
611f08c3bdfSopenharmony_ci		if (!path)
612f08c3bdfSopenharmony_ci			die("missing argument for -idirafter option");
613f08c3bdfSopenharmony_ci		add_pre_buffer("#add_dirafter \"%s/\"\n", path);
614f08c3bdfSopenharmony_ci	}
615f08c3bdfSopenharmony_ci	return next;
616f08c3bdfSopenharmony_ci}
617f08c3bdfSopenharmony_ci
618f08c3bdfSopenharmony_cistatic char **handle_switch_M(char *arg, char **next)
619f08c3bdfSopenharmony_ci{
620f08c3bdfSopenharmony_ci	if (!strcmp(arg, "MF") || !strcmp(arg,"MQ") || !strcmp(arg,"MT")) {
621f08c3bdfSopenharmony_ci		if (!*next)
622f08c3bdfSopenharmony_ci			die("missing argument for -%s option", arg);
623f08c3bdfSopenharmony_ci		return next + 1;
624f08c3bdfSopenharmony_ci	}
625f08c3bdfSopenharmony_ci	return next;
626f08c3bdfSopenharmony_ci}
627f08c3bdfSopenharmony_ci
628f08c3bdfSopenharmony_cistatic int handle_march(const char *opt, const char *arg, const struct flag *flag, int options)
629f08c3bdfSopenharmony_ci{
630f08c3bdfSopenharmony_ci	if (arch_target->parse_march)
631f08c3bdfSopenharmony_ci		arch_target->parse_march(arg);
632f08c3bdfSopenharmony_ci	return 1;
633f08c3bdfSopenharmony_ci}
634f08c3bdfSopenharmony_ci
635f08c3bdfSopenharmony_cistatic int handle_mcmodel(const char *opt, const char *arg, const struct flag *flag, int options)
636f08c3bdfSopenharmony_ci{
637f08c3bdfSopenharmony_ci	static const struct val_map cmodels[] = {
638f08c3bdfSopenharmony_ci		{ "kernel",	CMODEL_KERNEL },
639f08c3bdfSopenharmony_ci		{ "large",	CMODEL_LARGE },
640f08c3bdfSopenharmony_ci		{ "medany",	CMODEL_MEDANY },
641f08c3bdfSopenharmony_ci		{ "medium",	CMODEL_MEDIUM },
642f08c3bdfSopenharmony_ci		{ "medlow",	CMODEL_MEDLOW },
643f08c3bdfSopenharmony_ci		{ "small",	CMODEL_SMALL },
644f08c3bdfSopenharmony_ci		{ "tiny",	CMODEL_TINY },
645f08c3bdfSopenharmony_ci		{ },
646f08c3bdfSopenharmony_ci	};
647f08c3bdfSopenharmony_ci	return handle_subopt_val(opt, arg, cmodels, flag->flag);
648f08c3bdfSopenharmony_ci}
649f08c3bdfSopenharmony_ci
650f08c3bdfSopenharmony_cistatic int handle_mfloat_abi(const char *opt, const char *arg, const struct flag *flag, int options) {
651f08c3bdfSopenharmony_ci	static const struct val_map fp_abis[] = {
652f08c3bdfSopenharmony_ci		{ "hard",		FP_ABI_HARD },
653f08c3bdfSopenharmony_ci		{ "soft",		FP_ABI_SOFT },
654f08c3bdfSopenharmony_ci		{ "softfp",		FP_ABI_HYBRID },
655f08c3bdfSopenharmony_ci		{ "?" },
656f08c3bdfSopenharmony_ci	};
657f08c3bdfSopenharmony_ci	return handle_subopt_val(opt, arg, fp_abis, flag->flag);
658f08c3bdfSopenharmony_ci}
659f08c3bdfSopenharmony_ci
660f08c3bdfSopenharmony_cistatic char **handle_multiarch_dir(char *arg, char **next)
661f08c3bdfSopenharmony_ci{
662f08c3bdfSopenharmony_ci	multiarch_dir = *++next;
663f08c3bdfSopenharmony_ci	if (!multiarch_dir)
664f08c3bdfSopenharmony_ci		die("missing argument for -multiarch-dir option");
665f08c3bdfSopenharmony_ci	return next;
666f08c3bdfSopenharmony_ci}
667f08c3bdfSopenharmony_ci
668f08c3bdfSopenharmony_cistatic const struct flag mflags[] = {
669f08c3bdfSopenharmony_ci	{ "64", &arch_m64, NULL, OPT_VAL, ARCH_LP64 },
670f08c3bdfSopenharmony_ci	{ "32", &arch_m64, NULL, OPT_VAL, ARCH_LP32 },
671f08c3bdfSopenharmony_ci	{ "31", &arch_m64, NULL, OPT_VAL, ARCH_LP32 },
672f08c3bdfSopenharmony_ci	{ "16", &arch_m64, NULL, OPT_VAL, ARCH_LP32 },
673f08c3bdfSopenharmony_ci	{ "x32",&arch_m64, NULL, OPT_VAL, ARCH_X32 },
674f08c3bdfSopenharmony_ci	{ "size-llp64", &arch_m64, NULL, OPT_VAL, ARCH_LLP64 },
675f08c3bdfSopenharmony_ci	{ "size-long", &arch_msize_long },
676f08c3bdfSopenharmony_ci	{ "arch=", NULL, handle_march },
677f08c3bdfSopenharmony_ci	{ "big-endian", &arch_big_endian, NULL },
678f08c3bdfSopenharmony_ci	{ "little-endian", &arch_big_endian, NULL, OPT_INVERSE },
679f08c3bdfSopenharmony_ci	{ "cmodel", &arch_cmodel, handle_mcmodel },
680f08c3bdfSopenharmony_ci	{ "float-abi", &arch_fp_abi, handle_mfloat_abi },
681f08c3bdfSopenharmony_ci	{ "hard-float", &arch_fp_abi, NULL, OPT_VAL, FP_ABI_HARD },
682f08c3bdfSopenharmony_ci	{ "soft-float", &arch_fp_abi, NULL, OPT_VAL, FP_ABI_SOFT },
683f08c3bdfSopenharmony_ci	{ }
684f08c3bdfSopenharmony_ci};
685f08c3bdfSopenharmony_ci
686f08c3bdfSopenharmony_cistatic char **handle_switch_m(char *arg, char **next)
687f08c3bdfSopenharmony_ci{
688f08c3bdfSopenharmony_ci	if (!strcmp(arg, "multiarch-dir")) {
689f08c3bdfSopenharmony_ci		return handle_multiarch_dir(arg, next);
690f08c3bdfSopenharmony_ci	} else {
691f08c3bdfSopenharmony_ci		handle_switches(arg-1, arg+1, mflags);
692f08c3bdfSopenharmony_ci	}
693f08c3bdfSopenharmony_ci
694f08c3bdfSopenharmony_ci	return next;
695f08c3bdfSopenharmony_ci}
696f08c3bdfSopenharmony_ci
697f08c3bdfSopenharmony_cistatic char **handle_nostdinc(char *arg, char **next)
698f08c3bdfSopenharmony_ci{
699f08c3bdfSopenharmony_ci	add_pre_buffer("#nostdinc\n");
700f08c3bdfSopenharmony_ci	return next;
701f08c3bdfSopenharmony_ci}
702f08c3bdfSopenharmony_ci
703f08c3bdfSopenharmony_cistatic char **handle_switch_n(char *arg, char **next)
704f08c3bdfSopenharmony_ci{
705f08c3bdfSopenharmony_ci	if (!strcmp(arg, "nostdinc"))
706f08c3bdfSopenharmony_ci		return handle_nostdinc(arg, next);
707f08c3bdfSopenharmony_ci
708f08c3bdfSopenharmony_ci	return next;
709f08c3bdfSopenharmony_ci}
710f08c3bdfSopenharmony_ci
711f08c3bdfSopenharmony_cistatic char **handle_switch_O(char *arg, char **next)
712f08c3bdfSopenharmony_ci{
713f08c3bdfSopenharmony_ci	int level = 1;
714f08c3bdfSopenharmony_ci	if (arg[1] >= '0' && arg[1] <= '9')
715f08c3bdfSopenharmony_ci		level = arg[1] - '0';
716f08c3bdfSopenharmony_ci	optimize_level = level;
717f08c3bdfSopenharmony_ci	optimize_size = arg[1] == 's';
718f08c3bdfSopenharmony_ci	return next;
719f08c3bdfSopenharmony_ci}
720f08c3bdfSopenharmony_ci
721f08c3bdfSopenharmony_cistatic char **handle_switch_o(char *arg, char **next)
722f08c3bdfSopenharmony_ci{
723f08c3bdfSopenharmony_ci	if (!strcmp(arg, "o")) {	// "-o foo"
724f08c3bdfSopenharmony_ci		if (!*++next)
725f08c3bdfSopenharmony_ci			die("argument to '-o' is missing");
726f08c3bdfSopenharmony_ci		outfile = *next;
727f08c3bdfSopenharmony_ci	}
728f08c3bdfSopenharmony_ci	// else "-ofoo"
729f08c3bdfSopenharmony_ci
730f08c3bdfSopenharmony_ci	return next;
731f08c3bdfSopenharmony_ci}
732f08c3bdfSopenharmony_ci
733f08c3bdfSopenharmony_cistatic const struct flag pflags[] = {
734f08c3bdfSopenharmony_ci	{ "pedantic", &Wpedantic, NULL, OPT_VAL, FLAG_ON },
735f08c3bdfSopenharmony_ci	{ }
736f08c3bdfSopenharmony_ci};
737f08c3bdfSopenharmony_ci
738f08c3bdfSopenharmony_cistatic char **handle_switch_p(char *arg, char **next)
739f08c3bdfSopenharmony_ci{
740f08c3bdfSopenharmony_ci	handle_switches(arg-1, arg, pflags);
741f08c3bdfSopenharmony_ci	return next;
742f08c3bdfSopenharmony_ci}
743f08c3bdfSopenharmony_ci
744f08c3bdfSopenharmony_cistatic char **handle_switch_s(const char *arg, char **next)
745f08c3bdfSopenharmony_ci{
746f08c3bdfSopenharmony_ci	if ((arg = match_option(arg, "std="))) {
747f08c3bdfSopenharmony_ci		if (!strcmp(arg, "c89") ||
748f08c3bdfSopenharmony_ci		    !strcmp(arg, "iso9899:1990"))
749f08c3bdfSopenharmony_ci			standard = STANDARD_C89;
750f08c3bdfSopenharmony_ci
751f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "iso9899:199409"))
752f08c3bdfSopenharmony_ci			standard = STANDARD_C94;
753f08c3bdfSopenharmony_ci
754f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "c99") ||
755f08c3bdfSopenharmony_ci			 !strcmp(arg, "c9x") ||
756f08c3bdfSopenharmony_ci			 !strcmp(arg, "iso9899:1999") ||
757f08c3bdfSopenharmony_ci			 !strcmp(arg, "iso9899:199x"))
758f08c3bdfSopenharmony_ci			standard = STANDARD_C99;
759f08c3bdfSopenharmony_ci
760f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "gnu89"))
761f08c3bdfSopenharmony_ci			standard = STANDARD_GNU89;
762f08c3bdfSopenharmony_ci
763f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "gnu99") || !strcmp(arg, "gnu9x"))
764f08c3bdfSopenharmony_ci			standard = STANDARD_GNU99;
765f08c3bdfSopenharmony_ci
766f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "c11") ||
767f08c3bdfSopenharmony_ci			 !strcmp(arg, "c1x") ||
768f08c3bdfSopenharmony_ci			 !strcmp(arg, "iso9899:2011"))
769f08c3bdfSopenharmony_ci			standard = STANDARD_C11;
770f08c3bdfSopenharmony_ci
771f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "gnu11"))
772f08c3bdfSopenharmony_ci			standard = STANDARD_GNU11;
773f08c3bdfSopenharmony_ci
774f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "c17") ||
775f08c3bdfSopenharmony_ci			 !strcmp(arg, "c18") ||
776f08c3bdfSopenharmony_ci			 !strcmp(arg, "iso9899:2017") ||
777f08c3bdfSopenharmony_ci			 !strcmp(arg, "iso9899:2018"))
778f08c3bdfSopenharmony_ci			standard = STANDARD_C17;
779f08c3bdfSopenharmony_ci		else if (!strcmp(arg, "gnu17") ||
780f08c3bdfSopenharmony_ci			 !strcmp(arg, "gnu18"))
781f08c3bdfSopenharmony_ci			standard = STANDARD_GNU17;
782f08c3bdfSopenharmony_ci
783f08c3bdfSopenharmony_ci		else
784f08c3bdfSopenharmony_ci			die("Unsupported C dialect");
785f08c3bdfSopenharmony_ci	}
786f08c3bdfSopenharmony_ci
787f08c3bdfSopenharmony_ci	return next;
788f08c3bdfSopenharmony_ci}
789f08c3bdfSopenharmony_ci
790f08c3bdfSopenharmony_cistatic char **handle_switch_U(char *arg, char **next)
791f08c3bdfSopenharmony_ci{
792f08c3bdfSopenharmony_ci	const char *name = arg + 1;
793f08c3bdfSopenharmony_ci
794f08c3bdfSopenharmony_ci	if (*name == '\0') {
795f08c3bdfSopenharmony_ci		name = *++next;
796f08c3bdfSopenharmony_ci		if (!name)
797f08c3bdfSopenharmony_ci			die("argument to `-U' is missing");
798f08c3bdfSopenharmony_ci	}
799f08c3bdfSopenharmony_ci	add_pre_buffer("#undef %s\n", name);
800f08c3bdfSopenharmony_ci	return next;
801f08c3bdfSopenharmony_ci}
802f08c3bdfSopenharmony_ci
803f08c3bdfSopenharmony_cistatic struct flag debugs[] = {
804f08c3bdfSopenharmony_ci	{ "compound", &dbg_compound},
805f08c3bdfSopenharmony_ci	{ "dead", &dbg_dead},
806f08c3bdfSopenharmony_ci	{ "domtree", &dbg_domtree},
807f08c3bdfSopenharmony_ci	{ "entry", &dbg_entry},
808f08c3bdfSopenharmony_ci	{ "ir", &dbg_ir},
809f08c3bdfSopenharmony_ci	{ "postorder", &dbg_postorder},
810f08c3bdfSopenharmony_ci	{ }
811f08c3bdfSopenharmony_ci};
812f08c3bdfSopenharmony_ci
813f08c3bdfSopenharmony_cistatic char **handle_switch_v(char *arg, char **next)
814f08c3bdfSopenharmony_ci{
815f08c3bdfSopenharmony_ci	char ** ret = handle_onoff_switch(arg, next, debugs);
816f08c3bdfSopenharmony_ci	if (ret)
817f08c3bdfSopenharmony_ci		return ret;
818f08c3bdfSopenharmony_ci
819f08c3bdfSopenharmony_ci	// Unknown.
820f08c3bdfSopenharmony_ci	do {
821f08c3bdfSopenharmony_ci		verbose++;
822f08c3bdfSopenharmony_ci	} while (*++arg == 'v');
823f08c3bdfSopenharmony_ci	return next;
824f08c3bdfSopenharmony_ci}
825f08c3bdfSopenharmony_ci
826f08c3bdfSopenharmony_cistatic void handle_switch_v_finalize(void)
827f08c3bdfSopenharmony_ci{
828f08c3bdfSopenharmony_ci	handle_onoff_switch_finalize(debugs);
829f08c3bdfSopenharmony_ci}
830f08c3bdfSopenharmony_ci
831f08c3bdfSopenharmony_cistatic const struct flag warnings[] = {
832f08c3bdfSopenharmony_ci	{ "address", &Waddress },
833f08c3bdfSopenharmony_ci	{ "address-space", &Waddress_space },
834f08c3bdfSopenharmony_ci	{ "bitwise", &Wbitwise },
835f08c3bdfSopenharmony_ci	{ "bitwise-pointer", &Wbitwise_pointer},
836f08c3bdfSopenharmony_ci	{ "cast-from-as", &Wcast_from_as },
837f08c3bdfSopenharmony_ci	{ "cast-to-as", &Wcast_to_as },
838f08c3bdfSopenharmony_ci	{ "cast-truncate", &Wcast_truncate },
839f08c3bdfSopenharmony_ci	{ "constant-suffix", &Wconstant_suffix },
840f08c3bdfSopenharmony_ci	{ "constexpr-not-const", &Wconstexpr_not_const},
841f08c3bdfSopenharmony_ci	{ "context", &Wcontext },
842f08c3bdfSopenharmony_ci	{ "decl", &Wdecl },
843f08c3bdfSopenharmony_ci	{ "declaration-after-statement", &Wdeclarationafterstatement },
844f08c3bdfSopenharmony_ci	{ "default-bitfield-sign", &Wdefault_bitfield_sign },
845f08c3bdfSopenharmony_ci	{ "designated-init", &Wdesignated_init },
846f08c3bdfSopenharmony_ci	{ "do-while", &Wdo_while },
847f08c3bdfSopenharmony_ci	{ "enum-mismatch", &Wenum_mismatch },
848f08c3bdfSopenharmony_ci	{ "external-function-has-definition", &Wexternal_function_has_definition },
849f08c3bdfSopenharmony_ci	{ "flexible-array-array", &Wflexible_array_array },
850f08c3bdfSopenharmony_ci	{ "flexible-array-nested", &Wflexible_array_nested },
851f08c3bdfSopenharmony_ci	{ "flexible-array-sizeof", &Wflexible_array_sizeof },
852f08c3bdfSopenharmony_ci	{ "flexible-array-union", &Wflexible_array_union },
853f08c3bdfSopenharmony_ci	{ "implicit-int", &Wimplicit_int },
854f08c3bdfSopenharmony_ci	{ "init-cstring", &Winit_cstring },
855f08c3bdfSopenharmony_ci	{ "int-to-pointer-cast", &Wint_to_pointer_cast },
856f08c3bdfSopenharmony_ci	{ "memcpy-max-count", &Wmemcpy_max_count },
857f08c3bdfSopenharmony_ci	{ "non-pointer-null", &Wnon_pointer_null },
858f08c3bdfSopenharmony_ci	{ "newline-eof", &Wnewline_eof },
859f08c3bdfSopenharmony_ci	{ "old-initializer", &Wold_initializer },
860f08c3bdfSopenharmony_ci	{ "old-style-definition", &Wold_style_definition },
861f08c3bdfSopenharmony_ci	{ "one-bit-signed-bitfield", &Wone_bit_signed_bitfield },
862f08c3bdfSopenharmony_ci	{ "override-init", &Woverride_init },
863f08c3bdfSopenharmony_ci	{ "override-init-all", &Woverride_init_all },
864f08c3bdfSopenharmony_ci	{ "paren-string", &Wparen_string },
865f08c3bdfSopenharmony_ci	{ "past-deep-designator", &Wpast_deep_designator },
866f08c3bdfSopenharmony_ci	{ "pedantic", &Wpedantic },
867f08c3bdfSopenharmony_ci	{ "pointer-to-int-cast", &Wpointer_to_int_cast },
868f08c3bdfSopenharmony_ci	{ "ptr-subtraction-blows", &Wptr_subtraction_blows },
869f08c3bdfSopenharmony_ci	{ "return-void", &Wreturn_void },
870f08c3bdfSopenharmony_ci	{ "shadow", &Wshadow },
871f08c3bdfSopenharmony_ci	{ "shift-count-negative", &Wshift_count_negative },
872f08c3bdfSopenharmony_ci	{ "shift-count-overflow", &Wshift_count_overflow },
873f08c3bdfSopenharmony_ci	{ "sizeof-bool", &Wsizeof_bool },
874f08c3bdfSopenharmony_ci	{ "strict-prototypes", &Wstrict_prototypes },
875f08c3bdfSopenharmony_ci	{ "pointer-arith", &Wpointer_arith },
876f08c3bdfSopenharmony_ci	{ "sparse-error", &Wsparse_error },
877f08c3bdfSopenharmony_ci	{ "tautological-compare", &Wtautological_compare },
878f08c3bdfSopenharmony_ci	{ "transparent-union", &Wtransparent_union },
879f08c3bdfSopenharmony_ci	{ "typesign", &Wtypesign },
880f08c3bdfSopenharmony_ci	{ "undef", &Wundef },
881f08c3bdfSopenharmony_ci	{ "uninitialized", &Wuninitialized },
882f08c3bdfSopenharmony_ci	{ "union-cast", &Wunion_cast },
883f08c3bdfSopenharmony_ci	{ "universal-initializer", &Wuniversal_initializer },
884f08c3bdfSopenharmony_ci	{ "unknown-attribute", &Wunknown_attribute },
885f08c3bdfSopenharmony_ci	{ "vla", &Wvla },
886f08c3bdfSopenharmony_ci	{ }
887f08c3bdfSopenharmony_ci};
888f08c3bdfSopenharmony_ci
889f08c3bdfSopenharmony_cistatic char **handle_switch_W(char *arg, char **next)
890f08c3bdfSopenharmony_ci{
891f08c3bdfSopenharmony_ci	char ** ret = handle_onoff_switch(arg, next, warnings);
892f08c3bdfSopenharmony_ci	if (ret)
893f08c3bdfSopenharmony_ci		return ret;
894f08c3bdfSopenharmony_ci
895f08c3bdfSopenharmony_ci	if (!strcmp(arg, "Wsparse-all")) {
896f08c3bdfSopenharmony_ci		int i;
897f08c3bdfSopenharmony_ci		for (i = 0; warnings[i].name; i++) {
898f08c3bdfSopenharmony_ci			if (*warnings[i].flag != FLAG_FORCE_OFF)
899f08c3bdfSopenharmony_ci				*warnings[i].flag = FLAG_ON;
900f08c3bdfSopenharmony_ci		}
901f08c3bdfSopenharmony_ci	}
902f08c3bdfSopenharmony_ci
903f08c3bdfSopenharmony_ci	// Unknown.
904f08c3bdfSopenharmony_ci	return next;
905f08c3bdfSopenharmony_ci}
906f08c3bdfSopenharmony_ci
907f08c3bdfSopenharmony_cistatic void handle_switch_W_finalize(void)
908f08c3bdfSopenharmony_ci{
909f08c3bdfSopenharmony_ci	handle_onoff_switch_finalize(warnings);
910f08c3bdfSopenharmony_ci
911f08c3bdfSopenharmony_ci	/* default Wdeclarationafterstatement based on the C dialect */
912f08c3bdfSopenharmony_ci	if (-1 == Wdeclarationafterstatement) {
913f08c3bdfSopenharmony_ci		switch (standard) {
914f08c3bdfSopenharmony_ci			case STANDARD_C89:
915f08c3bdfSopenharmony_ci			case STANDARD_C94:
916f08c3bdfSopenharmony_ci				Wdeclarationafterstatement = 1;
917f08c3bdfSopenharmony_ci				break;
918f08c3bdfSopenharmony_ci			default:
919f08c3bdfSopenharmony_ci				Wdeclarationafterstatement = 0;
920f08c3bdfSopenharmony_ci				break;
921f08c3bdfSopenharmony_ci		}
922f08c3bdfSopenharmony_ci	}
923f08c3bdfSopenharmony_ci}
924f08c3bdfSopenharmony_ci
925f08c3bdfSopenharmony_cistatic char **handle_switch_x(char *arg, char **next)
926f08c3bdfSopenharmony_ci{
927f08c3bdfSopenharmony_ci	if (!*++next)
928f08c3bdfSopenharmony_ci		die("missing argument for -x option");
929f08c3bdfSopenharmony_ci	return next;
930f08c3bdfSopenharmony_ci}
931f08c3bdfSopenharmony_ci
932f08c3bdfSopenharmony_ci
933f08c3bdfSopenharmony_cistatic char **handle_arch(char *arg, char **next)
934f08c3bdfSopenharmony_ci{
935f08c3bdfSopenharmony_ci	enum machine mach;
936f08c3bdfSopenharmony_ci
937f08c3bdfSopenharmony_ci	if (*arg++ != '=')
938f08c3bdfSopenharmony_ci		die("missing argument for --arch option");
939f08c3bdfSopenharmony_ci
940f08c3bdfSopenharmony_ci	mach = target_parse(arg);
941f08c3bdfSopenharmony_ci	if (mach != MACH_UNKNOWN)
942f08c3bdfSopenharmony_ci		target_config(mach);
943f08c3bdfSopenharmony_ci
944f08c3bdfSopenharmony_ci	return next;
945f08c3bdfSopenharmony_ci}
946f08c3bdfSopenharmony_ci
947f08c3bdfSopenharmony_cistatic char **handle_param(char *arg, char **next)
948f08c3bdfSopenharmony_ci{
949f08c3bdfSopenharmony_ci	char *value = NULL;
950f08c3bdfSopenharmony_ci
951f08c3bdfSopenharmony_ci	/* For now just skip any '--param=*' or '--param *' */
952f08c3bdfSopenharmony_ci	if (*arg == '\0') {
953f08c3bdfSopenharmony_ci		value = *++next;
954f08c3bdfSopenharmony_ci	} else if (isspace((unsigned char)*arg) || *arg == '=') {
955f08c3bdfSopenharmony_ci		value = ++arg;
956f08c3bdfSopenharmony_ci	}
957f08c3bdfSopenharmony_ci
958f08c3bdfSopenharmony_ci	if (!value)
959f08c3bdfSopenharmony_ci		die("missing argument for --param option");
960f08c3bdfSopenharmony_ci
961f08c3bdfSopenharmony_ci	return next;
962f08c3bdfSopenharmony_ci}
963f08c3bdfSopenharmony_ci
964f08c3bdfSopenharmony_cistatic char **handle_os(char *arg, char **next)
965f08c3bdfSopenharmony_ci{
966f08c3bdfSopenharmony_ci	if (*arg++ != '=')
967f08c3bdfSopenharmony_ci		die("missing argument for --os option");
968f08c3bdfSopenharmony_ci
969f08c3bdfSopenharmony_ci	target_os(arg);
970f08c3bdfSopenharmony_ci
971f08c3bdfSopenharmony_ci	return next;
972f08c3bdfSopenharmony_ci}
973f08c3bdfSopenharmony_ci
974f08c3bdfSopenharmony_cistatic char **handle_version(char *arg, char **next)
975f08c3bdfSopenharmony_ci{
976f08c3bdfSopenharmony_ci	printf("%s\n", sparse_version);
977f08c3bdfSopenharmony_ci	exit(0);
978f08c3bdfSopenharmony_ci}
979f08c3bdfSopenharmony_ci
980f08c3bdfSopenharmony_cistruct switches {
981f08c3bdfSopenharmony_ci	const char *name;
982f08c3bdfSopenharmony_ci	char **(*fn)(char *, char **);
983f08c3bdfSopenharmony_ci	unsigned int prefix:1;
984f08c3bdfSopenharmony_ci};
985f08c3bdfSopenharmony_ci
986f08c3bdfSopenharmony_cistatic char **handle_long_options(char *arg, char **next)
987f08c3bdfSopenharmony_ci{
988f08c3bdfSopenharmony_ci	static struct switches cmd[] = {
989f08c3bdfSopenharmony_ci		{ "arch", handle_arch, 1 },
990f08c3bdfSopenharmony_ci		{ "os",   handle_os, 1 },
991f08c3bdfSopenharmony_ci		{ "param", handle_param, 1 },
992f08c3bdfSopenharmony_ci		{ "version", handle_version },
993f08c3bdfSopenharmony_ci		{ NULL, NULL }
994f08c3bdfSopenharmony_ci	};
995f08c3bdfSopenharmony_ci	struct switches *s = cmd;
996f08c3bdfSopenharmony_ci
997f08c3bdfSopenharmony_ci	while (s->name) {
998f08c3bdfSopenharmony_ci		int optlen = strlen(s->name);
999f08c3bdfSopenharmony_ci		if (!strncmp(s->name, arg, optlen + !s->prefix))
1000f08c3bdfSopenharmony_ci			return s->fn(arg + optlen, next);
1001f08c3bdfSopenharmony_ci		s++;
1002f08c3bdfSopenharmony_ci	}
1003f08c3bdfSopenharmony_ci	return next;
1004f08c3bdfSopenharmony_ci}
1005f08c3bdfSopenharmony_ci
1006f08c3bdfSopenharmony_cichar **handle_switch(char *arg, char **next)
1007f08c3bdfSopenharmony_ci{
1008f08c3bdfSopenharmony_ci	switch (*arg) {
1009f08c3bdfSopenharmony_ci	case 'a': return handle_switch_a(arg, next);
1010f08c3bdfSopenharmony_ci	case 'D': return handle_switch_D(arg, next);
1011f08c3bdfSopenharmony_ci	case 'd': return handle_switch_d(arg, next);
1012f08c3bdfSopenharmony_ci	case 'E': return handle_switch_E(arg, next);
1013f08c3bdfSopenharmony_ci	case 'f': return handle_switch_f(arg, next);
1014f08c3bdfSopenharmony_ci	case 'g': return handle_switch_g(arg, next);
1015f08c3bdfSopenharmony_ci	case 'G': return handle_switch_G(arg, next);
1016f08c3bdfSopenharmony_ci	case 'I': return handle_switch_I(arg, next);
1017f08c3bdfSopenharmony_ci	case 'i': return handle_switch_i(arg, next);
1018f08c3bdfSopenharmony_ci	case 'M': return handle_switch_M(arg, next);
1019f08c3bdfSopenharmony_ci	case 'm': return handle_switch_m(arg, next);
1020f08c3bdfSopenharmony_ci	case 'n': return handle_switch_n(arg, next);
1021f08c3bdfSopenharmony_ci	case 'o': return handle_switch_o(arg, next);
1022f08c3bdfSopenharmony_ci	case 'O': return handle_switch_O(arg, next);
1023f08c3bdfSopenharmony_ci	case 'p': return handle_switch_p(arg, next);
1024f08c3bdfSopenharmony_ci	case 's': return handle_switch_s(arg, next);
1025f08c3bdfSopenharmony_ci	case 'U': return handle_switch_U(arg, next);
1026f08c3bdfSopenharmony_ci	case 'v': return handle_switch_v(arg, next);
1027f08c3bdfSopenharmony_ci	case 'W': return handle_switch_W(arg, next);
1028f08c3bdfSopenharmony_ci	case 'x': return handle_switch_x(arg, next);
1029f08c3bdfSopenharmony_ci	case '-': return handle_long_options(arg + 1, next);
1030f08c3bdfSopenharmony_ci	default:
1031f08c3bdfSopenharmony_ci		break;
1032f08c3bdfSopenharmony_ci	}
1033f08c3bdfSopenharmony_ci
1034f08c3bdfSopenharmony_ci	/*
1035f08c3bdfSopenharmony_ci	 * Ignore unknown command line options:
1036f08c3bdfSopenharmony_ci	 * they're probably gcc switches
1037f08c3bdfSopenharmony_ci	 */
1038f08c3bdfSopenharmony_ci	return next;
1039f08c3bdfSopenharmony_ci}
1040f08c3bdfSopenharmony_ci
1041f08c3bdfSopenharmony_civoid handle_switch_finalize(void)
1042f08c3bdfSopenharmony_ci{
1043f08c3bdfSopenharmony_ci	handle_switch_v_finalize();
1044f08c3bdfSopenharmony_ci	handle_switch_W_finalize();
1045f08c3bdfSopenharmony_ci}
1046