1aa9ef484SJohn Levon
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate * CDDL HEADER START
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
602e56f3fSwesolows * Common Development and Distribution License (the "License").
702e56f3fSwesolows * You may not use this file except in compliance with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
2202e56f3fSwesolows
237c478bd9Sstevel@tonic-gate /*
247fbf8d03SScott Rotondo * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
257c478bd9Sstevel@tonic-gate * Use is subject to license terms.
261f5207b7SJohn Levon *
27564d5236SRichard Lowe * Copyright 2018 Richard Lowe.
281f5207b7SJohn Levon * Copyright 2019 Joyent, Inc.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate * Wrapper for the GNU C compiler to make it accept the Sun C compiler
337c478bd9Sstevel@tonic-gate * arguments where possible.
347c478bd9Sstevel@tonic-gate *
357c478bd9Sstevel@tonic-gate * Since the translation is inexact, this is something of a work-in-progress.
369a70fc3bSMark J. Nelson *
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
395d9d9091SRichard Lowe /*
40*d17be682SRichard Lowe * If you modify this file, you must increment CW_VERSION. This is a semver,
41*d17be682SRichard Lowe * incompatible changes should bump the major, anything else the minor.
425d9d9091SRichard Lowe */
43*d17be682SRichard Lowe #define CW_VERSION "9.0"
449a70fc3bSMark J. Nelson
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate * -# Verbose mode
477c478bd9Sstevel@tonic-gate * -### Show compiler commands built by driver, no compilation
487c478bd9Sstevel@tonic-gate * -A<name[(tokens)]> Preprocessor predicate assertion
497c478bd9Sstevel@tonic-gate * -C Prevent preprocessor from removing comments
507c478bd9Sstevel@tonic-gate * -c Compile only - produce .o files, suppress linking
517c478bd9Sstevel@tonic-gate * -D<name[=token]> Associate name with token as if by #define
527c478bd9Sstevel@tonic-gate * -d[y|n] dynamic [-dy] or static [-dn] option to linker
537c478bd9Sstevel@tonic-gate * -E Compile source through preprocessor only, output to stdout
547c478bd9Sstevel@tonic-gate * -erroff=<t> Suppress warnings specified by tags t(%none, %all, <tag list>)
557c478bd9Sstevel@tonic-gate * -errtags=<a> Display messages with tags a(no, yes)
567c478bd9Sstevel@tonic-gate * -errwarn=<t> Treats warnings specified by tags t(%none, %all, <tag list>)
577c478bd9Sstevel@tonic-gate * as errors
587c478bd9Sstevel@tonic-gate * -g Compile for debugging
597c478bd9Sstevel@tonic-gate * -H Print path name of each file included during compilation
607c478bd9Sstevel@tonic-gate * -h <name> Assign <name> to generated dynamic shared library
617c478bd9Sstevel@tonic-gate * -I<dir> Add <dir> to preprocessor #include file search path
627c478bd9Sstevel@tonic-gate * -i Passed to linker to ignore any LD_LIBRARY_PATH setting
637c478bd9Sstevel@tonic-gate * -keeptmp Keep temporary files created during compilation
647c478bd9Sstevel@tonic-gate * -L<dir> Pass to linker to add <dir> to the library search path
657c478bd9Sstevel@tonic-gate * -l<name> Link with library lib<name>.a or lib<name>.so
667c478bd9Sstevel@tonic-gate * -mt Specify options needed when compiling multi-threaded code
67662492f5Ssherrym * -O Use default optimization level (-xO2 or -xO3. Check man page.)
687c478bd9Sstevel@tonic-gate * -o <outputfile> Set name of output file to <outputfile>
697c478bd9Sstevel@tonic-gate * -P Compile source through preprocessor only, output to .i file
707c478bd9Sstevel@tonic-gate * -p Compile for profiling with prof
717c478bd9Sstevel@tonic-gate * -R<dir[:dir]> Build runtime search path list into executable
727c478bd9Sstevel@tonic-gate * -S Compile and only generate assembly code (.s)
737c478bd9Sstevel@tonic-gate * -s Strip symbol table from the executable file
74159cf8a6Swesolows * -t Turn off duplicate symbol warnings when linking
757c478bd9Sstevel@tonic-gate * -U<name> Delete initial definition of preprocessor symbol <name>
767c478bd9Sstevel@tonic-gate * -V Report version number of each compilation phase
777c478bd9Sstevel@tonic-gate * -v Do stricter semantic checking
787c478bd9Sstevel@tonic-gate * -W<c>,<arg> Pass <arg> to specified component <c> (a,l,m,p,0,2,h,i,u)
797c478bd9Sstevel@tonic-gate * -w Suppress compiler warning messages
807c478bd9Sstevel@tonic-gate * -Xa Compile assuming ANSI C conformance, allow K & R extensions
817c478bd9Sstevel@tonic-gate * (default mode)
827c478bd9Sstevel@tonic-gate * -Xs Compile assuming (pre-ANSI) K & R C style code
837c478bd9Sstevel@tonic-gate * -xarch=<a> Specify target architecture instruction set
847c478bd9Sstevel@tonic-gate * -xbuiltin[=<b>] When profitable inline, or substitute intrinisic functions
857c478bd9Sstevel@tonic-gate * for system functions, b={%all,%none}
867c478bd9Sstevel@tonic-gate * -xchip=<c> Specify the target processor for use by the optimizer
877c478bd9Sstevel@tonic-gate * -xO<n> Generate optimized code (n={1|2|3|4|5})
887c478bd9Sstevel@tonic-gate * -xtarget=<t> Specify target system for optimization
89*d17be682SRichard Lowe * -YI,<dir> Specify <dir> for location of headers
907c478bd9Sstevel@tonic-gate */
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate * Translation table:
947c478bd9Sstevel@tonic-gate */
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate * -# -v
977c478bd9Sstevel@tonic-gate * -### error
987c478bd9Sstevel@tonic-gate * -A<name[(tokens)]> pass-thru
997c478bd9Sstevel@tonic-gate * -B<[static|dynamic]> pass-thru (syntax error for anything else)
1007c478bd9Sstevel@tonic-gate * -C pass-thru
1017c478bd9Sstevel@tonic-gate * -c pass-thru
1027c478bd9Sstevel@tonic-gate * -D<name[=token]> pass-thru
1037c478bd9Sstevel@tonic-gate * -E pass-thru
1047c478bd9Sstevel@tonic-gate * -errtags=%all -Wall
1057c478bd9Sstevel@tonic-gate * -errwarn=%all -Werror else -Wno-error
1067c478bd9Sstevel@tonic-gate * -g pass-thru
1077c478bd9Sstevel@tonic-gate * -H pass-thru
1087c478bd9Sstevel@tonic-gate * -I<dir> pass-thru
1097c478bd9Sstevel@tonic-gate * -i pass-thru
1107c478bd9Sstevel@tonic-gate * -keeptmp -save-temps
1117c478bd9Sstevel@tonic-gate * -L<dir> pass-thru
1127c478bd9Sstevel@tonic-gate * -l<name> pass-thru
1137c478bd9Sstevel@tonic-gate * -mt -D_REENTRANT
1147c478bd9Sstevel@tonic-gate * -nolib -nodefaultlibs
115662492f5Ssherrym * -O -O1 (Check the man page to be certain)
1167c478bd9Sstevel@tonic-gate * -o <outputfile> pass-thru
1177c478bd9Sstevel@tonic-gate * -P -E -o filename.i (or error)
1187c478bd9Sstevel@tonic-gate * -p pass-thru
1197c478bd9Sstevel@tonic-gate * -R<dir[:dir]> pass-thru
1207c478bd9Sstevel@tonic-gate * -S pass-thru
1217c478bd9Sstevel@tonic-gate * -U<name> pass-thru
1227c478bd9Sstevel@tonic-gate * -V --version
1237c478bd9Sstevel@tonic-gate * -v -Wall
1247c478bd9Sstevel@tonic-gate * -Wa,<arg> pass-thru
125*d17be682SRichard Lowe * -Wp,<arg> pass-thru
1267c478bd9Sstevel@tonic-gate * -Wl,<arg> pass-thru
12754836668Spetede * -xmodel=kernel -ffreestanding -mcmodel=kernel -mno-red-zone
128d430274bSsherrym * -Wu,-save_args -msave-args
1297c478bd9Sstevel@tonic-gate * -w pass-thru
1307c478bd9Sstevel@tonic-gate * -Xa -std=iso9899:199409 or -ansi
1317c478bd9Sstevel@tonic-gate * -Xs -traditional -std=c89
1327c478bd9Sstevel@tonic-gate * -xarch=<a> table
13302e56f3fSwesolows * -xbuiltin[=<b>] -fbuiltin (-fno-builtin otherwise)
1347c478bd9Sstevel@tonic-gate * -xchip=<c> table
1357c478bd9Sstevel@tonic-gate * -xO<n> -O<n>
1367c478bd9Sstevel@tonic-gate * -xtarget=<t> table
1377c478bd9Sstevel@tonic-gate * -xtransition -Wtransition
1387c478bd9Sstevel@tonic-gate * -YI,<dir> -nostdinc -I<dir>
1397c478bd9Sstevel@tonic-gate */
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate #include <ctype.h>
142aa9ef484SJohn Levon #include <err.h>
14380ab886dSwesolows #include <errno.h>
144aa9ef484SJohn Levon #include <fcntl.h>
145aa9ef484SJohn Levon #include <getopt.h>
146aa9ef484SJohn Levon #include <stdio.h>
147aa9ef484SJohn Levon #include <stdlib.h>
14822a8b493SToomas Soome #include <stdbool.h>
149aa9ef484SJohn Levon #include <string.h>
150aa9ef484SJohn Levon #include <unistd.h>
15188e61e85SRichard Lowe #include <dirent.h>
152aa9ef484SJohn Levon
1537c478bd9Sstevel@tonic-gate #include <sys/param.h>
15480ab886dSwesolows #include <sys/stat.h>
155aa9ef484SJohn Levon #include <sys/types.h>
156aa9ef484SJohn Levon #include <sys/utsname.h>
157aa9ef484SJohn Levon #include <sys/wait.h>
15880ab886dSwesolows
15980ab886dSwesolows #define CW_F_CXX 0x01
16080ab886dSwesolows #define CW_F_SHADOW 0x02
16180ab886dSwesolows #define CW_F_EXEC 0x04
16280ab886dSwesolows #define CW_F_ECHO 0x08
16380ab886dSwesolows #define CW_F_XLATE 0x10
1641912d2c4Swesolows #define CW_F_PROG 0x20
16580ab886dSwesolows
16680ab886dSwesolows typedef enum cw_op {
16780ab886dSwesolows CW_O_NONE = 0,
16880ab886dSwesolows CW_O_PREPROCESS,
16980ab886dSwesolows CW_O_COMPILE,
17080ab886dSwesolows CW_O_LINK
17180ab886dSwesolows } cw_op_t;
17280ab886dSwesolows
17380ab886dSwesolows struct aelist {
17480ab886dSwesolows struct ae {
17580ab886dSwesolows struct ae *ae_next;
17680ab886dSwesolows char *ae_arg;
17780ab886dSwesolows } *ael_head, *ael_tail;
17880ab886dSwesolows int ael_argc;
17980ab886dSwesolows };
18080ab886dSwesolows
181aa9ef484SJohn Levon typedef enum {
182aa9ef484SJohn Levon GNU,
1831f5207b7SJohn Levon SUN,
1841f5207b7SJohn Levon SMATCH
185aa9ef484SJohn Levon } compiler_style_t;
186aa9ef484SJohn Levon
187aa9ef484SJohn Levon typedef struct {
188aa9ef484SJohn Levon char *c_name;
189aa9ef484SJohn Levon char *c_path;
190aa9ef484SJohn Levon compiler_style_t c_style;
191aa9ef484SJohn Levon } cw_compiler_t;
192aa9ef484SJohn Levon
19380ab886dSwesolows typedef struct cw_ictx {
194aa9ef484SJohn Levon struct cw_ictx *i_next;
195aa9ef484SJohn Levon cw_compiler_t *i_compiler;
19669b1fd3fSRichard Lowe char *i_linker;
19780ab886dSwesolows struct aelist *i_ae;
19880ab886dSwesolows uint32_t i_flags;
19980ab886dSwesolows int i_oldargc;
20080ab886dSwesolows char **i_oldargv;
20180ab886dSwesolows pid_t i_pid;
20288e61e85SRichard Lowe char *i_tmpdir;
2031912d2c4Swesolows char *i_stderr;
20480ab886dSwesolows } cw_ictx_t;
20580ab886dSwesolows
206e521259dSpetede /*
207e521259dSpetede * Status values to indicate which Studio compiler and associated
208e521259dSpetede * flags are being used.
209e521259dSpetede */
210e521259dSpetede #define M32 0x01 /* -m32 - only on Studio 12 */
211e521259dSpetede #define M64 0x02 /* -m64 - only on Studio 12 */
212e521259dSpetede #define SS11 0x100 /* Studio 11 */
213e521259dSpetede #define SS12 0x200 /* Studio 12 */
2147c478bd9Sstevel@tonic-gate
215e521259dSpetede #define TRANS_ENTRY 5
216e521259dSpetede /*
217e521259dSpetede * Translation table definition for the -xarch= flag. The "x_arg"
218e521259dSpetede * value is translated into the appropriate gcc flags according
219e521259dSpetede * to the values in x_trans[n]. The x_flags indicates what compiler
220e521259dSpetede * is being used and what flags have been set via the use of
221e521259dSpetede * "x_arg".
222e521259dSpetede */
223e521259dSpetede typedef struct xarch_table {
224e521259dSpetede char *x_arg;
225e521259dSpetede int x_flags;
226e521259dSpetede char *x_trans[TRANS_ENTRY];
227e521259dSpetede } xarch_table_t;
228e521259dSpetede
229e521259dSpetede /*
230e521259dSpetede * The translation table for the -xarch= flag used in the Studio compilers.
231e521259dSpetede */
232e521259dSpetede static const xarch_table_t xtbl[] = {
2337c478bd9Sstevel@tonic-gate #if defined(__x86)
234aa9ef484SJohn Levon { "generic", SS11, {NULL} },
2357a6460b6Spetede { "generic64", (SS11|M64), { "-m64", "-mtune=opteron" } },
2367a6460b6Spetede { "amd64", (SS11|M64), { "-m64", "-mtune=opteron" } },
2377a6460b6Spetede { "386", SS11, { "-march=i386" } },
2387a6460b6Spetede { "pentium_pro", SS11, { "-march=pentiumpro" } },
23925c28e83SPiotr Jasiukajtis { "sse", SS11, { "-msse", "-mfpmath=sse" } },
24025c28e83SPiotr Jasiukajtis { "sse2", SS11, { "-msse2", "-mfpmath=sse" } },
2417c478bd9Sstevel@tonic-gate #endif
2427c478bd9Sstevel@tonic-gate };
2437c478bd9Sstevel@tonic-gate
244e521259dSpetede static int xtbl_size = sizeof (xtbl) / sizeof (xarch_table_t);
245e521259dSpetede
2467c478bd9Sstevel@tonic-gate static const char *xchip_tbl[] = {
2477c478bd9Sstevel@tonic-gate #if defined(__x86)
2487c478bd9Sstevel@tonic-gate "386", "-mtune=i386", NULL,
2497c478bd9Sstevel@tonic-gate "486", "-mtune=i486", NULL,
2507c478bd9Sstevel@tonic-gate "pentium", "-mtune=pentium", NULL,
2517c478bd9Sstevel@tonic-gate "pentium_pro", "-mtune=pentiumpro", NULL,
2527c478bd9Sstevel@tonic-gate #endif
2537c478bd9Sstevel@tonic-gate NULL, NULL
2547c478bd9Sstevel@tonic-gate };
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate static const char *xtarget_tbl[] = {
2577c478bd9Sstevel@tonic-gate #if defined(__x86)
2587c478bd9Sstevel@tonic-gate "pentium_pro", "-march=pentiumpro", NULL,
2597c478bd9Sstevel@tonic-gate #endif /* __x86 */
2607c478bd9Sstevel@tonic-gate NULL, NULL
2617c478bd9Sstevel@tonic-gate };
2627c478bd9Sstevel@tonic-gate
26380ab886dSwesolows static void
nomem(void)26480ab886dSwesolows nomem(void)
26580ab886dSwesolows {
266aa9ef484SJohn Levon errx(1, "out of memory");
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate static void
newae(struct aelist * ael,const char * arg)2707c478bd9Sstevel@tonic-gate newae(struct aelist *ael, const char *arg)
2717c478bd9Sstevel@tonic-gate {
2727c478bd9Sstevel@tonic-gate struct ae *ae;
2737c478bd9Sstevel@tonic-gate
27469b1fd3fSRichard Lowe if ((ae = calloc(1, sizeof (*ae))) == NULL)
27580ab886dSwesolows nomem();
2767c478bd9Sstevel@tonic-gate ae->ae_arg = strdup(arg);
2777c478bd9Sstevel@tonic-gate if (ael->ael_tail == NULL)
2787c478bd9Sstevel@tonic-gate ael->ael_head = ae;
2797c478bd9Sstevel@tonic-gate else
2807c478bd9Sstevel@tonic-gate ael->ael_tail->ae_next = ae;
2817c478bd9Sstevel@tonic-gate ael->ael_tail = ae;
28280ab886dSwesolows ael->ael_argc++;
28380ab886dSwesolows }
28480ab886dSwesolows
28580ab886dSwesolows static cw_ictx_t *
newictx(void)28680ab886dSwesolows newictx(void)
28780ab886dSwesolows {
28869b1fd3fSRichard Lowe cw_ictx_t *ctx = calloc(1, sizeof (cw_ictx_t));
28980ab886dSwesolows if (ctx)
29069b1fd3fSRichard Lowe if ((ctx->i_ae = calloc(1, sizeof (struct aelist))) == NULL) {
29180ab886dSwesolows free(ctx);
29280ab886dSwesolows return (NULL);
29380ab886dSwesolows }
29480ab886dSwesolows
29580ab886dSwesolows return (ctx);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate static void
error(const char * arg)2997c478bd9Sstevel@tonic-gate error(const char *arg)
3007c478bd9Sstevel@tonic-gate {
301aa9ef484SJohn Levon errx(2, "error: mapping failed at or near arg '%s'", arg);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate * Add the current favourite set of warnings to the gcc invocation.
3067c478bd9Sstevel@tonic-gate */
3077c478bd9Sstevel@tonic-gate static void
warnings(struct aelist * h)3087c478bd9Sstevel@tonic-gate warnings(struct aelist *h)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate static int warningsonce;
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate if (warningsonce++)
3137c478bd9Sstevel@tonic-gate return;
3147c478bd9Sstevel@tonic-gate
3157014882cSRichard Lowe /*
3167014882cSRichard Lowe * Enable as many warnings as exist, then disable those that we never
3177014882cSRichard Lowe * ever want.
3187014882cSRichard Lowe */
3197c478bd9Sstevel@tonic-gate newae(h, "-Wall");
3207014882cSRichard Lowe newae(h, "-Wextra");
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate static void
optim_disable(struct aelist * h,int level)3247c478bd9Sstevel@tonic-gate optim_disable(struct aelist *h, int level)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate if (level >= 2) {
3277c478bd9Sstevel@tonic-gate newae(h, "-fno-strict-aliasing");
3287c478bd9Sstevel@tonic-gate newae(h, "-fno-unit-at-a-time");
3297c478bd9Sstevel@tonic-gate newae(h, "-fno-optimize-sibling-calls");
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate static void
Xsmode(struct aelist * h)3347c478bd9Sstevel@tonic-gate Xsmode(struct aelist *h)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate static int xsonce;
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate if (xsonce++)
3397c478bd9Sstevel@tonic-gate return;
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate newae(h, "-traditional");
3427c478bd9Sstevel@tonic-gate newae(h, "-traditional-cpp");
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate static void
usage(void)34669b1fd3fSRichard Lowe usage(void)
3477c478bd9Sstevel@tonic-gate {
348aa9ef484SJohn Levon extern char *__progname;
3497c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
350aa9ef484SJohn Levon "usage: %s [-C] [--versions] --primary <compiler> "
351aa9ef484SJohn Levon "[--shadow <compiler>]... -- cflags...\n",
352aa9ef484SJohn Levon __progname);
353aa9ef484SJohn Levon (void) fprintf(stderr, "compilers take the form: name,path,style\n"
354aa9ef484SJohn Levon " - name: a unique name usable in flag specifiers\n"
355aa9ef484SJohn Levon " - path: path to the compiler binary\n"
356aa9ef484SJohn Levon " - style: the style of flags expected: either sun or gnu\n");
3577c478bd9Sstevel@tonic-gate exit(2);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
360e521259dSpetede static int
xlate_xtb(struct aelist * h,const char * xarg)361e521259dSpetede xlate_xtb(struct aelist *h, const char *xarg)
362e521259dSpetede {
363e521259dSpetede int i, j;
364e521259dSpetede
365e521259dSpetede for (i = 0; i < xtbl_size; i++) {
366e521259dSpetede if (strcmp(xtbl[i].x_arg, xarg) == 0)
367e521259dSpetede break;
368e521259dSpetede }
369e521259dSpetede
370e521259dSpetede /*
371e521259dSpetede * At the end of the table and so no matching "arg" entry
372e521259dSpetede * found and so this must be a bad -xarch= flag.
373e521259dSpetede */
374e521259dSpetede if (i == xtbl_size)
375e521259dSpetede error(xarg);
376e521259dSpetede
377e521259dSpetede for (j = 0; j < TRANS_ENTRY; j++) {
378e521259dSpetede if (xtbl[i].x_trans[j] != NULL)
379e521259dSpetede newae(h, xtbl[i].x_trans[j]);
380e521259dSpetede else
381e521259dSpetede break;
382e521259dSpetede }
383e521259dSpetede return (xtbl[i].x_flags);
384e521259dSpetede
385e521259dSpetede }
386e521259dSpetede
3877c478bd9Sstevel@tonic-gate static void
xlate(struct aelist * h,const char * xarg,const char ** table)3887c478bd9Sstevel@tonic-gate xlate(struct aelist *h, const char *xarg, const char **table)
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate while (*table != NULL && strcmp(xarg, *table) != 0) {
3917c478bd9Sstevel@tonic-gate while (*table != NULL)
3927c478bd9Sstevel@tonic-gate table++;
3937c478bd9Sstevel@tonic-gate table++;
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate if (*table == NULL)
3977c478bd9Sstevel@tonic-gate error(xarg);
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate table++;
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate while (*table != NULL) {
4027c478bd9Sstevel@tonic-gate newae(h, *table);
4037c478bd9Sstevel@tonic-gate table++;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
40788e61e85SRichard Lowe /*
40888e61e85SRichard Lowe * The compiler wants the output file to end in appropriate extension. If
40988e61e85SRichard Lowe * we're generating a name from whole cloth (path == NULL), we assume that
41088e61e85SRichard Lowe * extension to be .o, otherwise we match the extension of the caller.
41188e61e85SRichard Lowe */
41288e61e85SRichard Lowe static char *
discard_file_name(cw_ictx_t * ctx,const char * path)41388e61e85SRichard Lowe discard_file_name(cw_ictx_t *ctx, const char *path)
41488e61e85SRichard Lowe {
41588e61e85SRichard Lowe char *ret, *ext;
41688e61e85SRichard Lowe char tmpl[] = "cwXXXXXX";
41788e61e85SRichard Lowe
41888e61e85SRichard Lowe if (path == NULL) {
41988e61e85SRichard Lowe ext = ".o";
42088e61e85SRichard Lowe } else {
42188e61e85SRichard Lowe ext = strrchr(path, '.');
42288e61e85SRichard Lowe }
42388e61e85SRichard Lowe
42488e61e85SRichard Lowe /*
42588e61e85SRichard Lowe * We need absolute control over where the temporary file goes, since
42688e61e85SRichard Lowe * we rely on it for cleanup so tempnam(3C) and tmpnam(3C) are
42788e61e85SRichard Lowe * inappropriate (they use TMPDIR, preferentially).
42888e61e85SRichard Lowe *
42988e61e85SRichard Lowe * mkstemp(3C) doesn't actually help us, since the temporary file
43088e61e85SRichard Lowe * isn't used by us, only its name.
43188e61e85SRichard Lowe */
43288e61e85SRichard Lowe if (mktemp(tmpl) == NULL)
43388e61e85SRichard Lowe nomem();
43488e61e85SRichard Lowe
43588e61e85SRichard Lowe (void) asprintf(&ret, "%s/%s%s", ctx->i_tmpdir, tmpl,
43688e61e85SRichard Lowe (ext != NULL) ? ext : "");
43788e61e85SRichard Lowe
43888e61e85SRichard Lowe if (ret == NULL)
43988e61e85SRichard Lowe nomem();
44088e61e85SRichard Lowe
44188e61e85SRichard Lowe return (ret);
44288e61e85SRichard Lowe }
44388e61e85SRichard Lowe
44422a8b493SToomas Soome static bool
is_source_file(const char * path)44588e61e85SRichard Lowe is_source_file(const char *path)
44688e61e85SRichard Lowe {
44788e61e85SRichard Lowe char *ext = strrchr(path, '.');
44888e61e85SRichard Lowe
449406d4d29SJohn Levon if ((ext == NULL) || (*(ext + 1) == '\0'))
45022a8b493SToomas Soome return (false);
45188e61e85SRichard Lowe
45288e61e85SRichard Lowe ext += 1;
45388e61e85SRichard Lowe
45488e61e85SRichard Lowe if ((strcasecmp(ext, "c") == 0) ||
45588e61e85SRichard Lowe (strcmp(ext, "cc") == 0) ||
45688e61e85SRichard Lowe (strcmp(ext, "i") == 0) ||
45788e61e85SRichard Lowe (strcasecmp(ext, "s") == 0) ||
45888e61e85SRichard Lowe (strcmp(ext, "cpp") == 0)) {
45922a8b493SToomas Soome return (true);
46088e61e85SRichard Lowe }
46188e61e85SRichard Lowe
46222a8b493SToomas Soome return (false);
46388e61e85SRichard Lowe }
46488e61e85SRichard Lowe
4655d9d9091SRichard Lowe static bool
is_asm_file(const char * path)4665d9d9091SRichard Lowe is_asm_file(const char *path)
4675d9d9091SRichard Lowe {
4685d9d9091SRichard Lowe char *ext = strrchr(path, '.');
4695d9d9091SRichard Lowe
4705d9d9091SRichard Lowe if ((ext == NULL) || (*(ext + 1) == '\0'))
4715d9d9091SRichard Lowe return (false);
4725d9d9091SRichard Lowe
4735d9d9091SRichard Lowe ext += 1;
4745d9d9091SRichard Lowe
4755d9d9091SRichard Lowe if (strcasecmp(ext, "s") == 0)
4765d9d9091SRichard Lowe return (true);
4775d9d9091SRichard Lowe
4785d9d9091SRichard Lowe return (false);
4795d9d9091SRichard Lowe }
48088e61e85SRichard Lowe
4817c478bd9Sstevel@tonic-gate static void
do_gcc(cw_ictx_t * ctx)48280ab886dSwesolows do_gcc(cw_ictx_t *ctx)
4837c478bd9Sstevel@tonic-gate {
4847c478bd9Sstevel@tonic-gate int c;
485e1bf37b1SRichard Lowe int nolibc = 0;
48680ab886dSwesolows int in_output = 0, seen_o = 0, c_files = 0;
48780ab886dSwesolows cw_op_t op = CW_O_LINK;
4887c478bd9Sstevel@tonic-gate char *model = NULL;
489aa9ef484SJohn Levon char *nameflag;
49088e61e85SRichard Lowe int mflag = 0;
4917c478bd9Sstevel@tonic-gate
4921912d2c4Swesolows if (ctx->i_flags & CW_F_PROG) {
4931912d2c4Swesolows newae(ctx->i_ae, "--version");
4941912d2c4Swesolows return;
4951912d2c4Swesolows }
4961912d2c4Swesolows
49780ab886dSwesolows newae(ctx->i_ae, "-fident");
49880ab886dSwesolows newae(ctx->i_ae, "-finline");
49980ab886dSwesolows newae(ctx->i_ae, "-fno-inline-functions");
50080ab886dSwesolows newae(ctx->i_ae, "-fno-builtin");
50180ab886dSwesolows newae(ctx->i_ae, "-fno-asm");
5027014882cSRichard Lowe newae(ctx->i_ae, "-fdiagnostics-show-option");
50380ab886dSwesolows newae(ctx->i_ae, "-nodefaultlibs");
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate /*
5067c478bd9Sstevel@tonic-gate * This is needed because 'u' is defined
5077c478bd9Sstevel@tonic-gate * under a conditional on 'sun'. Should
5087c478bd9Sstevel@tonic-gate * probably just remove the conditional,
5097c478bd9Sstevel@tonic-gate * or make it be dependent on '__sun'.
5107c478bd9Sstevel@tonic-gate *
5117c478bd9Sstevel@tonic-gate * -Dunix is also missing in enhanced ANSI mode
5127c478bd9Sstevel@tonic-gate */
51380ab886dSwesolows newae(ctx->i_ae, "-D__sun");
5147c478bd9Sstevel@tonic-gate
515aa9ef484SJohn Levon if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
516aa9ef484SJohn Levon nomem();
517aa9ef484SJohn Levon
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate * Walk the argument list, translating as we go ..
5207c478bd9Sstevel@tonic-gate */
52180ab886dSwesolows while (--ctx->i_oldargc > 0) {
52280ab886dSwesolows char *arg = *++ctx->i_oldargv;
5237c478bd9Sstevel@tonic-gate size_t arglen = strlen(arg);
5247c478bd9Sstevel@tonic-gate
52580ab886dSwesolows if (*arg == '-') {
5267c478bd9Sstevel@tonic-gate arglen--;
52780ab886dSwesolows } else {
52888e61e85SRichard Lowe if (!in_output && is_source_file(arg))
52980ab886dSwesolows c_files++;
53080ab886dSwesolows
5317c478bd9Sstevel@tonic-gate /*
53280ab886dSwesolows * Otherwise, filenames and partial arguments
53380ab886dSwesolows * are passed through for gcc to chew on. However,
53480ab886dSwesolows * output is always discarded for the secondary
53580ab886dSwesolows * compiler.
5367c478bd9Sstevel@tonic-gate */
53788e61e85SRichard Lowe if ((ctx->i_flags & CW_F_SHADOW) && in_output) {
53888e61e85SRichard Lowe newae(ctx->i_ae, discard_file_name(ctx, arg));
53988e61e85SRichard Lowe } else {
54080ab886dSwesolows newae(ctx->i_ae, arg);
54188e61e85SRichard Lowe }
54280ab886dSwesolows in_output = 0;
5437c478bd9Sstevel@tonic-gate continue;
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate
54680ab886dSwesolows if (ctx->i_flags & CW_F_CXX) {
547aa9ef484SJohn Levon if (strncmp(arg, "-_g++=", 6) == 0) {
548aa9ef484SJohn Levon newae(ctx->i_ae, strchr(arg, '=') + 1);
549aa9ef484SJohn Levon continue;
550aa9ef484SJohn Levon }
551*d17be682SRichard Lowe
5527c478bd9Sstevel@tonic-gate if (strcmp(arg, "-xwe") == 0) {
5537c478bd9Sstevel@tonic-gate /* turn warnings into errors */
55480ab886dSwesolows newae(ctx->i_ae, "-Werror");
5557c478bd9Sstevel@tonic-gate continue;
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate if (strcmp(arg, "-nolib") == 0) {
5587c478bd9Sstevel@tonic-gate /* -nodefaultlibs is on by default */
5597c478bd9Sstevel@tonic-gate nolibc = 1;
5607c478bd9Sstevel@tonic-gate continue;
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate switch ((c = arg[1])) {
5657c478bd9Sstevel@tonic-gate case '_':
566aa9ef484SJohn Levon if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
567aa9ef484SJohn Levon (strncmp(arg, "-_gcc=", 6) == 0) ||
568aa9ef484SJohn Levon (strncmp(arg, "-_gnu=", 6) == 0)) {
569aa9ef484SJohn Levon newae(ctx->i_ae, strchr(arg, '=') + 1);
570aa9ef484SJohn Levon }
5717c478bd9Sstevel@tonic-gate break;
5727c478bd9Sstevel@tonic-gate case '#':
5737c478bd9Sstevel@tonic-gate if (arglen == 1) {
57480ab886dSwesolows newae(ctx->i_ae, "-v");
5757c478bd9Sstevel@tonic-gate break;
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate error(arg);
5787c478bd9Sstevel@tonic-gate break;
579e1bf37b1SRichard Lowe case 'f':
580e1bf37b1SRichard Lowe if ((strcmp(arg, "-fpic") == 0) ||
581e1bf37b1SRichard Lowe (strcmp(arg, "-fPIC") == 0)) {
582e1bf37b1SRichard Lowe newae(ctx->i_ae, arg);
583e1bf37b1SRichard Lowe break;
584e1bf37b1SRichard Lowe }
585e1bf37b1SRichard Lowe error(arg);
586e1bf37b1SRichard Lowe break;
5877c478bd9Sstevel@tonic-gate case 'E':
5887c478bd9Sstevel@tonic-gate if (arglen == 1) {
58980ab886dSwesolows newae(ctx->i_ae, "-xc");
59080ab886dSwesolows newae(ctx->i_ae, arg);
59180ab886dSwesolows op = CW_O_PREPROCESS;
5927c478bd9Sstevel@tonic-gate nolibc = 1;
5937c478bd9Sstevel@tonic-gate break;
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate error(arg);
5967c478bd9Sstevel@tonic-gate break;
5977c478bd9Sstevel@tonic-gate case 'c':
5987c478bd9Sstevel@tonic-gate case 'S':
59980ab886dSwesolows if (arglen == 1) {
60080ab886dSwesolows op = CW_O_COMPILE;
6017c478bd9Sstevel@tonic-gate nolibc = 1;
60280ab886dSwesolows }
6037c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
6047c478bd9Sstevel@tonic-gate case 'C':
6057c478bd9Sstevel@tonic-gate case 'H':
6067c478bd9Sstevel@tonic-gate case 'p':
6077c478bd9Sstevel@tonic-gate if (arglen == 1) {
60880ab886dSwesolows newae(ctx->i_ae, arg);
6097c478bd9Sstevel@tonic-gate break;
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate error(arg);
6127c478bd9Sstevel@tonic-gate break;
6137c478bd9Sstevel@tonic-gate case 'A':
614299e09deSRichard Lowe case 'g':
6157c478bd9Sstevel@tonic-gate case 'I':
6167c478bd9Sstevel@tonic-gate case 'i':
6177c478bd9Sstevel@tonic-gate case 'L':
6187c478bd9Sstevel@tonic-gate case 'l':
6197c478bd9Sstevel@tonic-gate case 'R':
6207c478bd9Sstevel@tonic-gate case 'U':
6217c478bd9Sstevel@tonic-gate case 'u':
6227c478bd9Sstevel@tonic-gate case 'w':
62380ab886dSwesolows newae(ctx->i_ae, arg);
62480ab886dSwesolows break;
62580ab886dSwesolows case 'o':
62680ab886dSwesolows seen_o = 1;
62780ab886dSwesolows if (arglen == 1) {
62880ab886dSwesolows in_output = 1;
62980ab886dSwesolows newae(ctx->i_ae, arg);
63080ab886dSwesolows } else if (ctx->i_flags & CW_F_SHADOW) {
63180ab886dSwesolows newae(ctx->i_ae, "-o");
63288e61e85SRichard Lowe newae(ctx->i_ae, discard_file_name(ctx, arg));
63380ab886dSwesolows } else {
63480ab886dSwesolows newae(ctx->i_ae, arg);
63580ab886dSwesolows }
6367c478bd9Sstevel@tonic-gate break;
6377c478bd9Sstevel@tonic-gate case 'D':
63880ab886dSwesolows newae(ctx->i_ae, arg);
6397c478bd9Sstevel@tonic-gate /*
6407c478bd9Sstevel@tonic-gate * XXX Clearly a hack ... do we need _KADB too?
6417c478bd9Sstevel@tonic-gate */
6427c478bd9Sstevel@tonic-gate if (strcmp(arg, "-D_KERNEL") == 0 ||
6437c478bd9Sstevel@tonic-gate strcmp(arg, "-D_BOOT") == 0)
64480ab886dSwesolows newae(ctx->i_ae, "-ffreestanding");
6457c478bd9Sstevel@tonic-gate break;
6467c478bd9Sstevel@tonic-gate case 'e':
6477c478bd9Sstevel@tonic-gate if (strcmp(arg, "-errtags=yes") == 0) {
64880ab886dSwesolows warnings(ctx->i_ae);
6497c478bd9Sstevel@tonic-gate break;
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate if (strcmp(arg, "-errwarn=%all") == 0) {
65280ab886dSwesolows newae(ctx->i_ae, "-Werror");
6537c478bd9Sstevel@tonic-gate break;
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate error(arg);
6567c478bd9Sstevel@tonic-gate break;
6577c478bd9Sstevel@tonic-gate case 'k':
6587c478bd9Sstevel@tonic-gate if (strcmp(arg, "-keeptmp") == 0) {
65980ab886dSwesolows newae(ctx->i_ae, "-save-temps");
6607c478bd9Sstevel@tonic-gate break;
6617c478bd9Sstevel@tonic-gate }
6627c478bd9Sstevel@tonic-gate error(arg);
6637c478bd9Sstevel@tonic-gate break;
6647c478bd9Sstevel@tonic-gate case 'm':
6657c478bd9Sstevel@tonic-gate if (strcmp(arg, "-mt") == 0) {
66680ab886dSwesolows newae(ctx->i_ae, "-D_REENTRANT");
6677c478bd9Sstevel@tonic-gate break;
6687c478bd9Sstevel@tonic-gate }
669e521259dSpetede if (strcmp(arg, "-m64") == 0) {
670e521259dSpetede newae(ctx->i_ae, "-m64");
671e521259dSpetede #if defined(__x86)
672e521259dSpetede newae(ctx->i_ae, "-mtune=opteron");
673e521259dSpetede #endif
674e521259dSpetede mflag |= M64;
675e521259dSpetede break;
676e521259dSpetede }
677e521259dSpetede if (strcmp(arg, "-m32") == 0) {
678e521259dSpetede newae(ctx->i_ae, "-m32");
679e521259dSpetede mflag |= M32;
680e521259dSpetede break;
681e521259dSpetede }
6827c478bd9Sstevel@tonic-gate error(arg);
6837c478bd9Sstevel@tonic-gate break;
6847c478bd9Sstevel@tonic-gate case 'O':
6857c478bd9Sstevel@tonic-gate if (arglen == 1) {
68680ab886dSwesolows newae(ctx->i_ae, "-O");
6877c478bd9Sstevel@tonic-gate break;
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate error(arg);
6907c478bd9Sstevel@tonic-gate break;
6917c478bd9Sstevel@tonic-gate case 'P':
6927c478bd9Sstevel@tonic-gate /*
6937c478bd9Sstevel@tonic-gate * We could do '-E -o filename.i', but that's hard,
6947c478bd9Sstevel@tonic-gate * and we don't need it for the case that's triggering
6957c478bd9Sstevel@tonic-gate * this addition. We'll require the user to specify
6967c478bd9Sstevel@tonic-gate * -o in the Makefile. If they don't they'll find out
6977c478bd9Sstevel@tonic-gate * in a hurry.
6987c478bd9Sstevel@tonic-gate */
69980ab886dSwesolows newae(ctx->i_ae, "-E");
70080ab886dSwesolows op = CW_O_PREPROCESS;
7017c478bd9Sstevel@tonic-gate nolibc = 1;
7027c478bd9Sstevel@tonic-gate break;
7037c478bd9Sstevel@tonic-gate case 's':
70485f4cb87SRichard Lowe if (strcmp(arg, "-shared") == 0) {
70585f4cb87SRichard Lowe newae(ctx->i_ae, "-shared");
70685f4cb87SRichard Lowe nolibc = 1;
707159cf8a6Swesolows break;
708159cf8a6Swesolows }
709159cf8a6Swesolows error(arg);
710159cf8a6Swesolows break;
71185f4cb87SRichard Lowe
7127c478bd9Sstevel@tonic-gate case 'V':
7137c478bd9Sstevel@tonic-gate if (arglen == 1) {
71480ab886dSwesolows ctx->i_flags &= ~CW_F_ECHO;
71580ab886dSwesolows newae(ctx->i_ae, "--version");
7167c478bd9Sstevel@tonic-gate break;
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate error(arg);
7197c478bd9Sstevel@tonic-gate break;
7207c478bd9Sstevel@tonic-gate case 'v':
7217c478bd9Sstevel@tonic-gate if (arglen == 1) {
72280ab886dSwesolows warnings(ctx->i_ae);
7237c478bd9Sstevel@tonic-gate break;
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate error(arg);
7267c478bd9Sstevel@tonic-gate break;
7277c478bd9Sstevel@tonic-gate case 'W':
7287c478bd9Sstevel@tonic-gate if (strncmp(arg, "-Wa,", 4) == 0 ||
7297c478bd9Sstevel@tonic-gate strncmp(arg, "-Wp,", 4) == 0 ||
7307c478bd9Sstevel@tonic-gate strncmp(arg, "-Wl,", 4) == 0) {
73180ab886dSwesolows newae(ctx->i_ae, arg);
7327c478bd9Sstevel@tonic-gate break;
7337c478bd9Sstevel@tonic-gate }
734*d17be682SRichard Lowe
7357c478bd9Sstevel@tonic-gate #if defined(__x86)
736d430274bSsherrym if (strcmp(arg, "-Wu,-save_args") == 0) {
73780ab886dSwesolows newae(ctx->i_ae, "-msave-args");
738d430274bSsherrym break;
739d430274bSsherrym }
7407c478bd9Sstevel@tonic-gate #endif /* __x86 */
7417c478bd9Sstevel@tonic-gate error(arg);
7427c478bd9Sstevel@tonic-gate break;
7437c478bd9Sstevel@tonic-gate case 'X':
7447c478bd9Sstevel@tonic-gate if (strcmp(arg, "-Xs") == 0) {
74580ab886dSwesolows Xsmode(ctx->i_ae);
7467c478bd9Sstevel@tonic-gate break;
7477c478bd9Sstevel@tonic-gate }
7487c478bd9Sstevel@tonic-gate error(arg);
7497c478bd9Sstevel@tonic-gate break;
7507c478bd9Sstevel@tonic-gate case 'x':
7517c478bd9Sstevel@tonic-gate if (arglen == 1)
7527c478bd9Sstevel@tonic-gate error(arg);
7537c478bd9Sstevel@tonic-gate switch (arg[2]) {
7547c478bd9Sstevel@tonic-gate case 'a':
7557c478bd9Sstevel@tonic-gate if (strncmp(arg, "-xarch=", 7) == 0) {
756e521259dSpetede mflag |= xlate_xtb(ctx->i_ae, arg + 7);
7577c478bd9Sstevel@tonic-gate break;
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate error(arg);
7607c478bd9Sstevel@tonic-gate break;
76102e56f3fSwesolows case 'b':
76202e56f3fSwesolows if (strncmp(arg, "-xbuiltin=", 10) == 0) {
76302e56f3fSwesolows if (strcmp(arg + 10, "%all"))
76480ab886dSwesolows newae(ctx->i_ae, "-fbuiltin");
76502e56f3fSwesolows break;
76602e56f3fSwesolows }
76702e56f3fSwesolows error(arg);
76802e56f3fSwesolows break;
7697c478bd9Sstevel@tonic-gate case 'c':
7707c478bd9Sstevel@tonic-gate if (strncmp(arg, "-xc99=%all", 10) == 0) {
77180ab886dSwesolows newae(ctx->i_ae, "-std=gnu99");
7727c478bd9Sstevel@tonic-gate break;
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate if (strncmp(arg, "-xc99=%none", 11) == 0) {
77580ab886dSwesolows newae(ctx->i_ae, "-std=gnu89");
7767c478bd9Sstevel@tonic-gate break;
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate if (strncmp(arg, "-xchip=", 7) == 0) {
77980ab886dSwesolows xlate(ctx->i_ae, arg + 7, xchip_tbl);
7807c478bd9Sstevel@tonic-gate break;
7817c478bd9Sstevel@tonic-gate }
782*d17be682SRichard Lowe
7837c478bd9Sstevel@tonic-gate error(arg);
7847c478bd9Sstevel@tonic-gate break;
78554836668Spetede #if defined(__x86)
78654836668Spetede case 'm':
78754836668Spetede if (strcmp(arg, "-xmodel=kernel") == 0) {
78854836668Spetede newae(ctx->i_ae, "-ffreestanding");
78954836668Spetede newae(ctx->i_ae, "-mno-red-zone");
79054836668Spetede model = "-mcmodel=kernel";
79154836668Spetede nolibc = 1;
79254836668Spetede break;
79354836668Spetede }
79454836668Spetede error(arg);
79554836668Spetede break;
79654836668Spetede #endif /* __x86 */
7977c478bd9Sstevel@tonic-gate case 'O':
7987c478bd9Sstevel@tonic-gate if (strncmp(arg, "-xO", 3) == 0) {
7997c478bd9Sstevel@tonic-gate size_t len = strlen(arg);
800538ff303SToomas Soome char *s = NULL;
8017c478bd9Sstevel@tonic-gate int c = *(arg + 3);
8027c478bd9Sstevel@tonic-gate int level;
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate if (len != 4 || !isdigit(c))
8057c478bd9Sstevel@tonic-gate error(arg);
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate level = atoi(arg + 3);
8087c478bd9Sstevel@tonic-gate if (level > 5)
8097c478bd9Sstevel@tonic-gate error(arg);
8107c478bd9Sstevel@tonic-gate if (level >= 2) {
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate * For gcc-3.4.x at -O2 we
8137c478bd9Sstevel@tonic-gate * need to disable optimizations
8147c478bd9Sstevel@tonic-gate * that break ON.
8157c478bd9Sstevel@tonic-gate */
81680ab886dSwesolows optim_disable(ctx->i_ae, level);
8177c478bd9Sstevel@tonic-gate /*
8187c478bd9Sstevel@tonic-gate * limit -xO3 to -O2 as well.
8197c478bd9Sstevel@tonic-gate */
8207c478bd9Sstevel@tonic-gate level = 2;
8217c478bd9Sstevel@tonic-gate }
822538ff303SToomas Soome if (asprintf(&s, "-O%d", level) == -1)
823538ff303SToomas Soome nomem();
82480ab886dSwesolows newae(ctx->i_ae, s);
8257c478bd9Sstevel@tonic-gate free(s);
8267c478bd9Sstevel@tonic-gate break;
8277c478bd9Sstevel@tonic-gate }
8287c478bd9Sstevel@tonic-gate error(arg);
8297c478bd9Sstevel@tonic-gate break;
8307c478bd9Sstevel@tonic-gate case 't':
8317c478bd9Sstevel@tonic-gate if (strncmp(arg, "-xtarget=", 9) == 0) {
83280ab886dSwesolows xlate(ctx->i_ae, arg + 9, xtarget_tbl);
8337c478bd9Sstevel@tonic-gate break;
8347c478bd9Sstevel@tonic-gate }
8357c478bd9Sstevel@tonic-gate error(arg);
8367c478bd9Sstevel@tonic-gate break;
8377c478bd9Sstevel@tonic-gate default:
8387c478bd9Sstevel@tonic-gate error(arg);
8397c478bd9Sstevel@tonic-gate break;
8407c478bd9Sstevel@tonic-gate }
8417c478bd9Sstevel@tonic-gate break;
8427c478bd9Sstevel@tonic-gate case 'Y':
8437c478bd9Sstevel@tonic-gate if (arglen == 1) {
84480ab886dSwesolows if ((arg = *++ctx->i_oldargv) == NULL ||
84580ab886dSwesolows *arg == '\0')
8467c478bd9Sstevel@tonic-gate error("-Y");
84780ab886dSwesolows ctx->i_oldargc--;
8487c478bd9Sstevel@tonic-gate arglen = strlen(arg + 1);
8497c478bd9Sstevel@tonic-gate } else {
8507c478bd9Sstevel@tonic-gate arg += 2;
8517c478bd9Sstevel@tonic-gate }
8527c478bd9Sstevel@tonic-gate if (strncmp(arg, "I,", 2) == 0) {
8537c478bd9Sstevel@tonic-gate char *s = strdup(arg);
8547c478bd9Sstevel@tonic-gate s[0] = '-';
8557c478bd9Sstevel@tonic-gate s[1] = 'I';
85680ab886dSwesolows newae(ctx->i_ae, "-nostdinc");
85780ab886dSwesolows newae(ctx->i_ae, s);
8587c478bd9Sstevel@tonic-gate free(s);
8597c478bd9Sstevel@tonic-gate break;
8607c478bd9Sstevel@tonic-gate }
8617c478bd9Sstevel@tonic-gate error(arg);
8627c478bd9Sstevel@tonic-gate break;
8637c478bd9Sstevel@tonic-gate default:
8647c478bd9Sstevel@tonic-gate error(arg);
8657c478bd9Sstevel@tonic-gate break;
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate
869aa9ef484SJohn Levon free(nameflag);
870aa9ef484SJohn Levon
87188e61e85SRichard Lowe /*
87288e61e85SRichard Lowe * When compiling multiple source files in a single invocation some
87388e61e85SRichard Lowe * compilers output objects into the current directory with
87488e61e85SRichard Lowe * predictable and conventional names.
87588e61e85SRichard Lowe *
87688e61e85SRichard Lowe * We prevent any attempt to compile multiple files at once so that
87788e61e85SRichard Lowe * any such objects created by a shadow can't escape into a later
87888e61e85SRichard Lowe * link-edit.
87988e61e85SRichard Lowe */
88088e61e85SRichard Lowe if (c_files > 1 && op != CW_O_PREPROCESS) {
881aa9ef484SJohn Levon errx(2, "multiple source files are "
882aa9ef484SJohn Levon "allowed only with -E or -P");
88380ab886dSwesolows }
884e521259dSpetede
885e521259dSpetede /*
886e521259dSpetede * Make sure that we do not have any unintended interactions between
887e521259dSpetede * the xarch options passed in and the version of the Studio compiler
888e521259dSpetede * used.
889e521259dSpetede */
890e521259dSpetede if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
891aa9ef484SJohn Levon errx(2,
892e521259dSpetede "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
893e521259dSpetede }
894e521259dSpetede
895e521259dSpetede switch (mflag) {
896e521259dSpetede case 0:
897e521259dSpetede case M32:
898e521259dSpetede case M64:
899e521259dSpetede case SS12:
900e521259dSpetede case SS11:
901e521259dSpetede case (SS11|M32):
902e521259dSpetede case (SS11|M64):
903e521259dSpetede case (SS12|M32):
904e521259dSpetede case (SS12|M64):
905e521259dSpetede break;
906e521259dSpetede default:
907e521259dSpetede (void) fprintf(stderr,
9087a6460b6Spetede "Incompatible -xarch= and/or -m32/-m64 options used.\n");
909e521259dSpetede exit(2);
910e521259dSpetede }
911aa9ef484SJohn Levon
91288e61e85SRichard Lowe if (ctx->i_flags & CW_F_SHADOW) {
91388e61e85SRichard Lowe if (op == CW_O_PREPROCESS)
91488e61e85SRichard Lowe exit(0);
91588e61e85SRichard Lowe else if (op == CW_O_LINK && c_files == 0)
91688e61e85SRichard Lowe exit(0);
91788e61e85SRichard Lowe }
91880ab886dSwesolows
919e1bf37b1SRichard Lowe if (model != NULL)
92080ab886dSwesolows newae(ctx->i_ae, model);
9217c478bd9Sstevel@tonic-gate if (!nolibc)
92280ab886dSwesolows newae(ctx->i_ae, "-lc");
92380ab886dSwesolows if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
92480ab886dSwesolows newae(ctx->i_ae, "-o");
92588e61e85SRichard Lowe newae(ctx->i_ae, discard_file_name(ctx, NULL));
92680ab886dSwesolows }
92780ab886dSwesolows }
92880ab886dSwesolows
9291f5207b7SJohn Levon static void
do_smatch(cw_ictx_t * ctx)9301f5207b7SJohn Levon do_smatch(cw_ictx_t *ctx)
9311f5207b7SJohn Levon {
9321f5207b7SJohn Levon if (ctx->i_flags & CW_F_PROG) {
9331f5207b7SJohn Levon newae(ctx->i_ae, "--version");
9341f5207b7SJohn Levon return;
9351f5207b7SJohn Levon }
9361f5207b7SJohn Levon
9371f5207b7SJohn Levon /*
9381f5207b7SJohn Levon * Some sources shouldn't run smatch at all.
9391f5207b7SJohn Levon */
9401f5207b7SJohn Levon for (int i = 0; i < ctx->i_oldargc; i++) {
9411f5207b7SJohn Levon char *arg = ctx->i_oldargv[i];
9421f5207b7SJohn Levon
9431f5207b7SJohn Levon if (strcmp(arg, "-_smatch=off") == 0) {
9445d9d9091SRichard Lowe ctx->i_flags &= ~(CW_F_EXEC | CW_F_ECHO);
9455d9d9091SRichard Lowe return;
9465d9d9091SRichard Lowe }
9475d9d9091SRichard Lowe
9485d9d9091SRichard Lowe /* smatch can't handle asm */
9495d9d9091SRichard Lowe if ((arg[0] != '-') && is_asm_file(arg)) {
9505d9d9091SRichard Lowe ctx->i_flags &= ~(CW_F_EXEC | CW_F_ECHO);
9511f5207b7SJohn Levon return;
9521f5207b7SJohn Levon }
9531f5207b7SJohn Levon }
9541f5207b7SJohn Levon
9551f5207b7SJohn Levon /*
9561f5207b7SJohn Levon * smatch can handle gcc's options.
9571f5207b7SJohn Levon */
9581f5207b7SJohn Levon do_gcc(ctx);
9591f5207b7SJohn Levon }
9601f5207b7SJohn Levon
96180ab886dSwesolows static void
do_cc(cw_ictx_t * ctx)96280ab886dSwesolows do_cc(cw_ictx_t *ctx)
96380ab886dSwesolows {
96488e61e85SRichard Lowe int in_output = 0, seen_o = 0, c_files = 0;
96580ab886dSwesolows cw_op_t op = CW_O_LINK;
966aa9ef484SJohn Levon char *nameflag;
96780ab886dSwesolows
9681912d2c4Swesolows if (ctx->i_flags & CW_F_PROG) {
9691912d2c4Swesolows newae(ctx->i_ae, "-V");
9701912d2c4Swesolows return;
9711912d2c4Swesolows }
9721912d2c4Swesolows
973aa9ef484SJohn Levon if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
974aa9ef484SJohn Levon nomem();
975aa9ef484SJohn Levon
97680ab886dSwesolows while (--ctx->i_oldargc > 0) {
97780ab886dSwesolows char *arg = *++ctx->i_oldargv;
97880ab886dSwesolows
979aa9ef484SJohn Levon if (strncmp(arg, "-_CC=", 5) == 0) {
980aa9ef484SJohn Levon newae(ctx->i_ae, strchr(arg, '=') + 1);
981aa9ef484SJohn Levon continue;
982aa9ef484SJohn Levon }
983aa9ef484SJohn Levon
98480ab886dSwesolows if (*arg != '-') {
98588e61e85SRichard Lowe if (!in_output && is_source_file(arg))
98688e61e85SRichard Lowe c_files++;
98788e61e85SRichard Lowe
98880ab886dSwesolows if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
98980ab886dSwesolows newae(ctx->i_ae, arg);
99080ab886dSwesolows } else {
99180ab886dSwesolows in_output = 0;
99288e61e85SRichard Lowe newae(ctx->i_ae, discard_file_name(ctx, arg));
99380ab886dSwesolows }
99480ab886dSwesolows continue;
99580ab886dSwesolows }
99680ab886dSwesolows switch (*(arg + 1)) {
99780ab886dSwesolows case '_':
998aa9ef484SJohn Levon if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
999aa9ef484SJohn Levon (strncmp(arg, "-_cc=", 5) == 0) ||
1000aa9ef484SJohn Levon (strncmp(arg, "-_sun=", 6) == 0)) {
1001aa9ef484SJohn Levon newae(ctx->i_ae, strchr(arg, '=') + 1);
100280ab886dSwesolows }
100380ab886dSwesolows break;
1004aa9ef484SJohn Levon
100580ab886dSwesolows case 'V':
100680ab886dSwesolows ctx->i_flags &= ~CW_F_ECHO;
100780ab886dSwesolows newae(ctx->i_ae, arg);
100880ab886dSwesolows break;
100980ab886dSwesolows case 'o':
101080ab886dSwesolows seen_o = 1;
101180ab886dSwesolows if (strlen(arg) == 2) {
101280ab886dSwesolows in_output = 1;
101380ab886dSwesolows newae(ctx->i_ae, arg);
101480ab886dSwesolows } else if (ctx->i_flags & CW_F_SHADOW) {
101580ab886dSwesolows newae(ctx->i_ae, "-o");
101688e61e85SRichard Lowe newae(ctx->i_ae, discard_file_name(ctx, arg));
101780ab886dSwesolows } else {
101880ab886dSwesolows newae(ctx->i_ae, arg);
101980ab886dSwesolows }
102080ab886dSwesolows break;
102180ab886dSwesolows case 'c':
102280ab886dSwesolows case 'S':
10230bb3415fSrie if (strlen(arg) == 2)
10240bb3415fSrie op = CW_O_COMPILE;
102580ab886dSwesolows newae(ctx->i_ae, arg);
102680ab886dSwesolows break;
102780ab886dSwesolows case 'E':
102880ab886dSwesolows case 'P':
10290bb3415fSrie if (strlen(arg) == 2)
10300bb3415fSrie op = CW_O_PREPROCESS;
103180ab886dSwesolows /*FALLTHROUGH*/
103280ab886dSwesolows default:
103380ab886dSwesolows newae(ctx->i_ae, arg);
103480ab886dSwesolows }
103580ab886dSwesolows }
103680ab886dSwesolows
1037aa9ef484SJohn Levon free(nameflag);
1038aa9ef484SJohn Levon
103988e61e85SRichard Lowe /* See the comment on this same code in do_gcc() */
104088e61e85SRichard Lowe if (c_files > 1 && op != CW_O_PREPROCESS) {
104188e61e85SRichard Lowe errx(2, "multiple source files are "
104288e61e85SRichard Lowe "allowed only with -E or -P");
104388e61e85SRichard Lowe }
104488e61e85SRichard Lowe
104588e61e85SRichard Lowe if (ctx->i_flags & CW_F_SHADOW) {
104688e61e85SRichard Lowe if (op == CW_O_PREPROCESS)
104788e61e85SRichard Lowe exit(0);
104888e61e85SRichard Lowe else if (op == CW_O_LINK && c_files == 0)
104988e61e85SRichard Lowe exit(0);
105088e61e85SRichard Lowe }
105180ab886dSwesolows
105280ab886dSwesolows if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
105380ab886dSwesolows newae(ctx->i_ae, "-o");
105488e61e85SRichard Lowe newae(ctx->i_ae, discard_file_name(ctx, NULL));
105580ab886dSwesolows }
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate static void
prepctx(cw_ictx_t * ctx)105980ab886dSwesolows prepctx(cw_ictx_t *ctx)
10607c478bd9Sstevel@tonic-gate {
1061aa9ef484SJohn Levon newae(ctx->i_ae, ctx->i_compiler->c_path);
106280ab886dSwesolows
10631912d2c4Swesolows if (ctx->i_flags & CW_F_PROG) {
10641912d2c4Swesolows (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1065aa9ef484SJohn Levon "shadow" : "primary", ctx->i_compiler->c_path);
10661912d2c4Swesolows (void) fflush(stdout);
10671912d2c4Swesolows }
10681912d2c4Swesolows
106969b1fd3fSRichard Lowe /*
107069b1fd3fSRichard Lowe * If LD_ALTEXEC is already set, the expectation would be that that
107169b1fd3fSRichard Lowe * link-editor is run, as such we need to leave it the environment
107269b1fd3fSRichard Lowe * alone and let that happen.
107369b1fd3fSRichard Lowe */
107469b1fd3fSRichard Lowe if ((ctx->i_linker != NULL) && (getenv("LD_ALTEXEC") == NULL))
107569b1fd3fSRichard Lowe setenv("LD_ALTEXEC", ctx->i_linker, 1);
107669b1fd3fSRichard Lowe
107780ab886dSwesolows if (!(ctx->i_flags & CW_F_XLATE))
107880ab886dSwesolows return;
107980ab886dSwesolows
1080aa9ef484SJohn Levon switch (ctx->i_compiler->c_style) {
1081aa9ef484SJohn Levon case SUN:
108280ab886dSwesolows do_cc(ctx);
108380ab886dSwesolows break;
1084aa9ef484SJohn Levon case GNU:
108580ab886dSwesolows do_gcc(ctx);
108680ab886dSwesolows break;
10871f5207b7SJohn Levon case SMATCH:
10881f5207b7SJohn Levon do_smatch(ctx);
10891f5207b7SJohn Levon break;
109080ab886dSwesolows }
109180ab886dSwesolows }
109280ab886dSwesolows
109380ab886dSwesolows static int
invoke(cw_ictx_t * ctx)109480ab886dSwesolows invoke(cw_ictx_t *ctx)
109580ab886dSwesolows {
1096c3d5f7c4SRyan Goodfellow char **newargv, *makeflags;
109780ab886dSwesolows int ac;
109880ab886dSwesolows struct ae *a;
109980ab886dSwesolows
1100c3d5f7c4SRyan Goodfellow newargv = calloc(ctx->i_ae->ael_argc + 1, sizeof (*newargv));
1101c3d5f7c4SRyan Goodfellow if (newargv == NULL)
110280ab886dSwesolows nomem();
110380ab886dSwesolows
1104c3d5f7c4SRyan Goodfellow /*
1105c3d5f7c4SRyan Goodfellow * Check to see if the silent make flag is present (-s), if so, do not
1106c3d5f7c4SRyan Goodfellow * echo. The MAKEFLAGS environment variable is set by dmake. By
1107c3d5f7c4SRyan Goodfellow * observation it appears to place short flags without any arguments
1108c3d5f7c4SRyan Goodfellow * first followed by any long form flags or flags with arguments.
1109c3d5f7c4SRyan Goodfellow */
1110c3d5f7c4SRyan Goodfellow makeflags = getenv("MAKEFLAGS");
1111c3d5f7c4SRyan Goodfellow if (makeflags != NULL) {
1112c3d5f7c4SRyan Goodfellow size_t makeflags_len = strlen(makeflags);
1113c3d5f7c4SRyan Goodfellow for (size_t i = 0; i < makeflags_len; i++) {
1114c3d5f7c4SRyan Goodfellow if (makeflags[i] == 's') {
1115c3d5f7c4SRyan Goodfellow ctx->i_flags &= ~CW_F_ECHO;
1116c3d5f7c4SRyan Goodfellow break;
1117c3d5f7c4SRyan Goodfellow }
1118c3d5f7c4SRyan Goodfellow /* end of short flags */
1119c3d5f7c4SRyan Goodfellow if (makeflags[i] == ' ')
1120c3d5f7c4SRyan Goodfellow break;
1121c3d5f7c4SRyan Goodfellow }
1122c3d5f7c4SRyan Goodfellow }
1123c3d5f7c4SRyan Goodfellow
112480ab886dSwesolows if (ctx->i_flags & CW_F_ECHO)
112580ab886dSwesolows (void) fprintf(stderr, "+ ");
112680ab886dSwesolows
112780ab886dSwesolows for (ac = 0, a = ctx->i_ae->ael_head; a; a = a->ae_next, ac++) {
112880ab886dSwesolows newargv[ac] = a->ae_arg;
112980ab886dSwesolows if (ctx->i_flags & CW_F_ECHO)
113080ab886dSwesolows (void) fprintf(stderr, "%s ", a->ae_arg);
113180ab886dSwesolows if (a == ctx->i_ae->ael_tail)
113280ab886dSwesolows break;
113380ab886dSwesolows }
113480ab886dSwesolows
113580ab886dSwesolows if (ctx->i_flags & CW_F_ECHO) {
113680ab886dSwesolows (void) fprintf(stderr, "\n");
113780ab886dSwesolows (void) fflush(stderr);
113880ab886dSwesolows }
113980ab886dSwesolows
114080ab886dSwesolows if (!(ctx->i_flags & CW_F_EXEC))
114180ab886dSwesolows return (0);
114280ab886dSwesolows
11437c478bd9Sstevel@tonic-gate /*
1144aa9ef484SJohn Levon * We must fix up the environment here so that the dependency files are
1145aa9ef484SJohn Levon * not trampled by the shadow compiler. Also take care of GCC
1146aa9ef484SJohn Levon * environment variables that will throw off gcc. This assumes a primary
1147aa9ef484SJohn Levon * gcc.
11487c478bd9Sstevel@tonic-gate */
114980ab886dSwesolows if ((ctx->i_flags & CW_F_SHADOW) &&
115080ab886dSwesolows (unsetenv("SUNPRO_DEPENDENCIES") != 0 ||
1151aa9ef484SJohn Levon unsetenv("DEPENDENCIES_OUTPUT") != 0 ||
1152aa9ef484SJohn Levon unsetenv("GCC_ROOT") != 0)) {
115380ab886dSwesolows (void) fprintf(stderr, "error: environment setup failed: %s\n",
115480ab886dSwesolows strerror(errno));
115580ab886dSwesolows return (-1);
115680ab886dSwesolows }
11577c478bd9Sstevel@tonic-gate
115880ab886dSwesolows (void) execv(newargv[0], newargv);
1159aa9ef484SJohn Levon warn("couldn't run %s", newargv[0]);
11607c478bd9Sstevel@tonic-gate
116180ab886dSwesolows return (-1);
116280ab886dSwesolows }
116380ab886dSwesolows
116480ab886dSwesolows static int
reap(cw_ictx_t * ctx)116580ab886dSwesolows reap(cw_ictx_t *ctx)
116680ab886dSwesolows {
11671912d2c4Swesolows int status, ret = 0;
116880ab886dSwesolows char buf[1024];
116980ab886dSwesolows struct stat s;
117080ab886dSwesolows
1171c3f177eaSPeter Dennis - Sustaining Engineer /*
1172c3f177eaSPeter Dennis - Sustaining Engineer * Only wait for one specific child.
1173c3f177eaSPeter Dennis - Sustaining Engineer */
1174c3f177eaSPeter Dennis - Sustaining Engineer if (ctx->i_pid <= 0)
1175c3f177eaSPeter Dennis - Sustaining Engineer return (-1);
1176c3f177eaSPeter Dennis - Sustaining Engineer
117780ab886dSwesolows do {
1178c3f177eaSPeter Dennis - Sustaining Engineer if (waitpid(ctx->i_pid, &status, 0) < 0) {
1179aa9ef484SJohn Levon warn("cannot reap child");
1180c3f177eaSPeter Dennis - Sustaining Engineer return (-1);
1181c3f177eaSPeter Dennis - Sustaining Engineer }
11821912d2c4Swesolows if (status != 0) {
11831912d2c4Swesolows if (WIFSIGNALED(status)) {
11841912d2c4Swesolows ret = -WTERMSIG(status);
118580ab886dSwesolows break;
11861912d2c4Swesolows } else if (WIFEXITED(status)) {
11871912d2c4Swesolows ret = WEXITSTATUS(status);
118880ab886dSwesolows break;
118980ab886dSwesolows }
11907c478bd9Sstevel@tonic-gate }
11911912d2c4Swesolows } while (!WIFEXITED(status) && !WIFSIGNALED(status));
119280ab886dSwesolows
11931912d2c4Swesolows if (stat(ctx->i_stderr, &s) < 0) {
1194aa9ef484SJohn Levon warn("stat failed on child cleanup");
119580ab886dSwesolows return (-1);
11967c478bd9Sstevel@tonic-gate }
119780ab886dSwesolows if (s.st_size != 0) {
11981912d2c4Swesolows FILE *f;
119980ab886dSwesolows
12001912d2c4Swesolows if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
12011912d2c4Swesolows while (fgets(buf, sizeof (buf), f))
12021912d2c4Swesolows (void) fprintf(stderr, "%s", buf);
12031912d2c4Swesolows (void) fflush(stderr);
12041912d2c4Swesolows (void) fclose(f);
12051912d2c4Swesolows }
120680ab886dSwesolows }
12071912d2c4Swesolows (void) unlink(ctx->i_stderr);
12081912d2c4Swesolows free(ctx->i_stderr);
12091912d2c4Swesolows
12101912d2c4Swesolows /*
12111912d2c4Swesolows * cc returns an error code when given -V; we want that to succeed.
12121912d2c4Swesolows */
12131912d2c4Swesolows if (ctx->i_flags & CW_F_PROG)
12141912d2c4Swesolows return (0);
121580ab886dSwesolows
121680ab886dSwesolows return (ret);
121780ab886dSwesolows }
121880ab886dSwesolows
121980ab886dSwesolows static int
exec_ctx(cw_ictx_t * ctx,int block)122080ab886dSwesolows exec_ctx(cw_ictx_t *ctx, int block)
122180ab886dSwesolows {
122288e61e85SRichard Lowe if ((ctx->i_stderr = tempnam(ctx->i_tmpdir, "cw")) == NULL) {
12231912d2c4Swesolows nomem();
122480ab886dSwesolows return (-1);
122580ab886dSwesolows }
122680ab886dSwesolows
122780ab886dSwesolows if ((ctx->i_pid = fork()) == 0) {
12281912d2c4Swesolows int fd;
12291912d2c4Swesolows
123080ab886dSwesolows (void) fclose(stderr);
12311912d2c4Swesolows if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
12321912d2c4Swesolows 0666)) < 0) {
1233aa9ef484SJohn Levon err(1, "open failed for standard error");
12341912d2c4Swesolows }
12351912d2c4Swesolows if (dup2(fd, 2) < 0) {
1236aa9ef484SJohn Levon err(1, "dup2 failed for standard error");
123780ab886dSwesolows }
12381912d2c4Swesolows if (fd != 2)
12391912d2c4Swesolows (void) close(fd);
124080ab886dSwesolows if (freopen("/dev/fd/2", "w", stderr) == NULL) {
1241aa9ef484SJohn Levon err(1, "freopen failed for /dev/fd/2");
124280ab886dSwesolows }
1243aa9ef484SJohn Levon
124480ab886dSwesolows prepctx(ctx);
124580ab886dSwesolows exit(invoke(ctx));
124680ab886dSwesolows }
124780ab886dSwesolows
124880ab886dSwesolows if (ctx->i_pid < 0) {
1249aa9ef484SJohn Levon err(1, "fork failed");
125080ab886dSwesolows }
125180ab886dSwesolows
125280ab886dSwesolows if (block)
125380ab886dSwesolows return (reap(ctx));
125480ab886dSwesolows
125580ab886dSwesolows return (0);
12567c478bd9Sstevel@tonic-gate }
12577c478bd9Sstevel@tonic-gate
1258aa9ef484SJohn Levon static void
parse_compiler(const char * spec,cw_compiler_t * compiler)1259aa9ef484SJohn Levon parse_compiler(const char *spec, cw_compiler_t *compiler)
12607c478bd9Sstevel@tonic-gate {
1261aa9ef484SJohn Levon char *tspec, *token;
12627c478bd9Sstevel@tonic-gate
1263aa9ef484SJohn Levon if ((tspec = strdup(spec)) == NULL)
126480ab886dSwesolows nomem();
126580ab886dSwesolows
1266aa9ef484SJohn Levon if ((token = strsep(&tspec, ",")) == NULL)
1267aa9ef484SJohn Levon errx(1, "Compiler is missing a name: %s", spec);
1268aa9ef484SJohn Levon compiler->c_name = token;
12697c478bd9Sstevel@tonic-gate
1270aa9ef484SJohn Levon if ((token = strsep(&tspec, ",")) == NULL)
1271aa9ef484SJohn Levon errx(1, "Compiler is missing a path: %s", spec);
1272aa9ef484SJohn Levon compiler->c_path = token;
12737c478bd9Sstevel@tonic-gate
1274aa9ef484SJohn Levon if ((token = strsep(&tspec, ",")) == NULL)
1275aa9ef484SJohn Levon errx(1, "Compiler is missing a style: %s", spec);
12767c478bd9Sstevel@tonic-gate
1277aa9ef484SJohn Levon if ((strcasecmp(token, "gnu") == 0) ||
12781f5207b7SJohn Levon (strcasecmp(token, "gcc") == 0)) {
1279aa9ef484SJohn Levon compiler->c_style = GNU;
12801f5207b7SJohn Levon } else if ((strcasecmp(token, "sun") == 0) ||
12811f5207b7SJohn Levon (strcasecmp(token, "cc") == 0)) {
1282aa9ef484SJohn Levon compiler->c_style = SUN;
12831f5207b7SJohn Levon } else if ((strcasecmp(token, "smatch") == 0)) {
12841f5207b7SJohn Levon compiler->c_style = SMATCH;
12851f5207b7SJohn Levon } else {
1286aa9ef484SJohn Levon errx(1, "unknown compiler style: %s", token);
12871f5207b7SJohn Levon }
128880ab886dSwesolows
1289aa9ef484SJohn Levon if (tspec != NULL)
1290aa9ef484SJohn Levon errx(1, "Excess tokens in compiler: %s", spec);
1291aa9ef484SJohn Levon }
12927c478bd9Sstevel@tonic-gate
129388e61e85SRichard Lowe static void
cleanup(cw_ictx_t * ctx)129488e61e85SRichard Lowe cleanup(cw_ictx_t *ctx)
129588e61e85SRichard Lowe {
129688e61e85SRichard Lowe DIR *dirp;
129788e61e85SRichard Lowe struct dirent *dp;
129888e61e85SRichard Lowe char buf[MAXPATHLEN];
129988e61e85SRichard Lowe
130088e61e85SRichard Lowe if ((dirp = opendir(ctx->i_tmpdir)) == NULL) {
130188e61e85SRichard Lowe if (errno != ENOENT) {
130288e61e85SRichard Lowe err(1, "couldn't open temp directory: %s",
130388e61e85SRichard Lowe ctx->i_tmpdir);
130488e61e85SRichard Lowe } else {
130588e61e85SRichard Lowe return;
130688e61e85SRichard Lowe }
130788e61e85SRichard Lowe }
130888e61e85SRichard Lowe
130988e61e85SRichard Lowe errno = 0;
131088e61e85SRichard Lowe while ((dp = readdir(dirp)) != NULL) {
131188e61e85SRichard Lowe (void) snprintf(buf, MAXPATHLEN, "%s/%s", ctx->i_tmpdir,
131288e61e85SRichard Lowe dp->d_name);
131388e61e85SRichard Lowe
131488e61e85SRichard Lowe if (strcmp(dp->d_name, ".") == 0 ||
131588e61e85SRichard Lowe strcmp(dp->d_name, "..") == 0) {
131688e61e85SRichard Lowe continue;
131788e61e85SRichard Lowe }
131888e61e85SRichard Lowe
131988e61e85SRichard Lowe if (unlink(buf) == -1)
132088e61e85SRichard Lowe err(1, "failed to unlink temp file: %s", dp->d_name);
132188e61e85SRichard Lowe errno = 0;
132288e61e85SRichard Lowe }
132388e61e85SRichard Lowe
132488e61e85SRichard Lowe if (errno != 0) {
132588e61e85SRichard Lowe err(1, "failed to read temporary directory: %s",
132688e61e85SRichard Lowe ctx->i_tmpdir);
132788e61e85SRichard Lowe }
132888e61e85SRichard Lowe
132988e61e85SRichard Lowe (void) closedir(dirp);
133088e61e85SRichard Lowe if (rmdir(ctx->i_tmpdir) != 0) {
133188e61e85SRichard Lowe err(1, "failed to unlink temporary directory: %s",
133288e61e85SRichard Lowe ctx->i_tmpdir);
133388e61e85SRichard Lowe }
133488e61e85SRichard Lowe }
133588e61e85SRichard Lowe
1336aa9ef484SJohn Levon int
main(int argc,char ** argv)1337aa9ef484SJohn Levon main(int argc, char **argv)
1338aa9ef484SJohn Levon {
1339aa9ef484SJohn Levon int ch;
1340aa9ef484SJohn Levon cw_compiler_t primary = { NULL, NULL, 0 };
1341aa9ef484SJohn Levon cw_compiler_t shadows[10];
1342aa9ef484SJohn Levon int nshadows = 0;
1343aa9ef484SJohn Levon int ret = 0;
134422a8b493SToomas Soome bool do_serial;
134522a8b493SToomas Soome bool do_exec;
134622a8b493SToomas Soome bool vflg = false;
134722a8b493SToomas Soome bool Cflg = false;
134822a8b493SToomas Soome bool cflg = false;
134922a8b493SToomas Soome bool nflg = false;
135088e61e85SRichard Lowe char *tmpdir;
1351aa9ef484SJohn Levon
1352aa9ef484SJohn Levon cw_ictx_t *main_ctx;
1353aa9ef484SJohn Levon
1354aa9ef484SJohn Levon static struct option longopts[] = {
1355aa9ef484SJohn Levon { "compiler", no_argument, NULL, 'c' },
135669b1fd3fSRichard Lowe { "linker", required_argument, NULL, 'l' },
1357aa9ef484SJohn Levon { "noecho", no_argument, NULL, 'n' },
1358aa9ef484SJohn Levon { "primary", required_argument, NULL, 'p' },
1359aa9ef484SJohn Levon { "shadow", required_argument, NULL, 's' },
1360aa9ef484SJohn Levon { "versions", no_argument, NULL, 'v' },
1361aa9ef484SJohn Levon { NULL, 0, NULL, 0 },
1362aa9ef484SJohn Levon };
1363aa9ef484SJohn Levon
1364aa9ef484SJohn Levon
1365aa9ef484SJohn Levon if ((main_ctx = newictx()) == NULL)
1366aa9ef484SJohn Levon nomem();
1367aa9ef484SJohn Levon
1368aa9ef484SJohn Levon while ((ch = getopt_long(argc, argv, "C", longopts, NULL)) != -1) {
1369aa9ef484SJohn Levon switch (ch) {
1370aa9ef484SJohn Levon case 'c':
137122a8b493SToomas Soome cflg = true;
1372aa9ef484SJohn Levon break;
1373aa9ef484SJohn Levon case 'C':
137422a8b493SToomas Soome Cflg = true;
1375aa9ef484SJohn Levon break;
137669b1fd3fSRichard Lowe case 'l':
137769b1fd3fSRichard Lowe if ((main_ctx->i_linker = strdup(optarg)) == NULL)
137869b1fd3fSRichard Lowe nomem();
137969b1fd3fSRichard Lowe break;
1380aa9ef484SJohn Levon case 'n':
138122a8b493SToomas Soome nflg = true;
1382aa9ef484SJohn Levon break;
1383aa9ef484SJohn Levon case 'p':
1384aa9ef484SJohn Levon if (primary.c_path != NULL) {
1385aa9ef484SJohn Levon warnx("Only one primary compiler may "
1386aa9ef484SJohn Levon "be specified");
1387aa9ef484SJohn Levon usage();
1388aa9ef484SJohn Levon }
1389aa9ef484SJohn Levon
1390aa9ef484SJohn Levon parse_compiler(optarg, &primary);
1391aa9ef484SJohn Levon break;
1392aa9ef484SJohn Levon case 's':
1393aa9ef484SJohn Levon if (nshadows >= 10)
1394aa9ef484SJohn Levon errx(1, "May only use 10 shadows at "
1395aa9ef484SJohn Levon "the moment");
1396aa9ef484SJohn Levon parse_compiler(optarg, &shadows[nshadows]);
1397aa9ef484SJohn Levon nshadows++;
1398aa9ef484SJohn Levon break;
1399aa9ef484SJohn Levon case 'v':
140022a8b493SToomas Soome vflg = true;
1401aa9ef484SJohn Levon break;
1402aa9ef484SJohn Levon default:
1403aa9ef484SJohn Levon (void) fprintf(stderr, "Did you forget '--'?\n");
1404aa9ef484SJohn Levon usage();
1405aa9ef484SJohn Levon }
1406aa9ef484SJohn Levon }
1407aa9ef484SJohn Levon
1408aa9ef484SJohn Levon if (primary.c_path == NULL) {
1409aa9ef484SJohn Levon warnx("A primary compiler must be specified");
14107c478bd9Sstevel@tonic-gate usage();
14117c478bd9Sstevel@tonic-gate }
14127c478bd9Sstevel@tonic-gate
141322a8b493SToomas Soome do_serial = getenv("CW_SHADOW_SERIAL") != NULL;
141422a8b493SToomas Soome do_exec = getenv("CW_NO_EXEC") == NULL;
1415aa9ef484SJohn Levon
1416aa9ef484SJohn Levon /* Leave room for argv[0] */
1417aa9ef484SJohn Levon argc -= (optind - 1);
1418aa9ef484SJohn Levon argv += (optind - 1);
1419aa9ef484SJohn Levon
1420aa9ef484SJohn Levon main_ctx->i_oldargc = argc;
1421aa9ef484SJohn Levon main_ctx->i_oldargv = argv;
1422aa9ef484SJohn Levon main_ctx->i_flags = CW_F_XLATE;
1423aa9ef484SJohn Levon if (nflg == 0)
1424aa9ef484SJohn Levon main_ctx->i_flags |= CW_F_ECHO;
1425aa9ef484SJohn Levon if (do_exec)
1426aa9ef484SJohn Levon main_ctx->i_flags |= CW_F_EXEC;
1427aa9ef484SJohn Levon if (Cflg)
1428aa9ef484SJohn Levon main_ctx->i_flags |= CW_F_CXX;
1429aa9ef484SJohn Levon main_ctx->i_compiler = &primary;
1430aa9ef484SJohn Levon
1431aa9ef484SJohn Levon if (cflg) {
1432aa9ef484SJohn Levon (void) fputs(primary.c_path, stdout);
14337c478bd9Sstevel@tonic-gate }
14347c478bd9Sstevel@tonic-gate
1435aa9ef484SJohn Levon if (vflg) {
1436aa9ef484SJohn Levon (void) printf("cw version %s\n", CW_VERSION);
14371912d2c4Swesolows (void) fflush(stdout);
1438aa9ef484SJohn Levon main_ctx->i_flags &= ~CW_F_ECHO;
1439aa9ef484SJohn Levon main_ctx->i_flags |= CW_F_PROG | CW_F_EXEC;
14401912d2c4Swesolows do_serial = 1;
14411912d2c4Swesolows }
14421912d2c4Swesolows
144388e61e85SRichard Lowe tmpdir = getenv("TMPDIR");
144488e61e85SRichard Lowe if (tmpdir == NULL)
144588e61e85SRichard Lowe tmpdir = "/tmp";
144688e61e85SRichard Lowe
144788e61e85SRichard Lowe if (asprintf(&main_ctx->i_tmpdir, "%s/cw.XXXXXX", tmpdir) == -1)
144888e61e85SRichard Lowe nomem();
144988e61e85SRichard Lowe
145088e61e85SRichard Lowe if ((main_ctx->i_tmpdir = mkdtemp(main_ctx->i_tmpdir)) == NULL)
145188e61e85SRichard Lowe errx(1, "failed to create temporary directory");
145288e61e85SRichard Lowe
1453aa9ef484SJohn Levon ret |= exec_ctx(main_ctx, do_serial);
14541912d2c4Swesolows
1455aa9ef484SJohn Levon for (int i = 0; i < nshadows; i++) {
1456aa9ef484SJohn Levon int r;
1457aa9ef484SJohn Levon cw_ictx_t *shadow_ctx;
145880ab886dSwesolows
1459aa9ef484SJohn Levon if ((shadow_ctx = newictx()) == NULL)
1460aa9ef484SJohn Levon nomem();
1461aa9ef484SJohn Levon
146288e61e85SRichard Lowe (void) memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
1463aa9ef484SJohn Levon
1464aa9ef484SJohn Levon shadow_ctx->i_flags |= CW_F_SHADOW;
1465aa9ef484SJohn Levon shadow_ctx->i_compiler = &shadows[i];
1466aa9ef484SJohn Levon
1467aa9ef484SJohn Levon r = exec_ctx(shadow_ctx, do_serial);
1468aa9ef484SJohn Levon if (r == 0) {
1469aa9ef484SJohn Levon shadow_ctx->i_next = main_ctx->i_next;
1470aa9ef484SJohn Levon main_ctx->i_next = shadow_ctx;
1471aa9ef484SJohn Levon }
1472aa9ef484SJohn Levon ret |= r;
14737c478bd9Sstevel@tonic-gate }
14747c478bd9Sstevel@tonic-gate
1475aa9ef484SJohn Levon if (!do_serial) {
1476aa9ef484SJohn Levon cw_ictx_t *next = main_ctx;
1477aa9ef484SJohn Levon while (next != NULL) {
1478aa9ef484SJohn Levon cw_ictx_t *toreap = next;
1479aa9ef484SJohn Levon next = next->i_next;
1480aa9ef484SJohn Levon ret |= reap(toreap);
1481aa9ef484SJohn Levon }
1482aa9ef484SJohn Levon }
14837c478bd9Sstevel@tonic-gate
148488e61e85SRichard Lowe cleanup(main_ctx);
148580ab886dSwesolows return (ret);
14867c478bd9Sstevel@tonic-gate }
1487