diff --git a/libtcc.c b/libtcc.c index 70d5e6a4..8809e617 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1547,6 +1547,7 @@ enum { TCC_OPTION_rdynamic, TCC_OPTION_pthread, TCC_OPTION_run, + TCC_OPTION_rstdin, TCC_OPTION_w, TCC_OPTION_E, TCC_OPTION_M, @@ -1637,6 +1638,7 @@ static const TCCOption tcc_options[] = { { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, { "pthread", TCC_OPTION_pthread, 0}, { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, + { "rstdin", TCC_OPTION_rstdin, TCC_OPTION_HAS_ARG }, { "rdynamic", TCC_OPTION_rdynamic, 0 }, { "r", TCC_OPTION_r, 0 }, { "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) goto set_output_type; #else return tcc_error_noabort("-run is not available in a cross compiler"); +#endif +#ifdef TCC_IS_NATIVE + case TCC_OPTION_rstdin: + /* custom stdin for run_main */ + s->run_stdin = optarg; + break; #endif case TCC_OPTION_v: do ++s->verbose; while (*optarg++ == 'v'); diff --git a/tcc.c b/tcc.c index f1f527a5..e1819239 100644 --- a/tcc.c +++ b/tcc.c @@ -35,7 +35,7 @@ static const char help[] = "General options:\n" " -c compile only - generate an object file\n" " -o outfile set output filename\n" - " -run run compiled source\n" + " -run run compiled source [with custom stdin: -rstdin FILE]\n" " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n" " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" " -w disable all warnings\n" diff --git a/tcc.h b/tcc.h index 3157379d..410a5d8f 100644 --- a/tcc.h +++ b/tcc.h @@ -976,6 +976,7 @@ struct TCCState { const char *run_main; /* entry for tcc_run() */ void *run_ptr; /* runtime_memory */ unsigned run_size; /* size of runtime_memory */ + const char *run_stdin; /* custom stdin file for run_main */ #ifdef _WIN64 void *run_function_table; /* unwind data */ #endif diff --git a/tccrun.c b/tccrun.c index b9072da2..8ef0b659 100644 --- a/tccrun.c +++ b/tccrun.c @@ -233,6 +233,17 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1); if ((addr_t)-1 == (addr_t)prog_main) return -1; + + /* custom stdin for run_main, mainly if stdin is/was an input file. + * fileno(stdin) should remain 0, as posix mandates to use the smallest + * free fd, which is 0 after the initial fclose in freopen. windows too. + * to set stdin to the tty, use /dev/tty (posix) or con (windows). + */ + if (s1->run_stdin && !freopen(s1->run_stdin, "r", stdin)) { + tcc_error_noabort("failed to reopen stdin from '%s'", s1->run_stdin); + return -1; + } + errno = 0; /* clean errno value */ fflush(stdout); fflush(stderr);