aboutsummaryrefslogtreecommitdiffstats
path: root/erts/test/utils/gccifier.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/test/utils/gccifier.c')
-rw-r--r--erts/test/utils/gccifier.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/erts/test/utils/gccifier.c b/erts/test/utils/gccifier.c
new file mode 100644
index 0000000000..64de764260
--- /dev/null
+++ b/erts/test/utils/gccifier.c
@@ -0,0 +1,316 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+ */
+
+/*
+ * A compiler wrapper that translate (some) gcc command line arguments
+ * to the Visual C++ compiler and (of course) the gcc compiler. It also
+ * makes some changes in the command line arguments when debug compiling.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+
+#if !defined(__WIN32__)
+#define USE_EXEC
+#include <unistd.h>
+#endif
+
+
+#ifdef __WIN32__
+#define EOL "\r\n"
+#else
+#define EOL "\n"
+#endif
+
+#define ARGS_INCR 20
+
+static char *prog;
+
+typedef struct {
+ char **vec;
+ int no;
+ int ix;
+ int chars;
+} args_t;
+
+static void
+enomem(void)
+{
+ fprintf(stderr, "%s: Out of memory%s", prog, EOL);
+ exit(1);
+}
+
+static void
+save_arg(args_t *args, char *arg1, ...)
+{
+ char *carg;
+ va_list argp;
+
+ va_start(argp, arg1);
+ carg = arg1;
+ while (carg) {
+ if (args->no <= args->ix) {
+ args->vec = (char **) (args->no
+ ? realloc((void *) args->vec,
+ (sizeof(char *)
+ *(args->no + ARGS_INCR + 1)))
+ : malloc((sizeof(char *)
+ *(args->no + ARGS_INCR + 1))));
+ if (!args->vec)
+ enomem();
+ args->no += ARGS_INCR;
+ }
+ args->vec[args->ix++] = carg;
+ args->chars += strlen(carg);
+ carg = va_arg(argp, char *);
+ }
+ args->vec[args->ix++] = " ";
+ args->chars++;
+ va_end(argp);
+}
+
+static int
+is_prefix(char *prfx, char **str)
+{
+ int i;
+ for (i = 0; prfx[i] && (*str)[i]; i++) {
+ if (prfx[i] != (*str)[i])
+ return 0;
+ }
+ if (!prfx[i]) {
+ *str = &(*str)[i];
+ return 1;
+ }
+ return 0;
+}
+
+static void
+cpy(char **dst, char *src)
+{
+ int i;
+ for (i = 0; src[i]; i++)
+ (*dst)[i] = src[i];
+ *dst = &(*dst)[i];
+}
+
+typedef enum {
+ STDLIB_NONE,
+ STDLIB_MD,
+ STDLIB_ML,
+ STDLIB_MT
+} stdlib_t;
+
+int
+main(int argc, char *argv[])
+{
+ int res;
+ int i;
+ size_t cmd_len;
+ char *cmd;
+ char *cmd_end;
+ char *cc = NULL;
+ args_t args = {0};
+ int is_debug = 0;
+ int is_purify = 0;
+ int is_quantify = 0;
+ int is_purecov = 0;
+#ifdef __WIN32__
+ int is_shared = 0;
+ stdlib_t stdlib = STDLIB_NONE;
+ char *shared_flag = "";
+ char *stdlib_flag = "";
+ int have_link_args = 0;
+ args_t link_args = {0};
+
+#define CHECK_FIRST_LINK_ARG \
+ if (!have_link_args) { \
+ save_arg(&link_args, "-link", NULL); \
+ have_link_args = 1; \
+ }
+#else /* #ifdef __WIN32__ */
+#define CHECK_FIRST_LINK_ARG
+#endif /* #ifdef __WIN32__ */
+
+ prog = argv[0];
+
+
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+ if (is_prefix("-CC", &arg)) {
+ cc = arg;
+ }
+ else if (is_prefix("-O", &arg)) {
+ if (!is_debug)
+ save_arg(&args, argv[i], NULL);
+ }
+ else if (strcmp("-DDEBUG", arg) == 0) {
+ save_arg(&args, arg, NULL);
+#ifdef __WIN32__
+ set_debug:
+#endif
+ if (!is_debug) {
+ int j;
+ is_debug = 1;
+#ifdef __WIN32__
+ save_arg(&args, "-Z7", NULL);
+ CHECK_FIRST_LINK_ARG;
+ save_arg(&link_args, "-debug", NULL);
+ save_arg(&link_args, "-pdb:none", NULL);
+#endif
+ for (j = 0; j < args.ix; j++) {
+ char *tmp_arg = args.vec[j];
+ if (is_prefix("-O", &tmp_arg))
+ args.vec[j] = "";
+ }
+ }
+ }
+ else if (strcmp("-DPURIFY", arg) == 0) {
+ save_arg(&args, arg, NULL);
+ is_purify = 1;
+ }
+ else if (strcmp("-DQUANTIFY", arg) == 0) {
+ save_arg(&args, arg, NULL);
+ is_quantify = 1;
+ }
+ else if (strcmp("-DPURECOV", arg) == 0) {
+ save_arg(&args, arg, NULL);
+ is_purecov = 1;
+ }
+#ifdef __WIN32__
+ else if (strcmp("-g", arg) == 0) {
+ goto set_debug;
+ }
+ else if (strcmp("-MD", arg) == 0)
+ stdlib = STDLIB_MD;
+ else if (strcmp("-MDd", arg) == 0) {
+ stdlib = STDLIB_MD;
+ goto set_debug;
+ }
+ else if (strcmp("-ML", arg) == 0)
+ stdlib = STDLIB_ML;
+ else if (strcmp("-MLd", arg) == 0) {
+ stdlib = STDLIB_ML;
+ goto set_debug;
+ }
+ else if (strcmp("-MT", arg) == 0)
+ stdlib = STDLIB_MT;
+ else if (strcmp("-MTd", arg) == 0) {
+ stdlib = STDLIB_MT;
+ goto set_debug;
+ }
+ else if (strcmp("-shared", arg) == 0 || strcmp("-LD", arg) == 0)
+ is_shared = 1;
+ else if (strcmp("-LDd", arg) == 0) {
+ is_shared = 1;
+ goto set_debug;
+ }
+ else if (strcmp("-Wall", arg) == 0) {
+ save_arg(&args, "-W3", NULL);
+ }
+ else if (is_prefix("-L", &arg)) {
+ CHECK_FIRST_LINK_ARG;
+ save_arg(&link_args, "-libpath:", arg, NULL);
+ }
+#endif /* #ifdef __WIN32__ */
+ else if (is_prefix("-l", &arg)) {
+ CHECK_FIRST_LINK_ARG;
+ if (is_debug && strcmp("ethread", arg) == 0)
+ arg = "ethread.debug";
+ else if (is_purify && strcmp("ethread", arg) == 0)
+ arg = "ethread.purify";
+ else if (is_quantify && strcmp("ethread", arg) == 0)
+ arg = "ethread.quantify";
+ else if (is_purecov && strcmp("ethread", arg) == 0)
+ arg = "ethread.purecov";
+#ifdef __WIN32__
+ else if (strcmp("socket", arg) == 0)
+ arg = "ws2_32";
+ save_arg(&link_args, arg, ".lib", NULL);
+#else
+ save_arg(&args, "-l", arg, NULL);
+#endif
+ }
+ else
+ save_arg(&args, argv[i], NULL);
+ }
+
+ if (!cc || !cc[0]) {
+ fprintf(stderr, "%s: Missing compulsory -CC flag%s", prog, EOL);
+ exit(1);
+ }
+
+ cmd_len = strlen(cc) + 1 + args.chars + 1;
+
+#ifdef __WIN32__
+ if (is_shared)
+ shared_flag = is_debug ? "-LDd " : "-LD ";
+ switch (stdlib) {
+ case STDLIB_MD: stdlib_flag = is_debug ? "-MDd " : "-MD "; break;
+ case STDLIB_ML: stdlib_flag = is_debug ? "-MLd " : "-ML "; break;
+ case STDLIB_MT: stdlib_flag = is_debug ? "-MTd " : "-MT "; break;
+ case STDLIB_NONE: break;
+ }
+
+ cmd_len += strlen(shared_flag) + strlen(stdlib_flag) + link_args.chars;
+#endif
+
+ cmd = (char *) malloc(sizeof(char) * cmd_len);
+
+ if (!cmd)
+ enomem();
+ cmd_end = cmd;
+ cpy(&cmd_end, cc);
+ cpy(&cmd_end, " ");
+#ifdef __WIN32__
+ cpy(&cmd_end, stdlib_flag);
+ cpy(&cmd_end, shared_flag);
+#endif
+ for (i = 0; i < args.ix; i++)
+ cpy(&cmd_end, args.vec[i]);
+#ifdef __WIN32__
+ for (i = 0; i < link_args.ix; i++)
+ cpy(&cmd_end, link_args.vec[i]);
+#endif
+ *cmd_end = '\0';
+
+ printf("==> %s%s", cmd, EOL);
+ fflush(stdout);
+
+#ifdef USE_EXEC
+ (void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
+ perror(NULL);
+ res = 1;
+#else
+ res = system(cmd);
+#endif
+
+ free((void *) args.vec);
+#ifdef __WIN32__
+ free((void *) link_args.vec);
+#endif
+ free((void *) cmd);
+
+ if (res < 0)
+ res = 1;
+ return res;
+}