| @@ -2074,43 +2074,51 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 2073 unmodified lines |
| 2074 | 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 | 2097 | const TCCOption *popt; |
| 2080 | 2098 | const char *optarg, *r; |
| 2081 | 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 | 2107 | while (optind < argc) { |
| 2085 | 2108 | |
| 2086 | 2109 | r = argv[optind++]; |
| 2110 | + |
| 2111 | + if (r[0] == '@' && r[1] != '\0') { |
| 2112 | + args_parser_listfile(s, r + 1); |
| 2113 | + continue; |
| 2114 | + } |
| 2115 | + |
| 2087 | 2116 | if (r[0] != '-' || r[1] == '\0') { |
| 2088 | | − /* handle list files */ |
| 2089 | | − if (r[0] == '@' && r[1]) { |
| 2090 | | − char buf[sizeof file->filename], *p; |
| 2091 | | − char **argv = NULL; |
| 2092 | | − int argc = 0; |
| 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 | | − } |
| 2117 | + args_parser_add_file(s, r, filetype); |
| 2118 | + if (run) { |
| 2119 | + optind--; |
| 2120 | + /* argv[0] will be this file */ |
| 2121 | + break; |
| 2114 | 2122 | } |
| 2115 | 2123 | continue; |
| 2116 | 2124 | } |
| @@ -2160,7 +2168,7 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 43 unmodified lines |
| 2160 | 2168 | break; |
| 2161 | 2169 | case TCC_OPTION_pthread: |
| 2162 | 2170 | parse_option_D(s, "_REENTRANT"); |
| 2163 | | − pas->pthread = 1; |
| 2171 | + s->args_pthread = 1; |
| 2164 | 2172 | break; |
| 2165 | 2173 | case TCC_OPTION_bench: |
| 2166 | 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 | 2188 | s->do_debug = 1; |
| 2181 | 2189 | break; |
| 2182 | 2190 | case TCC_OPTION_c: |
| 2191 | + x = TCC_OUTPUT_OBJ; |
| 2192 | + set_output_type: |
| 2183 | 2193 | if (s->output_type) |
| 2184 | | − tcc_warning("-c: some compiler action already specified (%d)", s->output_type); |
| 2185 | | − s->output_type = TCC_OUTPUT_OBJ; |
| 2194 | + tcc_warning("-%s: overriding compiler action already specified", popt->name); |
| 2195 | + s->output_type = x; |
| 2186 | 2196 | break; |
| 2187 | 2197 | case TCC_OPTION_d: |
| 2188 | 2198 | if (*optarg == 'D') |
| @@ -2214,10 +2224,8 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 25 unmodified lines |
| 2214 | 2224 | allow to use a tcc as a reference compiler for "make test" */ |
| 2215 | 2225 | break; |
| 2216 | 2226 | case TCC_OPTION_shared: |
| 2217 | | − if (s->output_type) |
| 2218 | | − tcc_warning("-shared: some compiler action already specified (%d)", s->output_type); |
| 2219 | | − s->output_type = TCC_OUTPUT_DLL; |
| 2220 | | − break; |
| 2227 | + x = TCC_OUTPUT_DLL; |
| 2228 | + goto set_output_type; |
| 2221 | 2229 | case TCC_OPTION_soname: |
| 2222 | 2230 | s->soname = tcc_strdup(optarg); |
| 2223 | 2231 | break; |
| @@ -2233,34 +2241,15 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 9 unmodified lines |
| 2233 | 2241 | break; |
| 2234 | 2242 | case TCC_OPTION_r: |
| 2235 | 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 | 2244 | s->option_r = 1; |
| 2239 | | − s->output_type = TCC_OUTPUT_OBJ; |
| 2240 | | − break; |
| 2245 | + x = TCC_OUTPUT_OBJ; |
| 2246 | + goto set_output_type; |
| 2241 | 2247 | case TCC_OPTION_isystem: |
| 2242 | 2248 | tcc_add_sysinclude_path(s, optarg); |
| 2243 | 2249 | break; |
| 2244 | 2250 | case TCC_OPTION_iwithprefix: |
| 2245 | | − if (1) { |
| 2246 | | − char buf[1024]; |
| 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 | | − } |
| 2251 | + snprintf(buf, sizeof buf, "{B}/%s", optarg); |
| 2252 | + tcc_add_sysinclude_path(s, buf); |
| 2264 | 2253 | break; |
| 2265 | 2254 | case TCC_OPTION_nostdinc: |
| 2266 | 2255 | s->nostdinc = 1; |
| @@ -2275,12 +2264,10 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 8 unmodified lines |
| 2275 | 2264 | #ifndef TCC_IS_NATIVE |
| 2276 | 2265 | tcc_error("-run is not available in a cross compiler"); |
| 2277 | 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 | 2267 | tcc_set_options(s, optarg); |
| 2282 | | − pas->run = 1; |
| 2283 | | − break; |
| 2268 | + run = 1; |
| 2269 | + x = TCC_OUTPUT_MEMORY; |
| 2270 | + goto set_output_type; |
| 2284 | 2271 | case TCC_OPTION_v: |
| 2285 | 2272 | do ++s->verbose; while (*optarg++ == 'v'); |
| 2286 | 2273 | break; |
| @@ -2299,15 +2286,13 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 12 unmodified lines |
| 2299 | 2286 | s->rdynamic = 1; |
| 2300 | 2287 | break; |
| 2301 | 2288 | case TCC_OPTION_Wl: |
| 2302 | | − if (pas->linker_arg.size) |
| 2303 | | − --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ','); |
| 2304 | | − cstr_cat(&pas->linker_arg, optarg, 0); |
| 2289 | + if (s->linker_arg.size) |
| 2290 | + --s->linker_arg.size, cstr_ccat(&s->linker_arg, ','); |
| 2291 | + cstr_cat(&s->linker_arg, optarg, 0); |
| 2305 | 2292 | break; |
| 2306 | 2293 | case TCC_OPTION_E: |
| 2307 | | − if (s->output_type) |
| 2308 | | − tcc_warning("-E: some compiler action already specified (%d)", s->output_type); |
| 2309 | | − s->output_type = TCC_OUTPUT_PREPROCESS; |
| 2310 | | − break; |
| 2294 | + x = TCC_OUTPUT_PREPROCESS; |
| 2295 | + goto set_output_type; |
| 2311 | 2296 | case TCC_OPTION_P: |
| 2312 | 2297 | s->Pflag = atoi(optarg) + 1; |
| 2313 | 2298 | break; |
| @@ -2327,25 +2312,20 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) · 13 unmodified lines |
| 2327 | 2312 | break; |
| 2328 | 2313 | case TCC_OPTION_x: |
| 2329 | 2314 | if (*optarg == 'c') |
| 2330 | | − pas->filetype = TCC_FILETYPE_C; |
| 2315 | + filetype = TCC_FILETYPE_C; |
| 2331 | 2316 | else |
| 2332 | 2317 | if (*optarg == 'a') |
| 2333 | | − pas->filetype = TCC_FILETYPE_ASM_PP; |
| 2318 | + filetype = TCC_FILETYPE_ASM_PP; |
| 2334 | 2319 | else |
| 2335 | 2320 | if (*optarg == 'n') |
| 2336 | | − pas->filetype = 0; |
| 2321 | + filetype = 0; |
| 2337 | 2322 | else |
| 2338 | 2323 | tcc_warning("unsupported language '%s'", optarg); |
| 2339 | 2324 | break; |
| 2340 | 2325 | case TCC_OPTION_O: |
| 2341 | | − if (1) { |
| 2342 | | − int opt = atoi(optarg); |
| 2343 | | − char *sym = "__OPTIMIZE__"; |
| 2344 | | − if (opt) |
| 2345 | | − tcc_define_symbol(s, sym, 0); |
| 2346 | | − else |
| 2347 | | − tcc_undefine_symbol(s, sym); |
| 2348 | | − } |
| 2326 | + x = atoi(optarg); |
| 2327 | + if (x > 0) |
| 2328 | + tcc_define_symbol(s, "__OPTIMIZE__", NULL); |
| 2349 | 2329 | break; |
| 2350 | 2330 | case TCC_OPTION_pedantic: |
| 2351 | 2331 | case TCC_OPTION_pipe: |
| @@ -2358,62 +2338,55 @@ unsupported_option: · 6 unmodified lines |
| 2358 | 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); |
| 2377 | | − |
| 2378 | | − if (s->output_type == 0) |
| 2379 | | − s->output_type = TCC_OUTPUT_EXE; |
| 2380 | | − |
| 2381 | | − if (pas->pthread && s->output_type != TCC_OUTPUT_OBJ) { |
| 2382 | | − args_parser_add_file(s, "-lpthread", TCC_FILETYPE_BINARY); |
| 2383 | | − s->nb_libraries++; |
| 2342 | + if (1 == s->args_ref) { |
| 2343 | + /* top instance */ |
| 2344 | + if (s->output_type != TCC_OUTPUT_OBJ) { |
| 2345 | + tcc_set_linker(s, (const char *)s->linker_arg.data); |
| 2346 | + if (s->args_pthread) { |
| 2347 | + args_parser_add_file(s, optarg, 'l'); |
| 2348 | + 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) |
| 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; |
| 2356 | + return optind; |
| 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; |
| 2400 | | − char **argv, *arg; |
| 2401 | | − int argc, len; |
| 2402 | | − int ret; |
| 2361 | + char **argv; |
| 2362 | + int argc; |
| 2363 | + int ret, q, c; |
| 2364 | + CString str; |
| 2403 | 2365 | |
| 2404 | 2366 | argc = 0, argv = NULL; |
| 2405 | 2367 | for(;;) { |
| 2406 | | − while (is_space(*str)) |
| 2407 | | − str++; |
| 2408 | | − if (*str == '\0') |
| 2368 | + while (c = (unsigned char)*r, c && c <= ' ') |
| 2369 | + ++r; |
| 2370 | + if (c == 0) |
| 2409 | 2371 | break; |
| 2410 | | − s1 = str; |
| 2411 | | − while (*str != '\0' && !is_space(*str)) |
| 2412 | | − str++; |
| 2413 | | − len = str - s1; |
| 2414 | | − arg = tcc_malloc(len + 1); |
| 2415 | | − pstrncpy(arg, s1, len); |
| 2416 | | − dynarray_add((void ***)&argv, &argc, arg); |
| 2372 | + q = 0; |
| 2373 | + cstr_new(&str); |
| 2374 | + while (c = (unsigned char)*r, c) { |
| 2375 | + ++r; |
| 2376 | + if (c == '\\' && (*r == '"' || *r == '\\')) { |
| 2377 | + c = *r++; |
| 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 | 2391 | ret = tcc_parse_args(s, argc, argv); |
| 2419 | 2392 | dynarray_reset(&argv, &argc); |