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 = 1; 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 = 1; i < argc; i++) {
77 /* Escape any \ and " characters */
78 if ((*src == '\\') || (*src == '"')) {
87 /* Note: Used to use _spawnv(_P_WAIT, ...) here, but it suffered
88 from the parent intercepting console events such as Ctrl-C,
89 which it shouldn't. Installing an ignore-all console handler
90 didn't do the trick either.
92 Irrespective of this issue, using CreateProcess() is preferable,
93 as it makes this wrapper work on both mingw and cygwin.
96 fprintf(stderr, "Invoking ghc: %s %s\n", programShort, new_cmdline);
99 if (!CreateProcess(programShort,
104 0, /* dwCreationFlags */
105 NULL, /* lpEnvironment */
106 NULL, /* lpCurrentDirectory */
107 &si, /* lpStartupInfo */
109 error("%s: Unable to start ghc.exe (error code: %lu)\n",
110 this, GetLastError());
113 /* Disable handling of console events in the parent by dropping its
114 * connection to the console. This has the (minor) downside of not being
115 * able to subsequently emit any error messages to the console.
119 switch (WaitForSingleObject(pi.hProcess, INFINITE) ) {
121 if (GetExitCodeProcess(pi.hProcess, &dwExitCode)) {
129 /* in the event we get any hard errors, bring the child
131 TerminateProcess(pi.hProcess, 1);