diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3373192..2b87a3a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -169,6 +169,8 @@ jobs: powershell -NoProfile -Command "$before = @(Get-ChildItem -Path $env:TEMP -Filter 'tcc*.tmp' -Name -ErrorAction SilentlyContinue); & .\tcc -B. -run ..\win32\test_run_exit.c; if ($LASTEXITCODE -ne 27) { exit 1 }; $after = @(Get-ChildItem -Path $env:TEMP -Filter 'tcc*.tmp' -Name -ErrorAction SilentlyContinue); if (Compare-Object $before $after) { Write-Host 'Temporary -run file cleanup mismatch'; Compare-Object $before $after; exit 1 }" .\tcc -B. ..\win32\test_arm64.c -o test_arm64.exe && .\test_arm64.exe .\tcc -B. -run ..\examples\ex1.c + .\tcc -B. -run ..\tcc.c -B. -run ..\tcc.c -B. -run ..\examples\ex1.c > test_nested_run.out + findstr /x /c:"Hello World" test_nested_run.out clang -O0 -I.. ..\win32\test_arm64_libtcc_context.c ..\win32\test_arm64_libtcc_context.S -o test_libtcc_context.exe .\test_libtcc_context.exe .\tcc -B. ..\win32\test_arm64_inline_asm.c -o test_inline_asm.exe && .\test_inline_asm.exe > test_inline_asm.out diff --git a/tcc.c b/tcc.c index 48526cad..c5e07978 100644 --- a/tcc.c +++ b/tcc.c @@ -330,7 +330,9 @@ redo: argc = argc0, argv = argv0; s = s1 = tcc_new(); opt = tcc_parse_args(s, &argc, &argv); +#ifdef TCC_IS_NATIVE s->run_arg_start = (int)(argv - argv0); +#endif if (n == 0) { ret = 0; diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c index 64d73130..43de92f2 100644 --- a/win32/lib/crt1.c +++ b/win32/lib/crt1.c @@ -48,9 +48,7 @@ __attribute__((weak)) char **__cdecl __rt_get_environ(void); #endif __attribute__((weak)) int __cdecl __rt_get_run_argstart(void); -void __tcc_run_on_exit(int ret); -int __tcc_on_exit(void *function, void *arg); -int __tcc_atexit(void (*function)(void)); +__attribute__((weak)) void __run_on_exit(int ret); void __attribute__((noreturn)) __tcc_exit(int code); #include "crtinit.c" @@ -235,6 +233,28 @@ static wchar_t *dup_run_wstr(const wchar_t *s) return copy; } +static wchar_t *dup_run_wstr_from_tchar(const _TCHAR *s) +{ +#ifdef UNICODE + return dup_run_wstr(s); +#else + size_t len; + wchar_t *copy; + + len = mbstowcs(NULL, s, 0); + if ((size_t)-1 == len) + return NULL; + copy = malloc(sizeof(*copy) * (len + 1)); + if (!copy) + return NULL; + if ((size_t)-1 == mbstowcs(copy, s, len + 1)) { + free(copy); + return NULL; + } + return copy; +#endif +} + static void free_run_wargv(wchar_t **argv) { int i; @@ -327,6 +347,39 @@ done: return ok; } +static wchar_t **build_run_wargv_from_targv(int src_argc, _TCHAR **src_argv, int base, int *prun_argc) +{ + wchar_t **run_argv = NULL; + int run_argc = 0, i; + + if (base < 0 || base >= src_argc) + return NULL; + for (i = base; i < src_argc; ++i) { + wchar_t *copy; + + if (!src_argv[i]) + continue; + copy = dup_run_wstr_from_tchar(src_argv[i]); + if (!copy) + goto fail; + if (_dowildcard && i > base && run_has_wildcard(copy)) { + if (run_expand_wildcard_arg(copy, &run_argv, &run_argc)) { + free(copy); + continue; + } + } + if (!append_run_warg(&run_argv, &run_argc, copy)) { + free(copy); + goto fail; + } + } + *prun_argc = run_argc; + return run_argv; +fail: + free_run_wargv(run_argv); + return NULL; +} + static wchar_t **build_run_wargv(int *prun_argc) { wchar_t **cmd_argv = NULL, **run_argv = NULL; @@ -337,6 +390,16 @@ static wchar_t **build_run_wargv(int *prun_argc) base = __rt_get_run_argstart(); if (base < 0) return NULL; + /* The active CRT argv slice is process-wide and already reflects the + current host `tcc -run ...` context, including nested runs. Reuse it + first so nested `-run tcc.c ... -run ...` keeps advancing through the + current slice instead of restarting from the original process command + line. */ + run_argv = build_run_wargv_from_targv(__argc, __targv, base, &run_argc); + if (run_argv) { + *prun_argc = run_argc; + return run_argv; + } cmd_argv = run_command_line_to_argv_w(&cmd_argc); if (!cmd_argv || base >= cmd_argc) goto fail; @@ -439,7 +502,7 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv) if (!argv_state.run_argv) return 1; run_targv_tls = &argv_state; - if (__tcc_atexit(restore_run_targv_atexit)) + if (atexit(restore_run_targv_atexit)) goto fail; __argc = run_argc; __targv = argv_state.run_argv; @@ -451,7 +514,8 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv) run_ctors(__argc, __targv, env); ret = _tmain(__argc, __targv, env); run_dtors(); - __tcc_run_on_exit(ret); + if (__run_on_exit) + __run_on_exit(ret); return ret; fail: run_targv_tls = NULL;