1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014 Gary Mills 24 * 25 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* 30 * Wrapper for the GNU C compiler to make it accept the Sun C compiler 31 * arguments where possible. 32 * 33 * Since the translation is inexact, this is something of a work-in-progress. 34 * 35 */ 36 37 /* If you modify this file, you must increment CW_VERSION */ 38 #define CW_VERSION "1.30" 39 40 /* 41 * -# Verbose mode 42 * -### Show compiler commands built by driver, no compilation 43 * -A<name[(tokens)]> Preprocessor predicate assertion 44 * -B<[static|dynamic]> Specify dynamic or static binding 45 * -C Prevent preprocessor from removing comments 46 * -c Compile only - produce .o files, suppress linking 47 * -cg92 Alias for -xtarget=ss1000 48 * -D<name[=token]> Associate name with token as if by #define 49 * -d[y|n] dynamic [-dy] or static [-dn] option to linker 50 * -E Compile source through preprocessor only, output to stdout 51 * -erroff=<t> Suppress warnings specified by tags t(%none, %all, <tag list>) 52 * -errtags=<a> Display messages with tags a(no, yes) 53 * -errwarn=<t> Treats warnings specified by tags t(%none, %all, <tag list>) 54 * as errors 55 * -fast Optimize using a selection of options 56 * -fd Report old-style function definitions and declarations 57 * -features=zla Allow zero-length arrays 58 * -flags Show this summary of compiler options 59 * -fnonstd Initialize floating-point hardware to non-standard preferences 60 * -fns[=<yes|no>] Select non-standard floating point mode 61 * -fprecision=<p> Set FP rounding precision mode p(single, double, extended) 62 * -fround=<r> Select the IEEE rounding mode in effect at startup 63 * -fsimple[=<n>] Select floating-point optimization preferences <n> 64 * -fsingle Use single-precision arithmetic (-Xt and -Xs modes only) 65 * -ftrap=<t> Select floating-point trapping mode in effect at startup 66 * -fstore force floating pt. values to target precision on assignment 67 * -G Build a dynamic shared library 68 * -g Compile for debugging 69 * -H Print path name of each file included during compilation 70 * -h <name> Assign <name> to generated dynamic shared library 71 * -I<dir> Add <dir> to preprocessor #include file search path 72 * -i Passed to linker to ignore any LD_LIBRARY_PATH setting 73 * -keeptmp Keep temporary files created during compilation 74 * -KPIC Compile position independent code with 32-bit addresses 75 * -Kpic Compile position independent code 76 * -L<dir> Pass to linker to add <dir> to the library search path 77 * -l<name> Link with library lib<name>.a or lib<name>.so 78 * -mc Remove duplicate strings from .comment section of output files 79 * -mr Remove all strings from .comment section of output files 80 * -mr,"string" Remove all strings and append "string" to .comment section 81 * -mt Specify options needed when compiling multi-threaded code 82 * -native Find available processor, generate code accordingly 83 * -nofstore Do not force floating pt. values to target precision 84 * on assignment 85 * -nolib Same as -xnolib 86 * -noqueue Disable queuing of compiler license requests 87 * -norunpath Do not build in a runtime path for shared libraries 88 * -O Use default optimization level (-xO2 or -xO3. Check man page.) 89 * -o <outputfile> Set name of output file to <outputfile> 90 * -P Compile source through preprocessor only, output to .i file 91 * -PIC Alias for -KPIC or -xcode=pic32 92 * -p Compile for profiling with prof 93 * -pic Alias for -Kpic or -xcode=pic13 94 * -Q[y|n] Emit/don't emit identification info to output file 95 * -qp Compile for profiling with prof 96 * -R<dir[:dir]> Build runtime search path list into executable 97 * -S Compile and only generate assembly code (.s) 98 * -s Strip symbol table from the executable file 99 * -t Turn off duplicate symbol warnings when linking 100 * -U<name> Delete initial definition of preprocessor symbol <name> 101 * -V Report version number of each compilation phase 102 * -v Do stricter semantic checking 103 * -W<c>,<arg> Pass <arg> to specified component <c> (a,l,m,p,0,2,h,i,u) 104 * -w Suppress compiler warning messages 105 * -Xa Compile assuming ANSI C conformance, allow K & R extensions 106 * (default mode) 107 * -Xc Compile assuming strict ANSI C conformance 108 * -Xs Compile assuming (pre-ANSI) K & R C style code 109 * -Xt Compile assuming K & R conformance, allow ANSI C 110 * -x386 Generate code for the 80386 processor 111 * -x486 Generate code for the 80486 processor 112 * -xarch=<a> Specify target architecture instruction set 113 * -xbuiltin[=<b>] When profitable inline, or substitute intrinisic functions 114 * for system functions, b={%all,%none} 115 * -xCC Accept C++ style comments 116 * -xchar_byte_order=<o> Specify multi-char byte order <o> (default, high, low) 117 * -xchip=<c> Specify the target processor for use by the optimizer 118 * -xcode=<c> Generate different code for forming addresses 119 * -xcrossfile[=<n>] Enable optimization and inlining across source files, 120 * n={0|1} 121 * -xe Perform only syntax/semantic checking, no code generation 122 * -xF Compile for later mapfile reordering or unused section 123 * elimination 124 * -xhelp=<f> Display on-line help information f(flags, readme, errors) 125 * -xildoff Cancel -xildon 126 * -xildon Enable use of the incremental linker, ild 127 * -xinline=[<a>,...,<a>] Attempt inlining of specified user routines, 128 * <a>={%auto,func,no%func} 129 * -xlibmieee Force IEEE 754 return values for math routines in 130 * exceptional cases 131 * -xlibmil Inline selected libm math routines for optimization 132 * -xlic_lib=sunperf Link in the Sun supplied performance libraries 133 * -xlicinfo Show license server information 134 * -xM Generate makefile dependencies 135 * -xM1 Generate makefile dependencies, but exclude /usr/include 136 * -xmaxopt=[off,1,2,3,4,5] maximum optimization level allowed on #pragma opt 137 * -xnolib Do not link with default system libraries 138 * -xnolibmil Cancel -xlibmil on command line 139 * -xO<n> Generate optimized code (n={1|2|3|4|5}) 140 * -xP Print prototypes for function definitions 141 * -xpentium Generate code for the pentium processor 142 * -xpg Compile for profiling with gprof 143 * -xprofile=<p> Collect data for a profile or use a profile to optimize 144 * <p>={{collect,use}[:<path>],tcov} 145 * -xregs=<r> Control register allocation 146 * -xs Allow debugging without object (.o) files 147 * -xsb Compile for use with the WorkShop source browser 148 * -xsbfast Generate only WorkShop source browser info, no compilation 149 * -xsfpconst Represent unsuffixed floating point constants as single 150 * precision 151 * -xspace Do not do optimizations that increase code size 152 * -xstrconst Place string literals into read-only data segment 153 * -xtarget=<t> Specify target system for optimization 154 * -xtemp=<dir> Set directory for temporary files to <dir> 155 * -xtime Report the execution time for each compilation phase 156 * -xtransition Emit warnings for differences between K&R C and ANSI C 157 * -xtrigraphs[=<yes|no>] Enable|disable trigraph translation 158 * -xunroll=n Enable unrolling loops n times where possible 159 * -Y<c>,<dir> Specify <dir> for location of component <c> (a,l,m,p,0,h,i,u) 160 * -YA,<dir> Change default directory searched for components 161 * -YI,<dir> Change default directory searched for include files 162 * -YP,<dir> Change default directory for finding libraries files 163 * -YS,<dir> Change default directory for startup object files 164 */ 165 166 /* 167 * Translation table: 168 */ 169 /* 170 * -# -v 171 * -### error 172 * -A<name[(tokens)]> pass-thru 173 * -B<[static|dynamic]> pass-thru (syntax error for anything else) 174 * -C pass-thru 175 * -c pass-thru 176 * -cg92 -m32 -mcpu=v8 -mtune=supersparc (SPARC only) 177 * -D<name[=token]> pass-thru 178 * -dy or -dn -Wl,-dy or -Wl,-dn 179 * -E pass-thru 180 * -erroff=E_EMPTY_TRANSLATION_UNIT ignore 181 * -errtags=%all -Wall 182 * -errwarn=%all -Werror else -Wno-error 183 * -fast error 184 * -fd error 185 * -features=zla ignore 186 * -flags --help 187 * -fnonstd error 188 * -fns[=<yes|no>] error 189 * -fprecision=<p> error 190 * -fround=<r> error 191 * -fsimple[=<n>] error 192 * -fsingle[=<n>] error 193 * -ftrap=<t> error 194 * -fstore error 195 * -G pass-thru 196 * -g pass-thru 197 * -H pass-thru 198 * -h <name> pass-thru 199 * -I<dir> pass-thru 200 * -i pass-thru 201 * -keeptmp -save-temps 202 * -KPIC -fPIC 203 * -Kpic -fpic 204 * -L<dir> pass-thru 205 * -l<name> pass-thru 206 * -mc error 207 * -mr error 208 * -mr,"string" error 209 * -mt -D_REENTRANT 210 * -native error 211 * -nofstore error 212 * -nolib -nodefaultlibs 213 * -noqueue ignore 214 * -norunpath ignore 215 * -O -O1 (Check the man page to be certain) 216 * -o <outputfile> pass-thru 217 * -P -E -o filename.i (or error) 218 * -PIC -fPIC (C++ only) 219 * -p pass-thru 220 * -pic -fpic (C++ only) 221 * -Q[y|n] error 222 * -qp -p 223 * -R<dir[:dir]> pass-thru 224 * -S pass-thru 225 * -s -Wl,-s 226 * -t -Wl,-t 227 * -U<name> pass-thru 228 * -V --version 229 * -v -Wall 230 * -Wa,<arg> pass-thru 231 * -Wp,<arg> pass-thru except -xc99=<a> 232 * -Wl,<arg> pass-thru 233 * -W{m,0,2,h,i,u> error/ignore 234 * -Wu,-xmodel=kernel -ffreestanding -mcmodel=kernel -mno-red-zone 235 * -xmodel=kernel -ffreestanding -mcmodel=kernel -mno-red-zone 236 * -Wu,-save_args -msave-args 237 * -w pass-thru 238 * -Xa -std=iso9899:199409 or -ansi 239 * -Xc -ansi -pedantic 240 * -Xt error 241 * -Xs -traditional -std=c89 242 * -x386 -march=i386 (x86 only) 243 * -x486 -march=i486 (x86 only) 244 * -xarch=<a> table 245 * -xbuiltin[=<b>] -fbuiltin (-fno-builtin otherwise) 246 * -xCC ignore 247 * -xchar_byte_order=<o> error 248 * -xchip=<c> table 249 * -xcode=<c> table 250 * -xdebugformat=<format> ignore (always use dwarf-2 for gcc) 251 * -xcrossfile[=<n>] ignore 252 * -xe error 253 * -xF error 254 * -xhelp=<f> error 255 * -xildoff ignore 256 * -xildon ignore 257 * -xinline ignore 258 * -xlibmieee error 259 * -xlibmil error 260 * -xlic_lib=sunperf error 261 * -xM -M 262 * -xM1 -MM 263 * -xmaxopt=[...] error 264 * -xnolib -nodefaultlibs 265 * -xnolibmil error 266 * -xO<n> -O<n> 267 * -xP error 268 * -xpentium -march=pentium (x86 only) 269 * -xpg error 270 * -xprofile=<p> error 271 * -xregs=<r> table 272 * -xs error 273 * -xsb error 274 * -xsbfast error 275 * -xsfpconst error 276 * -xspace ignore (-not -Os) 277 * -xstrconst ignore 278 * -xtarget=<t> table 279 * -xtemp=<dir> error 280 * -xtime error 281 * -xtransition -Wtransition 282 * -xtrigraphs=<yes|no> -trigraphs -notrigraphs 283 * -xunroll=n error 284 * -W0,-xdbggen=no%usedonly -fno-eliminate-unused-debug-symbols 285 * -fno-eliminate-unused-debug-types 286 * -Y<c>,<dir> error 287 * -YA,<dir> error 288 * -YI,<dir> -nostdinc -I<dir> 289 * -YP,<dir> error 290 * -YS,<dir> error 291 */ 292 293 #include <stdio.h> 294 #include <sys/types.h> 295 #include <unistd.h> 296 #include <string.h> 297 #include <stdlib.h> 298 #include <ctype.h> 299 #include <fcntl.h> 300 #include <errno.h> 301 #include <stdarg.h> 302 #include <sys/utsname.h> 303 #include <sys/param.h> 304 #include <sys/isa_defs.h> 305 #include <sys/wait.h> 306 #include <sys/stat.h> 307 308 #define CW_F_CXX 0x01 309 #define CW_F_SHADOW 0x02 310 #define CW_F_EXEC 0x04 311 #define CW_F_ECHO 0x08 312 #define CW_F_XLATE 0x10 313 #define CW_F_PROG 0x20 314 315 typedef enum cw_compiler { 316 CW_C_CC = 0, 317 CW_C_GCC 318 } cw_compiler_t; 319 320 static const char *cmds[] = { 321 "cc", "CC", 322 "gcc", "g++" 323 }; 324 325 static char default_dir[2][MAXPATHLEN] = { 326 DEFAULT_CC_DIR, 327 DEFAULT_GCC_DIR, 328 }; 329 330 #define CC(ctx) \ 331 (((ctx)->i_flags & CW_F_SHADOW) ? \ 332 ((ctx)->i_compiler == CW_C_CC ? CW_C_GCC : CW_C_CC) : \ 333 (ctx)->i_compiler) 334 335 #define CIDX(compiler, flags) \ 336 ((int)(compiler) << 1) + ((flags) & CW_F_CXX ? 1 : 0) 337 338 typedef enum cw_op { 339 CW_O_NONE = 0, 340 CW_O_PREPROCESS, 341 CW_O_COMPILE, 342 CW_O_LINK 343 } cw_op_t; 344 345 struct aelist { 346 struct ae { 347 struct ae *ae_next; 348 char *ae_arg; 349 } *ael_head, *ael_tail; 350 int ael_argc; 351 }; 352 353 typedef struct cw_ictx { 354 cw_compiler_t i_compiler; 355 struct aelist *i_ae; 356 uint32_t i_flags; 357 int i_oldargc; 358 char **i_oldargv; 359 pid_t i_pid; 360 char i_discard[MAXPATHLEN]; 361 char *i_stderr; 362 } cw_ictx_t; 363 364 /* 365 * Status values to indicate which Studio compiler and associated 366 * flags are being used. 367 */ 368 #define M32 0x01 /* -m32 - only on Studio 12 */ 369 #define M64 0x02 /* -m64 - only on Studio 12 */ 370 #define SS11 0x100 /* Studio 11 */ 371 #define SS12 0x200 /* Studio 12 */ 372 373 #define TRANS_ENTRY 5 374 /* 375 * Translation table definition for the -xarch= flag. The "x_arg" 376 * value is translated into the appropriate gcc flags according 377 * to the values in x_trans[n]. The x_flags indicates what compiler 378 * is being used and what flags have been set via the use of 379 * "x_arg". 380 */ 381 typedef struct xarch_table { 382 char *x_arg; 383 int x_flags; 384 char *x_trans[TRANS_ENTRY]; 385 } xarch_table_t; 386 387 /* 388 * The translation table for the -xarch= flag used in the Studio compilers. 389 */ 390 static const xarch_table_t xtbl[] = { 391 #if defined(__x86) 392 { "generic", SS11 }, 393 { "generic64", (SS11|M64), { "-m64", "-mtune=opteron" } }, 394 { "amd64", (SS11|M64), { "-m64", "-mtune=opteron" } }, 395 { "386", SS11, { "-march=i386" } }, 396 { "pentium_pro", SS11, { "-march=pentiumpro" } }, 397 #elif defined(__sparc) 398 { "generic", (SS11|M32), { "-m32", "-mcpu=v8" } }, 399 { "generic64", (SS11|M64), { "-m64", "-mcpu=v9" } }, 400 { "v8", (SS11|M32), { "-m32", "-mcpu=v8", "-mno-v8plus" } }, 401 { "v8plus", (SS11|M32), { "-m32", "-mcpu=v9", "-mv8plus" } }, 402 { "v8plusa", (SS11|M32), { "-m32", "-mcpu=ultrasparc", "-mv8plus", 403 "-mvis" } }, 404 { "v8plusb", (SS11|M32), { "-m32", "-mcpu=ultrasparc3", "-mv8plus", 405 "-mvis" } }, 406 { "v9", (SS11|M64), { "-m64", "-mcpu=v9" } }, 407 { "v9a", (SS11|M64), { "-m64", "-mcpu=ultrasparc", "-mvis" } }, 408 { "v9b", (SS11|M64), { "-m64", "-mcpu=ultrasparc3", "-mvis" } }, 409 { "sparc", SS12, { "-mcpu=v9", "-mv8plus" } }, 410 { "sparcvis", SS12, { "-mcpu=ultrasparc", "-mvis" } }, 411 { "sparcvis2", SS12, { "-mcpu=ultrasparc3", "-mvis" } } 412 #endif 413 }; 414 415 static int xtbl_size = sizeof (xtbl) / sizeof (xarch_table_t); 416 417 static const char *progname; 418 419 static const char *xchip_tbl[] = { 420 #if defined(__x86) 421 "386", "-mtune=i386", NULL, 422 "486", "-mtune=i486", NULL, 423 "pentium", "-mtune=pentium", NULL, 424 "pentium_pro", "-mtune=pentiumpro", NULL, 425 #elif defined(__sparc) 426 "super", "-mtune=supersparc", NULL, 427 "ultra", "-mtune=ultrasparc", NULL, 428 "ultra3", "-mtune=ultrasparc3", NULL, 429 #endif 430 NULL, NULL 431 }; 432 433 static const char *xcode_tbl[] = { 434 #if defined(__sparc) 435 "abs32", "-fno-pic", "-mcmodel=medlow", NULL, 436 "abs44", "-fno-pic", "-mcmodel=medmid", NULL, 437 "abs64", "-fno-pic", "-mcmodel=medany", NULL, 438 "pic13", "-fpic", NULL, 439 "pic32", "-fPIC", NULL, 440 #endif 441 NULL, NULL 442 }; 443 444 static const char *xtarget_tbl[] = { 445 #if defined(__x86) 446 "pentium_pro", "-march=pentiumpro", NULL, 447 #endif /* __x86 */ 448 NULL, NULL 449 }; 450 451 static const char *xregs_tbl[] = { 452 #if defined(__sparc) 453 "appl", "-mapp-regs", NULL, 454 "no%appl", "-mno-app-regs", NULL, 455 "float", "-mfpu", NULL, 456 "no%float", "-mno-fpu", NULL, 457 #endif /* __sparc */ 458 NULL, NULL 459 }; 460 461 static void 462 nomem(void) 463 { 464 (void) fprintf(stderr, "%s: error: out of memory\n", progname); 465 exit(1); 466 } 467 468 static void 469 cw_perror(const char *fmt, ...) 470 { 471 va_list ap; 472 int saved_errno = errno; 473 474 (void) fprintf(stderr, "%s: error: ", progname); 475 476 va_start(ap, fmt); 477 (void) vfprintf(stderr, fmt, ap); 478 va_end(ap); 479 480 (void) fprintf(stderr, " (%s)\n", strerror(saved_errno)); 481 } 482 483 static void 484 newae(struct aelist *ael, const char *arg) 485 { 486 struct ae *ae; 487 488 if ((ae = calloc(sizeof (*ae), 1)) == NULL) 489 nomem(); 490 ae->ae_arg = strdup(arg); 491 if (ael->ael_tail == NULL) 492 ael->ael_head = ae; 493 else 494 ael->ael_tail->ae_next = ae; 495 ael->ael_tail = ae; 496 ael->ael_argc++; 497 } 498 499 static cw_ictx_t * 500 newictx(void) 501 { 502 cw_ictx_t *ctx = calloc(sizeof (cw_ictx_t), 1); 503 if (ctx) 504 if ((ctx->i_ae = calloc(sizeof (struct aelist), 1)) == NULL) { 505 free(ctx); 506 return (NULL); 507 } 508 509 return (ctx); 510 } 511 512 static void 513 error(const char *arg) 514 { 515 (void) fprintf(stderr, 516 "%s: error: mapping failed at or near arg '%s'\n", progname, arg); 517 exit(2); 518 } 519 520 /* 521 * Add the current favourite set of warnings to the gcc invocation. 522 */ 523 static void 524 warnings(struct aelist *h) 525 { 526 static int warningsonce; 527 528 if (warningsonce++) 529 return; 530 531 /* 532 * Enable as many warnings as exist, then disable those that we never 533 * ever want. 534 */ 535 newae(h, "-Wall"); 536 newae(h, "-Wextra"); 537 } 538 539 /* ARGSUSED */ 540 static void 541 Xamode(struct aelist *h) 542 { 543 } 544 545 static void 546 Xcmode(struct aelist *h) 547 { 548 static int xconce; 549 550 if (xconce++) 551 return; 552 553 newae(h, "-ansi"); 554 newae(h, "-pedantic-errors"); 555 } 556 557 static void 558 Xsmode(struct aelist *h) 559 { 560 static int xsonce; 561 562 if (xsonce++) 563 return; 564 565 newae(h, "-traditional"); 566 newae(h, "-traditional-cpp"); 567 } 568 569 static void 570 usage() 571 { 572 (void) fprintf(stderr, 573 "usage: %s { -_cc | -_gcc | -_CC | -_g++ } [ -_compiler | ... ]\n", 574 progname); 575 exit(2); 576 } 577 578 static int 579 xlate_xtb(struct aelist *h, const char *xarg) 580 { 581 int i, j; 582 583 for (i = 0; i < xtbl_size; i++) { 584 if (strcmp(xtbl[i].x_arg, xarg) == 0) 585 break; 586 } 587 588 /* 589 * At the end of the table and so no matching "arg" entry 590 * found and so this must be a bad -xarch= flag. 591 */ 592 if (i == xtbl_size) 593 error(xarg); 594 595 for (j = 0; j < TRANS_ENTRY; j++) { 596 if (xtbl[i].x_trans[j] != NULL) 597 newae(h, xtbl[i].x_trans[j]); 598 else 599 break; 600 } 601 return (xtbl[i].x_flags); 602 603 } 604 605 static void 606 xlate(struct aelist *h, const char *xarg, const char **table) 607 { 608 while (*table != NULL && strcmp(xarg, *table) != 0) { 609 while (*table != NULL) 610 table++; 611 table++; 612 } 613 614 if (*table == NULL) 615 error(xarg); 616 617 table++; 618 619 while (*table != NULL) { 620 newae(h, *table); 621 table++; 622 } 623 } 624 625 static void 626 do_gcc(cw_ictx_t *ctx) 627 { 628 int c; 629 int pic = 0, nolibc = 0; 630 int in_output = 0, seen_o = 0, c_files = 0; 631 cw_op_t op = CW_O_LINK; 632 char *model = NULL; 633 int mflag = 0; 634 635 if (ctx->i_flags & CW_F_PROG) { 636 newae(ctx->i_ae, "--version"); 637 return; 638 } 639 640 newae(ctx->i_ae, "-fident"); 641 newae(ctx->i_ae, "-finline"); 642 newae(ctx->i_ae, "-fno-inline-functions"); 643 newae(ctx->i_ae, "-fno-builtin"); 644 newae(ctx->i_ae, "-fno-asm"); 645 newae(ctx->i_ae, "-fdiagnostics-show-option"); 646 newae(ctx->i_ae, "-nodefaultlibs"); 647 648 #if defined(__sparc) 649 /* 650 * The SPARC ldd and std instructions require 8-byte alignment of 651 * their address operand. gcc correctly uses them only when the 652 * ABI requires 8-byte alignment; unfortunately we have a number of 653 * pieces of buggy code that doesn't conform to the ABI. This 654 * flag makes gcc work more like Studio with -xmemalign=4. 655 */ 656 newae(ctx->i_ae, "-mno-integer-ldd-std"); 657 #endif 658 659 /* 660 * This is needed because 'u' is defined 661 * under a conditional on 'sun'. Should 662 * probably just remove the conditional, 663 * or make it be dependent on '__sun'. 664 * 665 * -Dunix is also missing in enhanced ANSI mode 666 */ 667 newae(ctx->i_ae, "-D__sun"); 668 669 /* 670 * Walk the argument list, translating as we go .. 671 */ 672 673 while (--ctx->i_oldargc > 0) { 674 char *arg = *++ctx->i_oldargv; 675 size_t arglen = strlen(arg); 676 677 if (*arg == '-') { 678 arglen--; 679 } else { 680 /* 681 * Discard inline files that gcc doesn't grok 682 */ 683 if (!in_output && arglen > 3 && 684 strcmp(arg + arglen - 3, ".il") == 0) 685 continue; 686 687 if (!in_output && arglen > 2 && 688 arg[arglen - 2] == '.' && 689 (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' || 690 arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i')) 691 c_files++; 692 693 /* 694 * Otherwise, filenames and partial arguments 695 * are passed through for gcc to chew on. However, 696 * output is always discarded for the secondary 697 * compiler. 698 */ 699 if ((ctx->i_flags & CW_F_SHADOW) && in_output) 700 newae(ctx->i_ae, ctx->i_discard); 701 else 702 newae(ctx->i_ae, arg); 703 in_output = 0; 704 continue; 705 } 706 707 if (ctx->i_flags & CW_F_CXX) { 708 if (strncmp(arg, "-compat=", 8) == 0) { 709 /* discard -compat=4 and -compat=5 */ 710 continue; 711 } 712 if (strcmp(arg, "-Qoption") == 0) { 713 /* discard -Qoption and its two arguments */ 714 if (ctx->i_oldargc < 3) 715 error(arg); 716 ctx->i_oldargc -= 2; 717 ctx->i_oldargv += 2; 718 continue; 719 } 720 if (strcmp(arg, "-xwe") == 0) { 721 /* turn warnings into errors */ 722 newae(ctx->i_ae, "-Werror"); 723 continue; 724 } 725 if (strcmp(arg, "-noex") == 0) { 726 /* no exceptions */ 727 newae(ctx->i_ae, "-fno-exceptions"); 728 /* no run time type descriptor information */ 729 newae(ctx->i_ae, "-fno-rtti"); 730 continue; 731 } 732 if (strcmp(arg, "-pic") == 0) { 733 newae(ctx->i_ae, "-fpic"); 734 pic = 1; 735 continue; 736 } 737 if (strcmp(arg, "-PIC") == 0) { 738 newae(ctx->i_ae, "-fPIC"); 739 pic = 1; 740 continue; 741 } 742 if (strcmp(arg, "-norunpath") == 0) { 743 /* gcc has no corresponding option */ 744 continue; 745 } 746 if (strcmp(arg, "-nolib") == 0) { 747 /* -nodefaultlibs is on by default */ 748 nolibc = 1; 749 continue; 750 } 751 #if defined(__sparc) 752 if (strcmp(arg, "-cg92") == 0) { 753 mflag |= xlate_xtb(ctx->i_ae, "v8"); 754 xlate(ctx->i_ae, "super", xchip_tbl); 755 continue; 756 } 757 #endif /* __sparc */ 758 } 759 760 switch ((c = arg[1])) { 761 case '_': 762 if (strcmp(arg, "-_noecho") == 0) 763 ctx->i_flags &= ~CW_F_ECHO; 764 else if (strncmp(arg, "-_cc=", 5) == 0 || 765 strncmp(arg, "-_CC=", 5) == 0) 766 /* EMPTY */; 767 else if (strncmp(arg, "-_gcc=", 6) == 0 || 768 strncmp(arg, "-_g++=", 6) == 0) 769 newae(ctx->i_ae, arg + 6); 770 else 771 error(arg); 772 break; 773 case '#': 774 if (arglen == 1) { 775 newae(ctx->i_ae, "-v"); 776 break; 777 } 778 error(arg); 779 break; 780 case 'g': 781 newae(ctx->i_ae, "-gdwarf-2"); 782 break; 783 case 'E': 784 if (arglen == 1) { 785 newae(ctx->i_ae, "-xc"); 786 newae(ctx->i_ae, arg); 787 op = CW_O_PREPROCESS; 788 nolibc = 1; 789 break; 790 } 791 error(arg); 792 break; 793 case 'c': 794 case 'S': 795 if (arglen == 1) { 796 op = CW_O_COMPILE; 797 nolibc = 1; 798 } 799 /* FALLTHROUGH */ 800 case 'C': 801 case 'H': 802 case 'p': 803 if (arglen == 1) { 804 newae(ctx->i_ae, arg); 805 break; 806 } 807 error(arg); 808 break; 809 case 'A': 810 case 'h': 811 case 'I': 812 case 'i': 813 case 'L': 814 case 'l': 815 case 'R': 816 case 'U': 817 case 'u': 818 case 'w': 819 newae(ctx->i_ae, arg); 820 break; 821 case 'o': 822 seen_o = 1; 823 if (arglen == 1) { 824 in_output = 1; 825 newae(ctx->i_ae, arg); 826 } else if (ctx->i_flags & CW_F_SHADOW) { 827 newae(ctx->i_ae, "-o"); 828 newae(ctx->i_ae, ctx->i_discard); 829 } else { 830 newae(ctx->i_ae, arg); 831 } 832 break; 833 case 'D': 834 newae(ctx->i_ae, arg); 835 /* 836 * XXX Clearly a hack ... do we need _KADB too? 837 */ 838 if (strcmp(arg, "-D_KERNEL") == 0 || 839 strcmp(arg, "-D_BOOT") == 0) 840 newae(ctx->i_ae, "-ffreestanding"); 841 break; 842 case 'd': 843 if (arglen == 2) { 844 if (strcmp(arg, "-dy") == 0) { 845 newae(ctx->i_ae, "-Wl,-dy"); 846 break; 847 } 848 if (strcmp(arg, "-dn") == 0) { 849 newae(ctx->i_ae, "-Wl,-dn"); 850 break; 851 } 852 } 853 if (strcmp(arg, "-dalign") == 0) { 854 /* 855 * -dalign forces alignment in some cases; 856 * gcc does not need any flag to do this. 857 */ 858 break; 859 } 860 error(arg); 861 break; 862 case 'e': 863 if (strcmp(arg, 864 "-erroff=E_EMPTY_TRANSLATION_UNIT") == 0) { 865 /* 866 * Accept but ignore this -- gcc doesn't 867 * seem to complain about empty translation 868 * units 869 */ 870 break; 871 } 872 /* XX64 -- ignore all -erroff= options, for now */ 873 if (strncmp(arg, "-erroff=", 8) == 0) 874 break; 875 if (strcmp(arg, "-errtags=yes") == 0) { 876 warnings(ctx->i_ae); 877 break; 878 } 879 if (strcmp(arg, "-errwarn=%all") == 0) { 880 newae(ctx->i_ae, "-Werror"); 881 break; 882 } 883 error(arg); 884 break; 885 case 'f': 886 if (strcmp(arg, "-flags") == 0) { 887 newae(ctx->i_ae, "--help"); 888 break; 889 } 890 if (strncmp(arg, "-features=zla", 13) == 0) { 891 /* 892 * Accept but ignore this -- gcc allows 893 * zero length arrays. 894 */ 895 break; 896 } 897 error(arg); 898 break; 899 case 'G': 900 newae(ctx->i_ae, "-shared"); 901 nolibc = 1; 902 break; 903 case 'k': 904 if (strcmp(arg, "-keeptmp") == 0) { 905 newae(ctx->i_ae, "-save-temps"); 906 break; 907 } 908 error(arg); 909 break; 910 case 'K': 911 if (arglen == 1) { 912 if ((arg = *++ctx->i_oldargv) == NULL || 913 *arg == '\0') 914 error("-K"); 915 ctx->i_oldargc--; 916 } else { 917 arg += 2; 918 } 919 if (strcmp(arg, "pic") == 0) { 920 newae(ctx->i_ae, "-fpic"); 921 pic = 1; 922 break; 923 } 924 if (strcmp(arg, "PIC") == 0) { 925 newae(ctx->i_ae, "-fPIC"); 926 pic = 1; 927 break; 928 } 929 error("-K"); 930 break; 931 case 'm': 932 if (strcmp(arg, "-mt") == 0) { 933 newae(ctx->i_ae, "-D_REENTRANT"); 934 break; 935 } 936 if (strcmp(arg, "-m64") == 0) { 937 newae(ctx->i_ae, "-m64"); 938 #if defined(__x86) 939 newae(ctx->i_ae, "-mtune=opteron"); 940 #endif 941 mflag |= M64; 942 break; 943 } 944 if (strcmp(arg, "-m32") == 0) { 945 newae(ctx->i_ae, "-m32"); 946 mflag |= M32; 947 break; 948 } 949 error(arg); 950 break; 951 case 'B': /* linker options */ 952 case 'M': 953 case 'z': 954 { 955 char *opt; 956 size_t len; 957 char *s; 958 959 if (arglen == 1) { 960 opt = *++ctx->i_oldargv; 961 if (opt == NULL || *opt == '\0') 962 error(arg); 963 ctx->i_oldargc--; 964 } else { 965 opt = arg + 2; 966 } 967 len = strlen(opt) + 7; 968 if ((s = malloc(len)) == NULL) 969 nomem(); 970 (void) snprintf(s, len, "-Wl,-%c%s", c, opt); 971 newae(ctx->i_ae, s); 972 free(s); 973 } 974 break; 975 case 'n': 976 if (strcmp(arg, "-noqueue") == 0) { 977 /* 978 * Horrid license server stuff - n/a 979 */ 980 break; 981 } 982 error(arg); 983 break; 984 case 'O': 985 if (arglen == 1) { 986 newae(ctx->i_ae, "-O"); 987 break; 988 } 989 error(arg); 990 break; 991 case 'P': 992 /* 993 * We could do '-E -o filename.i', but that's hard, 994 * and we don't need it for the case that's triggering 995 * this addition. We'll require the user to specify 996 * -o in the Makefile. If they don't they'll find out 997 * in a hurry. 998 */ 999 newae(ctx->i_ae, "-E"); 1000 op = CW_O_PREPROCESS; 1001 nolibc = 1; 1002 break; 1003 case 'q': 1004 if (strcmp(arg, "-qp") == 0) { 1005 newae(ctx->i_ae, "-p"); 1006 break; 1007 } 1008 error(arg); 1009 break; 1010 case 's': 1011 if (arglen == 1) { 1012 newae(ctx->i_ae, "-Wl,-s"); 1013 break; 1014 } 1015 error(arg); 1016 break; 1017 case 't': 1018 if (arglen == 1) { 1019 newae(ctx->i_ae, "-Wl,-t"); 1020 break; 1021 } 1022 error(arg); 1023 break; 1024 case 'V': 1025 if (arglen == 1) { 1026 ctx->i_flags &= ~CW_F_ECHO; 1027 newae(ctx->i_ae, "--version"); 1028 break; 1029 } 1030 error(arg); 1031 break; 1032 case 'v': 1033 if (arglen == 1) { 1034 warnings(ctx->i_ae); 1035 break; 1036 } 1037 error(arg); 1038 break; 1039 case 'W': 1040 if (strncmp(arg, "-Wp,-xc99", 9) == 0) { 1041 /* 1042 * gcc's preprocessor will accept c99 1043 * regardless, so accept and ignore. 1044 */ 1045 break; 1046 } 1047 if (strncmp(arg, "-Wa,", 4) == 0 || 1048 strncmp(arg, "-Wp,", 4) == 0 || 1049 strncmp(arg, "-Wl,", 4) == 0) { 1050 newae(ctx->i_ae, arg); 1051 break; 1052 } 1053 if (strcmp(arg, "-W0,-xc99=pragma") == 0) { 1054 /* (undocumented) enables _Pragma */ 1055 break; 1056 } 1057 if (strcmp(arg, "-W0,-xc99=%none") == 0) { 1058 /* 1059 * This is a polite way of saying 1060 * "no c99 constructs allowed!" 1061 * For now, just accept and ignore this. 1062 */ 1063 break; 1064 } 1065 if (strcmp(arg, "-W0,-noglobal") == 0 || 1066 strcmp(arg, "-W0,-xglobalstatic") == 0) { 1067 /* 1068 * gcc doesn't prefix local symbols 1069 * in debug mode, so this is not needed. 1070 */ 1071 break; 1072 } 1073 if (strcmp(arg, "-W0,-Lt") == 0) { 1074 /* 1075 * Generate tests at the top of loops. 1076 * There is no direct gcc equivalent, ignore. 1077 */ 1078 break; 1079 } 1080 if (strcmp(arg, "-W0,-xdbggen=no%usedonly") == 0) { 1081 newae(ctx->i_ae, 1082 "-fno-eliminate-unused-debug-symbols"); 1083 newae(ctx->i_ae, 1084 "-fno-eliminate-unused-debug-types"); 1085 break; 1086 } 1087 if (strcmp(arg, "-W2,-xwrap_int") == 0) { 1088 /* 1089 * Use the legacy behaviour (pre-SS11) 1090 * for integer wrapping. 1091 * gcc does not need this. 1092 */ 1093 break; 1094 } 1095 if (strcmp(arg, "-W2,-Rcond_elim") == 0) { 1096 /* 1097 * Elimination and expansion of conditionals; 1098 * gcc has no direct equivalent. 1099 */ 1100 break; 1101 } 1102 if (strcmp(arg, "-Wd,-xsafe=unboundsym") == 0) { 1103 /* 1104 * Prevents optimizing away checks for 1105 * unbound weak symbol addresses. gcc does 1106 * not do this, so it's not needed. 1107 */ 1108 break; 1109 } 1110 if (strncmp(arg, "-Wc,-xcode=", 11) == 0) { 1111 xlate(ctx->i_ae, arg + 11, xcode_tbl); 1112 if (strncmp(arg + 11, "pic", 3) == 0) 1113 pic = 1; 1114 break; 1115 } 1116 if (strncmp(arg, "-Wc,-Qiselect", 13) == 0) { 1117 /* 1118 * Prevents insertion of register symbols. 1119 * gcc doesn't do this, so ignore it. 1120 */ 1121 break; 1122 } 1123 if (strcmp(arg, "-Wc,-Qassembler-ounrefsym=0") == 0) { 1124 /* 1125 * Prevents optimizing away of static variables. 1126 * gcc does not do this, so it's not needed. 1127 */ 1128 break; 1129 } 1130 #if defined(__x86) 1131 if (strcmp(arg, "-Wu,-xmodel=kernel") == 0) { 1132 newae(ctx->i_ae, "-ffreestanding"); 1133 newae(ctx->i_ae, "-mno-red-zone"); 1134 model = "-mcmodel=kernel"; 1135 nolibc = 1; 1136 break; 1137 } 1138 if (strcmp(arg, "-Wu,-save_args") == 0) { 1139 newae(ctx->i_ae, "-msave-args"); 1140 break; 1141 } 1142 #endif /* __x86 */ 1143 error(arg); 1144 break; 1145 case 'X': 1146 if (strcmp(arg, "-Xa") == 0 || 1147 strcmp(arg, "-Xt") == 0) { 1148 Xamode(ctx->i_ae); 1149 break; 1150 } 1151 if (strcmp(arg, "-Xc") == 0) { 1152 Xcmode(ctx->i_ae); 1153 break; 1154 } 1155 if (strcmp(arg, "-Xs") == 0) { 1156 Xsmode(ctx->i_ae); 1157 break; 1158 } 1159 error(arg); 1160 break; 1161 case 'x': 1162 if (arglen == 1) 1163 error(arg); 1164 switch (arg[2]) { 1165 #if defined(__x86) 1166 case '3': 1167 if (strcmp(arg, "-x386") == 0) { 1168 newae(ctx->i_ae, "-march=i386"); 1169 break; 1170 } 1171 error(arg); 1172 break; 1173 case '4': 1174 if (strcmp(arg, "-x486") == 0) { 1175 newae(ctx->i_ae, "-march=i486"); 1176 break; 1177 } 1178 error(arg); 1179 break; 1180 #endif /* __x86 */ 1181 case 'a': 1182 if (strncmp(arg, "-xarch=", 7) == 0) { 1183 mflag |= xlate_xtb(ctx->i_ae, arg + 7); 1184 break; 1185 } 1186 error(arg); 1187 break; 1188 case 'b': 1189 if (strncmp(arg, "-xbuiltin=", 10) == 0) { 1190 if (strcmp(arg + 10, "%all")) 1191 newae(ctx->i_ae, "-fbuiltin"); 1192 break; 1193 } 1194 error(arg); 1195 break; 1196 case 'C': 1197 /* Accept C++ style comments -- ignore */ 1198 if (strcmp(arg, "-xCC") == 0) 1199 break; 1200 error(arg); 1201 break; 1202 case 'c': 1203 if (strncmp(arg, "-xc99=%all", 10) == 0) { 1204 newae(ctx->i_ae, "-std=gnu99"); 1205 break; 1206 } 1207 if (strncmp(arg, "-xc99=%none", 11) == 0) { 1208 newae(ctx->i_ae, "-std=gnu89"); 1209 break; 1210 } 1211 if (strncmp(arg, "-xchip=", 7) == 0) { 1212 xlate(ctx->i_ae, arg + 7, xchip_tbl); 1213 break; 1214 } 1215 if (strncmp(arg, "-xcode=", 7) == 0) { 1216 xlate(ctx->i_ae, arg + 7, xcode_tbl); 1217 if (strncmp(arg + 7, "pic", 3) == 0) 1218 pic = 1; 1219 break; 1220 } 1221 if (strncmp(arg, "-xcache=", 8) == 0) 1222 break; 1223 if (strncmp(arg, "-xcrossfile", 11) == 0) 1224 break; 1225 error(arg); 1226 break; 1227 case 'd': 1228 if (strcmp(arg, "-xdepend") == 0) 1229 break; 1230 if (strncmp(arg, "-xdebugformat=", 14) == 0) 1231 break; 1232 error(arg); 1233 break; 1234 case 'F': 1235 /* 1236 * Compile for mapfile reordering, or unused 1237 * section elimination, syntax can be -xF or 1238 * more complex, like -xF=%all -- ignore. 1239 */ 1240 if (strncmp(arg, "-xF", 3) == 0) 1241 break; 1242 error(arg); 1243 break; 1244 case 'i': 1245 if (strncmp(arg, "-xinline", 8) == 0) 1246 /* No inlining; ignore */ 1247 break; 1248 if (strcmp(arg, "-xildon") == 0 || 1249 strcmp(arg, "-xildoff") == 0) 1250 /* No incremental linking; ignore */ 1251 break; 1252 error(arg); 1253 break; 1254 #if defined(__x86) 1255 case 'm': 1256 if (strcmp(arg, "-xmodel=kernel") == 0) { 1257 newae(ctx->i_ae, "-ffreestanding"); 1258 newae(ctx->i_ae, "-mno-red-zone"); 1259 model = "-mcmodel=kernel"; 1260 nolibc = 1; 1261 break; 1262 } 1263 error(arg); 1264 break; 1265 #endif /* __x86 */ 1266 case 'M': 1267 if (strcmp(arg, "-xM") == 0) { 1268 newae(ctx->i_ae, "-M"); 1269 break; 1270 } 1271 if (strcmp(arg, "-xM1") == 0) { 1272 newae(ctx->i_ae, "-MM"); 1273 break; 1274 } 1275 error(arg); 1276 break; 1277 case 'n': 1278 if (strcmp(arg, "-xnolib") == 0) { 1279 nolibc = 1; 1280 break; 1281 } 1282 error(arg); 1283 break; 1284 case 'O': 1285 if (strncmp(arg, "-xO", 3) == 0) { 1286 size_t len = strlen(arg); 1287 char *s; 1288 int c = *(arg + 3); 1289 int level; 1290 1291 if (len != 4 || !isdigit(c)) 1292 error(arg); 1293 1294 if ((s = malloc(len)) == NULL) 1295 nomem(); 1296 1297 level = atoi(arg + 3); 1298 if (level > 5) 1299 error(arg); 1300 (void) snprintf(s, len, "-O%d", level); 1301 newae(ctx->i_ae, s); 1302 free(s); 1303 break; 1304 } 1305 error(arg); 1306 break; 1307 case 'p': 1308 if (strcmp(arg, "-xpentium") == 0) { 1309 newae(ctx->i_ae, "-march=pentium"); 1310 break; 1311 } 1312 if (strcmp(arg, "-xpg") == 0) { 1313 newae(ctx->i_ae, "-pg"); 1314 break; 1315 } 1316 error(arg); 1317 break; 1318 case 'r': 1319 if (strncmp(arg, "-xregs=", 7) == 0) { 1320 xlate(ctx->i_ae, arg + 7, xregs_tbl); 1321 break; 1322 } 1323 error(arg); 1324 break; 1325 case 's': 1326 if (strcmp(arg, "-xs") == 0 || 1327 strcmp(arg, "-xspace") == 0 || 1328 strcmp(arg, "-xstrconst") == 0) 1329 break; 1330 error(arg); 1331 break; 1332 case 't': 1333 if (strcmp(arg, "-xtransition") == 0) { 1334 newae(ctx->i_ae, "-Wtransition"); 1335 break; 1336 } 1337 if (strcmp(arg, "-xtrigraphs=yes") == 0) { 1338 newae(ctx->i_ae, "-trigraphs"); 1339 break; 1340 } 1341 if (strcmp(arg, "-xtrigraphs=no") == 0) { 1342 newae(ctx->i_ae, "-notrigraphs"); 1343 break; 1344 } 1345 if (strncmp(arg, "-xtarget=", 9) == 0) { 1346 xlate(ctx->i_ae, arg + 9, xtarget_tbl); 1347 break; 1348 } 1349 error(arg); 1350 break; 1351 case 'e': 1352 case 'h': 1353 case 'l': 1354 default: 1355 error(arg); 1356 break; 1357 } 1358 break; 1359 case 'Y': 1360 if (arglen == 1) { 1361 if ((arg = *++ctx->i_oldargv) == NULL || 1362 *arg == '\0') 1363 error("-Y"); 1364 ctx->i_oldargc--; 1365 arglen = strlen(arg + 1); 1366 } else { 1367 arg += 2; 1368 } 1369 /* Just ignore -YS,... for now */ 1370 if (strncmp(arg, "S,", 2) == 0) 1371 break; 1372 if (strncmp(arg, "l,", 2) == 0) { 1373 char *s = strdup(arg); 1374 s[0] = '-'; 1375 s[1] = 'B'; 1376 newae(ctx->i_ae, s); 1377 free(s); 1378 break; 1379 } 1380 if (strncmp(arg, "I,", 2) == 0) { 1381 char *s = strdup(arg); 1382 s[0] = '-'; 1383 s[1] = 'I'; 1384 newae(ctx->i_ae, "-nostdinc"); 1385 newae(ctx->i_ae, s); 1386 free(s); 1387 break; 1388 } 1389 error(arg); 1390 break; 1391 case 'Q': 1392 /* 1393 * We could map -Qy into -Wl,-Qy etc. 1394 */ 1395 default: 1396 error(arg); 1397 break; 1398 } 1399 } 1400 1401 if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) && 1402 op != CW_O_PREPROCESS) { 1403 (void) fprintf(stderr, "%s: error: multiple source files are " 1404 "allowed only with -E or -P\n", progname); 1405 exit(2); 1406 } 1407 1408 /* 1409 * Make sure that we do not have any unintended interactions between 1410 * the xarch options passed in and the version of the Studio compiler 1411 * used. 1412 */ 1413 if ((mflag & (SS11|SS12)) == (SS11|SS12)) { 1414 (void) fprintf(stderr, 1415 "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n"); 1416 exit(2); 1417 } 1418 1419 switch (mflag) { 1420 case 0: 1421 /* FALLTHROUGH */ 1422 case M32: 1423 #if defined(__sparc) 1424 /* 1425 * Only -m32 is defined and so put in the missing xarch 1426 * translation. 1427 */ 1428 newae(ctx->i_ae, "-mcpu=v8"); 1429 newae(ctx->i_ae, "-mno-v8plus"); 1430 #endif 1431 break; 1432 case M64: 1433 #if defined(__sparc) 1434 /* 1435 * Only -m64 is defined and so put in the missing xarch 1436 * translation. 1437 */ 1438 newae(ctx->i_ae, "-mcpu=v9"); 1439 #endif 1440 break; 1441 case SS12: 1442 #if defined(__sparc) 1443 /* no -m32/-m64 flag used - this is an error for sparc builds */ 1444 (void) fprintf(stderr, "No -m32/-m64 flag defined\n"); 1445 exit(2); 1446 #endif 1447 break; 1448 case SS11: 1449 /* FALLTHROUGH */ 1450 case (SS11|M32): 1451 case (SS11|M64): 1452 break; 1453 case (SS12|M32): 1454 #if defined(__sparc) 1455 /* 1456 * Need to add in further 32 bit options because with SS12 1457 * the xarch=sparcvis option can be applied to 32 or 64 1458 * bit, and so the translatation table (xtbl) cannot handle 1459 * that. 1460 */ 1461 newae(ctx->i_ae, "-mv8plus"); 1462 #endif 1463 break; 1464 case (SS12|M64): 1465 break; 1466 default: 1467 (void) fprintf(stderr, 1468 "Incompatible -xarch= and/or -m32/-m64 options used.\n"); 1469 exit(2); 1470 } 1471 if (op == CW_O_LINK && (ctx->i_flags & CW_F_SHADOW)) 1472 exit(0); 1473 1474 if (model && !pic) 1475 newae(ctx->i_ae, model); 1476 if (!nolibc) 1477 newae(ctx->i_ae, "-lc"); 1478 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) { 1479 newae(ctx->i_ae, "-o"); 1480 newae(ctx->i_ae, ctx->i_discard); 1481 } 1482 } 1483 1484 static void 1485 do_cc(cw_ictx_t *ctx) 1486 { 1487 int in_output = 0, seen_o = 0; 1488 cw_op_t op = CW_O_LINK; 1489 1490 if (ctx->i_flags & CW_F_PROG) { 1491 newae(ctx->i_ae, "-V"); 1492 return; 1493 } 1494 1495 while (--ctx->i_oldargc > 0) { 1496 char *arg = *++ctx->i_oldargv; 1497 1498 if (*arg != '-') { 1499 if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) { 1500 newae(ctx->i_ae, arg); 1501 } else { 1502 in_output = 0; 1503 newae(ctx->i_ae, ctx->i_discard); 1504 } 1505 continue; 1506 } 1507 switch (*(arg + 1)) { 1508 case '_': 1509 if (strcmp(arg, "-_noecho") == 0) { 1510 ctx->i_flags &= ~CW_F_ECHO; 1511 } else if (strncmp(arg, "-_cc=", 5) == 0 || 1512 strncmp(arg, "-_CC=", 5) == 0) { 1513 newae(ctx->i_ae, arg + 5); 1514 } else if (strncmp(arg, "-_gcc=", 6) != 0 && 1515 strncmp(arg, "-_g++=", 6) != 0) { 1516 (void) fprintf(stderr, 1517 "%s: invalid argument '%s'\n", progname, 1518 arg); 1519 exit(2); 1520 } 1521 break; 1522 case 'V': 1523 ctx->i_flags &= ~CW_F_ECHO; 1524 newae(ctx->i_ae, arg); 1525 break; 1526 case 'o': 1527 seen_o = 1; 1528 if (strlen(arg) == 2) { 1529 in_output = 1; 1530 newae(ctx->i_ae, arg); 1531 } else if (ctx->i_flags & CW_F_SHADOW) { 1532 newae(ctx->i_ae, "-o"); 1533 newae(ctx->i_ae, ctx->i_discard); 1534 } else { 1535 newae(ctx->i_ae, arg); 1536 } 1537 break; 1538 case 'c': 1539 case 'S': 1540 if (strlen(arg) == 2) 1541 op = CW_O_COMPILE; 1542 newae(ctx->i_ae, arg); 1543 break; 1544 case 'E': 1545 case 'P': 1546 if (strlen(arg) == 2) 1547 op = CW_O_PREPROCESS; 1548 /*FALLTHROUGH*/ 1549 default: 1550 newae(ctx->i_ae, arg); 1551 } 1552 } 1553 1554 if ((op == CW_O_LINK || op == CW_O_PREPROCESS) && 1555 (ctx->i_flags & CW_F_SHADOW)) 1556 exit(0); 1557 1558 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) { 1559 newae(ctx->i_ae, "-o"); 1560 newae(ctx->i_ae, ctx->i_discard); 1561 } 1562 } 1563 1564 static void 1565 prepctx(cw_ictx_t *ctx) 1566 { 1567 const char *dir = NULL, *cmd; 1568 char *program = NULL; 1569 size_t len; 1570 1571 switch (CIDX(CC(ctx), ctx->i_flags)) { 1572 case CIDX(CW_C_CC, 0): 1573 program = getenv("CW_CC"); 1574 dir = getenv("CW_CC_DIR"); 1575 break; 1576 case CIDX(CW_C_CC, CW_F_CXX): 1577 program = getenv("CW_CPLUSPLUS"); 1578 dir = getenv("CW_CPLUSPLUS_DIR"); 1579 break; 1580 case CIDX(CW_C_GCC, 0): 1581 program = getenv("CW_GCC"); 1582 dir = getenv("CW_GCC_DIR"); 1583 break; 1584 case CIDX(CW_C_GCC, CW_F_CXX): 1585 program = getenv("CW_GPLUSPLUS"); 1586 dir = getenv("CW_GPLUSPLUS_DIR"); 1587 break; 1588 } 1589 1590 if (program == NULL) { 1591 if (dir == NULL) 1592 dir = default_dir[CC(ctx)]; 1593 cmd = cmds[CIDX(CC(ctx), ctx->i_flags)]; 1594 len = strlen(dir) + strlen(cmd) + 2; 1595 if ((program = malloc(len)) == NULL) 1596 nomem(); 1597 (void) snprintf(program, len, "%s/%s", dir, cmd); 1598 } 1599 1600 newae(ctx->i_ae, program); 1601 1602 if (ctx->i_flags & CW_F_PROG) { 1603 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ? 1604 "shadow" : "primary", program); 1605 (void) fflush(stdout); 1606 } 1607 1608 if (!(ctx->i_flags & CW_F_XLATE)) 1609 return; 1610 1611 switch (CC(ctx)) { 1612 case CW_C_CC: 1613 do_cc(ctx); 1614 break; 1615 case CW_C_GCC: 1616 do_gcc(ctx); 1617 break; 1618 } 1619 } 1620 1621 static int 1622 invoke(cw_ictx_t *ctx) 1623 { 1624 char **newargv; 1625 int ac; 1626 struct ae *a; 1627 1628 if ((newargv = calloc(sizeof (*newargv), ctx->i_ae->ael_argc + 1)) == 1629 NULL) 1630 nomem(); 1631 1632 if (ctx->i_flags & CW_F_ECHO) 1633 (void) fprintf(stderr, "+ "); 1634 1635 for (ac = 0, a = ctx->i_ae->ael_head; a; a = a->ae_next, ac++) { 1636 newargv[ac] = a->ae_arg; 1637 if (ctx->i_flags & CW_F_ECHO) 1638 (void) fprintf(stderr, "%s ", a->ae_arg); 1639 if (a == ctx->i_ae->ael_tail) 1640 break; 1641 } 1642 1643 if (ctx->i_flags & CW_F_ECHO) { 1644 (void) fprintf(stderr, "\n"); 1645 (void) fflush(stderr); 1646 } 1647 1648 if (!(ctx->i_flags & CW_F_EXEC)) 1649 return (0); 1650 1651 /* 1652 * We must fix up the environment here so that the 1653 * dependency files are not trampled by the shadow compiler. 1654 */ 1655 if ((ctx->i_flags & CW_F_SHADOW) && 1656 (unsetenv("SUNPRO_DEPENDENCIES") != 0 || 1657 unsetenv("DEPENDENCIES_OUTPUT") != 0)) { 1658 (void) fprintf(stderr, "error: environment setup failed: %s\n", 1659 strerror(errno)); 1660 return (-1); 1661 } 1662 1663 (void) execv(newargv[0], newargv); 1664 cw_perror("couldn't run %s", newargv[0]); 1665 1666 return (-1); 1667 } 1668 1669 static int 1670 reap(cw_ictx_t *ctx) 1671 { 1672 int status, ret = 0; 1673 char buf[1024]; 1674 struct stat s; 1675 1676 /* 1677 * Only wait for one specific child. 1678 */ 1679 if (ctx->i_pid <= 0) 1680 return (-1); 1681 1682 do { 1683 if (waitpid(ctx->i_pid, &status, 0) < 0) { 1684 cw_perror("cannot reap child"); 1685 return (-1); 1686 } 1687 if (status != 0) { 1688 if (WIFSIGNALED(status)) { 1689 ret = -WTERMSIG(status); 1690 break; 1691 } else if (WIFEXITED(status)) { 1692 ret = WEXITSTATUS(status); 1693 break; 1694 } 1695 } 1696 } while (!WIFEXITED(status) && !WIFSIGNALED(status)); 1697 1698 (void) unlink(ctx->i_discard); 1699 1700 if (stat(ctx->i_stderr, &s) < 0) { 1701 cw_perror("stat failed on child cleanup"); 1702 return (-1); 1703 } 1704 if (s.st_size != 0) { 1705 FILE *f; 1706 1707 if ((f = fopen(ctx->i_stderr, "r")) != NULL) { 1708 while (fgets(buf, sizeof (buf), f)) 1709 (void) fprintf(stderr, "%s", buf); 1710 (void) fflush(stderr); 1711 (void) fclose(f); 1712 } 1713 } 1714 (void) unlink(ctx->i_stderr); 1715 free(ctx->i_stderr); 1716 1717 /* 1718 * cc returns an error code when given -V; we want that to succeed. 1719 */ 1720 if (ctx->i_flags & CW_F_PROG) 1721 return (0); 1722 1723 return (ret); 1724 } 1725 1726 static int 1727 exec_ctx(cw_ictx_t *ctx, int block) 1728 { 1729 char *file; 1730 1731 /* 1732 * To avoid offending cc's sensibilities, the name of its output 1733 * file must end in '.o'. 1734 */ 1735 if ((file = tempnam(NULL, ".cw")) == NULL) { 1736 nomem(); 1737 return (-1); 1738 } 1739 (void) strlcpy(ctx->i_discard, file, MAXPATHLEN); 1740 (void) strlcat(ctx->i_discard, ".o", MAXPATHLEN); 1741 free(file); 1742 1743 if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) { 1744 nomem(); 1745 return (-1); 1746 } 1747 1748 if ((ctx->i_pid = fork()) == 0) { 1749 int fd; 1750 1751 (void) fclose(stderr); 1752 if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL, 1753 0666)) < 0) { 1754 cw_perror("open failed for standard error"); 1755 exit(1); 1756 } 1757 if (dup2(fd, 2) < 0) { 1758 cw_perror("dup2 failed for standard error"); 1759 exit(1); 1760 } 1761 if (fd != 2) 1762 (void) close(fd); 1763 if (freopen("/dev/fd/2", "w", stderr) == NULL) { 1764 cw_perror("freopen failed for /dev/fd/2"); 1765 exit(1); 1766 } 1767 prepctx(ctx); 1768 exit(invoke(ctx)); 1769 } 1770 1771 if (ctx->i_pid < 0) { 1772 cw_perror("fork failed"); 1773 return (1); 1774 } 1775 1776 if (block) 1777 return (reap(ctx)); 1778 1779 return (0); 1780 } 1781 1782 int 1783 main(int argc, char **argv) 1784 { 1785 cw_ictx_t *ctx = newictx(); 1786 cw_ictx_t *ctx_shadow = newictx(); 1787 const char *dir; 1788 int do_serial, do_shadow; 1789 int ret = 0; 1790 1791 if ((progname = strrchr(argv[0], '/')) == NULL) 1792 progname = argv[0]; 1793 else 1794 progname++; 1795 1796 if (ctx == NULL || ctx_shadow == NULL) 1797 nomem(); 1798 1799 ctx->i_flags = CW_F_ECHO|CW_F_XLATE; 1800 1801 /* 1802 * Figure out where to get our tools from. This depends on 1803 * the environment variables set at run time. 1804 */ 1805 if ((dir = getenv("SPRO_VROOT")) != NULL) { 1806 (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN, 1807 "%s/bin", dir); 1808 } else if ((dir = getenv("SPRO_ROOT")) != NULL) { 1809 (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN, 1810 "%s/SS12/bin", dir); 1811 } else if ((dir = getenv("BUILD_TOOLS")) != NULL) { 1812 (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN, 1813 "%s/SUNWspro/SS12/bin", dir); 1814 } 1815 1816 if ((dir = getenv("GCC_ROOT")) != NULL) { 1817 (void) snprintf(default_dir[CW_C_GCC], MAXPATHLEN, 1818 "%s/bin", dir); 1819 } 1820 1821 do_shadow = (getenv("CW_NO_SHADOW") ? 0 : 1); 1822 do_serial = (getenv("CW_SHADOW_SERIAL") ? 1 : 0); 1823 1824 if (getenv("CW_NO_EXEC") == NULL) 1825 ctx->i_flags |= CW_F_EXEC; 1826 1827 /* 1828 * The first argument must be one of "-_cc", "-_gcc", "-_CC", or "-_g++" 1829 */ 1830 if (argc == 1) 1831 usage(); 1832 argc--; 1833 argv++; 1834 if (strcmp(argv[0], "-_cc") == 0) { 1835 ctx->i_compiler = CW_C_CC; 1836 } else if (strcmp(argv[0], "-_gcc") == 0) { 1837 ctx->i_compiler = CW_C_GCC; 1838 } else if (strcmp(argv[0], "-_CC") == 0) { 1839 ctx->i_compiler = CW_C_CC; 1840 ctx->i_flags |= CW_F_CXX; 1841 } else if (strcmp(argv[0], "-_g++") == 0) { 1842 ctx->i_compiler = CW_C_GCC; 1843 ctx->i_flags |= CW_F_CXX; 1844 } else { 1845 /* assume "-_gcc" by default */ 1846 argc++; 1847 argv--; 1848 ctx->i_compiler = CW_C_GCC; 1849 } 1850 1851 /* 1852 * -_compiler - tell us the path to the primary compiler only 1853 */ 1854 if (argc > 1 && strcmp(argv[1], "-_compiler") == 0) { 1855 ctx->i_flags &= ~CW_F_XLATE; 1856 prepctx(ctx); 1857 (void) printf("%s\n", ctx->i_ae->ael_head->ae_arg); 1858 return (0); 1859 } 1860 1861 /* 1862 * -_versions - tell us the cw version, paths to all compilers, and 1863 * ask each for its version if we know how. 1864 */ 1865 if (argc > 1 && strcmp(argv[1], "-_versions") == 0) { 1866 (void) printf("cw version %s", CW_VERSION); 1867 if (!do_shadow) 1868 (void) printf(" (SHADOW MODE DISABLED)"); 1869 (void) printf("\n"); 1870 (void) fflush(stdout); 1871 ctx->i_flags &= ~CW_F_ECHO; 1872 ctx->i_flags |= CW_F_PROG|CW_F_EXEC; 1873 argc--; 1874 argv++; 1875 do_serial = 1; 1876 } 1877 1878 ctx->i_oldargc = argc; 1879 ctx->i_oldargv = argv; 1880 1881 ret |= exec_ctx(ctx, do_serial); 1882 1883 if (do_shadow) { 1884 (void) memcpy(ctx_shadow, ctx, sizeof (cw_ictx_t)); 1885 ctx_shadow->i_flags |= CW_F_SHADOW; 1886 ret |= exec_ctx(ctx_shadow, 1); 1887 } 1888 1889 if (!do_serial) 1890 ret |= reap(ctx); 1891 1892 return (ret); 1893 }