| @@ -2081,28 +2081,65 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 2080 unmodified lines |
| 2081 | 2081 | dynarray_add((void ***)&s->files, &s->nb_files, p); |
| 2082 | 2082 | } |
| 2083 | 2083 | |
| 2084 | | −PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) |
| 2084 | +ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv); |
| 2085 | + |
| 2086 | +ST_FUNC void args_parser_trim_ws() |
| 2087 | +{ |
| 2088 | + for (; ch != CH_EOF; inp()) { |
| 2089 | + if (ch != '\n' && ch != '\r' && !is_space(ch)) |
| 2090 | + break; |
| 2091 | + } |
| 2092 | +} |
| 2093 | + |
| 2094 | +ST_FUNC void args_parser_add_listfile(TCCState *s, const char *filename) |
| 2095 | +{ |
| 2096 | + char buf[sizeof file->filename], *pb = buf; |
| 2097 | + char **argv = NULL; |
| 2098 | + int argc = 0; |
| 2099 | + |
| 2100 | + if (tcc_open(s, filename) < 0) |
| 2101 | + tcc_error("list file '%s' not found", filename); |
| 2102 | + |
| 2103 | + for (ch = handle_eob(), args_parser_trim_ws(); ; inp()) { |
| 2104 | + /* on new line or buffer overflow */ |
| 2105 | + if (ch == '\n' || ch == '\r' || ch == CH_EOF |
| 2106 | + || pb - buf >= sizeof(buf) - 1) { |
| 2107 | + if (pb > buf) { |
| 2108 | + *pb = 0, pb = buf; |
| 2109 | + dynarray_add((void ***)&argv, &argc, tcc_strdup(buf)); |
| 2110 | + args_parser_trim_ws(); |
| 2111 | + } |
| 2112 | + } |
| 2113 | + if (ch == CH_EOF) |
| 2114 | + break; |
| 2115 | + *pb++ = ch; |
| 2116 | + } |
| 2117 | + tcc_close(); |
| 2118 | + tcc_parse_args1(s, argc, argv); |
| 2119 | + dynarray_reset(&argv, &argc); |
| 2120 | +} |
| 2121 | + |
| 2122 | +ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) |
| 2085 | 2123 | { |
| 2086 | 2124 | const TCCOption *popt; |
| 2087 | 2125 | const char *optarg, *r; |
| 2088 | | − int run = 0; |
| 2089 | | − int pthread = 0; |
| 2090 | 2126 | int optind = 0; |
| 2091 | | − int filetype = 0; |
| 2092 | | − |
| 2093 | | − /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */ |
| 2094 | | − CString linker_arg; |
| 2095 | | − cstr_new(&linker_arg); |
| 2127 | + ParseArgsState *pas = s->parse_args_state; |
| 2096 | 2128 | |
| 2097 | 2129 | while (optind < argc) { |
| 2098 | 2130 | |
| 2099 | 2131 | r = argv[optind++]; |
| 2100 | 2132 | if (r[0] != '-' || r[1] == '\0') { |
| 2101 | | − args_parser_add_file(s, r, filetype); |
| 2102 | | − if (run) { |
| 2103 | | − optind--; |
| 2104 | | − /* argv[0] will be this file */ |
| 2105 | | − break; |
| 2133 | + /* handle list files */ |
| 2134 | + if (r[0] == '@' && r[1]) { |
| 2135 | + args_parser_add_listfile(s, r + 1); |
| 2136 | + } else { |
| 2137 | + args_parser_add_file(s, r, pas->filetype); |
| 2138 | + if (pas->run) { |
| 2139 | + optind--; |
| 2140 | + /* argv[0] will be this file */ |
| 2141 | + break; |
| 2142 | + } |
| 2106 | 2143 | } |
| 2107 | 2144 | continue; |
| 2108 | 2145 | } |
| @@ -2152,7 +2189,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 43 unmodified lines |
| 2152 | 2189 | break; |
| 2153 | 2190 | case TCC_OPTION_pthread: |
| 2154 | 2191 | parse_option_D(s, "_REENTRANT"); |
| 2155 | | − pthread = 1; |
| 2192 | + pas->pthread = 1; |
| 2156 | 2193 | break; |
| 2157 | 2194 | case TCC_OPTION_bench: |
| 2158 | 2195 | s->do_bench = 1; |
| @@ -2267,7 +2304,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 108 unmodified lines |
| 2267 | 2304 | tcc_warning("-run: some compiler action already specified (%d)", s->output_type); |
| 2268 | 2305 | s->output_type = TCC_OUTPUT_MEMORY; |
| 2269 | 2306 | tcc_set_options(s, optarg); |
| 2270 | | − run = 1; |
| 2307 | + pas->run = 1; |
| 2271 | 2308 | break; |
| 2272 | 2309 | case TCC_OPTION_v: |
| 2273 | 2310 | do ++s->verbose; while (*optarg++ == 'v'); |
| @@ -2288,10 +2325,10 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 14 unmodified lines |
| 2288 | 2325 | s->rdynamic = 1; |
| 2289 | 2326 | break; |
| 2290 | 2327 | case TCC_OPTION_Wl: |
| 2291 | | − if (linker_arg.size) |
| 2292 | | − --linker_arg.size, cstr_ccat(&linker_arg, ','); |
| 2293 | | − cstr_cat(&linker_arg, optarg); |
| 2294 | | − cstr_ccat(&linker_arg, '\0'); |
| 2328 | + if (pas->linker_arg.size) |
| 2329 | + --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ','); |
| 2330 | + cstr_cat(&pas->linker_arg, optarg); |
| 2331 | + cstr_ccat(&pas->linker_arg, '\0'); |
| 2295 | 2332 | break; |
| 2296 | 2333 | case TCC_OPTION_E: |
| 2297 | 2334 | if (s->output_type) |
| @@ -2317,13 +2354,13 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 19 unmodified lines |
| 2317 | 2354 | break; |
| 2318 | 2355 | case TCC_OPTION_x: |
| 2319 | 2356 | if (*optarg == 'c') |
| 2320 | | − filetype = TCC_FILETYPE_C; |
| 2357 | + pas->filetype = TCC_FILETYPE_C; |
| 2321 | 2358 | else |
| 2322 | 2359 | if (*optarg == 'a') |
| 2323 | | − filetype = TCC_FILETYPE_ASM_PP; |
| 2360 | + pas->filetype = TCC_FILETYPE_ASM_PP; |
| 2324 | 2361 | else |
| 2325 | 2362 | if (*optarg == 'n') |
| 2326 | | − filetype = 0; |
| 2363 | + pas->filetype = 0; |
| 2327 | 2364 | else |
| 2328 | 2365 | tcc_warning("unsupported language '%s'", optarg); |
| 2329 | 2366 | break; |
| @@ -2349,18 +2386,38 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 19 unmodified lines |
| 2349 | 2386 | break; |
| 2350 | 2387 | } |
| 2351 | 2388 | } |
| 2389 | + return optind; |
| 2390 | +} |
| 2391 | + |
| 2392 | +PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) |
| 2393 | +{ |
| 2394 | + ParseArgsState *pas; |
| 2395 | + int ret, is_allocated = 0; |
| 2396 | + |
| 2397 | + if (!s->parse_args_state) { |
| 2398 | + s->parse_args_state = tcc_mallocz(sizeof(ParseArgsState)); |
| 2399 | + cstr_new(&s->parse_args_state->linker_arg); |
| 2400 | + is_allocated = 1; |
| 2401 | + } |
| 2402 | + pas = s->parse_args_state; |
| 2403 | + |
| 2404 | + ret = tcc_parse_args1(s, argc, argv); |
| 2352 | 2405 | |
| 2353 | 2406 | if (s->output_type == 0) |
| 2354 | | − s->output_type = TCC_OUTPUT_EXE; |
| 2407 | + s->output_type = TCC_OUTPUT_EXE; |
| 2355 | 2408 | |
| 2356 | | − if (pthread && s->output_type != TCC_OUTPUT_OBJ) |
| 2409 | + if (pas->pthread && s->output_type != TCC_OUTPUT_OBJ) |
| 2357 | 2410 | tcc_set_options(s, "-lpthread"); |
| 2358 | 2411 | |
| 2359 | 2412 | if (s->output_type == TCC_OUTPUT_EXE) |
| 2360 | | − tcc_set_linker(s, (const char *)linker_arg.data); |
| 2361 | | − cstr_free(&linker_arg); |
| 2413 | + tcc_set_linker(s, (const char *)pas->linker_arg.data); |
| 2362 | 2414 | |
| 2363 | | − return optind; |
| 2415 | + if (is_allocated) { |
| 2416 | + cstr_free(&pas->linker_arg); |
| 2417 | + tcc_free(pas); |
| 2418 | + s->parse_args_state = NULL; |
| 2419 | + } |
| 2420 | + return ret; |
| 2364 | 2421 | } |
| 2365 | 2422 | |
| 2366 | 2423 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) |