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