Print this page
cw: give cw(1onbld) a new interface allowing for multiple arbitrary shadows
*** 1,5 ****
--- 1,6 ----
+
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
*** 18,28 ****
*
* CDDL HEADER END
*/
/*
! * Copyright 2011, Richard Lowe.
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
--- 19,29 ----
*
* CDDL HEADER END
*/
/*
! * Copyright 2018, Richard Lowe.
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
*** 34,44 ****
* Since the translation is inexact, this is something of a work-in-progress.
*
*/
/* If you modify this file, you must increment CW_VERSION */
! #define CW_VERSION "1.30"
/*
* -# Verbose mode
* -### Show compiler commands built by driver, no compilation
* -A<name[(tokens)]> Preprocessor predicate assertion
--- 35,45 ----
* Since the translation is inexact, this is something of a work-in-progress.
*
*/
/* If you modify this file, you must increment CW_VERSION */
! #define CW_VERSION "2.0"
/*
* -# Verbose mode
* -### Show compiler commands built by driver, no compilation
* -A<name[(tokens)]> Preprocessor predicate assertion
*** 289,343 ****
* -YI,<dir> -nostdinc -I<dir>
* -YP,<dir> error
* -YS,<dir> error
*/
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
#include <ctype.h>
! #include <fcntl.h>
#include <errno.h>
! #include <stdarg.h>
! #include <sys/utsname.h>
#include <sys/param.h>
- #include <sys/isa_defs.h>
- #include <sys/wait.h>
#include <sys/stat.h>
#define CW_F_CXX 0x01
#define CW_F_SHADOW 0x02
#define CW_F_EXEC 0x04
#define CW_F_ECHO 0x08
#define CW_F_XLATE 0x10
#define CW_F_PROG 0x20
- typedef enum cw_compiler {
- CW_C_CC = 0,
- CW_C_GCC
- } cw_compiler_t;
-
- static const char *cmds[] = {
- "cc", "CC",
- "gcc", "g++"
- };
-
- static char default_dir[2][MAXPATHLEN] = {
- DEFAULT_CC_DIR,
- DEFAULT_GCC_DIR,
- };
-
- #define CC(ctx) \
- (((ctx)->i_flags & CW_F_SHADOW) ? \
- ((ctx)->i_compiler == CW_C_CC ? CW_C_GCC : CW_C_CC) : \
- (ctx)->i_compiler)
-
- #define CIDX(compiler, flags) \
- ((int)(compiler) << 1) + ((flags) & CW_F_CXX ? 1 : 0)
-
typedef enum cw_op {
CW_O_NONE = 0,
CW_O_PREPROCESS,
CW_O_COMPILE,
CW_O_LINK
--- 290,322 ----
* -YI,<dir> -nostdinc -I<dir>
* -YP,<dir> error
* -YS,<dir> error
*/
#include <ctype.h>
! #include <err.h>
#include <errno.h>
! #include <fcntl.h>
! #include <getopt.h>
! #include <stdio.h>
! #include <stdlib.h>
! #include <string.h>
! #include <unistd.h>
!
#include <sys/param.h>
#include <sys/stat.h>
+ #include <sys/types.h>
+ #include <sys/utsname.h>
+ #include <sys/wait.h>
#define CW_F_CXX 0x01
#define CW_F_SHADOW 0x02
#define CW_F_EXEC 0x04
#define CW_F_ECHO 0x08
#define CW_F_XLATE 0x10
#define CW_F_PROG 0x20
typedef enum cw_op {
CW_O_NONE = 0,
CW_O_PREPROCESS,
CW_O_COMPILE,
CW_O_LINK
*** 349,360 ****
char *ae_arg;
} *ael_head, *ael_tail;
int ael_argc;
};
typedef struct cw_ictx {
! cw_compiler_t i_compiler;
struct aelist *i_ae;
uint32_t i_flags;
int i_oldargc;
char **i_oldargv;
pid_t i_pid;
--- 328,352 ----
char *ae_arg;
} *ael_head, *ael_tail;
int ael_argc;
};
+ typedef enum {
+ GNU,
+ SUN
+ } compiler_style_t;
+
+ #define COMPILER_STYLE(comp) (comp->style == SUN ? "cc" : "gcc")
+
+ typedef struct {
+ char *name;
+ char *path;
+ compiler_style_t style;
+ } cw_compiler_t;
+
typedef struct cw_ictx {
! cw_compiler_t *i_compiler;
struct aelist *i_ae;
uint32_t i_flags;
int i_oldargc;
char **i_oldargv;
pid_t i_pid;
*** 388,398 ****
/*
* The translation table for the -xarch= flag used in the Studio compilers.
*/
static const xarch_table_t xtbl[] = {
#if defined(__x86)
! { "generic", SS11 },
{ "generic64", (SS11|M64), { "-m64", "-mtune=opteron" } },
{ "amd64", (SS11|M64), { "-m64", "-mtune=opteron" } },
{ "386", SS11, { "-march=i386" } },
{ "pentium_pro", SS11, { "-march=pentiumpro" } },
{ "sse", SS11, { "-msse", "-mfpmath=sse" } },
--- 380,390 ----
/*
* The translation table for the -xarch= flag used in the Studio compilers.
*/
static const xarch_table_t xtbl[] = {
#if defined(__x86)
! { "generic", SS11, {NULL} },
{ "generic64", (SS11|M64), { "-m64", "-mtune=opteron" } },
{ "amd64", (SS11|M64), { "-m64", "-mtune=opteron" } },
{ "386", SS11, { "-march=i386" } },
{ "pentium_pro", SS11, { "-march=pentiumpro" } },
{ "sse", SS11, { "-msse", "-mfpmath=sse" } },
*** 415,426 ****
#endif
};
static int xtbl_size = sizeof (xtbl) / sizeof (xarch_table_t);
- static const char *progname;
-
static const char *xchip_tbl[] = {
#if defined(__x86)
"386", "-mtune=i386", NULL,
"486", "-mtune=i486", NULL,
"pentium", "-mtune=pentium", NULL,
--- 407,416 ----
*** 462,488 ****
};
static void
nomem(void)
{
! (void) fprintf(stderr, "%s: error: out of memory\n", progname);
! exit(1);
! }
!
! static void
! cw_perror(const char *fmt, ...)
! {
! va_list ap;
! int saved_errno = errno;
!
! (void) fprintf(stderr, "%s: error: ", progname);
!
! va_start(ap, fmt);
! (void) vfprintf(stderr, fmt, ap);
! va_end(ap);
!
! (void) fprintf(stderr, " (%s)\n", strerror(saved_errno));
}
static void
newae(struct aelist *ael, const char *arg)
{
--- 452,462 ----
};
static void
nomem(void)
{
! (void) errx(1, "out of memory");
}
static void
newae(struct aelist *ael, const char *arg)
{
*** 513,525 ****
}
static void
error(const char *arg)
{
! (void) fprintf(stderr,
! "%s: error: mapping failed at or near arg '%s'\n", progname, arg);
! exit(2);
}
/*
* Add the current favourite set of warnings to the gcc invocation.
*/
--- 487,497 ----
}
static void
error(const char *arg)
{
! errx(2, "error: mapping failed at or near arg '%s'\n", arg);
}
/*
* Add the current favourite set of warnings to the gcc invocation.
*/
*** 549,559 ****
}
}
/* ARGSUSED */
static void
! Xamode(struct aelist *h)
{
}
static void
Xcmode(struct aelist *h)
--- 521,531 ----
}
}
/* ARGSUSED */
static void
! Xamode(struct aelist *h __attribute__((__unused__)))
{
}
static void
Xcmode(struct aelist *h)
*** 580,592 ****
}
static void
usage()
{
(void) fprintf(stderr,
! "usage: %s { -_cc | -_gcc | -_CC | -_g++ } [ -_compiler | ... ]\n",
! progname);
exit(2);
}
static int
xlate_xtb(struct aelist *h, const char *xarg)
--- 552,570 ----
}
static void
usage()
{
+ extern char *__progname;
(void) fprintf(stderr,
! "usage: %s [-C] [--versions] --primary <compiler> "
! "[--shadow <compiler>]... -- cflags...\n",
! __progname);
! (void) fprintf(stderr, "compilers take the form: name,path,style\n"
! " - name: a unique name usable in flag specifiers\n"
! " - path: path to the compiler binary\n"
! " - style: the style of flags expected: either sun or gnu\n");
exit(2);
}
static int
xlate_xtb(struct aelist *h, const char *xarg)
*** 641,650 ****
--- 619,629 ----
int c;
int pic = 0, nolibc = 0;
int in_output = 0, seen_o = 0, c_files = 0;
cw_op_t op = CW_O_LINK;
char *model = NULL;
+ char *nameflag;
int mflag = 0;
if (ctx->i_flags & CW_F_PROG) {
newae(ctx->i_ae, "--version");
return;
*** 677,690 ****
*
* -Dunix is also missing in enhanced ANSI mode
*/
newae(ctx->i_ae, "-D__sun");
/*
* Walk the argument list, translating as we go ..
*/
-
while (--ctx->i_oldargc > 0) {
char *arg = *++ctx->i_oldargv;
size_t arglen = strlen(arg);
if (*arg == '-') {
--- 656,671 ----
*
* -Dunix is also missing in enhanced ANSI mode
*/
newae(ctx->i_ae, "-D__sun");
+ if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->name) == -1)
+ nomem();
+
/*
* Walk the argument list, translating as we go ..
*/
while (--ctx->i_oldargc > 0) {
char *arg = *++ctx->i_oldargv;
size_t arglen = strlen(arg);
if (*arg == '-') {
*** 716,725 ****
--- 697,710 ----
in_output = 0;
continue;
}
if (ctx->i_flags & CW_F_CXX) {
+ if (strncmp(arg, "-_g++=", 6) == 0) {
+ newae(ctx->i_ae, strchr(arg, '=') + 1);
+ continue;
+ }
if (strncmp(arg, "-compat=", 8) == 0) {
/* discard -compat=4 and -compat=5 */
continue;
}
if (strcmp(arg, "-Qoption") == 0) {
*** 770,789 ****
#endif /* __sparc */
}
switch ((c = arg[1])) {
case '_':
! if (strcmp(arg, "-_noecho") == 0)
! ctx->i_flags &= ~CW_F_ECHO;
! else if (strncmp(arg, "-_cc=", 5) == 0 ||
! strncmp(arg, "-_CC=", 5) == 0)
! /* EMPTY */;
! else if (strncmp(arg, "-_gcc=", 6) == 0 ||
! strncmp(arg, "-_g++=", 6) == 0)
! newae(ctx->i_ae, arg + 6);
! else
! error(arg);
break;
case '#':
if (arglen == 1) {
newae(ctx->i_ae, "-v");
break;
--- 755,769 ----
#endif /* __sparc */
}
switch ((c = arg[1])) {
case '_':
! if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
! (strncmp(arg, "-_gcc=", 6) == 0) ||
! (strncmp(arg, "-_gnu=", 6) == 0)) {
! newae(ctx->i_ae, strchr(arg, '=') + 1);
! }
break;
case '#':
if (arglen == 1) {
newae(ctx->i_ae, "-v");
break;
*** 1421,1446 ****
error(arg);
break;
}
}
if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
op != CW_O_PREPROCESS) {
! (void) fprintf(stderr, "%s: error: multiple source files are "
! "allowed only with -E or -P\n", progname);
! exit(2);
}
/*
* Make sure that we do not have any unintended interactions between
* the xarch options passed in and the version of the Studio compiler
* used.
*/
if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
! (void) fprintf(stderr,
"Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
- exit(2);
}
switch (mflag) {
case 0:
/* FALLTHROUGH */
--- 1401,1426 ----
error(arg);
break;
}
}
+ free(nameflag);
+
if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
op != CW_O_PREPROCESS) {
! (void) errx(2, "multiple source files are "
! "allowed only with -E or -P");
}
/*
* Make sure that we do not have any unintended interactions between
* the xarch options passed in and the version of the Studio compiler
* used.
*/
if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
! (void) errx(2,
"Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
}
switch (mflag) {
case 0:
/* FALLTHROUGH */
*** 1509,1527 ****
--- 1489,1516 ----
static void
do_cc(cw_ictx_t *ctx)
{
int in_output = 0, seen_o = 0;
cw_op_t op = CW_O_LINK;
+ char *nameflag;
if (ctx->i_flags & CW_F_PROG) {
newae(ctx->i_ae, "-V");
return;
}
+ if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->name) == -1)
+ nomem();
+
while (--ctx->i_oldargc > 0) {
char *arg = *++ctx->i_oldargv;
+ if (strncmp(arg, "-_CC=", 5) == 0) {
+ newae(ctx->i_ae, strchr(arg, '=') + 1);
+ continue;
+ }
+
if (*arg != '-') {
if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
newae(ctx->i_ae, arg);
} else {
in_output = 0;
*** 1529,1551 ****
}
continue;
}
switch (*(arg + 1)) {
case '_':
! if (strcmp(arg, "-_noecho") == 0) {
! ctx->i_flags &= ~CW_F_ECHO;
! } else if (strncmp(arg, "-_cc=", 5) == 0 ||
! strncmp(arg, "-_CC=", 5) == 0) {
! newae(ctx->i_ae, arg + 5);
! } else if (strncmp(arg, "-_gcc=", 6) != 0 &&
! strncmp(arg, "-_g++=", 6) != 0) {
! (void) fprintf(stderr,
! "%s: invalid argument '%s'\n", progname,
! arg);
! exit(2);
}
break;
case 'V':
ctx->i_flags &= ~CW_F_ECHO;
newae(ctx->i_ae, arg);
break;
case 'o':
--- 1518,1534 ----
}
continue;
}
switch (*(arg + 1)) {
case '_':
! if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
! (strncmp(arg, "-_cc=", 5) == 0) ||
! (strncmp(arg, "-_sun=", 6) == 0)) {
! newae(ctx->i_ae, strchr(arg, '=') + 1);
}
break;
+
case 'V':
ctx->i_flags &= ~CW_F_ECHO;
newae(ctx->i_ae, arg);
break;
case 'o':
*** 1574,1583 ****
--- 1557,1568 ----
default:
newae(ctx->i_ae, arg);
}
}
+ free(nameflag);
+
if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
(ctx->i_flags & CW_F_SHADOW))
exit(0);
if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
*** 1587,1645 ****
}
static void
prepctx(cw_ictx_t *ctx)
{
! const char *dir = NULL, *cmd;
! char *program = NULL;
! size_t len;
!
! switch (CIDX(CC(ctx), ctx->i_flags)) {
! case CIDX(CW_C_CC, 0):
! program = getenv("CW_CC");
! dir = getenv("CW_CC_DIR");
! break;
! case CIDX(CW_C_CC, CW_F_CXX):
! program = getenv("CW_CPLUSPLUS");
! dir = getenv("CW_CPLUSPLUS_DIR");
! break;
! case CIDX(CW_C_GCC, 0):
! program = getenv("CW_GCC");
! dir = getenv("CW_GCC_DIR");
! break;
! case CIDX(CW_C_GCC, CW_F_CXX):
! program = getenv("CW_GPLUSPLUS");
! dir = getenv("CW_GPLUSPLUS_DIR");
! break;
! }
!
! if (program == NULL) {
! if (dir == NULL)
! dir = default_dir[CC(ctx)];
! cmd = cmds[CIDX(CC(ctx), ctx->i_flags)];
! len = strlen(dir) + strlen(cmd) + 2;
! if ((program = malloc(len)) == NULL)
! nomem();
! (void) snprintf(program, len, "%s/%s", dir, cmd);
! }
!
! newae(ctx->i_ae, program);
if (ctx->i_flags & CW_F_PROG) {
(void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
! "shadow" : "primary", program);
(void) fflush(stdout);
}
if (!(ctx->i_flags & CW_F_XLATE))
return;
! switch (CC(ctx)) {
! case CW_C_CC:
do_cc(ctx);
break;
! case CW_C_GCC:
do_gcc(ctx);
break;
}
}
--- 1572,1597 ----
}
static void
prepctx(cw_ictx_t *ctx)
{
! newae(ctx->i_ae, ctx->i_compiler->path);
if (ctx->i_flags & CW_F_PROG) {
(void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
! "shadow" : "primary", ctx->i_compiler->path);
(void) fflush(stdout);
}
if (!(ctx->i_flags & CW_F_XLATE))
return;
! switch (ctx->i_compiler->style) {
! case SUN:
do_cc(ctx);
break;
! case GNU:
do_gcc(ctx);
break;
}
}
*** 1684,1694 ****
strerror(errno));
return (-1);
}
(void) execv(newargv[0], newargv);
! cw_perror("couldn't run %s", newargv[0]);
return (-1);
}
static int
--- 1636,1646 ----
strerror(errno));
return (-1);
}
(void) execv(newargv[0], newargv);
! warn("couldn't run %s", newargv[0]);
return (-1);
}
static int
*** 1704,1714 ****
if (ctx->i_pid <= 0)
return (-1);
do {
if (waitpid(ctx->i_pid, &status, 0) < 0) {
! cw_perror("cannot reap child");
return (-1);
}
if (status != 0) {
if (WIFSIGNALED(status)) {
ret = -WTERMSIG(status);
--- 1656,1666 ----
if (ctx->i_pid <= 0)
return (-1);
do {
if (waitpid(ctx->i_pid, &status, 0) < 0) {
! warn("cannot reap child");
return (-1);
}
if (status != 0) {
if (WIFSIGNALED(status)) {
ret = -WTERMSIG(status);
*** 1721,1731 ****
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
(void) unlink(ctx->i_discard);
if (stat(ctx->i_stderr, &s) < 0) {
! cw_perror("stat failed on child cleanup");
return (-1);
}
if (s.st_size != 0) {
FILE *f;
--- 1673,1683 ----
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
(void) unlink(ctx->i_discard);
if (stat(ctx->i_stderr, &s) < 0) {
! warn("stat failed on child cleanup");
return (-1);
}
if (s.st_size != 0) {
FILE *f;
*** 1774,1918 ****
int fd;
(void) fclose(stderr);
if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
0666)) < 0) {
! cw_perror("open failed for standard error");
! exit(1);
}
if (dup2(fd, 2) < 0) {
! cw_perror("dup2 failed for standard error");
! exit(1);
}
if (fd != 2)
(void) close(fd);
if (freopen("/dev/fd/2", "w", stderr) == NULL) {
! cw_perror("freopen failed for /dev/fd/2");
! exit(1);
}
prepctx(ctx);
exit(invoke(ctx));
}
if (ctx->i_pid < 0) {
! cw_perror("fork failed");
! return (1);
}
if (block)
return (reap(ctx));
return (0);
}
! int
! main(int argc, char **argv)
{
! cw_ictx_t *ctx = newictx();
! cw_ictx_t *ctx_shadow = newictx();
! const char *dir;
! int do_serial, do_shadow;
! int ret = 0;
! if ((progname = strrchr(argv[0], '/')) == NULL)
! progname = argv[0];
else
! progname++;
! if (ctx == NULL || ctx_shadow == NULL)
! nomem();
! ctx->i_flags = CW_F_ECHO|CW_F_XLATE;
! /*
! * Figure out where to get our tools from. This depends on
! * the environment variables set at run time.
! */
! if ((dir = getenv("SPRO_VROOT")) != NULL) {
! (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN,
! "%s/bin", dir);
! } else if ((dir = getenv("SPRO_ROOT")) != NULL) {
! (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN,
! "%s/SS12/bin", dir);
! } else if ((dir = getenv("BUILD_TOOLS")) != NULL) {
! (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN,
! "%s/SUNWspro/SS12/bin", dir);
! }
! if ((dir = getenv("GCC_ROOT")) != NULL) {
! (void) snprintf(default_dir[CW_C_GCC], MAXPATHLEN,
! "%s/bin", dir);
}
! do_shadow = (getenv("CW_NO_SHADOW") ? 0 : 1);
! do_serial = (getenv("CW_SHADOW_SERIAL") ? 1 : 0);
!
! if (getenv("CW_NO_EXEC") == NULL)
! ctx->i_flags |= CW_F_EXEC;
! /*
! * The first argument must be one of "-_cc", "-_gcc", "-_CC", or "-_g++"
! */
! if (argc == 1)
usage();
- argc--;
- argv++;
- if (strcmp(argv[0], "-_cc") == 0) {
- ctx->i_compiler = CW_C_CC;
- } else if (strcmp(argv[0], "-_gcc") == 0) {
- ctx->i_compiler = CW_C_GCC;
- } else if (strcmp(argv[0], "-_CC") == 0) {
- ctx->i_compiler = CW_C_CC;
- ctx->i_flags |= CW_F_CXX;
- } else if (strcmp(argv[0], "-_g++") == 0) {
- ctx->i_compiler = CW_C_GCC;
- ctx->i_flags |= CW_F_CXX;
- } else {
- /* assume "-_gcc" by default */
- argc++;
- argv--;
- ctx->i_compiler = CW_C_GCC;
}
! /*
! * -_compiler - tell us the path to the primary compiler only
! */
! if (argc > 1 && strcmp(argv[1], "-_compiler") == 0) {
! ctx->i_flags &= ~CW_F_XLATE;
! prepctx(ctx);
! (void) printf("%s\n", ctx->i_ae->ael_head->ae_arg);
! return (0);
}
! /*
! * -_versions - tell us the cw version, paths to all compilers, and
! * ask each for its version if we know how.
! */
! if (argc > 1 && strcmp(argv[1], "-_versions") == 0) {
! (void) printf("cw version %s", CW_VERSION);
! if (!do_shadow)
! (void) printf(" (SHADOW MODE DISABLED)");
! (void) printf("\n");
(void) fflush(stdout);
! ctx->i_flags &= ~CW_F_ECHO;
! ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
! argc--;
! argv++;
do_serial = 1;
}
! ctx->i_oldargc = argc;
! ctx->i_oldargv = argv;
! ret |= exec_ctx(ctx, do_serial);
! if (do_shadow) {
! (void) memcpy(ctx_shadow, ctx, sizeof (cw_ictx_t));
! ctx_shadow->i_flags |= CW_F_SHADOW;
! ret |= exec_ctx(ctx_shadow, 1);
}
if (!do_serial)
! ret |= reap(ctx);
return (ret);
}
--- 1726,1910 ----
int fd;
(void) fclose(stderr);
if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
0666)) < 0) {
! err(1, "open failed for standard error");
}
if (dup2(fd, 2) < 0) {
! err(1, "dup2 failed for standard error");
}
if (fd != 2)
(void) close(fd);
if (freopen("/dev/fd/2", "w", stderr) == NULL) {
! err(1, "freopen failed for /dev/fd/2");
}
prepctx(ctx);
exit(invoke(ctx));
}
if (ctx->i_pid < 0) {
! err(1, "fork failed");
}
if (block)
return (reap(ctx));
return (0);
}
! static int
! parse_compiler(const char *spec, cw_compiler_t *compiler)
{
! char *tspec, *token;
! if ((tspec = strdup(spec)) == NULL)
! err(1, "out of memory");
!
! if ((token = strsep(&tspec, ",")) == NULL)
! errx(1, "Compiler is missing a name: %s", spec);
! compiler->name = token;
!
! if ((token = strsep(&tspec, ",")) == NULL)
! errx(1, "Compiler is missing a path: %s", spec);
! compiler->path = token;
!
! if ((token = strsep(&tspec, ",")) == NULL)
! errx(1, "Compiler is missing a style: %s", spec);
!
! if ((strcasecmp(token, "gnu") == 0) ||
! (strcasecmp(token, "gcc") == 0))
! compiler->style = GNU;
! else if ((strcasecmp(token, "sun") == 0) ||
! (strcasecmp(token, "cc") == 0))
! compiler->style = SUN;
else
! errx(1, "unknown compiler style: %s", token);
! if (tspec != NULL)
! errx(1, "Excess tokens in compiler: %s", spec);
! return (0);
! }
! int
! main(int argc, char **argv)
! {
! int ch;
! cw_compiler_t primary = { NULL, NULL, 0 };
! cw_compiler_t shadows[10];
! int nshadows = 0;
! int ret = 0;
! boolean_t do_serial = B_FALSE;
! boolean_t do_exec = B_FALSE;
! boolean_t vflg = B_FALSE;
! boolean_t Cflg = B_FALSE;
! boolean_t cflg = B_FALSE;
! boolean_t nflg = B_FALSE;
!
! cw_ictx_t *main_ctx = newictx();
!
! static struct option longopts[] = {
! { "compiler", no_argument, NULL, 'c' },
! { "noecho", no_argument, NULL ,'n' },
! { "primary", required_argument, NULL, 'p' },
! { "shadow", required_argument, NULL, 's' },
! { "versions", no_argument, NULL, 'v' },
! { NULL, 0, NULL, 0 },
! };
! while ((ch = getopt_long(argc, argv, "C", longopts, NULL)) != -1) {
! switch (ch) {
! case 'c':
! cflg = B_TRUE;
! break;
! case 'C':
! Cflg = B_TRUE;
! break;
! case 'n':
! nflg = B_TRUE;
! break;
! case 'p':
! if (primary.path != NULL) {
! warnx("Only one primary compiler may be specified");
! usage();
}
! if (parse_compiler(optarg, &primary) != 0)
! errx(1, "Couldn't parse %s as a compiler spec", optarg);
! break;
! case 's':
! if (nshadows >= 10)
! errx(1, "May only use 10 shadows at the moment");
! if (parse_compiler(optarg, &shadows[nshadows]) != 0)
! errx(1, "Couldn't parse %s as a compiler spec", optarg);
! nshadows++;
! break;
! case 'v':
! vflg = B_TRUE;
! break;
! default:
! fprintf(stderr, "Did you forget '--'?\n");
! usage();
! }
! }
! if (primary.path == NULL) {
! warnx("A primary compiler must be specified");
usage();
}
! do_serial = (getenv("CW_SHADOW_SERIAL") == NULL) ? B_FALSE : B_TRUE;
! do_exec = (getenv("CW_NO_EXEC") == NULL) ? B_TRUE : B_FALSE;
!
! /* Leave room for argv[0] */
! argc -= (optind - 1);
! argv += (optind - 1);
!
! if (main_ctx == NULL)
! nomem();
!
! main_ctx->i_oldargc = argc;
! main_ctx->i_oldargv = argv;
! main_ctx->i_flags = CW_F_XLATE;
! if (nflg == 0)
! main_ctx->i_flags |= CW_F_ECHO;
! if (do_exec)
! main_ctx->i_flags |= CW_F_EXEC;
! if (Cflg)
! main_ctx->i_flags |= CW_F_CXX;
! main_ctx->i_compiler = &primary;
!
! if (cflg) {
! fputs(primary.path, stdout);
}
! if (vflg) {
! (void) printf("cw version %s\n", CW_VERSION);
(void) fflush(stdout);
! main_ctx->i_flags &= ~CW_F_ECHO;
! main_ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
do_serial = 1;
}
! ret |= exec_ctx(main_ctx, do_serial);
!
! for (int i = 0; i < nshadows; i++) {
! cw_ictx_t *shadow_ctx = newictx();
!
! if (shadow_ctx == NULL)
! nomem();
!
! memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
! shadow_ctx->i_flags |= CW_F_SHADOW;
! shadow_ctx->i_compiler = &shadows[i];
! /* XXX: Would be nice to run these parallel, too */
! ret |= exec_ctx(shadow_ctx, 1);
}
if (!do_serial)
! ret |= reap(main_ctx);
return (ret);
}