When tcc -run is used with input file from stdin, then run_main's stdin (which is tcc's stdin) is already EOF after we've read it. If the program operates exclusively on stdin, then it cannot be used. This commit adds an option -rstdin FILE which sets run_main's stdin. Can also be used in such case to set run_main's stdin to the tty, using -rstdin /dev/tty (posix) or -rstdin con (windows).
Unified · Split
| @@ -1547,6 +1547,7 @@ enum { · 1546 unmodified lines | |||
| 1547 | TCC_OPTION_rdynamic, | 1547 | TCC_OPTION_rdynamic, |
| 1548 | TCC_OPTION_pthread, | 1548 | TCC_OPTION_pthread, |
| 1549 | TCC_OPTION_run, | 1549 | TCC_OPTION_run, |
| 1550 | TCC_OPTION_rstdin, | ||
| 1550 | TCC_OPTION_w, | 1551 | TCC_OPTION_w, |
| 1551 | TCC_OPTION_E, | 1552 | TCC_OPTION_E, |
| 1552 | TCC_OPTION_M, | 1553 | TCC_OPTION_M, |
| @@ -1637,6 +1638,7 @@ static const TCCOption tcc_options[] = { · 84 unmodified lines | |||
| 1637 | { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, | 1638 | { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, |
| 1638 | { "pthread", TCC_OPTION_pthread, 0}, | 1639 | { "pthread", TCC_OPTION_pthread, 0}, |
| 1639 | { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, | 1640 | { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
| 1641 | { "rstdin", TCC_OPTION_rstdin, TCC_OPTION_HAS_ARG }, | ||
| 1640 | { "rdynamic", TCC_OPTION_rdynamic, 0 }, | 1642 | { "rdynamic", TCC_OPTION_rdynamic, 0 }, |
| 1641 | { "r", TCC_OPTION_r, 0 }, | 1643 | { "r", TCC_OPTION_r, 0 }, |
| 1642 | { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, | 1644 | { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
| @@ -2041,6 +2043,12 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 398 unmodified lines | |||
| 2041 | goto set_output_type; | 2043 | goto set_output_type; |
| 2042 | #else | 2044 | #else |
| 2043 | return tcc_error_noabort("-run is not available in a cross compiler"); | 2045 | return tcc_error_noabort("-run is not available in a cross compiler"); |
| 2046 | #endif | ||
| 2047 | #ifdef TCC_IS_NATIVE | ||
| 2048 | case TCC_OPTION_rstdin: | ||
| 2049 | /* custom stdin for run_main */ | ||
| 2050 | s->run_stdin = optarg; | ||
| 2051 | break; | ||
| 2044 | #endif | 2052 | #endif |
| 2045 | case TCC_OPTION_v: | 2053 | case TCC_OPTION_v: |
| 2046 | do ++s->verbose; while (*optarg++ == 'v'); | 2054 | do ++s->verbose; while (*optarg++ == 'v'); |
| @@ -35,7 +35,7 @@ static const char help[] = · 34 unmodified lines | |||
| 35 | "General options:\n" | 35 | "General options:\n" |
| 36 | " -c compile only - generate an object file\n" | 36 | " -c compile only - generate an object file\n" |
| 37 | " -o outfile set output filename\n" | 37 | " -o outfile set output filename\n" |
| 38 | " -run run compiled source\n" | 38 | " -run run compiled source [with custom stdin: -rstdin FILE]\n" |
| 39 | " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n" | 39 | " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n" |
| 40 | " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" | 40 | " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" |
| 41 | " -w disable all warnings\n" | 41 | " -w disable all warnings\n" |
| @@ -976,6 +976,7 @@ struct TCCState { · 975 unmodified lines | |||
| 976 | const char *run_main; /* entry for tcc_run() */ | 976 | const char *run_main; /* entry for tcc_run() */ |
| 977 | void *run_ptr; /* runtime_memory */ | 977 | void *run_ptr; /* runtime_memory */ |
| 978 | unsigned run_size; /* size of runtime_memory */ | 978 | unsigned run_size; /* size of runtime_memory */ |
| 979 | const char *run_stdin; /* custom stdin file for run_main */ | ||
| 979 | #ifdef _WIN64 | 980 | #ifdef _WIN64 |
| 980 | void *run_function_table; /* unwind data */ | 981 | void *run_function_table; /* unwind data */ |
| 981 | #endif | 982 | #endif |
| @@ -233,6 +233,17 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 232 unmodified lines | |||
| 233 | prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1); | 233 | prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1); |
| 234 | if ((addr_t)-1 == (addr_t)prog_main) | 234 | if ((addr_t)-1 == (addr_t)prog_main) |
| 235 | return -1; | 235 | return -1; |
| 236 | |||
| 237 | /* custom stdin for run_main, mainly if stdin is/was an input file. | ||
| 238 | * fileno(stdin) should remain 0, as posix mandates to use the smallest | ||
| 239 | * free fd, which is 0 after the initial fclose in freopen. windows too. | ||
| 240 | * to set stdin to the tty, use /dev/tty (posix) or con (windows). | ||
| 241 | */ | ||
| 242 | if (s1->run_stdin && !freopen(s1->run_stdin, "r", stdin)) { | ||
| 243 | tcc_error_noabort("failed to reopen stdin from '%s'", s1->run_stdin); | ||
| 244 | return -1; | ||
| 245 | } | ||
| 246 | |||
| 236 | errno = 0; /* clean errno value */ | 247 | errno = 0; /* clean errno value */ |
| 237 | fflush(stdout); | 248 | fflush(stdout); |
| 238 | fflush(stderr); | 249 | fflush(stderr); |