16 int run(char *this, char *program, int argc, char **argv);
18 void error(const char *fmt, ...) {
21 vfprintf(stderr, fmt, argp);
23 fprintf(stderr, "\n");
27 int main(int argc, char **argv) {
29 args = malloc(sizeof(char *) * (argc + 3));
31 fprintf(stderr, "Malloc failed\n");
35 args[1] = "-B" TOP_ABS;
36 args[2] = "-fhardwire-lib-paths";
37 if ((argc >= 2) && (strcmp(argv[1], "-v") == 0)) {
38 printf("Using %s %s %s\n", args[0], args[1], args[2]);
40 memcpy(args + 3, argv + 1, sizeof(char *) * (argc - 1));
42 return run(argv[0], GHC_PATH, argc + 2, args);
46 int run(char *this, char *program, int argc, char** argv) {
48 return 1; /* Not reached */
51 int run(char *this, char *program, int argc, char** argv) {
52 TCHAR programShort[MAX_PATH+1];
59 unsigned int cmdline_len;
62 PROCESS_INFORMATION pi;
64 ZeroMemory(&si, sizeof(STARTUPINFO));
65 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
67 si.cb = sizeof(STARTUPINFO);
70 /* Turn the path into short form - LFN form causes problems
71 when passed in argv[0]. */
72 if ( !(GetShortPathName(program, programShort, dwSize)) ) {
73 error("%s: Unable to locate %s", this, program);
77 /* Compute length of the flattened 'argv', including spaces! */
79 for(i = 1; i < argc; i++) {
80 /* Note: play it safe and quote all argv strings */
81 cmdline_len += 1 + strlen(argv[i]) + 2;
83 new_cmdline = (char*)malloc(sizeof(char) * (cmdline_len + 1));
85 error("%s: failed to start up ghc.exe; insufficient memory", this);
90 for(i = 1; i < argc; i++) {
101 /* Note: Used to use _spawnv(_P_WAIT, ...) here, but it suffered
102 from the parent intercepting console events such as Ctrl-C,
103 which it shouldn't. Installing an ignore-all console handler
104 didn't do the trick either.
106 Irrespective of this issue, using CreateProcess() is preferable,
107 as it makes this wrapper work on both mingw and cygwin.
110 fprintf(stderr, "Invoking ghc: %s %s\n", programShort, new_cmdline);
113 if (!CreateProcess(programShort,
118 0, /* dwCreationFlags */
119 NULL, /* lpEnvironment */
120 NULL, /* lpCurrentDirectory */
121 &si, /* lpStartupInfo */
123 error("%s: Unable to start ghc.exe (error code: %lu)",
124 this, GetLastError());
127 /* Disable handling of console events in the parent by dropping its
128 * connection to the console. This has the (minor) downside of not being
129 * able to subsequently emit any error messages to the console.
133 switch (WaitForSingleObject(pi.hProcess, INFINITE) ) {
135 if (GetExitCodeProcess(pi.hProcess, &dwExitCode)) {
143 /* in the event we get any hard errors, bring the child
145 TerminateProcess(pi.hProcess, 1);