--- old/exception_lists/check_rtime	2018-02-22 01:20:05.498655939 +0000
+++ new/exception_lists/check_rtime	2018-02-22 01:20:05.563737886 +0000
@@ -143,11 +143,8 @@
 UNUSED_RPATH	/usr/gnu/lib.*\ from\ .*/usr/lib/64/libpython2\..
 UNUSED_RPATH	/usr/snadm/lib.*\ from\ .*/usr/snadm/lib/libspmicommon\.so\.1
 
-
 # Unused runpaths for reasons not captured above
 UNUSED_RPATH	/usr/lib/smbsrv.*\ from\ .*libsmb\.so\.1 	# future needs
-UNUSED_RPATH	/usr.*\ from\ .*tst\.gcc\.exe			# gcc built
-
 
 # Unreferenced objects of non-OSnet objects we can't change
 UNREF_OBJ	/lib.*\ of\ .*libcimapi\.so
--- old/usr/src/Makefile	2018-02-22 01:20:06.970225666 +0000
+++ new/usr/src/Makefile	2018-02-22 01:20:07.014643524 +0000
@@ -241,42 +241,14 @@
 #
 
 cc-version:
-	@if $($(MACH)_CC) -_versions >/dev/null 2>/dev/null; then \
-		$(ECHO) 32-bit compiler;			\
-		$(ECHO) $($(MACH)_CC);				\
-		$($(MACH)_CC) -_versions 2>&1 |			\
-		    $(EGREP) '^(cw|cc|gcc|primary|shadow)';	\
-	else							\
-		__COMPILER=`$($(MACH)_CC) -_compiler 2>/dev/null || $(TRUE)`;\
-		if [ -z "$$__COMPILER" ]; then			\
-			$(ECHO) No 32-bit compiler found;	\
-			exit 1;					\
-		else						\
-			$(ECHO) 32-bit compiler;		\
-			$(ECHO) $($(MACH)_CC);			\
-			$(ECHO) $$__COMPILER;			\
-			$($(MACH)_CC) -V 2>&1 | head -1;	\
-		fi;						\
-	fi
+	@$(ECHO) 32-bit compiler;			\
+	$(ECHO) $($(MACH)_CC);				\
+	$(CW) --versions $(CW_CC_COMPILERS) 2>&1
 
 cc64-version:
-	@if $($(MACH64)_CC) -_versions >/dev/null 2>/dev/null; then \
-		$(ECHO) 64-bit compiler;			\
-		$(ECHO) $($(MACH64)_CC);			\
-		$($(MACH64)_CC) -_versions 2>&1 |		\
-		    $(EGREP) '^(cw|cc|gcc|primary|shadow)';	\
-	else							\
-		__COMPILER=`$($(MACH64)_CC) -_compiler 2>/dev/null || $(TRUE)`;\
-		if [ -z "$$__COMPILER" ]; then			\
-			$(ECHO) No 64-bit compiler found;	\
-			exit 1;					\
-		else						\
-			$(ECHO) 64-bit compiler;		\
-			$(ECHO) $($(MACH64)_CC);		\
-			$(ECHO) $$__COMPILER;			\
-			$($(MACH64)_CC) -V 2>&1 | head -1;	\
-		fi;						\
-	fi
+	@$(ECHO) 64-bit compiler;			\
+	$(ECHO) $($(MACH)_CC);				\
+	$(CW) --versions $(CW_CC_COMPILERS) 2>&1
 
 java-version:
 	@if [ -x "$(JAVAC)" ]; then			\
--- old/usr/src/Makefile.master	2018-02-22 01:20:07.957109517 +0000
+++ new/usr/src/Makefile.master	2018-02-22 01:20:07.990630929 +0000
@@ -484,15 +484,13 @@
 #
 # Flags used with genoffsets
 #
-GOFLAGS = -_noecho \
-	$(CALLSYMS) \
-	$(CDWARFSTR)
+GOFLAGS = $(CALLSYMS) $(CDWARFSTR)
 
 OFFSETS_CREATE = $(GENOFFSETS) -s $(CTFSTABS) -r $(CTFCONVERT) \
-	$(CC) $(GOFLAGS) $(CFLAGS) $(CPPFLAGS)
+	$(CW) --noecho $(CW_CC_COMPILERS) -- $(GOFLAGS) $(CFLAGS) $(CPPFLAGS)
 
 OFFSETS_CREATE64 = $(GENOFFSETS) -s $(CTFSTABS) -r $(CTFCONVERT) \
-	$(CC) $(GOFLAGS) $(CFLAGS64) $(CPPFLAGS)
+	$(CW) --noecho $(CW_CC_COMPILERS) -- $(GOFLAGS) $(CFLAGS64) $(CPPFLAGS)
 
 #
 # tradeoff time for space (smaller is better)
@@ -781,6 +779,15 @@
 SPRO_VROOT=		$(SPRO_ROOT)/SS12
 GNU_ROOT=		/usr
 
+$(__GNUC)PRIMARY_CC=	gcc4,$(GCC_ROOT)/bin/gcc,gnu
+$(__SUNC)PRIMARY_CC=	studio12,$(SPRO_VROOT)/bin/cc,sun
+$(__GNUC)PRIMARY_CCC=	gcc4,$(GCC_ROOT)/bin/g++,gnu
+$(__SUNC)PRIMARY_CCC=	studio12,$(SPRO_VROOT)/bin/CC,sun
+
+CW_CC_COMPILERS=	$(PRIMARY_CC:%=--primary %) $(SHADOW_CCS:%=--shadow %)
+CW_CCC_COMPILERS=	$(PRIMARY_CCC:%=--primary %) $(SHADOW_CCCS:%=--shadow %)
+
+
 # Till SS12u1 formally becomes the NV CBE, LINT is hard
 # coded to be picked up from the $SPRO_ROOT/sunstudio12.1/
 # location. Impacted variables are sparc_LINT, sparcv9_LINT,
@@ -791,38 +798,32 @@
 # Specify platform compiler versions for languages
 # that we use (currently only c and c++).
 #
-sparc_CC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_cc
-$(__GNUC)sparc_CC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
-sparc_CCC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_CC
-$(__GNUC)sparc_CCC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_g++
+CW=			$(ONBLD_TOOLS)/bin/$(MACH)/cw
+
+sparc_CC=		$(CW) $(CW_CC_COMPILERS) --
+sparc_CCC=		$(CW) -C $(CW_CCC_COMPILERS) --
 sparc_CPP=		/usr/ccs/lib/cpp
 sparc_AS=		/usr/ccs/bin/as -xregsym=no
 sparc_LD=		/usr/ccs/bin/ld
 sparc_LINT=		$(SPRO_ROOT)/sunstudio12.1/bin/lint
 
-sparcv9_CC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_cc
-$(__GNUC64)sparcv9_CC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
-sparcv9_CCC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_CC
-$(__GNUC64)sparcv9_CCC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_g++
+sparcv9_CC=		$(CW) $(CW_CC_COMPILERS) --
+sparcv9_CCC=		$(CW) -C $(CW_CCC_COMPILERS) --
 sparcv9_CPP=		/usr/ccs/lib/cpp
 sparcv9_AS=		/usr/ccs/bin/as -xregsym=no
 sparcv9_LD=		/usr/ccs/bin/ld
 sparcv9_LINT=		$(SPRO_ROOT)/sunstudio12.1/bin/lint
 
-i386_CC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_cc
-$(__GNUC)i386_CC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
-i386_CCC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_CC
-$(__GNUC)i386_CCC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_g++
+i386_CC=		$(CW) $(CW_CC_COMPILERS) --
+i386_CCC=		$(CW) -C $(CW_CCC_COMPILERS) --
 i386_CPP=		/usr/ccs/lib/cpp
 i386_AS=		/usr/ccs/bin/as
 $(__GNUC)i386_AS=	$(ONBLD_TOOLS)/bin/$(MACH)/aw
 i386_LD=		/usr/ccs/bin/ld
 i386_LINT=		$(SPRO_ROOT)/sunstudio12.1/bin/lint
 
-amd64_CC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_cc
-$(__GNUC64)amd64_CC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
-amd64_CCC=		$(ONBLD_TOOLS)/bin/$(MACH)/cw -_CC
-$(__GNUC64)amd64_CCC=	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_g++
+amd64_CC=		$(CW) $(CW_CC_COMPILERS) --
+amd64_CCC=		$(CW) -C $(CW_CCC_COMPILERS) --
 amd64_CPP=		/usr/ccs/lib/cpp
 amd64_AS=		$(ONBLD_TOOLS)/bin/$(MACH)/aw
 amd64_LD=		/usr/ccs/bin/ld
@@ -845,12 +846,6 @@
 LD=			$(NATIVELD)
 LINT=			$(NATIVELINT)
 
-# The real compilers used for this build
-CW_CC_CMD=		$(CC) -_compiler
-CW_CCC_CMD=		$(CCC) -_compiler
-REAL_CC=		$(CW_CC_CMD:sh)
-REAL_CCC=		$(CW_CCC_CMD:sh)
-
 # Pass -Y flag to cpp (method of which is release-dependent)
 CCYFLAG=		-Y I,
 
--- old/usr/src/Makefile.master.64	2018-02-22 01:20:09.083727511 +0000
+++ new/usr/src/Makefile.master.64	2018-02-22 01:20:09.115085404 +0000
@@ -63,9 +63,6 @@
 LD=		$($(MACH64)_LD)
 LINT=		$($(MACH64)_LINT)
 
-REAL_CC=	$(CW_CC_CMD:sh)
-REAL_CCC=	$(CW_CCC_CMD:sh)
-
 BUILD.SO=	$(CC) $(CFLAGS) -o $@ $(GSHARED) $(DYNFLAGS) \
 		$(PICS) $(EXTPICS) -L $(ROOTLIBDIR64) $(LDLIBS)
 
--- old/usr/src/cmd/dtrace/test/tst/common/Makefile	2018-02-22 01:20:10.972257340 +0000
+++ new/usr/src/cmd/dtrace/test/tst/common/Makefile	2018-02-22 01:20:11.017338315 +0000
@@ -57,8 +57,6 @@
 
 ustack/tst.bigstack.exe := COPTFLAG += -xO1
 
-GCC = $(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
-
 nfs/%.o: $(SNOOPDIR)/%.c
 	$(COMPILE.c) -o $@ $< -I$(SNOOPDIR)
 	$(POST_PROCESS_O)
@@ -75,10 +73,6 @@
 	$(LDLIBS) -lnsl -lrpcsvc
 	$(POST_PROCESS) ; $(STRIP_STABS)
 
-pid/tst.gcc.exe: pid/tst.gcc.c
-	$(GCC) -o pid/tst.gcc.exe pid/tst.gcc.c $(LDFLAGS) $(LDLIBS)
-	$(POST_PROCESS) ; $(STRIP_STABS)
-
 json/tst.usdt.o: json/usdt.h
 
 json/usdt.h: json/usdt.d
--- old/usr/src/cmd/dtrace/test/tst/common/pid/tst.gcc.c	2018-02-22 01:20:11.929687615 +0000
+++ /dev/null	2018-02-22 01:20:11.000000000 +0000
@@ -1,63 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <spawn.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-void
-go(void)
-{
-	pid_t pid;
-
-	(void) posix_spawn(&pid, "/usr/bin/ls", NULL, NULL, NULL, NULL);
-
-	(void) waitpid(pid, NULL, 0);
-}
-
-void
-intr(int sig)
-{
-}
-
-int
-main(int argc, char **argv)
-{
-	struct sigaction sa;
-
-	sa.sa_handler = intr;
-	sigfillset(&sa.sa_mask);
-	sa.sa_flags = 0;
-
-	(void) sigaction(SIGUSR1, &sa, NULL);
-
-	for (;;) {
-		go();
-	}
-
-	return (0);
-}
--- old/usr/src/cmd/dtrace/test/tst/common/pid/tst.gcc.d	2018-02-22 01:20:12.289283286 +0000
+++ /dev/null	2018-02-22 01:20:12.000000000 +0000
@@ -1,52 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * ASSERTION: test that we can trace every instruction safely for gcc
- * compiled apps.
- *
- * SECTION: pid provider
- *
- */
-
-BEGIN
-{
-	/*
-	 * Let's just do this for 2 seconds.
-	 */
-	timeout = timestamp + 2000000000;
-}
-
-pid$1:a.out::
-{}
-
-profile:::tick-4
-/timestamp > timeout/
-{
-	exit(0);
-}
--- old/usr/src/common/mapfiles/gen/Makefile	2018-02-22 01:20:12.735077463 +0000
+++ new/usr/src/common/mapfiles/gen/Makefile	2018-02-22 01:20:12.782309057 +0000
@@ -27,13 +27,12 @@
 
 include		$(SRC)/Makefile.master
 
-FILES=	\
-		$(MACH)_cc_map.noexeglobs \
-		$(MACH)_gcc_map.noexeglobs
-
-$(BUILD64)FILES += \
-		$(MACH64)_cc_map.noexeglobs \
-		$(MACH64)_gcc_map.noexeglobs
+
+$(__GNUC)FILES=	$(MACH)_gcc_map.noexeglobs
+$(__SUNC)FILES= $(MACH)_cc_map.noexeglobs
+
+$(__GNUC)$(BUILD64)FILES += $(MACH64)_gcc_map.noexeglobs
+$(__SUNC)$(BUILD64)FILES += $(MACH64)_cc_map.noexeglobs 
 
 SYMS1=		syms.1
 SYMS2=		syms.2
@@ -73,12 +72,9 @@
 
 $(MACH)_cc_map.noexeglobs :=	LINK =	$(LINK.c)
 $(MACH64)_cc_map.noexeglobs :=	LINK =	$(LINK64.c)
-
-$(MACH)_gcc_map.noexeglobs :=	CC =	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
 $(MACH)_gcc_map.noexeglobs :=	LINK =	$(LINK.c)
-$(MACH64)_gcc_map.noexeglobs :=	CC =	$(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
 $(MACH64)_gcc_map.noexeglobs :=	LINK =	$(LINK64.c)
- 
+
 # This generic target creates two dynamic executables from an empty "main"
 # program.  These objects are not executed, but are analyzed to determine the
 # global symbols each provides.
--- old/usr/src/lib/smbsrv/Makefile.targ	2018-02-22 01:20:13.956413362 +0000
+++ new/usr/src/lib/smbsrv/Makefile.targ	2018-02-22 01:20:13.998457871 +0000
@@ -22,14 +22,13 @@
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 
 #
 # Common targets for smbsrv Makefiles
 #
 
 %_ndr.c: $(NDLDIR)/%.ndl
-	$(NDRGEN) -Y $(CC) $<
+	$(NDRGEN) -Y "$(CC)" $<
 
 pics/%.o:	$(SRC)/common/smbsrv/%.c
 	$(COMPILE.c) -o $@ $<
--- old/usr/src/pkg/manifests/system-dtrace-tests.mf	2018-02-22 01:20:15.206346666 +0000
+++ new/usr/src/pkg/manifests/system-dtrace-tests.mf	2018-02-22 01:20:15.249849313 +0000
@@ -1145,8 +1145,6 @@
 file path=opt/SUNWdtrt/tst/common/pid/tst.float.exe mode=0555
 file path=opt/SUNWdtrt/tst/common/pid/tst.fork.d mode=0444
 file path=opt/SUNWdtrt/tst/common/pid/tst.fork.exe mode=0555
-file path=opt/SUNWdtrt/tst/common/pid/tst.gcc.d mode=0444
-file path=opt/SUNWdtrt/tst/common/pid/tst.gcc.exe mode=0555
 file path=opt/SUNWdtrt/tst/common/pid/tst.killonerror.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/pid/tst.main.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/pid/tst.manypids.ksh mode=0444
--- old/usr/src/test/os-tests/tests/file-locking/Makefile	2018-02-22 01:20:16.534656106 +0000
+++ new/usr/src/test/os-tests/tests/file-locking/Makefile	2018-02-22 01:20:16.590144764 +0000
@@ -16,7 +16,7 @@
 include $(SRC)/cmd/Makefile.cmd
 include $(SRC)/test/Makefile.com
 
-UTILS = util.c
+OBJECTS=util.o runtests.32.o runtests.64.o acquire-lock.32.o acquire-lock.64.o
 
 PROGS = \
 	runtests \
@@ -24,7 +24,7 @@
 
 CSTD = $(CSTD_GNU99)
 
-SRCS = $(PROGS:%=%.c) $(UTILS)
+SRCS = $(PROGS:%=%.c) $(UTILS:%.o=%.c)
 PROGS32 = $(PROGS:%=%.32)
 PROGS64 = $(PROGS:%=%.64)
 
@@ -61,12 +61,18 @@
 %.ln: %.c
 	$(LINT.c) $< $(UTILS) $(LDLIBS)
 
-%.64: %.c
-	$(LINK64.c) -o $@ $< $(UTILS) $(LDLIBS64)
+%.64.o: %.c
+	$(COMPILE64.c) $< -o $@
+
+%.32.o: %.c
+	$(COMPILE.c) $< -o $@
+
+%.64: %.64.o util.64.o
+	$(LINK64.c) -o $@ $< util.64.o $(LDLIBS64)
 	$(POST_PROCESS)
 
-%.32: %.c
-	$(LINK.c) -o $@ $< $(UTILS) $(LDLIBS)
+%.32: %.32.o util.32.o
+	$(LINK.c) -o $@ $< util.32.o $(LDLIBS)
 	$(POST_PROCESS)
 
 clobber:
--- old/usr/src/tools/cw/Makefile	2018-02-22 01:20:17.522894102 +0000
+++ new/usr/src/tools/cw/Makefile	2018-02-22 01:20:17.568781354 +0000
@@ -39,18 +39,14 @@
 
 # Override CFLAGS.  This is needed only for bootstrap of cw.
 $(__GNUC)CFLAGS=	-O -D__sun -Wall -Wno-unknown-pragmas -Werror \
-			-std=gnu89 -nodefaultlibs
+			-std=gnu99 -nodefaultlibs
 $(__SUNC)CFLAGS=	-xspace -Xa  -xildoff -errtags=yes -errwarn=%all \
-			-xc99=%none    -W0,-xglobalstatic -v
+			-xc99=%all    -W0,-xglobalstatic -v
 
 
 $(__GNUC)LDLIBS +=	-lc
 $(__GNUC)LDFLAGS= 	$(MAPFILE.NES:%=-Wl,-M%)
 
-CPPFLAGS += -DDEFAULT_CC_DIR='"$(SPRO_VROOT)/bin"'
-CPPFLAGS += -DDEFAULT_GCC_DIR='"$(GCC_ROOT)/bin"'
-CPPFLAGS += -DDEFAULT_CPLUSPLUS_DIR='"$(SPRO_VROOT)/bin"'
-CPPFLAGS += -DDEFAULT_GPLUSPLUS_DIR='"$(GCC_ROOT)/bin"'
 
 $(ROOTONBLDMAN1ONBLDFILES) := FILEMODE=      644
 
--- old/usr/src/tools/cw/cw.1onbld	2018-02-22 01:20:18.567596368 +0000
+++ new/usr/src/tools/cw/cw.1onbld	2018-02-22 01:20:18.604526327 +0000
@@ -21,211 +21,199 @@
 .\" Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 .\" Use is subject to license terms.
 .\"
-.TH CW 1ONBLD "Mar 22, 2010"
-.SH NAME
-.I cw
-\- invoke one or more compilers with argument translation
-.SH SYNOPSIS
-\fBcw {-_cc|-_gcc|-_CC|-_g++} [options] [compiler args...]\fP
-.SH DESCRIPTION
-.LP
-.I cw
-is a facility for invoking one or more compilers, providing
-translation from Sun Studio arguments as appropriate.  This allows
-the use of arbitrary compilers without the need to alter large
-numbers of makefiles.  A mode called shadow compilation, the default,
-invokes two different compilers so that warnings and errors may be
-obtained from both.  See SHADOW COMPILATION for details.  This version
-of cw supports Sun Studio 10 and 11 and gcc 3.4.3 as shipped in
-Solaris.
-.SH ARGUMENTS
-.LP
-Exactly one of the following arguments is required, and must appear
-immediately following \fBcw\fP in the argument list:
-.TP 4
-.B \-_cc
-Select Sun Studio C (cc) as the primary compiler.
-.TP 4
-.B \-_gcc
-Select GNU C (gcc) as the primary compiler.
-.TP 4
-.B \-_CC
-Select Sun Studio C++ (CC) as the primary compiler.
-.TP 4
-.B \-_g++
-Select GNU C++ (g++) as the primary compiler.
-.SH OPTIONS
-.LP
-The following options are supported:
-.TP 4
-.B \-_compiler
-Do not invoke any compiler; instead, write to standard output the
-full path to the primary compiler that would be invoked.  If this
-option is given, it must appear immediately following the compiler
-selection argument, and all other options will be disregarded.
-.TP 4
-.B \-_versions
-Print the cw version, followed in turn by the path to and versions
-of each compiler which would be invoked.  If this option is given,
-it must appear immediately following the compiler selection argument,
-and all other options will be disregarded.
-.TP 4
-.B \-_noecho
-Normally, cw writes to standard error the actual compiler commands
-invoked, each prefixed with '+'.  This option suppresses these
-messages.
-.TP 4
-.B \-_cc=,\-_gcc=,\-_CC=,\-g++=
-Pass compiler-dependent options.  See ARGUMENT TRANSLATION.
-.SH SHADOW COMPILATION
-.LP
-Unless otherwise directed by environment variables (see ENVIRONMENT),
-\fBcw\fP will invoke both the compiler specified by its first argument
-(primary) and a designated alternate compiler (shadow).  The primary
-compiler will be invoked with the arguments given to cw, translated
-as described in ARGUMENT TRANSLATION.  The secondary compiler will be
-invoked in parallel with the primary (but see ENVIRONMENT); its
-arguments will likewise be translated.  However, the shadow compiler's
-arguments will also be modified as follows:
-.TP 4
-.B 1.
-If none of \fI-c\fP, \fI-E\fP, \fI-P\fP, or \fI-S\fP appears in the
-argument list (that is, linking is attempted), the shadow compiler
-will not be invoked.  This is because the objects built with that
-compiler which would be linked have been previously discarded.
-.TP 4
-.B 2.
-If an option of the form \fI-ofilename\fP was provided, it will be
-replaced by two options of the form \fI-o\fP \fItempfile\fP.
-.TP 4
-.B 3.
-If the option \fI-o\fP was provided, its following argument will be
-replaced by \fItempfile\fP.
-.TP 4
-.B 4.
-If neither of the above options was provided, two options of the
-form \fI-o\fP \fItempfile\fP will be added to the end of the argument
-list used to invoke the shadow compiler.
-.LP
-In all three cases, \fItempfile\fP is the name of a temporary file
-which will be removed by \fBcw\fP before it terminates.
-.LP
-When shadow compilation is in effect, \fBcw\fP writes to standard error
-each compiler's standard error output following its argument list.
-Messages from the two compilers will not be interleaved.  If \fBcw\fP
+.Dd February 10, 2018
+.Dt CW 1ONBLD
+.Os
+.Sh NAME
+.Nm cw
+.Nd invoke one or more compilers with argument translation
+.Sh SYNOPSIS
+.Nm cw
+.Op Fl C
+.Op Fl -versions
+.Op Fl -noecho
+.Fl -primary Ar compiler
+.Op Fl -shadow Ar compiler ...
+.Fl -
+.Ar compiler args ...
+.Sh DESCRIPTION
+.Nm cw
+is a facility for invoking one or more compilers, providing translation from
+Sun style arguments as appropriate.
+This allows the use of arbitrary compilers without the need to alter large
+numbers of makefiles.
+A mode called shadow compilation invokes multiple compilers so that warnings
+and errors may be obtained from both.
+See
+.Sx SHADOW COMPILATION
+for details.
+This version of cw supports compilers with both Sun Studio 12 and GCC-style
+command lines.
+.Sh ARGUMENTS
+Both the
+.Fl -primary
+and
+.Fl -shadow
+parameters take a
+.Em compiler specification .
+This is a comma-separated list of the form
+.Ar name,executable,style
+Where
+.Ar name
+is a name for the compiler,
+.Ar executable
+is the full path to the compiler executable, and
+.Ar style
+is the style of command-line options the compiler expects, either
+.Em sun
+or
+.Em gnu .
+.Bl -tag -width indent
+.It Fl -primary Ar compiler
+Specify the compiler to be used primarily (that which is used for link-editing
+and pre-processing, and whos objects we deliver).
+.It Fl -shadow Ar compiler
+Specify a shadow compiler, which builds sources for the sake of checking code
+quality and compatibility, but has its output discarded.
+.It Fl -noecho
+Do not echo the actual command line of any compilers invoked.
+.It Fl -versions
+Request from each configured primary and shadow compiler its version
+information.
+.It Fl C
+The sources being compiled are C++.  This is necessary as it affects the
+translation of compiler arguments.
+.It Fl -
+Arguments intended for the compilers themselves must be separated from those
+of
+.Nm cw
+by a
+.Fl - .
+.It Fl _name=
+.It Fl _style=
+Parameters intended for the compiler be guarded with options of the form
+.Fl _name=
+and
+.Fl _style=
+Where
+.Em name
+and
+.Em style
+are those passed to
+.Fl -primary
+and
+.Fl -shadow
+this allows certain flags to be passed only to certain classes of compiler.
+.Pp
+For historical reasons, the
+.Fl _style=
+option is also translated such that a style of
+.Em sun
+may use the flag
+.Fl _cc=
+and a style of
+.Em gnu
+may use the flag
+.Fl _gcc= ,
+and when the
+.Fl C
+option is given and C++ is in use the style of
+.Em sun
+may use the flag
+.Fl _CC=
+and the style of
+.Em gnu
+may use the flag
+.Fl _g++= .
+.El
+.Sh SHADOW COMPILATION
+If
+.Fl -shadow
+compilers are specified
+.Nm cw
+will invoke shadow compiler, with the outputs modified (as well as any
+translation for compiler style) as follows:
+.Bl -enum
+.It
+If neither of 
+.Fl c ,
+.Fl S
+appears in the argument list (that is, linking is attempted or only the
+pre-processor is invoked), the shadow compilers will not be invoked.
+.It
+If the
+.Fl o Ar filename
+option was provided, with or without a separating space, it will be replaced with
+.Fl o Ar tempfile
+.It
+If the option
+.Fl o
+was not provided,
+.Fl o Ar tempfile
+will be added to the end of the argument list used to invoke
+the shadow compilers.
+.El
+When shadow compilation is in effect,
+.Nm cw
+writes to standard error each compiler's standard error output following its
+argument list.
+Messages from the compilers will not be interleaved.
+If
+.Nm cw
 is used to invoke the preprocessor and no output location is specified,
-\fBcw\fP will write to standard output the primary compiler's
-standard output, and the secondary compiler's standard output will
-be discarded.
-.LP
-Because the Studio compilers write intermediate objects to fixed
+.Nm cw
+will write to standard output the primary compiler's standard output.
+.Pp
+Because the Sun compilers write intermediate objects to fixed
 filenames in the current directory when instructed to compile and
 link multiple source files via a single command line, it would be
-unsafe to invoke more than one compiler in this fashion.  Therefore
-\fBcw\fP does not accept multiple source files unless the
-preprocessor is to be invoked.  An attempt to invoke \fBcw\fP in
-this manner will result in an error.
-.SH ARGUMENT TRANSLATION
-.LP
-The arguments provided to \fBcw\fP will be passed through to each
-compiler invoked, altered as follows:
-.TP 4
-.B 1.
-Options intended for \fBcw\fP itself are removed.
-.TP 4
-.B 2.
-The shadow compiler's arguments are modified as described in
-SHADOW COMPILATION so that its output is discarded.
-.TP 4
-.B 3.
-If the compiler to be invoked is a GNU C or C++ compiler, a set of
+unsafe to invoke more than one compiler in this fashion.
+Therefore
+.Nm cw
+does not accept multiple source files unless the preprocessor is to be
+invoked.
+An attempt to invoke
+.Nm cw
+in this manner will result in an error.
+.Sh ARGUMENT TRANSLATION
+If the compiler to be invoked is a GNU-style C or C++ compiler, a set of
 default flags is added to the beginning of the argument list, and the
 remaining arguments are translated to their closest appropriate
 semantic equivalents and passed in the same order as their
-counterparts given to \fBcw\fP.  Arguments which begin with
-\fI-_gcc=\fP or \fI-_g++=\fP will be passed in place with the
-leading portion removed.  Arguments which begin with \fI-_cc=\fP or
-\fI-_CC=\fP will be discarded.  See the comments at the head of
-\fIusr/src/tools/cw/cw.c\fP for a detailed list of translations.
-.TP 4
-.B 4.
-If the compiler to be invoked is a Studio C or C++ compiler, the
-remaining arguments are passed unmodified and in the same order as
-given to \fBcw\fP.  Arguments which begin with \fI-_cc=\fP or
-\fI-_CC=\fP will be passed in place with the leading portion removed.
-Arguments which begin with \fI-_gcc=\fP or \fI-_g++=\fP will be
-discarded.
-.SH ENVIRONMENT
-.TP 4
-.B CW_NO_SHADOW
-If this variable is set in the environment, invoke only the
-primary compiler.
-.TP 4
-.B CW_SHADOW_SERIAL
-If this variable is set in the environment, invoke the primary compiler,
-wait for it to complete, then invoke the shadow compiler.  Normally
-the two compilers are invoked in parallel.  If CW_NO_SHADOW is set,
-this has no effect.
-.TP 4
-.B CW_NO_EXEC
+counterparts given to
+.Nm cw .
+See the comments at the head of
+.Pa usr/src/tools/cw/cw.c
+for a detailed list of translations.
+.Sh ENVIRONMENT
+.Bl -tag -width indent
+.It CW_SHADOW_SERIAL
+If this variable is set in the environment, invoke the primary compiler, wait
+for it to complete, then invoke the shadow compilers.
+Normally the primary and shadow compilers are invoked in parallel.
+.It CW_NO_EXEC
 If this variable is set in the environment, write the usual output to
-standard error but do not actually invoke any compiler.  This is
-useful for debugging the translation engine.
-.TP 4
-.B CW_CC, CW_CPLUSPLUS
-If these variables are set in the environment, they specify the full
-pathname for the Studio C and C++ compilers, respectively.
-.TP 4
-.B CW_CC_DIR, CW_CPLUSPLUS_DIR, SPRO_VROOT, SPRO_ROOT, BUILD_TOOLS
-If CW_CC or CW_CPLUSPLUS are not set,
-these variables define the search path for Studio compilers as
-follows:
-.B
-If CW_CC_DIR is set, the Studio C compiler in \fI$CW_CC_DIR\fP
-will be used.  Likewise, if CW_CPLUSPLUS_DIR is set, the Studio C++
-compiler in \fI$CW_CPLUSPLUS_DIR\fP will be used.
-Otherwise, if SPRO_VROOT is set, the Studio C and C++ compilers
-in \fI$SPRO_VROOT/bin\fP will be used.
-Otherwise, if SPRO_ROOT is set, the Studio C and C++ compilers
-in \fI$SPRO_ROOT/SS12/bin\fP will be used.
-Otherwise, if BUILD_TOOLS is set, the Studio C and C++ compilers
-in \fI$BUILD_TOOLS/SUNWspro/SS12/bin\fP will be used.
-Otherwise, the Studio compilers in a predefined default location
-will be used.
-.TP 4
-.B CW_GCC, CW_GPLUSPLUS
-If these variables are set in the environment, they specify the full
-pathname for the GNU C and C++ compilers, respectively.
-.TP 4
-.B CW_GCC_DIR, CW_GPLUSPLUS_DIR, GNU_ROOT
-If CW_GCC or CW_GPLUSPLUS are not set,
-these variables alter the search path for GNU compilers in a manner
-similar to that described above for the Studio compilers.  Specifically:
-.B
-If CW_GCC_DIR is set, the GNU C compiler in \fI$CW_GCC_DIR\fP
-will be used.  Likewise, if CW_GPLUSPLUS_DIR is set, the GNU C++
-compiler in \fI$CW_GPLUSPLUS_DIR\fP will be used.
-Otherwise, if GNU_ROOT is set, the GNU C and C++ compilers
-in \fI$GCC_ROOT/bin\fP will be used.
-Otherwise, the GNU compilers in a predefined default location
-will be used.
-.SH EXIT STATUS
-.LP
+standard error but do not actually invoke any compiler.
+This is useful for debugging the translation engine.
+.El
+.Sh EXIT STATUS
 The following exit status values are returned:
-.IP "\fB0\fR" 4
-The primary compiler, and shadow compiler if invoked, both completed
+.Bl -tag -width indent
+.It 0
+The primary compiler, and shadow compilers if invoked, both completed
 successfully.
-.IP "\fB>0\fR" 4
+.It >0
 A usage error occurred, or one or more compilers returned a nonzero
 exit status.
-.SH BUGS
-.LP
-The translations provided for gcc are not always exact and in some
-cases reflect local ON policy rather than actual equivalence.
-.LP
+.El
+.Sh SEE ALSO
+.Xr cc 1 ,
+.Xr CC 1 ,
+.Xr gcc 1
+.Sh BUGS
+The translations provided for gcc are not always exact and in some cases
+reflect local policy rather than actual equivalence.
+.Pp
 Additional compiler types should be supported.
-.LP
+.Pp
 The translation engine is hacky.
-.SH SEE ALSO
-.LP
-cc(1), CC(1), gcc(1)
--- old/usr/src/tools/cw/cw.c	2018-02-22 01:20:20.082867900 +0000
+++ new/usr/src/tools/cw/cw.c	2018-02-22 01:20:20.116356868 +0000
@@ -1,3 +1,4 @@
+
 /*
  * CDDL HEADER START
  *
@@ -20,7 +21,7 @@
  */
 
 /*
- * Copyright 2011, Richard Lowe.
+ * Copyright 2018, Richard Lowe.
  */
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
@@ -36,7 +37,7 @@
  */
 
 /* If you modify this file, you must increment CW_VERSION */
-#define	CW_VERSION	"1.30"
+#define	CW_VERSION	"2.0"
 
 /*
  * -#		Verbose mode
@@ -291,20 +292,21 @@
  * -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 <err.h>
 #include <errno.h>
-#include <stdarg.h>
-#include <sys/utsname.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/isa_defs.h>
-#include <sys/wait.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
@@ -313,29 +315,6 @@
 #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,
@@ -351,8 +330,19 @@
 	int ael_argc;
 };
 
+typedef enum {
+	GNU,
+	SUN
+} compiler_style_t;
+
+typedef struct {
+	char *c_name;
+	char *c_path;
+	compiler_style_t c_style;
+} cw_compiler_t;
+
 typedef struct cw_ictx {
-	cw_compiler_t	i_compiler;
+	cw_compiler_t	*i_compiler;
 	struct aelist	*i_ae;
 	uint32_t	i_flags;
 	int		i_oldargc;
@@ -390,7 +380,7 @@
  */
 static const xarch_table_t xtbl[] = {
 #if defined(__x86)
-	{ "generic",	SS11 },
+	{ "generic",	SS11, {NULL} },
 	{ "generic64",	(SS11|M64), { "-m64", "-mtune=opteron" } },
 	{ "amd64",	(SS11|M64), { "-m64", "-mtune=opteron" } },
 	{ "386",	SS11,	{ "-march=i386" } },
@@ -417,8 +407,6 @@
 
 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,
@@ -464,23 +452,7 @@
 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));
+	errx(1, "out of memory");
 }
 
 static void
@@ -515,9 +487,7 @@
 static void
 error(const char *arg)
 {
-	(void) fprintf(stderr,
-	    "%s: error: mapping failed at or near arg '%s'\n", progname, arg);
-	exit(2);
+	errx(2, "error: mapping failed at or near arg '%s'\n", arg);
 }
 
 /*
@@ -551,7 +521,7 @@
 
 /* ARGSUSED */
 static void
-Xamode(struct aelist *h)
+Xamode(struct aelist __unused *h)
 {
 }
 
@@ -582,9 +552,15 @@
 static void
 usage()
 {
+	extern char *__progname;
 	(void) fprintf(stderr,
-	    "usage: %s { -_cc | -_gcc | -_CC | -_g++ } [ -_compiler | ... ]\n",
-	    progname);
+	    "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);
 }
 
@@ -643,6 +619,7 @@
 	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) {
@@ -679,10 +656,12 @@
 	 */
 	newae(ctx->i_ae, "-D__sun");
 
+	if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_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);
@@ -718,6 +697,10 @@
 		}
 
 		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;
@@ -772,16 +755,11 @@
 
 		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);
+			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) {
@@ -1423,11 +1401,12 @@
 		}
 	}
 
+	free(nameflag);
+
 	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);
+		errx(2, "multiple source files are "
+		    "allowed only with -E or -P");
 	}
 
 	/*
@@ -1436,9 +1415,8 @@
 	 * used.
 	 */
 	if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
-		(void) fprintf(stderr,
+		errx(2,
 		    "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
-		exit(2);
 	}
 
 	switch (mflag) {
@@ -1493,7 +1471,9 @@
 		    "Incompatible -xarch= and/or -m32/-m64 options used.\n");
 		exit(2);
 	}
-	if (op == CW_O_LINK && (ctx->i_flags & CW_F_SHADOW))
+
+	if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
+	    (ctx->i_flags & CW_F_SHADOW))
 		exit(0);
 
 	if (model && !pic)
@@ -1511,15 +1491,24 @@
 {
 	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->c_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);
@@ -1531,19 +1520,13 @@
 		}
 		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);
+			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);
@@ -1576,6 +1559,8 @@
 		}
 	}
 
+	free(nameflag);
+
 	if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
 	    (ctx->i_flags & CW_F_SHADOW))
 		exit(0);
@@ -1589,55 +1574,22 @@
 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);
+	newae(ctx->i_ae, ctx->i_compiler->c_path);
 
 	if (ctx->i_flags & CW_F_PROG) {
 		(void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
-		    "shadow" : "primary", program);
+		    "shadow" : "primary", ctx->i_compiler->c_path);
 		(void) fflush(stdout);
 	}
 
 	if (!(ctx->i_flags & CW_F_XLATE))
 		return;
 
-	switch (CC(ctx)) {
-	case CW_C_CC:
+	switch (ctx->i_compiler->c_style) {
+	case SUN:
 		do_cc(ctx);
 		break;
-	case CW_C_GCC:
+	case GNU:
 		do_gcc(ctx);
 		break;
 	}
@@ -1686,7 +1638,7 @@
 	}
 
 	(void) execv(newargv[0], newargv);
-	cw_perror("couldn't run %s", newargv[0]);
+	warn("couldn't run %s", newargv[0]);
 
 	return (-1);
 }
@@ -1706,7 +1658,7 @@
 
 	do {
 		if (waitpid(ctx->i_pid, &status, 0) < 0) {
-			cw_perror("cannot reap child");
+			warn("cannot reap child");
 			return (-1);
 		}
 		if (status != 0) {
@@ -1723,7 +1675,7 @@
 	(void) unlink(ctx->i_discard);
 
 	if (stat(ctx->i_stderr, &s) < 0) {
-		cw_perror("stat failed on child cleanup");
+		warn("stat failed on child cleanup");
 		return (-1);
 	}
 	if (s.st_size != 0) {
@@ -1776,26 +1728,22 @@
 		(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);
+			err(1, "open failed for standard error");
 		}
 		if (dup2(fd, 2) < 0) {
-			cw_perror("dup2 failed for standard error");
-			exit(1);
+			err(1, "dup2 failed for standard error");
 		}
 		if (fd != 2)
 			(void) close(fd);
 		if (freopen("/dev/fd/2", "w", stderr) == NULL) {
-			cw_perror("freopen failed for /dev/fd/2");
-			exit(1);
+			err(1, "freopen failed for /dev/fd/2");
 		}
 		prepctx(ctx);
 		exit(invoke(ctx));
 	}
 
 	if (ctx->i_pid < 0) {
-		cw_perror("fork failed");
-		return (1);
+		err(1, "fork failed");
 	}
 
 	if (block)
@@ -1804,115 +1752,165 @@
 	return (0);
 }
 
+static int
+parse_compiler(const char *spec, cw_compiler_t *compiler)
+{
+	char *tspec, *token;
+
+	if ((tspec = strdup(spec)) == NULL)
+		nomem();
+
+	if ((token = strsep(&tspec, ",")) == NULL)
+		errx(1, "Compiler is missing a name: %s", spec);
+	compiler->c_name = token;
+
+	if ((token = strsep(&tspec, ",")) == NULL)
+		errx(1, "Compiler is missing a path: %s", spec);
+	compiler->c_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->c_style = GNU;
+	else if ((strcasecmp(token, "sun") == 0) ||
+	    (strcasecmp(token, "cc") == 0))
+		compiler->c_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)
 {
-	cw_ictx_t *ctx = newictx();
-	cw_ictx_t *ctx_shadow = newictx();
-	const char *dir;
-	int do_serial, do_shadow;
+	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;
+
+	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 },
+	};
 
-	if ((progname = strrchr(argv[0], '/')) == NULL)
-		progname = argv[0];
-	else
-		progname++;
 
-	if (ctx == NULL || ctx_shadow == NULL)
+	if ((main_ctx = newictx()) == 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);
+	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.c_path != NULL) {
+				warnx("Only one primary compiler may "
+				    "be specified");
+				usage();
+			}
 
-	if (getenv("CW_NO_EXEC") == NULL)
-		ctx->i_flags |= CW_F_EXEC;
+			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:
+			(void) fprintf(stderr, "Did you forget '--'?\n");
+			usage();
+		}
+	}
 
-	/*
-	 * The first argument must be one of "-_cc", "-_gcc", "-_CC", or "-_g++"
-	 */
-	if (argc == 1)
+	if (primary.c_path == NULL) {
+		warnx("A primary compiler must be specified");
 		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);
+	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);
+
+	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) {
+		(void) fputs(primary.c_path, stdout);
 	}
 
-	/*
-	 * -_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");
+	if (vflg) {
+		(void) printf("cw version %s\n", CW_VERSION);
 		(void) fflush(stdout);
-		ctx->i_flags &= ~CW_F_ECHO;
-		ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
-		argc--;
-		argv++;
+		main_ctx->i_flags &= ~CW_F_ECHO;
+		main_ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
 		do_serial = 1;
 	}
 
-	ctx->i_oldargc = argc;
-	ctx->i_oldargv = argv;
+	ret |= exec_ctx(main_ctx, do_serial);
+
+	for (int i = 0; i < nshadows; i++) {
+		cw_ictx_t *shadow_ctx;
+
+		if ((shadow_ctx = newictx()) == NULL)
+			nomem();
+
+		memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
 
-	ret |= exec_ctx(ctx, do_serial);
+		shadow_ctx->i_flags |= CW_F_SHADOW;
+		shadow_ctx->i_compiler = &shadows[i];
 
-	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);
+		/* XXX: Would be nice to run these parallel, too */
+		ret |= exec_ctx(shadow_ctx, 1);
 	}
 
 	if (!do_serial)
-		ret |= reap(ctx);
+		ret |= reap(main_ctx);
 
 	return (ret);
 }
--- old/usr/src/tools/env/illumos.sh	2018-02-22 01:20:21.482803921 +0000
+++ new/usr/src/tools/env/illumos.sh	2018-02-22 01:20:21.528841997 +0000
@@ -196,8 +196,33 @@
 export SPRO_ROOT='/opt/SUNWspro'
 export SPRO_VROOT="$SPRO_ROOT"
 
-# Disable shadow compilation by default.
-export CW_NO_SHADOW='1'
+# Compilers may be specified using the following variables:
+# PRIMARY_CC	- primary C compiler
+# PRIMARY_CCC	- primary C++ compiler
+#
+# SHADOW_CCS    - list of shadow C compilers
+# SHADOW_CCCS	- list of shadow C++ compilers
+#
+# Each entry has the form <name>,<path to binary>,<style> where name is a
+# free-form name (possibly used in the makefiles to guard options), path is
+# the path to the executable.  style is the 'style' of command line taken by
+# the compiler, currently either gnu (or gcc) or sun (or cc), which is also
+# used by Makefiles to guard options.
+#
+# __SUNC and __GNUC must still be set to reflect the style of the primary
+# compiler (and to influence the default primary, otherwise)
+#
+# for example:
+# export PRIMARY_CC=gcc4,/opt/gcc/4.4.4/bin/gcc,gnu
+# export PRIMARY_CCC=gcc4,/opt/gcc/4.4.4/bin/g++,gnu
+# export SHADOW_CCS=studio12,/opt/SUNWspro/bin/cc,sun
+# export SHADOW_CCCS=studio12,/opt/SUNWspro/bin/CC,sun
+#
+# There can be several space-separated entries in SHADOW_* to run multiple
+# shadow compilers.
+#
+# To disable shadow compilation, unset SHADOW_* or set them to the empty string.
+#
 
 # This goes along with lint - it is a series of the form "A [y|n]" which
 # means "go to directory A and run 'make lint'" Then mail me (y) the
--- old/usr/src/tools/ndrgen/ndrgen.sh	2018-02-22 01:20:22.434666713 +0000
+++ new/usr/src/tools/ndrgen/ndrgen.sh	2018-02-22 01:20:22.476950726 +0000
@@ -77,12 +77,6 @@
 	else
 		CC=$1
 		shift $(($OPTIND - 1))
-
-		# Check for cw being invoked with -_cc or -_gcc
-		if [[ $1 = "-_cc" || $1 = "-_gcc" ]] ; then
-			CC_ARG=$1
-			shift $(($OPTIND - 1))
-		fi
 	fi
 fi
 
@@ -90,7 +84,10 @@
 	ndrgen_usage "C pre-processor is not defined"
 fi
 
-if [ ! -f $CC ] || [ ! -x $CC ] ; then
+# Remove the non-cw options
+CC=${CC%% -- *}
+
+if [ ! -f ${CC%% *} ] || [ ! -x ${CC%% *} ] ; then
 	ndrgen_usage "cannot run $CC"
 fi
 
@@ -106,7 +103,7 @@
 
 	cp $i $TMP_NAME
 
-	if $CC $CC_ARG -E  -D__a64 -D__EXTENSIONS__ -D_FILE_OFFSET_BITS=64 \
+	if $CC  -E  -D__a64 -D__EXTENSIONS__ -D_FILE_OFFSET_BITS=64 \
 		-I. -I${INCDIR} -I${INCDIR}/ndl -DNDRGEN $TMP_NAME | \
 		$NDRPROG > $BASENAME.raw
 	then
