6 #include <ghcplatform.h>
16 void error(const char *fmt, ...) {
19 vfprintf(stderr, fmt, argp);
24 #ifndef mingw32_HOST_OS
25 int run(char *this, char *program, int argc, char** argv) {
27 error("%s: Unable to start %s: ", this, program);
29 return 1; /* Not reached */
32 int run(char *this, char *program, int argc, char** argv) {
33 TCHAR programShort[MAX_PATH+1];
40 unsigned int cmdline_len;
43 PROCESS_INFORMATION pi;
45 ZeroMemory(&si, sizeof(STARTUPINFO));
46 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
48 si.cb = sizeof(STARTUPINFO);
51 /* Turn the path into short form - LFN form causes problems
52 when passed in argv[0]. */
53 if ( !(GetShortPathName(program, programShort, dwSize)) ) {
54 error("%s: Unable to locate %s\n", this, program);
58 /* Compute length of the flattened 'argv', including spaces! */
60 for(i = 0; i < argc; i++) {
61 /* Note: play it safe and quote all argv strings */
62 /* In the worst case we have to escape every character with a \ */
63 cmdline_len += 1 + 2 * strlen(argv[i]) + 2;
65 new_cmdline = (char*)malloc(sizeof(char) * (cmdline_len + 1));
67 error("%s: failed to start up ghc.exe; insufficient memory\n", this);
72 for(i = 0; i < argc; i++) {
77 /* Escape any \ and " characters */
78 if ((*src == '\\') || (*src == '"')) {
86 new_cmdline = new_cmdline + 1; /* Skip the leading space */
88 /* Note: Used to use _spawnv(_P_WAIT, ...) here, but it suffered
89 from the parent intercepting console events such as Ctrl-C,
90 which it shouldn't. Installing an ignore-all console handler
91 didn't do the trick either.
93 Irrespective of this issue, using CreateProcess() is preferable,
94 as it makes this wrapper work on both mingw and cygwin.
97 fprintf(stderr, "Invoking ghc: %s %s\n", programShort, new_cmdline);
100 if (!CreateProcess(programShort,
105 0, /* dwCreationFlags */
106 NULL, /* lpEnvironment */
107 NULL, /* lpCurrentDirectory */
108 &si, /* lpStartupInfo */
110 error("%s: Unable to start ghc.exe (error code: %lu)\n",
111 this, GetLastError());
114 /* Disable handling of console events in the parent by dropping its
115 * connection to the console. This has the (minor) downside of not being
116 * able to subsequently emit any error messages to the console.
120 switch (WaitForSingleObject(pi.hProcess, INFINITE) ) {
122 if (GetExitCodeProcess(pi.hProcess, &dwExitCode)) {
130 /* in the event we get any hard errors, bring the child
132 TerminateProcess(pi.hProcess, 1);