| @@ -2081,28 +2081,65 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 2080 unmodified lines |
| 2081 | dynarray_add((void ***)&s->files, &s->nb_files, p); | 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 | const TCCOption *popt; | 2124 | const TCCOption *popt; |
| 2087 | const char *optarg, *r; | 2125 | const char *optarg, *r; |
| 2088 | int run = 0; | | |
| 2089 | int pthread = 0; | | |
| 2090 | int optind = 0; | 2126 | int optind = 0; |
| 2091 | int filetype = 0; | 2127 | ParseArgsState *pas = s->parse_args_state; |
| 2092 | | | |
| 2093 | /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */ | | |
| 2094 | CString linker_arg; | | |
| 2095 | cstr_new(&linker_arg); | | |
| 2096 | | 2128 | |
| 2097 | while (optind < argc) { | 2129 | while (optind < argc) { |
| 2098 | | 2130 | |
| 2099 | r = argv[optind++]; | 2131 | r = argv[optind++]; |
| 2100 | if (r[0] != '-' || r[1] == '\0') { | 2132 | if (r[0] != '-' || r[1] == '\0') { |
| 2101 | args_parser_add_file(s, r, filetype); | 2133 | /* handle list files */ |
| 2102 | if (run) { | 2134 | if (r[0] == '@' && r[1]) { |
| 2103 | optind--; | 2135 | args_parser_add_listfile(s, r + 1); |
| 2104 | /* argv[0] will be this file */ | 2136 | } else { |
| 2105 | break; | 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 | continue; | 2144 | continue; |
| 2108 | } | 2145 | } |
| @@ -2152,7 +2189,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 43 unmodified lines |
| 2152 | break; | 2189 | break; |
| 2153 | case TCC_OPTION_pthread: | 2190 | case TCC_OPTION_pthread: |
| 2154 | parse_option_D(s, "_REENTRANT"); | 2191 | parse_option_D(s, "_REENTRANT"); |
| 2155 | pthread = 1; | 2192 | pas->pthread = 1; |
| 2156 | break; | 2193 | break; |
| 2157 | case TCC_OPTION_bench: | 2194 | case TCC_OPTION_bench: |
| 2158 | s->do_bench = 1; | 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 | tcc_warning("-run: some compiler action already specified (%d)", s->output_type); | 2304 | tcc_warning("-run: some compiler action already specified (%d)", s->output_type); |
| 2268 | s->output_type = TCC_OUTPUT_MEMORY; | 2305 | s->output_type = TCC_OUTPUT_MEMORY; |
| 2269 | tcc_set_options(s, optarg); | 2306 | tcc_set_options(s, optarg); |
| 2270 | run = 1; | 2307 | pas->run = 1; |
| 2271 | break; | 2308 | break; |
| 2272 | case TCC_OPTION_v: | 2309 | case TCC_OPTION_v: |
| 2273 | do ++s->verbose; while (*optarg++ == 'v'); | 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 | s->rdynamic = 1; | 2325 | s->rdynamic = 1; |
| 2289 | break; | 2326 | break; |
| 2290 | case TCC_OPTION_Wl: | 2327 | case TCC_OPTION_Wl: |
| 2291 | if (linker_arg.size) | 2328 | if (pas->linker_arg.size) |
| 2292 | --linker_arg.size, cstr_ccat(&linker_arg, ','); | 2329 | --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ','); |
| 2293 | cstr_cat(&linker_arg, optarg); | 2330 | cstr_cat(&pas->linker_arg, optarg); |
| 2294 | cstr_ccat(&linker_arg, '\0'); | 2331 | cstr_ccat(&pas->linker_arg, '\0'); |
| 2295 | break; | 2332 | break; |
| 2296 | case TCC_OPTION_E: | 2333 | case TCC_OPTION_E: |
| 2297 | if (s->output_type) | 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 | break; | 2354 | break; |
| 2318 | case TCC_OPTION_x: | 2355 | case TCC_OPTION_x: |
| 2319 | if (*optarg == 'c') | 2356 | if (*optarg == 'c') |
| 2320 | filetype = TCC_FILETYPE_C; | 2357 | pas->filetype = TCC_FILETYPE_C; |
| 2321 | else | 2358 | else |
| 2322 | if (*optarg == 'a') | 2359 | if (*optarg == 'a') |
| 2323 | filetype = TCC_FILETYPE_ASM_PP; | 2360 | pas->filetype = TCC_FILETYPE_ASM_PP; |
| 2324 | else | 2361 | else |
| 2325 | if (*optarg == 'n') | 2362 | if (*optarg == 'n') |
| 2326 | filetype = 0; | 2363 | pas->filetype = 0; |
| 2327 | else | 2364 | else |
| 2328 | tcc_warning("unsupported language '%s'", optarg); | 2365 | tcc_warning("unsupported language '%s'", optarg); |
| 2329 | break; | 2366 | break; |
| @@ -2349,18 +2386,38 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) · 19 unmodified lines |
| 2349 | break; | 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 | if (s->output_type == 0) | 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 | tcc_set_options(s, "-lpthread"); | 2410 | tcc_set_options(s, "-lpthread"); |
| 2358 | | 2411 | |
| 2359 | if (s->output_type == TCC_OUTPUT_EXE) | 2412 | if (s->output_type == TCC_OUTPUT_EXE) |
| 2360 | tcc_set_linker(s, (const char *)linker_arg.data); | 2413 | tcc_set_linker(s, (const char *)pas->linker_arg.data); |
| 2361 | cstr_free(&linker_arg); | | |
| 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 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) | 2423 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) |