Remove unused variables
[ghc-hetmet.git] / driver / ghci / ghci.c
1 /*
2  *
3  * $Id: ghci.c,v 1.10 2005/05/05 00:58:38 sof Exp $
4  *
5  * ghci wrapper for Win32 only
6  * 
7  * This wrapper invokes ghc.exe with the added command-line
8  *                option "--interactive".
9  * (On Unix this is done by the ghci.sh shell script, but
10  *  that does not work so well on Win32.)
11  *
12  * (c) The GHC Team 2001
13  *
14  * ghc.exe is searched for using the 'normal' search rules
15  * for DLLs / EXEs (i.e., first in the same dir as this wrapper,
16  * then system dirs, then PATH).
17  *
18  * To compile:
19  *
20  *   MSVC:    cl /o ghci.exe /c ghciwrap.c
21  *   mingw:   gcc -o ghci.exe ghciwrap.c
22  *
23  * If you want to associate your own icon with the wrapper,
24  * here's how to do it:
25  *
26  *   * Create a one-line .rc file, ghci.rc (say), containing
27  *          0 ICON "hsicon.ico"
28  *     (subst the string literal for the name of your icon file).
29  *   * Compile it up (assuming the .ico file is in the same dir
30  *     as the .rc file):
31  *
32  *         MSVC:    rc /i. /fo ghci.res ghci.rc 
33  *         mingw:   windres -o ghci.res -i ghci.rc -O coff
34  *
35  *   * Add the resulting .res file to the link line of the wrapper:
36  *
37  *     MSVC:    cl /o ghci.exe /c ghciwrap.c ghci.res
38  *     mingw:   gcc -o ghci.exe ghciwrap.c ghci.res
39  *
40  */
41
42 #include <windows.h>
43 #include <stdio.h>
44 #include <process.h>
45 #include <malloc.h>
46 #include <stdlib.h>
47 #include <signal.h>
48 #include <io.h>
49
50 #define BINARY_NAME "ghc.exe"
51 #define IACTIVE_OPTION "--interactive"
52
53 #define errmsg(msg) fprintf(stderr, msg "\n"); fflush(stderr)
54 #define errmsg1(msg,val) fprintf(stderr, msg "\n",val); fflush(stderr)
55
56 int
57 main(int argc, char** argv)
58 {
59   TCHAR  binPath[FILENAME_MAX+1];
60   TCHAR  binPathShort[MAX_PATH+1];
61   DWORD  dwSize = FILENAME_MAX;
62   TCHAR* szEnd;
63   int    i;
64   char*  new_cmdline;
65   char   *ptr, *src;
66   unsigned int cmdline_len = 0;
67
68   STARTUPINFO si;
69   PROCESS_INFORMATION pi;
70   
71   ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
72   ZeroMemory(&si, sizeof(STARTUPINFO));
73   si.cb = sizeof(STARTUPINFO);
74
75   if ( getenv("_") ) {
76       printf("WARNING: GHCi invoked via 'ghci.exe' in *nix-like shells (cygwin-bash, in particular)\n");
77       printf("         doesn't handle Ctrl-C well; use the 'ghcii.sh' shell wrapper instead\n");
78       fflush(stdout);
79   }
80
81   /* Locate the binary we want to start up */
82   if ( !SearchPath(NULL,
83                    BINARY_NAME,
84                    NULL,
85                    dwSize,
86                    (char*)binPath,
87                    &szEnd) ) {
88     errmsg1("%s: Unable to locate ghc.exe", argv[0]);
89     return 1;
90   }
91   
92   dwSize = MAX_PATH;
93   /* Turn the path into short form - LFN form causes problems
94      when passed in argv[0]. */
95   if ( !(GetShortPathName(binPath, binPathShort, dwSize)) ) {
96     errmsg1("%s: Unable to locate ghc.exe", argv[0]);
97     return 1;
98   }
99   
100   /* Compute length of the flattened 'argv', including extra IACTIVE_OPTION (and spaces!) */
101   cmdline_len += 1 + strlen(IACTIVE_OPTION);
102   for(i=1;i<argc;i++) {
103       /* Note: play it safe and quote all argv strings */
104       cmdline_len += 1 + strlen(argv[i]) + 2;
105   }
106   new_cmdline = (char*)malloc(sizeof(char) * (cmdline_len + 1));
107   if (!new_cmdline) {
108       errmsg1("%s: failed to start up ghc.exe; insufficient memory", argv[0]);
109       return 1;
110   }
111   
112   strcpy(new_cmdline, " " IACTIVE_OPTION);
113   ptr = new_cmdline + strlen(" " IACTIVE_OPTION);
114   for(i=1;i<argc;i++) {
115       *ptr++ = ' ';
116       *ptr++ = '"';
117       src = argv[i];
118       while(*src) {
119           *ptr++ = *src++;
120       }
121       *ptr++ = '"';
122   }
123   *ptr = '\0';
124   
125   /* Note: Used to use _spawnv(_P_WAIT, ...) here, but it suffered
126      from the parent intercepting console events such as Ctrl-C,
127      which it shouldn't. Installing an ignore-all console handler
128      didn't do the trick either.
129      
130      Irrespective of this issue, using CreateProcess() is preferable,
131      as it makes this wrapper work on both mingw and cygwin.
132   */
133 #if 0
134   fprintf(stderr, "Invoking ghc: %s %s\n", binPathShort, new_cmdline); fflush(stderr);
135 #endif
136   if (!CreateProcess(binPathShort,
137                      new_cmdline,
138                      NULL,
139                      NULL,
140                      TRUE,
141                      0, /* dwCreationFlags */
142                      NULL, /* lpEnvironment */
143                      NULL, /* lpCurrentDirectory */
144                      &si,  /* lpStartupInfo */
145                      &pi) ) {
146       errmsg1("Unable to start ghc.exe (error code: %lu)", GetLastError());
147       return 1;
148   }
149   /* Disable handling of console events in the parent by dropping its
150    * connection to the console. This has the (minor) downside of not being
151    * able to subsequently emit any error messages to the console.
152    */
153   FreeConsole();
154
155   switch (WaitForSingleObject(pi.hProcess, INFINITE) ) {
156   case WAIT_OBJECT_0:
157       return 0;
158   case WAIT_ABANDONED:
159   case WAIT_FAILED:
160       /* in the event we get any hard errors, bring the child to a halt. */
161       TerminateProcess(pi.hProcess,1);
162       return 1;
163   default:
164       return 1;
165   }
166 }