| @@ -2074,43 +2074,51 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 2073 unmodified lines |
| 2074 | dynarray_add((void ***)&s->files, &s->nb_files, f); | 2074 | dynarray_add((void ***)&s->files, &s->nb_files, f); |
| 2075 | } | 2075 | } |
| 2076 | | 2076 | |
| 2077 | ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) | 2077 | /* read list file */ |
| | 2078 | static void args_parser_listfile(TCCState *s, const char *filename) |
| | 2079 | { |
| | 2080 | int fd; |
| | 2081 | size_t len; |
| | 2082 | char *p; |
| | 2083 | |
| | 2084 | fd = open(filename, O_RDONLY | O_BINARY); |
| | 2085 | if (fd < 0) |
| | 2086 | tcc_error("file '%s' not found", filename); |
| | 2087 | |
| | 2088 | len = lseek(fd, 0, SEEK_END); |
| | 2089 | p = tcc_malloc(len + 1), p[len] = 0; |
| | 2090 | lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd); |
| | 2091 | tcc_set_options(s, p); |
| | 2092 | tcc_free(p); |
| | 2093 | } |
| | 2094 | |
| | 2095 | PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) |
| 2078 | { | 2096 | { |
| 2079 | const TCCOption *popt; | 2097 | const TCCOption *popt; |
| 2080 | const char *optarg, *r; | 2098 | const char *optarg, *r; |
| 2081 | int optind = 0; | 2099 | int optind = 0; |
| 2082 | ParseArgsState *pas = s->parse_args_state; | 2100 | int run = 0; |
| | 2101 | int filetype = 0; |
| | 2102 | int x; |
| | 2103 | char buf[1024]; |
| | 2104 | |
| | 2105 | ++s->args_ref; |
| 2083 | | 2106 | |
| 2084 | while (optind < argc) { | 2107 | while (optind < argc) { |
| 2085 | | 2108 | |
| 2086 | r = argv[optind++]; | 2109 | r = argv[optind++]; |
| | 2110 | |
| | 2111 | if (r[0] == '@' && r[1] != '\0') { |
| | 2112 | args_parser_listfile(s, r + 1); |
| | 2113 | continue; |
| | 2114 | } |
| | 2115 | |
| 2087 | if (r[0] != '-' || r[1] == '\0') { | 2116 | if (r[0] != '-' || r[1] == '\0') { |
| 2088 | /* handle list files */ | 2117 | args_parser_add_file(s, r, filetype); |
| 2089 | if (r[0] == '@' && r[1]) { | 2118 | if (run) { |
| 2090 | char buf[sizeof file->filename], *p; | 2119 | optind--; |
| 2091 | char **argv = NULL; | 2120 | /* argv[0] will be this file */ |
| 2092 | int argc = 0; | 2121 | break; |
| 2093 | FILE *fp; | | |
| 2094 | | | |
| 2095 | fp = fopen(r + 1, "rb"); | | |
| 2096 | if (fp == NULL) | | |
| 2097 | tcc_error("list file '%s' not found", r + 1); | | |
| 2098 | while (fgets(buf, sizeof buf, fp)) { | | |
| 2099 | p = trimfront(trimback(buf, strchr(buf, 0))); | | |
| 2100 | if (0 == *p || ';' == *p) | | |
| 2101 | continue; | | |
| 2102 | dynarray_add((void ***)&argv, &argc, tcc_strdup(p)); | | |
| 2103 | } | | |
| 2104 | fclose(fp); | | |
| 2105 | tcc_parse_args1(s, argc, argv); | | |
| 2106 | dynarray_reset(&argv, &argc); | | |
| 2107 | } else { | | |
| 2108 | args_parser_add_file(s, r, pas->filetype); | | |
| 2109 | if (pas->run) { | | |
| 2110 | optind--; | | |
| 2111 | /* argv[0] will be this file */ | | |
| 2112 | break; | | |
| 2113 | } | | |
| 2114 | } | 2122 | } |
| 2115 | continue; | 2123 | continue; |
| 2116 | } | 2124 | } |
| @@ -2160,7 +2168,7 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 43 unmodified lines |
| 2160 | break; | 2168 | break; |
| 2161 | case TCC_OPTION_pthread: | 2169 | case TCC_OPTION_pthread: |
| 2162 | parse_option_D(s, "_REENTRANT"); | 2170 | parse_option_D(s, "_REENTRANT"); |
| 2163 | pas->pthread = 1; | 2171 | s->args_pthread = 1; |
| 2164 | break; | 2172 | break; |
| 2165 | case TCC_OPTION_bench: | 2173 | case TCC_OPTION_bench: |
| 2166 | s->do_bench = 1; | 2174 | s->do_bench = 1; |
| @@ -2180,9 +2188,11 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 13 unmodified lines |
| 2180 | s->do_debug = 1; | 2188 | s->do_debug = 1; |
| 2181 | break; | 2189 | break; |
| 2182 | case TCC_OPTION_c: | 2190 | case TCC_OPTION_c: |
| | 2191 | x = TCC_OUTPUT_OBJ; |
| | 2192 | set_output_type: |
| 2183 | if (s->output_type) | 2193 | if (s->output_type) |
| 2184 | tcc_warning("-c: some compiler action already specified (%d)", s->output_type); | 2194 | tcc_warning("-%s: overriding compiler action already specified", popt->name); |
| 2185 | s->output_type = TCC_OUTPUT_OBJ; | 2195 | s->output_type = x; |
| 2186 | break; | 2196 | break; |
| 2187 | case TCC_OPTION_d: | 2197 | case TCC_OPTION_d: |
| 2188 | if (*optarg == 'D') | 2198 | if (*optarg == 'D') |
| @@ -2214,10 +2224,8 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 25 unmodified lines |
| 2214 | allow to use a tcc as a reference compiler for "make test" */ | 2224 | allow to use a tcc as a reference compiler for "make test" */ |
| 2215 | break; | 2225 | break; |
| 2216 | case TCC_OPTION_shared: | 2226 | case TCC_OPTION_shared: |
| 2217 | if (s->output_type) | 2227 | x = TCC_OUTPUT_DLL; |
| 2218 | tcc_warning("-shared: some compiler action already specified (%d)", s->output_type); | 2228 | goto set_output_type; |
| 2219 | s->output_type = TCC_OUTPUT_DLL; | | |
| 2220 | break; | | |
| 2221 | case TCC_OPTION_soname: | 2229 | case TCC_OPTION_soname: |
| 2222 | s->soname = tcc_strdup(optarg); | 2230 | s->soname = tcc_strdup(optarg); |
| 2223 | break; | 2231 | break; |
| @@ -2233,34 +2241,15 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 9 unmodified lines |
| 2233 | break; | 2241 | break; |
| 2234 | case TCC_OPTION_r: | 2242 | case TCC_OPTION_r: |
| 2235 | /* generate a .o merging several output files */ | 2243 | /* generate a .o merging several output files */ |
| 2236 | if (s->output_type) | | |
| 2237 | tcc_warning("-r: some compiler action already specified (%d)", s->output_type); | | |
| 2238 | s->option_r = 1; | 2244 | s->option_r = 1; |
| 2239 | s->output_type = TCC_OUTPUT_OBJ; | 2245 | x = TCC_OUTPUT_OBJ; |
| 2240 | break; | 2246 | goto set_output_type; |
| 2241 | case TCC_OPTION_isystem: | 2247 | case TCC_OPTION_isystem: |
| 2242 | tcc_add_sysinclude_path(s, optarg); | 2248 | tcc_add_sysinclude_path(s, optarg); |
| 2243 | break; | 2249 | break; |
| 2244 | case TCC_OPTION_iwithprefix: | 2250 | case TCC_OPTION_iwithprefix: |
| 2245 | if (1) { | 2251 | snprintf(buf, sizeof buf, "{B}/%s", optarg); |
| 2246 | char buf[1024]; | 2252 | tcc_add_sysinclude_path(s, buf); |
| 2247 | int buf_size = sizeof(buf)-1; | | |
| 2248 | char *p = &buf[0]; | | |
| 2249 | | | |
| 2250 | char *sysroot = "{B}/"; | | |
| 2251 | int len = strlen(sysroot); | | |
| 2252 | if (len > buf_size) | | |
| 2253 | len = buf_size; | | |
| 2254 | strncpy(p, sysroot, len); | | |
| 2255 | p += len; | | |
| 2256 | buf_size -= len; | | |
| 2257 | | | |
| 2258 | len = strlen(optarg); | | |
| 2259 | if (len > buf_size) | | |
| 2260 | len = buf_size; | | |
| 2261 | strncpy(p, optarg, len+1); | | |
| 2262 | tcc_add_sysinclude_path(s, buf); | | |
| 2263 | } | | |
| 2264 | break; | 2253 | break; |
| 2265 | case TCC_OPTION_nostdinc: | 2254 | case TCC_OPTION_nostdinc: |
| 2266 | s->nostdinc = 1; | 2255 | s->nostdinc = 1; |
| @@ -2275,12 +2264,10 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 8 unmodified lines |
| 2275 | #ifndef TCC_IS_NATIVE | 2264 | #ifndef TCC_IS_NATIVE |
| 2276 | tcc_error("-run is not available in a cross compiler"); | 2265 | tcc_error("-run is not available in a cross compiler"); |
| 2277 | #endif | 2266 | #endif |
| 2278 | if (s->output_type) | | |
| 2279 | tcc_warning("-run: some compiler action already specified (%d)", s->output_type); | | |
| 2280 | s->output_type = TCC_OUTPUT_MEMORY; | | |
| 2281 | tcc_set_options(s, optarg); | 2267 | tcc_set_options(s, optarg); |
| 2282 | pas->run = 1; | 2268 | run = 1; |
| 2283 | break; | 2269 | x = TCC_OUTPUT_MEMORY; |
| | 2270 | goto set_output_type; |
| 2284 | case TCC_OPTION_v: | 2271 | case TCC_OPTION_v: |
| 2285 | do ++s->verbose; while (*optarg++ == 'v'); | 2272 | do ++s->verbose; while (*optarg++ == 'v'); |
| 2286 | break; | 2273 | break; |
| @@ -2299,15 +2286,13 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 12 unmodified lines |
| 2299 | s->rdynamic = 1; | 2286 | s->rdynamic = 1; |
| 2300 | break; | 2287 | break; |
| 2301 | case TCC_OPTION_Wl: | 2288 | case TCC_OPTION_Wl: |
| 2302 | if (pas->linker_arg.size) | 2289 | if (s->linker_arg.size) |
| 2303 | --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ','); | 2290 | --s->linker_arg.size, cstr_ccat(&s->linker_arg, ','); |
| 2304 | cstr_cat(&pas->linker_arg, optarg, 0); | 2291 | cstr_cat(&s->linker_arg, optarg, 0); |
| 2305 | break; | 2292 | break; |
| 2306 | case TCC_OPTION_E: | 2293 | case TCC_OPTION_E: |
| 2307 | if (s->output_type) | 2294 | x = TCC_OUTPUT_PREPROCESS; |
| 2308 | tcc_warning("-E: some compiler action already specified (%d)", s->output_type); | 2295 | goto set_output_type; |
| 2309 | s->output_type = TCC_OUTPUT_PREPROCESS; | | |
| 2310 | break; | | |
| 2311 | case TCC_OPTION_P: | 2296 | case TCC_OPTION_P: |
| 2312 | s->Pflag = atoi(optarg) + 1; | 2297 | s->Pflag = atoi(optarg) + 1; |
| 2313 | break; | 2298 | break; |
| @@ -2327,25 +2312,20 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 13 unmodified lines |
| 2327 | break; | 2312 | break; |
| 2328 | case TCC_OPTION_x: | 2313 | case TCC_OPTION_x: |
| 2329 | if (*optarg == 'c') | 2314 | if (*optarg == 'c') |
| 2330 | pas->filetype = TCC_FILETYPE_C; | 2315 | filetype = TCC_FILETYPE_C; |
| 2331 | else | 2316 | else |
| 2332 | if (*optarg == 'a') | 2317 | if (*optarg == 'a') |
| 2333 | pas->filetype = TCC_FILETYPE_ASM_PP; | 2318 | filetype = TCC_FILETYPE_ASM_PP; |
| 2334 | else | 2319 | else |
| 2335 | if (*optarg == 'n') | 2320 | if (*optarg == 'n') |
| 2336 | pas->filetype = 0; | 2321 | filetype = 0; |
| 2337 | else | 2322 | else |
| 2338 | tcc_warning("unsupported language '%s'", optarg); | 2323 | tcc_warning("unsupported language '%s'", optarg); |
| 2339 | break; | 2324 | break; |
| 2340 | case TCC_OPTION_O: | 2325 | case TCC_OPTION_O: |
| 2341 | if (1) { | 2326 | x = atoi(optarg); |
| 2342 | int opt = atoi(optarg); | 2327 | if (x > 0) |
| 2343 | char *sym = "__OPTIMIZE__"; | 2328 | tcc_define_symbol(s, "__OPTIMIZE__", NULL); |
| 2344 | if (opt) | | |
| 2345 | tcc_define_symbol(s, sym, 0); | | |
| 2346 | else | | |
| 2347 | tcc_undefine_symbol(s, sym); | | |
| 2348 | } | | |
| 2349 | break; | 2329 | break; |
| 2350 | case TCC_OPTION_pedantic: | 2330 | case TCC_OPTION_pedantic: |
| 2351 | case TCC_OPTION_pipe: | 2331 | case TCC_OPTION_pipe: |
| @@ -2358,62 +2338,55 @@ unsupported_option: · 6 unmodified lines |
| 2358 | break; | 2338 | break; |
| 2359 | } | 2339 | } |
| 2360 | } | 2340 | } |
| 2361 | return optind; | | |
| 2362 | } | | |
| 2363 | | | |
| 2364 | PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) | | |
| 2365 | { | | |
| 2366 | ParseArgsState *pas; | | |
| 2367 | int ret, is_allocated = 0; | | |
| 2368 | | | |
| 2369 | if (!s->parse_args_state) { | | |
| 2370 | s->parse_args_state = tcc_mallocz(sizeof(ParseArgsState)); | | |
| 2371 | cstr_new(&s->parse_args_state->linker_arg); | | |
| 2372 | is_allocated = 1; | | |
| 2373 | } | | |
| 2374 | pas = s->parse_args_state; | | |
| 2375 | | 2341 | |
| 2376 | ret = tcc_parse_args1(s, argc, argv); | 2342 | if (1 == s->args_ref) { |
| 2377 | | 2343 | /* top instance */ |
| 2378 | if (s->output_type == 0) | 2344 | if (s->output_type != TCC_OUTPUT_OBJ) { |
| 2379 | s->output_type = TCC_OUTPUT_EXE; | 2345 | tcc_set_linker(s, (const char *)s->linker_arg.data); |
| 2380 | | 2346 | if (s->args_pthread) { |
| 2381 | if (pas->pthread && s->output_type != TCC_OUTPUT_OBJ) { | 2347 | args_parser_add_file(s, optarg, 'l'); |
| 2382 | args_parser_add_file(s, "-lpthread", TCC_FILETYPE_BINARY); | 2348 | s->nb_libraries++; |
| 2383 | s->nb_libraries++; | 2349 | } |
| | 2350 | } |
| | 2351 | cstr_free(&s->linker_arg); |
| | 2352 | s->args_pthread = 0; |
| 2384 | } | 2353 | } |
| | 2354 | --s->args_ref; |
| 2385 | | 2355 | |
| 2386 | if (s->output_type == TCC_OUTPUT_EXE || s->output_type == TCC_OUTPUT_DLL) | 2356 | return optind; |
| 2387 | tcc_set_linker(s, (const char *)pas->linker_arg.data); | | |
| 2388 | | | |
| 2389 | if (is_allocated) { | | |
| 2390 | cstr_free(&pas->linker_arg); | | |
| 2391 | tcc_free(pas); | | |
| 2392 | s->parse_args_state = NULL; | | |
| 2393 | } | | |
| 2394 | return ret; | | |
| 2395 | } | 2357 | } |
| 2396 | | 2358 | |
| 2397 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) | 2359 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *r) |
| 2398 | { | 2360 | { |
| 2399 | const char *s1; | 2361 | char **argv; |
| 2400 | char **argv, *arg; | 2362 | int argc; |
| 2401 | int argc, len; | 2363 | int ret, q, c; |
| 2402 | int ret; | 2364 | CString str; |
| 2403 | | 2365 | |
| 2404 | argc = 0, argv = NULL; | 2366 | argc = 0, argv = NULL; |
| 2405 | for(;;) { | 2367 | for(;;) { |
| 2406 | while (is_space(*str)) | 2368 | while (c = (unsigned char)*r, c && c <= ' ') |
| 2407 | str++; | 2369 | ++r; |
| 2408 | if (*str == '\0') | 2370 | if (c == 0) |
| 2409 | break; | 2371 | break; |
| 2410 | s1 = str; | 2372 | q = 0; |
| 2411 | while (*str != '\0' && !is_space(*str)) | 2373 | cstr_new(&str); |
| 2412 | str++; | 2374 | while (c = (unsigned char)*r, c) { |
| 2413 | len = str - s1; | 2375 | ++r; |
| 2414 | arg = tcc_malloc(len + 1); | 2376 | if (c == '\\' && (*r == '"' || *r == '\\')) { |
| 2415 | pstrncpy(arg, s1, len); | 2377 | c = *r++; |
| 2416 | dynarray_add((void ***)&argv, &argc, arg); | 2378 | } else if (c == '"') { |
| | 2379 | q = !q; |
| | 2380 | continue; |
| | 2381 | } else if (q == 0 && c <= ' ') { |
| | 2382 | break; |
| | 2383 | } |
| | 2384 | cstr_ccat(&str, c); |
| | 2385 | } |
| | 2386 | cstr_ccat(&str, 0); |
| | 2387 | //printf("<%s>\n", str.data), fflush(stdout); |
| | 2388 | dynarray_add((void ***)&argv, &argc, tcc_strdup(str.data)); |
| | 2389 | cstr_free(&str); |
| 2417 | } | 2390 | } |
| 2418 | ret = tcc_parse_args(s, argc, argv); | 2391 | ret = tcc_parse_args(s, argc, argv); |
| 2419 | dynarray_reset(&argv, &argc); | 2392 | dynarray_reset(&argv, &argc); |