X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdriver%2Fghci%2Fghci.c;h=f21a12a4ba44fa224be0b0bcda14865e9a160d61;hb=28a464a75e14cece5db40f2765a29348273ff2d2;hp=a9f79debbf19ef7c0eaffa3dccb13f87fccf0426;hpb=262df042d604476a0628c41c9f894fd04feccd0c;p=ghc-hetmet.git diff --git a/ghc/driver/ghci/ghci.c b/ghc/driver/ghci/ghci.c index a9f79de..f21a12a 100644 --- a/ghc/driver/ghci/ghci.c +++ b/ghc/driver/ghci/ghci.c @@ -1,9 +1,13 @@ /* * - * $Id: ghci.c,v 1.2 2001/08/01 21:55:04 sof Exp $ + * $Id: ghci.c,v 1.10 2005/05/05 00:58:38 sof Exp $ * - * ghci wrapper - invokes ghc.exe with the added command-line + * ghci wrapper for Win32 only + * + * This wrapper invokes ghc.exe with the added command-line * option "--interactive". + * (On Unix this is done by the ghci.sh shell script, but + * that does not work so well on Win32.) * * (c) The GHC Team 2001 * @@ -25,8 +29,8 @@ * * Compile it up (assuming the .ico file is in the same dir * as the .rc file): * - * MSVC: rc /I. ghci.rc /o ghci.res - * mingw: windres -o ghci.res -o ghci.rc -O coff + * MSVC: rc /i. /fo ghci.res ghci.rc + * mingw: windres -o ghci.res -i ghci.rc -O coff * * * Add the resulting .res file to the link line of the wrapper: * @@ -40,11 +44,14 @@ #include #include #include +#include +#include #define BINARY_NAME "ghc.exe" #define IACTIVE_OPTION "--interactive" #define errmsg(msg) fprintf(stderr, msg "\n"); fflush(stderr) +#define errmsg1(msg,val) fprintf(stderr, msg "\n",val); fflush(stderr) int main(int argc, char** argv) @@ -52,22 +59,35 @@ main(int argc, char** argv) TCHAR binPath[FILENAME_MAX+1]; TCHAR binPathShort[MAX_PATH+1]; DWORD dwSize = FILENAME_MAX; - DWORD dwRes; TCHAR* szEnd; - char** new_argv; int i; + char* new_cmdline; + char *ptr, *src; + unsigned int cmdline_len = 0; + char **pp; + LPTSTR pp1; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + + if ( getenv("_") ) { + printf("WARNING: GHCi invoked via 'ghci.exe' in *nix-like shells (cygwin-bash, in particular)\n"); + printf(" doesn't handle Ctrl-C well; use the 'ghcii.sh' shell wrapper instead\n"); + fflush(stdout); + } + /* Locate the binary we want to start up */ - dwRes = - SearchPath(NULL, - BINARY_NAME, - NULL, - dwSize, - (char*)binPath, - &szEnd); - - if (dwRes == 0) { - errmsg("Unable to locate ghc.exe"); + if ( !SearchPath(NULL, + BINARY_NAME, + NULL, + dwSize, + (char*)binPath, + &szEnd) ) { + errmsg1("%s: Unable to locate ghc.exe", argv[0]); return 1; } @@ -75,46 +95,74 @@ main(int argc, char** argv) /* Turn the path into short form - LFN form causes problems when passed in argv[0]. */ if ( !(GetShortPathName(binPath, binPathShort, dwSize)) ) { - errmsg("Unable to locate ghc.exe"); + errmsg1("%s: Unable to locate ghc.exe", argv[0]); return 1; } - new_argv = (char**)malloc(sizeof(char) * (argc + 1 + 1)); - if (new_argv == NULL) { - errmsg("failed to start up ghc.exe"); - return 1; + /* Compute length of the flattened 'argv', including extra IACTIVE_OPTION (and spaces!) */ + cmdline_len += 1 + strlen(IACTIVE_OPTION); + for(i=1;i Just use spawnv(). + Irrespective of this issue, using CreateProcess() is preferable, + as it makes this wrapper work on both mingw and cygwin. */ - return _spawnv(_P_WAIT, binPath, new_argv); +#if 0 + fprintf(stderr, "Invoking ghc: %s %s\n", binPathShort, new_cmdline); fflush(stderr); +#endif + if (!CreateProcess(binPathShort, + new_cmdline, + NULL, + NULL, + TRUE, + 0, /* dwCreationFlags */ + NULL, /* lpEnvironment */ + NULL, /* lpCurrentDirectory */ + &si, /* lpStartupInfo */ + &pi) ) { + errmsg1("Unable to start ghc.exe (error code: %lu)", 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: + return 0; + 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; + } }