8c6926cd7d84ecf3be649b5d2713d8eadb76bd0a
[ghc-hetmet.git] / ghc / driver / ghci / ghci.c
1 /*
2  *
3  * $Id: ghci.c,v 1.6 2003/06/02 16:24:07 sof Exp $
4  *
5  * ghci wrapper - invokes ghc.exe with the added command-line
6  *                option "--interactive".
7  *
8  * (c) The GHC Team 2001
9  *
10  * ghc.exe is searched for using the 'normal' search rules
11  * for DLLs / EXEs (i.e., first in the same dir as this wrapper,
12  * then system dirs, then PATH).
13  *
14  * To compile:
15  *
16  *   MSVC:    cl /o ghci.exe /c ghciwrap.c
17  *   mingw:   gcc -mno-cygwin -o ghci.exe ghciwrap.c
18  *
19  * If you want to associate your own icon with the wrapper,
20  * here's how to do it:
21  *
22  *   * Create a one-line .rc file, ghci.rc (say), containing
23  *          0 ICON "hsicon.ico"
24  *     (subst the string literal for the name of your icon file).
25  *   * Compile it up (assuming the .ico file is in the same dir
26  *     as the .rc file):
27  *
28  *         MSVC:    rc /i. /fo ghci.res ghci.rc 
29  *         mingw:   windres -o ghci.res -i ghci.rc -O coff
30  *
31  *   * Add the resulting .res file to the link line of the wrapper:
32  *
33  *     MSVC:    cl /o ghci.exe /c ghciwrap.c ghci.res
34  *     mingw:   gcc -mno-cygwin -o ghci.exe ghciwrap.c ghci.res
35  *
36  */
37
38 #include <windows.h>
39 #include <stdio.h>
40 #include <process.h>
41 #include <malloc.h>
42 #include <stdlib.h>
43
44 #define BINARY_NAME "ghc.exe"
45 #define IACTIVE_OPTION "--interactive"
46
47 #define errmsg(msg) fprintf(stderr, msg "\n"); fflush(stderr)
48
49 int
50 main(int argc, char** argv)
51 {
52   TCHAR  binPath[FILENAME_MAX+1];
53   TCHAR  binPathShort[MAX_PATH+1];
54   DWORD  dwSize = FILENAME_MAX;
55   DWORD  dwRes;
56   TCHAR* szEnd;
57   char** new_argv;
58   int    i;
59   
60   /* Locate the binary we want to start up */
61   dwRes = 
62     SearchPath(NULL,
63                BINARY_NAME,
64                NULL,
65                dwSize,
66                (char*)binPath,
67                &szEnd);
68                
69   if (dwRes == 0) {            
70     errmsg("Unable to locate ghc.exe");
71     return 1;
72   }
73   
74   dwSize = MAX_PATH;
75   /* Turn the path into short form - LFN form causes problems
76      when passed in argv[0]. */
77   if ( !(GetShortPathName(binPath, binPathShort, dwSize)) ) {
78     errmsg("Unable to locate ghc.exe");
79     return 1;
80   }
81   
82   new_argv = (char**)malloc(sizeof(char*) * (argc + 1 + 1));
83   if (new_argv == NULL) {
84     errmsg("failed to start up ghc.exe");
85     return 1;
86   }
87   new_argv[0] = binPathShort;
88
89   new_argv[1] = (char*)malloc(sizeof(char) * (strlen(IACTIVE_OPTION) + 1));
90   if (new_argv[1]) {
91     strcpy(new_argv[1], IACTIVE_OPTION);
92   } else {
93     errmsg("failed to start up ghc.exe");
94     return 1;
95   }
96
97   for ( i=1; i < argc; i++ ) {
98     int len = strlen(argv[i]);
99     /* to avoid quoting issues, surround each option in double quotes */
100     new_argv[i+1] = (char*)malloc(sizeof(char) * (len + 3));
101     if (new_argv[i+1] == NULL) {
102       errmsg("failed to start up ghc.exe");
103       return 1;
104     } else {
105       new_argv[i+1][0] = '"';
106       strcpy(1 + new_argv[i+1], argv[i]);
107       new_argv[i+1][len+1] = '"';
108       new_argv[i+1][len+2] = '\0';
109     }
110   }
111   new_argv[i+1] = NULL;
112   
113   /* I was hoping to be able to use execv() here, but
114      the MS implementation of said function doesn't appear to
115      be quite right (the 'parent' app seems to exit without
116      waiting, which is not a spec-fulfilling thing to do).
117      
118      Cygwin gives me the right behaviour, but does it by
119      implementing it in terms of spawnv(), so you pay
120      the cost of having to create an extra process.
121      
122      ==> Just use spawnv().
123   */
124 #if 0
125   fprintf(stderr, "Invoking ghc: ");
126   i=0;
127   while (new_argv[i] != NULL) {
128     fprintf(stderr, "%s ", new_argv[i++]);
129   }
130   fprintf(stderr, "\n"); fflush(stderr);
131 #endif
132   return _spawnv(_P_WAIT, binPath, new_argv);
133 }