Added missing file.
[tinycc/k1w1.git] / tccargs.c
blob7731b82f7ccbcc7f7f4a02677b350f7ba57e3013
1 /*
2 * Command line argument parsing for TCC
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "tcc.h"
22 #define TCC_OPTION_HAS_ARG 0x0001
23 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
25 typedef struct TCCOption {
26 const char *name;
27 uint16_t index;
28 uint16_t flags;
29 } TCCOption;
31 enum {
32 TCC_OPTION_HELP,
33 TCC_OPTION_I,
34 TCC_OPTION_D,
35 TCC_OPTION_U,
36 TCC_OPTION_L,
37 TCC_OPTION_B,
38 TCC_OPTION_l,
39 TCC_OPTION_bench,
40 TCC_OPTION_bt,
41 TCC_OPTION_b,
42 TCC_OPTION_g,
43 TCC_OPTION_c,
44 TCC_OPTION_static,
45 TCC_OPTION_shared,
46 TCC_OPTION_soname,
47 TCC_OPTION_o,
48 TCC_OPTION_r,
49 TCC_OPTION_Wl,
50 TCC_OPTION_W,
51 TCC_OPTION_O,
52 TCC_OPTION_m,
53 TCC_OPTION_f,
54 TCC_OPTION_nostdinc,
55 TCC_OPTION_nostdlib,
56 TCC_OPTION_print_search_dirs,
57 TCC_OPTION_rdynamic,
58 TCC_OPTION_run,
59 TCC_OPTION_v,
60 TCC_OPTION_w,
61 TCC_OPTION_pipe,
62 TCC_OPTION_E,
63 TCC_OPTION_x,
66 static const TCCOption tcc_options[] = {
67 { "h", TCC_OPTION_HELP, 0 },
68 { "?", TCC_OPTION_HELP, 0 },
69 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
70 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
71 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
72 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
73 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
74 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
75 { "bench", TCC_OPTION_bench, 0 },
76 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
77 #ifdef CONFIG_TCC_BCHECK
78 { "b", TCC_OPTION_b, 0 },
79 #endif
80 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
81 { "c", TCC_OPTION_c, 0 },
82 { "static", TCC_OPTION_static, 0 },
83 { "shared", TCC_OPTION_shared, 0 },
84 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
85 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
86 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
87 { "rdynamic", TCC_OPTION_rdynamic, 0 },
88 { "r", TCC_OPTION_r, 0 },
89 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
90 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
91 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
92 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
93 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
94 { "nostdinc", TCC_OPTION_nostdinc, 0 },
95 { "nostdlib", TCC_OPTION_nostdlib, 0 },
96 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
97 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
98 { "w", TCC_OPTION_w, 0 },
99 { "pipe", TCC_OPTION_pipe, 0},
100 { "E", TCC_OPTION_E, 0},
101 { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
102 { NULL },
105 static int strstart(const char *str, const char *val, const char **ptr)
107 const char *p, *q;
108 p = str;
109 q = val;
110 while (*q != '\0') {
111 if (*p != *q)
112 return 0;
113 p++;
114 q++;
116 if (ptr)
117 *ptr = p;
118 return 1;
121 /* convert 'str' into an array of space separated strings */
122 static int expand_args(char ***pargv, const char *str)
124 const char *s1;
125 char **argv, *arg;
126 int argc, len;
128 argc = 0;
129 argv = NULL;
130 for(;;) {
131 while (is_space(*str))
132 str++;
133 if (*str == '\0')
134 break;
135 s1 = str;
136 while (*str != '\0' && !is_space(*str))
137 str++;
138 len = str - s1;
139 arg = tcc_malloc(len + 1);
140 memcpy(arg, s1, len);
141 arg[len] = '\0';
142 dynarray_add((void ***)&argv, &argc, arg);
144 *pargv = argv;
145 return argc;
149 void init_tcc_config(TCCConfig *config)
151 config->output_type = TCC_OUTPUT_EXE;
152 config->outfile = NULL;
153 config->multiple_files = 1;
154 config->files = NULL;
155 config->nb_files = 0;
156 config->nb_libraries = 0;
157 config->reloc_output = 0;
158 config->print_search_dirs = 0;
159 config->do_bench = 0;
162 int parse_args(TCCConfig *config, TCCState *s, int argc, char **argv)
164 int optind;
165 const TCCOption *popt;
166 const char *optarg, *p1, *r1;
167 char *r;
169 optind = 0;
170 while (optind < argc) {
172 r = argv[optind++];
173 if (r[0] != '-' || r[1] == '\0') {
174 /* add a new file */
175 dynarray_add((void ***)&config->files, &config->nb_files, r);
176 if (!config->multiple_files) {
177 optind--;
178 /* argv[0] will be this file */
179 break;
181 } else {
182 /* find option in table (match only the first chars */
183 popt = tcc_options;
184 for(;;) {
185 p1 = popt->name;
186 if (p1 == NULL)
187 error("invalid option -- '%s'", r);
188 r1 = r + 1;
189 for(;;) {
190 if (*p1 == '\0')
191 goto option_found;
192 if (*r1 != *p1)
193 break;
194 p1++;
195 r1++;
197 popt++;
199 option_found:
200 if (popt->flags & TCC_OPTION_HAS_ARG) {
201 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
202 optarg = r1;
203 } else {
204 if (optind >= argc)
205 error("argument to '%s' is missing", r);
206 optarg = argv[optind++];
208 } else {
209 if (*r1 != '\0')
210 return 0;
211 optarg = NULL;
214 switch(popt->index) {
215 case TCC_OPTION_HELP:
216 return 0;
218 case TCC_OPTION_I:
219 if (tcc_add_include_path(s, optarg) < 0)
220 error("too many include paths");
221 break;
222 case TCC_OPTION_D:
224 char *sym, *value;
225 sym = (char *)optarg;
226 value = strchr(sym, '=');
227 if (value) {
228 *value = '\0';
229 value++;
231 tcc_define_symbol(s, sym, value);
233 break;
234 case TCC_OPTION_U:
235 tcc_undefine_symbol(s, optarg);
236 break;
237 case TCC_OPTION_L:
238 tcc_add_library_path(s, optarg);
239 break;
240 case TCC_OPTION_B:
241 /* set tcc utilities path (mainly for tcc development) */
242 tcc_set_lib_path(s, optarg);
243 break;
244 case TCC_OPTION_l:
245 dynarray_add((void ***)&config->files, &config->nb_files, r);
246 config->nb_libraries++;
247 break;
248 case TCC_OPTION_bench:
249 config->do_bench = 1;
250 break;
251 #ifdef CONFIG_TCC_BACKTRACE
252 case TCC_OPTION_bt:
253 num_callers = atoi(optarg);
254 break;
255 #endif
256 #ifdef CONFIG_TCC_BCHECK
257 case TCC_OPTION_b:
258 s->do_bounds_check = 1;
259 s->do_debug = 1;
260 break;
261 #endif
262 case TCC_OPTION_g:
263 s->do_debug = 1;
264 break;
265 case TCC_OPTION_c:
266 config->multiple_files = 1;
267 config->output_type = TCC_OUTPUT_OBJ;
268 break;
269 case TCC_OPTION_static:
270 s->static_link = 1;
271 break;
272 case TCC_OPTION_shared:
273 config->output_type = TCC_OUTPUT_DLL;
274 break;
275 case TCC_OPTION_soname:
276 s->soname = optarg;
277 break;
278 case TCC_OPTION_o:
279 config->multiple_files = 1;
280 config->outfile = optarg;
281 break;
282 case TCC_OPTION_r:
283 /* generate a .o merging several output files */
284 config->reloc_output = 1;
285 config->output_type = TCC_OUTPUT_OBJ;
286 break;
287 case TCC_OPTION_nostdinc:
288 s->nostdinc = 1;
289 break;
290 case TCC_OPTION_nostdlib:
291 s->nostdlib = 1;
292 break;
293 case TCC_OPTION_print_search_dirs:
294 config->print_search_dirs = 1;
295 break;
296 case TCC_OPTION_run:
298 int argc1;
299 char **argv1;
300 argc1 = expand_args(&argv1, optarg);
301 if (argc1 > 0) {
302 parse_args(config, s, argc1, argv1);
304 config->multiple_files = 0;
305 config->output_type = TCC_OUTPUT_MEMORY;
307 break;
308 case TCC_OPTION_v:
309 do {
310 if (0 == s->verbose++)
311 printf("tcc version %s\n", TCC_VERSION);
312 } while (*optarg++ == 'v');
313 break;
314 case TCC_OPTION_f:
315 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
316 goto unsupported_option;
317 break;
318 case TCC_OPTION_W:
319 if (tcc_set_warning(s, optarg, 1) < 0 &&
320 s->warn_unsupported)
321 goto unsupported_option;
322 break;
323 case TCC_OPTION_w:
324 s->warn_none = 1;
325 break;
326 case TCC_OPTION_rdynamic:
327 s->rdynamic = 1;
328 break;
329 case TCC_OPTION_Wl:
331 const char *p;
332 if (strstart(optarg, "-Ttext,", &p)) {
333 s->text_addr = strtoul(p, NULL, 16);
334 s->has_text_addr = 1;
335 } else if (strstart(optarg, "--section-alignment,", &p)) {
336 s->section_align = strtoul(p, NULL, 16);
337 } else if (strstart(optarg, "--image-base,", &p)) {
338 s->text_addr = strtoul(p, NULL, 16);
339 s->has_text_addr = 1;
340 #ifdef TCC_TARGET_PE
341 } else if (strstart(optarg, "--file-alignment,", &p)) {
342 s->pe_file_align = strtoul(p, NULL, 16);
343 } else if (strstart(optarg, "--subsystem,", &p)) {
344 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
345 if (!strcmp(p, "native"))
346 s->pe_subsystem = 1;
347 else if (!strcmp(p, "console"))
348 s->pe_subsystem = 3;
349 else if (!strcmp(p, "gui"))
350 s->pe_subsystem = 2;
351 else if (!strcmp(p, "posix"))
352 s->pe_subsystem = 7;
353 else if (!strcmp(p, "efiapp"))
354 s->pe_subsystem = 10;
355 else if (!strcmp(p, "efiboot"))
356 s->pe_subsystem = 11;
357 else if (!strcmp(p, "efiruntime"))
358 s->pe_subsystem = 12;
359 else if (!strcmp(p, "efirom"))
360 s->pe_subsystem = 13;
361 #elif defined(TCC_TARGET_ARM)
362 if (!strcmp(p, "wince"))
363 s->pe_subsystem = 9;
364 #endif
365 else {
366 error("invalid subsystem '%s'", p);
368 #endif
369 } else if (strstart(optarg, "--oformat,", &p)) {
370 #if defined(TCC_TARGET_PE)
371 if (strstart(p, "pe-", NULL)) {
372 #else
373 #if defined(TCC_TARGET_X86_64)
374 if (strstart(p, "elf64-", NULL)) {
375 #else
376 if (strstart(p, "elf32-", NULL)) {
377 #endif
378 #endif
379 s->output_format = TCC_OUTPUT_FORMAT_ELF;
380 } else if (!strcmp(p, "binary")) {
381 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
382 } else
383 #ifdef TCC_TARGET_COFF
384 if (!strcmp(p, "coff")) {
385 s->output_format = TCC_OUTPUT_FORMAT_COFF;
386 } else
387 #endif
389 error("target %s not found", p);
391 } else {
392 error("unsupported linker option '%s'", optarg);
395 break;
396 case TCC_OPTION_E:
397 config->output_type = TCC_OUTPUT_PREPROCESS;
398 break;
399 case TCC_OPTION_x:
400 break;
401 default:
402 if (s->warn_unsupported) {
403 unsupported_option:
404 warning("unsupported option '%s'", r);
406 break;
410 return optind + 1;