From 7ea43827e739555c23f2b802a6a5eaf2a65570ae Mon Sep 17 00:00:00 2001 From: Clemens Fruhwirth Date: Thu, 10 Jan 2008 09:07:21 +0000 Subject: [PATCH] Refactor cross-plattform process spawning from ghc-inplace into shell-tools.c --- compiler/Makefile | 5 +- compiler/ghc-inplace.c | 130 +--------------------------------------------- includes/shell-tools.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 133 deletions(-) create mode 100644 includes/shell-tools.c diff --git a/compiler/Makefile b/compiler/Makefile index 04c7778..ceb47b0 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -745,16 +745,13 @@ SRC_LD_OPTS += -no-link-chk INPLACE_SRC = $(odir)/ghc-inplace.c INPLACE_PROG = $(odir)/ghc-inplace$(_way)$(exeext) +INPLACE_EXTRA_FLAGS = -I$(TOP)/includes EXCLUDED_C_SRCS += ghc-inplace.c CLEAN_FILES += $(INPLACE_SRC) GHC_PATH=$(FPTOOLS_TOP_ABS)/$(GHC_COMPILER_DIR_REL)/$(GHC_PROG)$(exeext) -ifeq "$(HOSTPLATFORM)" "i386-unknown-mingw32" -INPLACE_EXTRA_FLAGS = -optc-DWINDOWS -endif - $(INPLACE_PROG): ghc-inplace.c $(SED) -e "s@GHC_PATH@$(GHC_PATH)@g" -e "s@TOP_ABS@$(FPTOOLS_TOP_ABS)@g" < $< > $(INPLACE_SRC) $(HC) -cpp $(INPLACE_EXTRA_FLAGS) $(INPLACE_SRC) -o $@ diff --git a/compiler/ghc-inplace.c b/compiler/ghc-inplace.c index d7599ea..59ceae6 100644 --- a/compiler/ghc-inplace.c +++ b/compiler/ghc-inplace.c @@ -1,28 +1,9 @@ - #include #include #include #include #include - -#ifdef WINDOWS -#include -#include -#include -#include -#include -#endif - -int run(char *this, char *program, int argc, char **argv); - -void error(const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - vfprintf(stderr, fmt, argp); - va_end(argp); - fprintf(stderr, "\n"); - fflush(stderr); -} +#include int main(int argc, char **argv) { char **args; @@ -45,112 +26,3 @@ int main(int argc, char **argv) { argc + 2, args); } - -#ifndef WINDOWS -int run(char *this, char *program, int argc, char** argv) { - execv(program, argv); - return 1; /* Not reached */ -} -#else -int run(char *this, char *program, int argc, char** argv) { - TCHAR programShort[MAX_PATH+1]; - DWORD dwSize; - DWORD dwExitCode; - int i; - char* new_cmdline; - char *ptr; - char *src; - unsigned int cmdline_len; - - STARTUPINFO si; - PROCESS_INFORMATION pi; - - ZeroMemory(&si, sizeof(STARTUPINFO)); - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - - si.cb = sizeof(STARTUPINFO); - - dwSize = MAX_PATH; - /* Turn the path into short form - LFN form causes problems - when passed in argv[0]. */ - if ( !(GetShortPathName(program, programShort, dwSize)) ) { - error("%s: Unable to locate %s", this, program); - return 1; - } - - /* Compute length of the flattened 'argv', including spaces! */ - cmdline_len = 0; - for(i = 1; i < argc; i++) { - /* Note: play it safe and quote all argv strings */ - cmdline_len += 1 + strlen(argv[i]) + 2; - } - new_cmdline = (char*)malloc(sizeof(char) * (cmdline_len + 1)); - if (!new_cmdline) { - error("%s: failed to start up ghc.exe; insufficient memory", this); - return 1; - } - - ptr = new_cmdline; - for(i = 1; i < argc; i++) { - *ptr++ = ' '; - *ptr++ = '"'; - src = argv[i]; - while(*src) { - *ptr++ = *src++; - } - *ptr++ = '"'; - } - *ptr = '\0'; - - /* Note: Used to use _spawnv(_P_WAIT, ...) here, but it suffered - from the parent intercepting console events such as Ctrl-C, - which it shouldn't. Installing an ignore-all console handler - didn't do the trick either. - - Irrespective of this issue, using CreateProcess() is preferable, - as it makes this wrapper work on both mingw and cygwin. - */ -#if 0 - fprintf(stderr, "Invoking ghc: %s %s\n", programShort, new_cmdline); - fflush(stderr); -#endif - if (!CreateProcess(programShort, - new_cmdline, - NULL, - NULL, - TRUE, - 0, /* dwCreationFlags */ - NULL, /* lpEnvironment */ - NULL, /* lpCurrentDirectory */ - &si, /* lpStartupInfo */ - &pi) ) { - error("%s: Unable to start ghc.exe (error code: %lu)", - this, GetLastError()); - return 1; - } - /* Disable handling of console events in the parent by dropping its - * connection to the console. This has the (minor) downside of not being - * able to subsequently emit any error messages to the console. - */ - FreeConsole(); - - switch (WaitForSingleObject(pi.hProcess, INFINITE) ) { - case WAIT_OBJECT_0: - if (GetExitCodeProcess(pi.hProcess, &dwExitCode)) { - return dwExitCode; - } - else { - return 1; - } - case WAIT_ABANDONED: - case WAIT_FAILED: - /* in the event we get any hard errors, bring the child - to a halt. */ - TerminateProcess(pi.hProcess, 1); - return 1; - default: - return 1; - } -} -#endif - diff --git a/includes/shell-tools.c b/includes/shell-tools.c new file mode 100644 index 0000000..29b2e2d --- /dev/null +++ b/includes/shell-tools.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include + +#ifdef mingw32_HOST_OS +#include +#include +#include +#include +#include +#endif + +void error(const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + fflush(stderr); +} + +#ifndef mingw32_HOST_OS +int run(char *this, char *program, int argc, char** argv) { + execv(program, argv); + error("%s: Unable to start %s: ", this, program); + perror(""); + return 1; /* Not reached */ +} +#else +int run(char *this, char *program, int argc, char** argv) { + TCHAR programShort[MAX_PATH+1]; + DWORD dwSize; + DWORD dwExitCode; + int i; + char* new_cmdline; + char *ptr; + char *src; + unsigned int cmdline_len; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(STARTUPINFO)); + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + + si.cb = sizeof(STARTUPINFO); + + dwSize = MAX_PATH; + /* Turn the path into short form - LFN form causes problems + when passed in argv[0]. */ + if ( !(GetShortPathName(program, programShort, dwSize)) ) { + error("%s: Unable to locate %s\n", this, program); + return 1; + } + + /* Compute length of the flattened 'argv', including spaces! */ + cmdline_len = 0; + for(i = 1; i < argc; i++) { + /* Note: play it safe and quote all argv strings */ + cmdline_len += 1 + strlen(argv[i]) + 2; + } + new_cmdline = (char*)malloc(sizeof(char) * (cmdline_len + 1)); + if (!new_cmdline) { + error("%s: failed to start up ghc.exe; insufficient memory\n", this); + return 1; + } + + ptr = new_cmdline; + for(i = 1; i < argc; i++) { + *ptr++ = ' '; + *ptr++ = '"'; + src = argv[i]; + while(*src) { + *ptr++ = *src++; + } + *ptr++ = '"'; + } + *ptr = '\0'; + + /* Note: Used to use _spawnv(_P_WAIT, ...) here, but it suffered + from the parent intercepting console events such as Ctrl-C, + which it shouldn't. Installing an ignore-all console handler + didn't do the trick either. + + Irrespective of this issue, using CreateProcess() is preferable, + as it makes this wrapper work on both mingw and cygwin. + */ +#if 0 + fprintf(stderr, "Invoking ghc: %s %s\n", programShort, new_cmdline); + fflush(stderr); +#endif + if (!CreateProcess(programShort, + new_cmdline, + NULL, + NULL, + TRUE, + 0, /* dwCreationFlags */ + NULL, /* lpEnvironment */ + NULL, /* lpCurrentDirectory */ + &si, /* lpStartupInfo */ + &pi) ) { + error("%s: Unable to start ghc.exe (error code: %lu)\n", + this, GetLastError()); + return 1; + } + /* Disable handling of console events in the parent by dropping its + * connection to the console. This has the (minor) downside of not being + * able to subsequently emit any error messages to the console. + */ + FreeConsole(); + + switch (WaitForSingleObject(pi.hProcess, INFINITE) ) { + case WAIT_OBJECT_0: + if (GetExitCodeProcess(pi.hProcess, &dwExitCode)) { + return dwExitCode; + } + else { + return 1; + } + case WAIT_ABANDONED: + case WAIT_FAILED: + /* in the event we get any hard errors, bring the child + to a halt. */ + TerminateProcess(pi.hProcess, 1); + return 1; + default: + return 1; + } +} +#endif + -- 1.7.10.4