xref: /netbsd-src/external/bsd/pcc/dist/pcc/driver/options.c (revision 411dcbec990c8aa9c57d3bd2f4bcacadec0b1ab5)
1 /*	Id	*/
2 /*	$NetBSD: options.c,v 1.1.1.1 2016/02/09 20:29:13 plunky Exp $	*/
3 
4 /*-
5  * Copyright (c) 2014 Iain Hibbert.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #include <ctype.h>
27 #include <string.h>
28 
29 #include "driver.h"
30 
31 /*
32  * list of options we understand. The list should be sorted by
33  * initial char, then by increasing match
34  */
35 struct options {
36 	const char *	name;
37 	unsigned int	type;
38 	void		(*func)(int, char *);
39 	void *		addr;
40 };
41 
42 /* option types */
43 #define FLAG		(0)		/* match name exactly */
44 #define STR(n)		((n) & 0xff)	/* match n chars (or all if n = 0) */
45 #define ARG(n)		(STR(n)|VAL)	/* match, and require an argument */
46 #define VAL		0x0100		/* arg value is required */
47 
48 static void ignore(int, char *);	/* do nothing */
49 
50 static void opt_set(int, char *);	/* set option */
51 static void opt_set2(int, char *);	/* set option */
52 static void opt_clr(int, char *);	/* clear option */
53 static void opt_add(int, char *);	/* add option to list */
54 
55 static void str_set(int, char *);	/* set string option */
56 static void str_add(int, char *);	/* add string to list */
57 static void str_expand(int, char *);	/* expand string to list */
58 
59 static void arg_add(int, char *);	/* add option and argument to list */
60 
61 static void str_Olevel(int, char *);	/* handle -Olevel */
62 static void str_glevel(int, char *);	/* handle -glevel */
63 
64 static struct options options[] = {
65     { "-param",			ARG(0),		ignore,		NULL		},
66     { "-sysroot=",		STR(9),		str_set,	&opt.sysroot	},
67     { "-version",		FLAG,		opt_set,	&opt.version,	},
68     { "B",			ARG(1),		arg_add,	&opt.prefix	},
69     { "C",			FLAG,		opt_set,	&opt.C		},
70     { "CC",			FLAG,		opt_set2,	&opt.C		},
71     { "D",			ARG(1),		arg_add,	&opt.DIU	},
72     { "E",			FLAG,		opt_set,	&opt.E		},
73     { "I",			ARG(1),		arg_add,	&opt.DIU	},
74     { "L",			ARG(1),		arg_add,	&opt.ldargs	},
75     { "M",			FLAG,		opt_set,	&opt.M		},
76     { "O",			STR(1),		str_Olevel,	NULL		},
77     { "P",			FLAG,		opt_set,	&opt.P		},
78     { "S",			FLAG,		opt_set,	&opt.S		},
79     { "U",			ARG(1),		arg_add,	&opt.DIU	},
80     { "Wa,",			STR(3),		str_expand,	&opt.Wa		},
81     { "Wl,",			STR(3),		str_expand,	&opt.Wl		},
82     { "Wp,",			STR(3),		str_expand,	&opt.Wp		},
83     { "W",			STR(1),		str_Wflag,	NULL		},	// XX
84     { "X",			FLAG,		opt_set,	&opt.savetemps	},
85     { "c",			FLAG,		opt_set,	&opt.c		},
86     { "compatibility-version",	FLAG,		ignore,		NULL		},
87     { "current-version",	FLAG,		ignore,		NULL		},
88     { "dynamiclib",		FLAG,		opt_set,	&opt.dynamiclib	},
89     { "ffreestanding",		FLAG,		opt_clr,	&opt.hosted	},
90     { "fno-freestanding",	FLAG,		opt_set,	&opt.hosted	},
91     { "fsigned-char",		FLAG,		opt_clr,	&opt.uchar	},
92     { "fno-signed-char",	FLAG,		opt_set,	&opt.uchar	},
93     { "funsigned-char",		FLAG,		opt_set,	&opt.uchar	},
94     { "fno-unsigned-char",	FLAG,		opt_clr,	&opt.uchar	},
95     { "fpic",			FLAG,		opt_set,	&opt.pic	},
96     { "fno-pic",		FLAG,		opt_clr,	&opt.pic	},
97     { "fPIC",			FLAG,		opt_set,	&opt.pic	},
98     { "fno-PIC",		FLAG,		opt_clr,	&opt.pic	},
99     { "fstack-protector",	FLAG,		opt_set,	&opt.ssp	},
100     { "fno-stack-protector",	FLAG,		opt_clr,	&opt.ssp	},
101     { "fstack-protector-all",	FLAG,		opt_set,	&opt.ssp	},
102     { "fno-stack-protector-all",FLAG,		opt_clr,	&opt.ssp	},
103     { "f",			STR(1),		ignore,		NULL		},
104     { "g",			STR(1),		str_glevel,	NULL		},
105     { "idirafter",		FLAG,		opt_set,	&opt.idirafter	},
106     { "isystem",		ARG(0),		str_set,	&opt.isystem	},
107     { "include",		ARG(0),		str_add,	&opt.include	},
108     { "install-name",		ARG(0),		ignore,		NULL		},	// XX
109     { "iquote",			ARG(0),		ignore,		NULL		},	// XX
110     { "isysroot",		ARG(0),		str_set,	&opt.isysroot	},
111     { "i",			STR(1),		opt_add,	&opt.ldargs	},
112     { "k",			FLAG,		opt_set,	&opt.pic	},
113     { "l",			ARG(1),		arg_add,	&opt.ldargs	},
114 #ifdef mach_arm
115     { "mbig-endian",		FLAG,		opt_set,	&opt.bigendian	},
116     { "mlittle-endian",		FLAG,		opt_clr,	&opt.bigendian	},
117 #endif
118 #ifdef mach_amd64 || mach_i386
119     { "m32",			FLAG,		opt_set,	&opt.m32	},
120     { "m64",			FLAG,		opt_clr,	&opt.m32	},
121 #endif
122     { "m",			ARG(1),		ignore,		NULL		},	// XX
123     { "nostdinc",		FLAG,		opt_clr,	&opt.stdinc	},
124     { "nostdinc++",		FLAG,		opt_clr,	&opt.cxxinc	},
125     { "nostdlib",		FLAG,		opt_clr,	&opt.stdlib	},
126     { "nostartfiles",		FLAG,		opt_clr,	&opt.startfiles	},
127     { "nodefaultlibs",		FLAG,		opt_clr,	&opt.defaultlibs},
128     { "n",			STR(1),		arg_add,	&opt.ldargs	},	// XX
129     { "o",			ARG(1),		str_set,	&opt.outfile	},
130     { "pedantic",		FLAG,		opt_set,	&opt.pedantic	},
131     { "p",			FLAG,		opt_set,	&opt.profile	},
132     { "pg",			FLAG,		opt_set,	&opt.profile	},
133     { "pipe",			FLAG,		opt_set,	&opt.pipe	},
134     { "print-prog-name=",	STR(15),	ignore,		NULL		},	// XX
135     { "print-multi-os-directory", FLAG,		opt_set,	&opt.print	},
136     { "pthread",		FLAG,		opt_set,	&opt.pthread	},
137     { "r",			FLAG,		opt_set,	&opt.r		},
138     { "save-temps",		FLAG,		opt_set,	&opt.savetemps	},
139     { "shared",			FLAG,		opt_set,	&opt.shared	},
140     { "static",			FLAG,		opt_set,	&opt.ldstatic	},
141     { "symbolic",		FLAG,		opt_set,	&opt.symbolic	},
142     { "std=",			STR(4),		str_standard,	NULL		},	// XX
143     { "t",			FLAG,		opt_set,	&opt.traditional},
144     { "traditional",		FLAG,		opt_set,	&opt.traditional},
145     { "undef",			FLAG,		opt_clr,	&opt.stddef	},
146     { "v",			FLAG,		opt_set,	&opt.verbose	},
147     { "x",			ARG(1),		arg_language,	NULL		},	// XX
148 };
149 
150 /* do nothing */
151 static void
ignore(int n,char * arg)152 ignore(int n, char *arg)
153 {
154 	fprintf(stderr, "option `-%s' ignored\n", options[n].name);
155 }
156 
157 /* set option */
158 static void
opt_set(int n,char * arg)159 opt_set(int n, char *arg)
160 {
161 
162 	*(int *)(options[n].addr) = 1;
163 }
164 
165 /* set option=2 */
166 static void
opt_set2(int n,char * arg)167 opt_set2(int n, char *arg)
168 {
169 
170 	*(int *)(options[n].addr) = 2;
171 }
172 
173 /* clear option */
174 static void
opt_clr(int n,char * arg)175 opt_clr(int n, char *arg)
176 {
177 
178 	*(int *)(options[n].addr) = 0;
179 }
180 
181 /* add option to list */
182 static void
opt_add(int n,char * arg)183 opt_add(int n, char *arg)
184 {
185 	list_t *l = options[n].addr;
186 
187 	list_add(l, "-%s", options[n].name);
188 }
189 
190 /* set string option */
191 static void
str_set(int n,char * arg)192 str_set(int n, char *arg)
193 {
194 	char **p = options[n].addr;
195 
196 	if (*p != NULL)
197 		warning("option `-%s' was already set", options[n].name);
198 
199 	*p = arg;
200 }
201 
202 /* add string to list */
203 static void
str_add(int n,char * arg)204 str_add(int n, char *arg)
205 {
206 	list_t *l = options[n].addr;
207 
208 	list_add(l, arg);
209 }
210 
211 /* expand comma separated string to list */
212 static void
str_expand(int n,char * arg)213 str_expand(int n, char *arg)
214 {
215 	list_t *l = options[n].addr;
216 	char *next;
217 
218 	while (arg != NULL) {
219 		next = strchr(arg, ',');
220 		if (next != NULL)
221 			*next++ = '\0';
222 
223 		list_add(l, arg);
224 		arg = next;
225 	}
226 }
227 
228 /* add option and argument to list */
229 static void
arg_add(int n,char * arg)230 arg_add(int n, char *arg)
231 {
232 	list_t *l = options[n].addr;
233 
234 	list_add(l, "-%s", options[n].name);
235 	list_add(l, arg);
236 }
237 
238 /* handle -Olevel */
239 static void
str_Olevel(int n,char * arg)240 str_Olevel(int n, char *arg)
241 {
242 
243 	if (arg[0] == '\0')
244 		opt.optim++;
245 	else if (arg[1] == '\0' && isdigit((unsigned char)arg[1]))
246 		opt.optim = arg[1] - '0';
247 	else if (arg[1] == '\0' && arg[1] == 's')
248 		opt.optim = 1;	/* optimize for space only */
249 	else
250 		warning("unknown optimization `-O%s'", arg);
251 }
252 
253 /* handle -glevel */
254 static void
str_glevel(int n,char * arg)255 str_glevel(int n, char *arg)
256 {
257 
258 	if (arg[0] == '\0')
259 		opt.debug++;
260 	else if (arg[1] == '\0' && isdigit((unsigned char)arg[1]))
261 		opt.debug = arg[1] - '0';
262 	else
263 		warning("unknown debug `-g%s'", arg);
264 }
265 
266 /*
267  * return true if av1 is used
268  */
269 bool
add_option(char * av0,char * av1)270 add_option(char *av0, char *av1)
271 {
272 	unsigned int n;
273 	char *p;
274 	size_t i
275 
276 	i = 0;
277 	p = av0 + 1;	/* skip initial `-' */
278 
279 	while (i < ARRAYLEN(options) && *p != options[i].name[0])
280 		i++;
281 
282 	while (i < ARRAYLEN(options) && *p == options[i].name[0]) {
283 		n = STR(options[i].type);
284 		if ((n > 0 && strncmp(options[i].name, p, n) == 0)
285 		    || (n == 0 && strcmp(options[i].name, p) == 0)) {
286 			if ((options[i].type & VAL)
287 			    && (n == 0 || *(p += n) == '\0')
288 			    && (p = av1) == NULL) {
289 				warning("option `%s' requires a value", av0);
290 				return false;
291 			}
292 
293 			options[i].func(i, p);
294 			return (p == av1);
295 		}
296 		i++;
297 	}
298 
299 	warning("unknown option `%s'", av0);
300 	return false;
301 }
302