summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2009-10-27 20:25:03 +0000
committerIan Lynagh <igloo@earth.li>2009-10-27 20:25:03 +0000
commit6cf8982ac30be6836a0cdd8be5a6ac1a1a144213 (patch)
tree604f63fabadfd1d2bd2b480f5f1a7ed2211778b8 /driver
parent48196c3c2a365ce085d0b0567cbd4ea047af59df (diff)
downloadhaskell-6cf8982ac30be6836a0cdd8be5a6ac1a1a144213.tar.gz
Wrap gcc on Windows, to provide the -B flags
Diffstat (limited to 'driver')
-rw-r--r--driver/gcc/gcc.c95
-rw-r--r--driver/utils/getLocation.c40
-rw-r--r--driver/utils/getLocation.h4
3 files changed, 139 insertions, 0 deletions
diff --git a/driver/gcc/gcc.c b/driver/gcc/gcc.c
new file mode 100644
index 0000000000..cd8a511074
--- /dev/null
+++ b/driver/gcc/gcc.c
@@ -0,0 +1,95 @@
+
+#include "getLocation.h"
+#include <process.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+static void die(char *msg) {
+ fprintf(stderr, "%s", msg);
+ exit(1);
+}
+
+static char *mkString(const char *fmt, ...) {
+ char *p;
+ int i, j;
+ va_list argp;
+
+ va_start(argp, fmt);
+ i = vsnprintf(p, 0, fmt, argp);
+ va_end(argp);
+
+ if (i < 0) {
+ die("snprintf failed\n");
+ }
+
+ p = malloc(i + 1);
+ if (p == NULL) {
+ die("malloc failed\n");
+ }
+
+ va_start(argp, fmt);
+ j = vsnprintf(p, i + 1, fmt, argp);
+ va_end(argp);
+ if (i < 0) {
+ die("snprintf failed\n");
+ }
+
+ return p;
+}
+
+char *quote(char *str) {
+ char *quotedStr;
+ char *p;
+ int i;
+
+ quotedStr = malloc(2 * strlen(str) + 2 + 1);
+ if (quotedStr == NULL) {
+ die("malloc failed\n");
+ }
+ p = quotedStr;
+ *p++ = '"';
+ while (*str) {
+ if (*str == '"') {
+ *p++ = '\\';
+ }
+ *p++ = *str++;
+ }
+ *p++ = '"';
+ *p = '\0';
+
+ return quotedStr;
+}
+
+int main(int argc, char** argv) {
+ char *p;
+ char *binDir;
+ char *exePath;
+ char *bArg;
+ char **newArgv;
+ int i, j, ret;
+
+ binDir = getExecutablePath();
+ exePath = mkString("%s/realgcc.exe", binDir);
+
+ /* Without these -B args, gcc will still work. However, if you
+ have a mingw installation in c:/mingw then it will use files
+ from that in preference to the in-tree files. */
+
+ newArgv = malloc(sizeof(char *) * (argc + 4 + 1));
+ newArgv[0] = quote(exePath);
+ newArgv[1] = quote(mkString("-B%s", binDir));
+ newArgv[2] = quote(mkString("-B%s/../lib", binDir));
+ newArgv[3] = quote(mkString("-B%s/../lib/gcc/mingw32/3.4.5", binDir));
+ newArgv[4] = quote(mkString("-B%s/../libexec/gcc/mingw32/3.4.5", binDir));
+ for (i = 1; i < argc; i++) {
+ newArgv[4 + i] = quote(argv[i]);
+ }
+ newArgv[4 + argc] = NULL;
+ // execv(exePath, argv);
+ ret = spawnv(_P_WAIT, exePath, (const char* const*)newArgv);
+ if (errno) {
+ die("Spawn failed\n");
+ }
+ exit(ret);
+}
diff --git a/driver/utils/getLocation.c b/driver/utils/getLocation.c
new file mode 100644
index 0000000000..fcbe1b940c
--- /dev/null
+++ b/driver/utils/getLocation.c
@@ -0,0 +1,40 @@
+
+#include "getLocation.h"
+#include <stdio.h>
+#include <windows.h>
+
+static void die(char *msg) {
+ fprintf(stderr, "%s", msg);
+ exit(1);
+}
+
+char *getExecutable(void) {
+ char *p;
+ int i;
+ int r;
+
+ i = 2048; /* plenty, PATH_MAX is 512 under Win32 */
+ p = malloc(i);
+ if (p == NULL) {
+ die("Malloc failed\n");
+ }
+ r = GetModuleFileNameA(NULL, p, i);
+ if (r == 0) {
+ die("getModuleFileName failed\n");
+ }
+ return p;
+}
+
+char *getExecutablePath(void) {
+ char *p;
+ char *f;
+
+ p = getExecutable();
+ f = strrchr(p, '\\');
+ if (f == NULL) {
+ die("No '\\' in executable location\n");
+ }
+ f[0] = '\0';
+ return p;
+}
+
diff --git a/driver/utils/getLocation.h b/driver/utils/getLocation.h
new file mode 100644
index 0000000000..689a4427ad
--- /dev/null
+++ b/driver/utils/getLocation.h
@@ -0,0 +1,4 @@
+
+char *getExecutable(void);
+char *getExecutablePath(void);
+