cw.c revision 580:70dfd36fd02c
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 2005 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 118 * -xhelp=<f> Display on-line help information f(flags, readme, errors) 119 * -xildoff Cancel -xildon 120 * -xildon Enable use of the incremental linker, ild 121 * -xinline=[<a>,...,<a>] Attempt inlining of specified user routines, 122 * <a>={%auto,func,no%func} 123 * -xlibmieee Force IEEE 754 return values for math routines in 124 * exceptional cases 125 * -xlibmil Inline selected libm math routines for optimization 126 * -xlic_lib=sunperf Link in the Sun supplied performance libraries 127 * -xlicinfo Show license server information 128 * -xM Generate makefile dependencies 129 * -xM1 Generate makefile dependencies, but exclude /usr/include 130 * -xmaxopt=[off,1,2,3,4,5] maximum optimization level allowed on #pragma opt 131 * -xnolib Do not link with default system libraries 132 * -xnolibmil Cancel -xlibmil on command line 133 * -xO<n> Generate optimized code (n={1|2|3|4|5}) 134 * -xP Print prototypes for function definitions 135 * -xpentium Generate code for the pentium processor 136 * -xpg Compile for profiling with gprof 137 * -xprofile=<p> Collect data for a profile or use a profile to optimize 138 * <p>={{collect,use}[:<path>],tcov} 139 * -xregs=<r> Control register allocation 140 * -xs Allow debugging without object (.o) files 141 * -xsb Compile for use with the WorkShop source browser 142 * -xsbfast Generate only WorkShop source browser info, no compilation 143 * -xsfpconst Represent unsuffixed floating point constants as single 144 * precision 145 * -xspace Do not do optimizations that increase code size 146 * -xstrconst Place string literals into read-only data segment 147 * -xtarget=<t> Specify target system for optimization 148 * -xtemp=<dir> Set directory for temporary files to <dir> 149 * -xtime Report the execution time for each compilation phase 150 * -xtransition Emit warnings for differences between K&R C and ANSI C 151 * -xtrigraphs[=<yes|no>] Enable|disable trigraph translation 152 * -xunroll=n Enable unrolling loops n times where possible 153 * -Y<c>,<dir> Specify <dir> for location of component <c> (a,l,m,p,0,h,i,u) 154 * -YA,<dir> Change default directory searched for components 155 * -YI,<dir> Change default directory searched for include files 156 * -YP,<dir> Change default directory for finding libraries files 157 * -YS,<dir> Change default directory for startup object files 158 */ 159 160/* 161 * Translation table: 162 */ 163/* 164 * -# -v 165 * -### error 166 * -A<name[(tokens)]> pass-thru 167 * -B<[static|dynamic]> pass-thru (syntax error for anything else) 168 * -C pass-thru 169 * -c pass-thru 170 * -cg92 -m32 -mcpu=v8 -mtune=supersparc (SPARC only) 171 * -D<name[=token]> pass-thru 172 * -dy or -dn -Wl,-dy or -Wl,-dn 173 * -E pass-thru 174 * -erroff=E_EMPTY_TRANSLATION_UNIT ignore 175 * -errtags=%all -Wall 176 * -errwarn=%all -Werror else -Wno-error 177 * -fast error 178 * -fd error 179 * -flags --help 180 * -fnonstd error 181 * -fns[=<yes|no>] error 182 * -fprecision=<p> error 183 * -fround=<r> error 184 * -fsimple[=<n>] error 185 * -fsingle[=<n>] error 186 * -ftrap=<t> error 187 * -fstore error 188 * -G pass-thru 189 * -g pass-thru 190 * -H pass-thru 191 * -h <name> pass-thru 192 * -I<dir> pass-thru 193 * -i pass-thru 194 * -keeptmp -save-temps 195 * -KPIC -fPIC 196 * -Kpic -fpic 197 * -L<dir> pass-thru 198 * -l<name> pass-thru 199 * -mc error 200 * -mr error 201 * -mr,"string" error 202 * -mt -D_REENTRANT 203 * -native error 204 * -nofstore error 205 * -nolib -nodefaultlibs 206 * -noqueue ignore 207 * -norunpath ignore 208 * -O -O1 (Check the man page to be certain) 209 * -o <outputfile> pass-thru 210 * -P -E -o filename.i (or error) 211 * -PIC -fPIC (C++ only) 212 * -p pass-thru 213 * -pic -fpic (C++ only) 214 * -Q[y|n] error 215 * -qp -p 216 * -R<dir[:dir]> pass-thru 217 * -S pass-thru 218 * -s -Wl,-s 219 * -t -Wl,-t 220 * -U<name> pass-thru 221 * -V --version 222 * -v -Wall 223 * -Wa,<arg> pass-thru 224 * -Wp,<arg> pass-thru except -xc99=<a> 225 * -Wl,<arg> pass-thru 226 * -W{m,0,2,h,i,u> error/ignore 227 * -Wu,-xmodel=kernel -ffreestanding -mcmodel=kernel -mno-red-zone 228 * -Wu,-save_args -msave-args 229 * -w pass-thru 230 * -Xa -std=iso9899:199409 or -ansi 231 * -Xc -ansi -pedantic 232 * -Xt error 233 * -Xs -traditional -std=c89 234 * -x386 -march=i386 (x86 only) 235 * -x486 -march=i486 (x86 only) 236 * -xarch=<a> table 237 * -xbuiltin[=<b>] -fbuiltin (-fno-builtin otherwise) 238 * -xCC ignore 239 * -xchar_byte_order=<o> error 240 * -xchip=<c> table 241 * -xcode=<c> table 242 * -xdebugformat=<format> ignore (always use dwarf-2 for gcc) 243 * -xcrossfile[=<n>] ignore 244 * -xe error 245 * -xF error 246 * -xhelp=<f> error 247 * -xildoff ignore 248 * -xildon ignore 249 * -xinline ignore 250 * -xlibmieee error 251 * -xlibmil error 252 * -xlic_lib=sunperf error 253 * -xM -M 254 * -xM1 -MM 255 * -xmaxopt=[...] error 256 * -xnolib -nodefaultlibs 257 * -xnolibmil error 258 * -xO<n> -O<n> 259 * -xP error 260 * -xpentium -march=pentium (x86 only) 261 * -xpg error 262 * -xprofile=<p> error 263 * -xregs=<r> table 264 * -xs error 265 * -xsb error 266 * -xsbfast error 267 * -xsfpconst error 268 * -xspace ignore (-not -Os) 269 * -xstrconst ignore 270 * -xtarget=<t> table 271 * -xtemp=<dir> error 272 * -xtime error 273 * -xtransition -Wtransition 274 * -xtrigraphs=<yes|no> -trigraphs -notrigraphs 275 * -xunroll=n error 276 * -W0,-xdbggen=no%usedonly -fno-eliminate-unused-debug-symbols 277 * -fno-eliminate-unused-debug-types 278 * -Y<c>,<dir> error 279 * -YA,<dir> error 280 * -YI,<dir> -nostdinc -I<dir> 281 * -YP,<dir> error 282 * -YS,<dir> error 283 */ 284 285#include <stdio.h> 286#include <sys/types.h> 287#include <unistd.h> 288#include <string.h> 289#include <stdlib.h> 290#include <ctype.h> 291#include <sys/utsname.h> 292#include <sys/param.h> 293#include <sys/isa_defs.h> 294 295static int echo = 1; 296static int newargc; 297static const char *progname; 298 299static char *default_cc_dir; 300static char *default_gcc_dir; 301 302static char *default_cplusplus_dir; 303static char *default_gplusplus_dir; 304 305static const char *xarch_tbl[] = { 306#if defined(__x86) 307 "generic", NULL, 308 "generic64", "-m64", "-mtune=opteron", NULL, 309 "amd64", "-m64", "-mtune=opteron", NULL, 310 "386", "-march=i386", NULL, 311 "pentium_pro", "-march=pentiumpro", NULL, 312#elif defined(__sparc) 313 "generic", "-m32", "-mcpu=v8", NULL, 314 "generic64", "-m64", "-mcpu=v9", NULL, 315 "v8", "-m32", "-mcpu=v8", "-mno-v8plus", NULL, 316 "v8plus", "-m32", "-mcpu=v9", "-mv8plus", NULL, 317 "v8plusa", "-m32", "-mcpu=ultrasparc", "-mv8plus", "-mvis", NULL, 318 "v8plusb", "-m32", "-mcpu=ultrasparc3", "-mv8plus", "-mvis", NULL, 319 "v9", "-m64", "-mcpu=v9", NULL, 320 "v9a", "-m64", "-mcpu=ultrasparc", "-mvis", NULL, 321 "v9b", "-m64", "-mcpu=ultrasparc3", "-mvis", NULL, 322#endif 323 NULL, NULL 324}; 325 326static const char *xchip_tbl[] = { 327#if defined(__x86) 328 "386", "-mtune=i386", NULL, 329 "486", "-mtune=i486", NULL, 330 "pentium", "-mtune=pentium", NULL, 331 "pentium_pro", "-mtune=pentiumpro", NULL, 332#elif defined(__sparc) 333 "super", "-mtune=supersparc", NULL, 334 "ultra", "-mtune=ultrasparc", NULL, 335 "ultra3", "-mtune=ultrasparc3", NULL, 336#endif 337 NULL, NULL 338}; 339 340static const char *xcode_tbl[] = { 341#if defined(__sparc) 342 "abs32", "-fno-pic", "-mcmodel=medlow", NULL, 343 "abs44", "-fno-pic", "-mcmodel=medmid", NULL, 344 "abs64", "-fno-pic", "-mcmodel=medany", NULL, 345 "pic13", "-fpic", NULL, 346 "pic32", "-fPIC", NULL, 347#endif 348 NULL, NULL 349}; 350 351static const char *xtarget_tbl[] = { 352#if defined(__x86) 353 "pentium_pro", "-march=pentiumpro", NULL, 354#endif /* __x86 */ 355 NULL, NULL 356}; 357 358static const char *xregs_tbl[] = { 359#if defined(__sparc) 360 "appl", "-mapp-regs", NULL, 361 "no%appl", "-mno-app-regs", NULL, 362 "float", "-mfpu", NULL, 363 "no%float", "-mno-fpu", NULL, 364#endif /* __sparc */ 365 NULL, NULL 366}; 367 368struct aelist { 369 struct ae { 370 struct ae *ae_next; 371 char *ae_arg; 372 } *ael_head, *ael_tail; 373}; 374 375static struct aelist * 376newael(void) 377{ 378 return (calloc(sizeof (struct aelist), 1)); 379} 380 381static void 382newae(struct aelist *ael, const char *arg) 383{ 384 struct ae *ae; 385 386 ae = calloc(sizeof (*ae), 1); 387 ae->ae_arg = strdup(arg); 388 if (ael->ael_tail == NULL) 389 ael->ael_head = ae; 390 else 391 ael->ael_tail->ae_next = ae; 392 ael->ael_tail = ae; 393 newargc++; 394} 395 396static void 397error(const char *arg) 398{ 399 (void) fprintf(stderr, 400 "%s: mapping failed at or near arg '%s'\n", progname, arg); 401 exit(2); 402} 403 404/* 405 * Add the current favourite set of warnings to the gcc invocation. 406 */ 407static void 408warnings(struct aelist *h) 409{ 410 static int warningsonce; 411 412 if (warningsonce++) 413 return; 414 415 newae(h, "-Wall"); 416 newae(h, "-Wno-unknown-pragmas"); 417 newae(h, "-Wno-missing-braces"); 418 newae(h, "-Wno-sign-compare"); 419 newae(h, "-Wno-parentheses"); 420 newae(h, "-Wno-uninitialized"); 421 newae(h, "-Wno-implicit-function-declaration"); 422 newae(h, "-Wno-unused"); 423 newae(h, "-Wno-trigraphs"); 424 newae(h, "-Wno-char-subscripts"); 425 newae(h, "-Wno-switch"); 426} 427 428static void 429optim_disable(struct aelist *h, int level) 430{ 431 if (level >= 2) { 432 newae(h, "-fno-strict-aliasing"); 433 newae(h, "-fno-unit-at-a-time"); 434 newae(h, "-fno-optimize-sibling-calls"); 435 } 436} 437 438/* ARGSUSED */ 439static void 440Xamode(struct aelist *h) 441{ 442} 443 444static void 445Xcmode(struct aelist *h) 446{ 447 static int xconce; 448 449 if (xconce++) 450 return; 451 452 newae(h, "-ansi"); 453 newae(h, "-pedantic-errors"); 454} 455 456static void 457Xsmode(struct aelist *h) 458{ 459 static int xsonce; 460 461 if (xsonce++) 462 return; 463 464 newae(h, "-traditional"); 465 newae(h, "-traditional-cpp"); 466} 467 468static void 469usage() 470{ 471 (void) fprintf(stderr, 472 "usage: %s { -_cc | -_gcc | -_CC | -_g++ } [ -_compiler | ... ]\n", 473 progname); 474 exit(2); 475} 476 477static void 478xlate(struct aelist *h, const char *xarg, const char **table) 479{ 480 while (*table != NULL && strcmp(xarg, *table) != 0) { 481 while (*table != NULL) 482 table++; 483 table++; 484 } 485 486 if (*table == NULL) 487 error(xarg); 488 489 table++; 490 491 while (*table != NULL) { 492 newae(h, *table); 493 table++; 494 } 495} 496 497static void 498do_gcc(const char *dir, const char *cmd, int argc, char **argv, 499 struct aelist *h, int cplusplus) 500{ 501 int c; 502 int pic = 0; 503 int nolibc = 0; 504 char *model = NULL; 505 char *program; 506 size_t len = strlen(dir) + strlen(cmd) + 2; 507 508 program = malloc(len); 509 (void) snprintf(program, len, "%s/%s", dir, cmd); 510 511 /* 512 * Basic defaults for ON compilation 513 */ 514 newae(h, program); 515 516 newae(h, "-fident"); 517 newae(h, "-finline"); 518 newae(h, "-fno-inline-functions"); 519 newae(h, "-fno-builtin"); 520 newae(h, "-fno-asm"); 521 newae(h, "-nodefaultlibs"); 522 523#if defined(__sparc) 524 /* 525 * The SPARC ldd and std instructions require 8-byte alignment of 526 * their address operand. gcc correctly uses them only when the 527 * ABI requires 8-byte alignment; unfortunately we have a number of 528 * pieces of buggy code that doesn't conform to the ABI. This 529 * flag makes gcc work more like Studio with -xmemalign=4. 530 */ 531 newae(h, "-mno-integer-ldd-std"); 532#endif 533 534 /* 535 * This is needed because 'u' is defined 536 * under a conditional on 'sun'. Should 537 * probably just remove the conditional, 538 * or make it be dependent on '__sun'. 539 * 540 * -Dunix is also missing in enhanced ANSI mode 541 */ 542 newae(h, "-D__sun"); 543 544 /* 545 * Walk the argument list, translating as we go .. 546 */ 547 548 while (--argc > 0) { 549 char *arg = *++argv; 550 size_t arglen = strlen(arg); 551 552 if (*arg == '-') 553 arglen--; 554 else { 555 /* 556 * Discard inline files that gcc doesn't grok 557 */ 558 if (arglen > 3 && 559 strcmp(arg + arglen - 3, ".il") == 0) 560 continue; 561 562 /* 563 * Otherwise, filenames, and partial arguments 564 * are simply passed through for gcc to chew on. 565 */ 566 newae(h, arg); 567 continue; 568 } 569 570 if (cplusplus) { 571 if (strncmp(arg, "-compat=", 8) == 0) { 572 /* discard -compat=4 and -compat=5 */ 573 continue; 574 } 575 if (strcmp(arg, "-Qoption") == 0) { 576 /* discard -Qoption and its two arguments */ 577 if (argc < 3) 578 error(arg); 579 argc -= 2; 580 argv += 2; 581 continue; 582 } 583 if (strcmp(arg, "-xwe") == 0) { 584 /* turn warnings into errors */ 585 /* newae(h, "-Werror"); */ 586 continue; 587 } 588 if (strcmp(arg, "-noex") == 0) { 589 /* no exceptions */ 590 newae(h, "-fno-exceptions"); 591 /* no run time type descriptor information */ 592 newae(h, "-fno-rtti"); 593 continue; 594 } 595 if (strcmp(arg, "-pic") == 0) { 596 newae(h, "-fpic"); 597 pic = 1; 598 continue; 599 } 600 if (strcmp(arg, "-PIC") == 0) { 601 newae(h, "-fPIC"); 602 pic = 1; 603 continue; 604 } 605 if (strcmp(arg, "-norunpath") == 0) { 606 /* gcc has no corresponding option */ 607 continue; 608 } 609 if (strcmp(arg, "-nolib") == 0) { 610 /* -nodefaultlibs is on by default */ 611 nolibc = 1; 612 continue; 613 } 614#if defined(__sparc) 615 if (strcmp(arg, "-cg92") == 0) { 616 xlate(h, "v8", xarch_tbl); 617 xlate(h, "super", xchip_tbl); 618 continue; 619 } 620#endif /* __sparc */ 621 } 622 623 switch ((c = arg[1])) { 624 case '_': 625 if (strcmp(arg, "-_noecho") == 0) 626 echo = 0; 627 else if (strncmp(arg, "-_cc=", 5) == 0 || 628 strncmp(arg, "-_CC=", 5) == 0) 629 /* EMPTY */; 630 else if (strncmp(arg, "-_gcc=", 6) == 0 || 631 strncmp(arg, "-_g++=", 6) == 0) 632 newae(h, arg + 6); 633 else if (strcmp(arg, "-_compiler") == 0) { 634 (void) printf("%s\n", program); 635 exit(0); 636 } else 637 error(arg); 638 break; 639 case '#': 640 if (arglen == 1) { 641 newae(h, "-v"); 642 break; 643 } 644 error(arg); 645 break; 646 case 'g': 647 newae(h, "-gdwarf-2"); 648 break; 649 case 'E': 650 if (arglen == 1) { 651 newae(h, "-xc"); 652 newae(h, arg); 653 nolibc = 1; 654 break; 655 } 656 error(arg); 657 break; 658 case 'c': 659 case 'S': 660 if (arglen == 1) 661 nolibc = 1; 662 /* FALLTHROUGH */ 663 case 'C': 664 case 'H': 665 case 'p': 666 if (arglen == 1) { 667 newae(h, arg); 668 break; 669 } 670 error(arg); 671 break; 672 case 'A': 673 case 'h': 674 case 'I': 675 case 'i': 676 case 'L': 677 case 'l': 678 case 'o': 679 case 'R': 680 case 'U': 681 case 'u': 682 case 'w': 683 newae(h, arg); 684 break; 685 case 'D': 686 newae(h, arg); 687 /* 688 * XXX Clearly a hack ... do we need _KADB too? 689 */ 690 if (strcmp(arg, "-D_KERNEL") == 0 || 691 strcmp(arg, "-D_BOOT") == 0) 692 newae(h, "-ffreestanding"); 693 break; 694 case 'd': 695 if (arglen == 2) { 696 if (strcmp(arg, "-dy") == 0) { 697 newae(h, "-Wl,-dy"); 698 break; 699 } 700 if (strcmp(arg, "-dn") == 0) { 701 newae(h, "-Wl,-dn"); 702 break; 703 } 704 } 705 if (strcmp(arg, "-dalign") == 0) { 706 /* 707 * -dalign forces alignment in some cases; 708 * gcc does not need any flag to do this. 709 */ 710 break; 711 } 712 error(arg); 713 break; 714 case 'e': 715 if (strcmp(arg, 716 "-erroff=E_EMPTY_TRANSLATION_UNIT") == 0) { 717 /* 718 * Accept but ignore this -- gcc doesn't 719 * seem to complain about empty translation 720 * units 721 */ 722 break; 723 } 724 /* XX64 -- ignore all -erroff= options, for now */ 725 if (strncmp(arg, "-erroff=", 8) == 0) 726 break; 727 if (strcmp(arg, "-errtags=yes") == 0) { 728 warnings(h); 729 break; 730 } 731 if (strcmp(arg, "-errwarn=%all") == 0) { 732 newae(h, "-Werror"); 733 break; 734 } 735 error(arg); 736 break; 737 case 'f': 738 if (strcmp(arg, "-flags") == 0) { 739 newae(h, "--help"); 740 break; 741 } 742 error(arg); 743 break; 744 case 'G': 745 newae(h, "-shared"); 746 nolibc = 1; 747 break; 748 case 'k': 749 if (strcmp(arg, "-keeptmp") == 0) { 750 newae(h, "-save-temps"); 751 break; 752 } 753 error(arg); 754 break; 755 case 'K': 756 if (arglen == 1) { 757 if ((arg = *++argv) == NULL || *arg == '\0') 758 error("-K"); 759 argc--; 760 } else { 761 arg += 2; 762 } 763 if (strcmp(arg, "pic") == 0) { 764 newae(h, "-fpic"); 765 pic = 1; 766 break; 767 } 768 if (strcmp(arg, "PIC") == 0) { 769 newae(h, "-fPIC"); 770 pic = 1; 771 break; 772 } 773 error("-K"); 774 break; 775 case 'm': 776 if (strcmp(arg, "-mt") == 0) { 777 newae(h, "-D_REENTRANT"); 778 break; 779 } 780 error(arg); 781 break; 782 case 'B': /* linker options */ 783 case 'M': 784 case 'z': 785 { 786 char *opt; 787 size_t len; 788 char *s; 789 790 if (arglen == 1) { 791 opt = *++argv; 792 if (opt == NULL || *opt == '\0') 793 error(arg); 794 argc--; 795 } else { 796 opt = arg + 2; 797 } 798 len = strlen(opt) + 7; 799 s = malloc(len); 800 (void) snprintf(s, len, "-Wl,-%c%s", c, opt); 801 newae(h, s); 802 free(s); 803 } 804 break; 805 case 'n': 806 if (strcmp(arg, "-noqueue") == 0) { 807 /* 808 * Horrid license server stuff - n/a 809 */ 810 break; 811 } 812 error(arg); 813 break; 814 case 'O': 815 if (arglen == 1) { 816 newae(h, "-O"); 817 break; 818 } 819 error(arg); 820 break; 821 case 'P': 822 /* 823 * We could do '-E -o filename.i', but that's hard, 824 * and we don't need it for the case that's triggering 825 * this addition. We'll require the user to specify 826 * -o in the Makefile. If they don't they'll find out 827 * in a hurry. 828 */ 829 newae(h, "-E"); 830 nolibc = 1; 831 break; 832 case 'q': 833 if (strcmp(arg, "-qp") == 0) { 834 newae(h, "-p"); 835 break; 836 } 837 error(arg); 838 break; 839 case 's': 840 if (arglen == 1) { 841 newae(h, "-Wl,-s"); 842 break; 843 } 844 error(arg); 845 break; 846 case 't': 847 if (arglen == 1) { 848 newae(h, "-Wl,-t"); 849 break; 850 } 851 error(arg); 852 break; 853 case 'V': 854 if (arglen == 1) { 855 echo = 0; 856 newae(h, "--version"); 857 break; 858 } 859 error(arg); 860 break; 861 case 'v': 862 if (arglen == 1) { 863 warnings(h); 864 break; 865 } 866 error(arg); 867 break; 868 case 'W': 869 if (strncmp(arg, "-Wp,-xc99", 9) == 0) { 870 /* 871 * gcc's preprocessor will accept c99 872 * regardless, so accept and ignore. 873 */ 874 break; 875 } 876 if (strncmp(arg, "-Wa,", 4) == 0 || 877 strncmp(arg, "-Wp,", 4) == 0 || 878 strncmp(arg, "-Wl,", 4) == 0) { 879 newae(h, arg); 880 break; 881 } 882 if (strcmp(arg, "-W0,-xc99=pragma") == 0) { 883 /* (undocumented) enables _Pragma */ 884 break; 885 } 886 if (strcmp(arg, "-W0,-xc99=%none") == 0) { 887 /* 888 * This is a polite way of saying 889 * "no c99 constructs allowed!" 890 * For now, just accept and ignore this. 891 */ 892 break; 893 } 894 if (strcmp(arg, "-W0,-noglobal") == 0) { 895 /* 896 * gcc doesn't prefix local symbols 897 * in debug mode, so this is not needed. 898 */ 899 break; 900 } 901 if (strcmp(arg, "-W0,-Lt") == 0) { 902 /* 903 * Generate tests at the top of loops. 904 * There is no direct gcc equivalent, ignore. 905 */ 906 break; 907 } 908 if (strcmp(arg, "-W0,-xdbggen=no%usedonly") == 0) { 909 newae(h, "-fno-eliminate-unused-debug-symbols"); 910 newae(h, "-fno-eliminate-unused-debug-types"); 911 break; 912 } 913 if (strcmp(arg, "-W2,-Rcond_elim") == 0) { 914 /* 915 * Elimination and expansion of conditionals; 916 * gcc has no direct equivalent. 917 */ 918 break; 919 } 920 if (strcmp(arg, "-Wd,-xsafe=unboundsym") == 0) { 921 /* 922 * Prevents optimizing away checks for 923 * unbound weak symbol addresses. gcc does 924 * not do this, so it's not needed. 925 */ 926 break; 927 } 928 if (strncmp(arg, "-Wc,-xcode=", 11) == 0) { 929 xlate(h, arg + 11, xcode_tbl); 930 if (strncmp(arg + 11, "pic", 3) == 0) 931 pic = 1; 932 break; 933 } 934 if (strncmp(arg, "-Wc,-Qiselect", 13) == 0) { 935 /* 936 * Prevents insertion of register symbols. 937 * gcc doesn't do this, so ignore it. 938 */ 939 break; 940 } 941#if defined(__x86) 942 if (strcmp(arg, "-Wu,-no_got_reloc") == 0) { 943 newae(h, "-fno-jump-tables"); 944 newae(h, "-fno-constant-pools"); 945 break; 946 } 947 if (strcmp(arg, "-Wu,-xmodel=kernel") == 0) { 948 newae(h, "-ffreestanding"); 949 newae(h, "-mno-red-zone"); 950 model = "-mcmodel=kernel"; 951 nolibc = 1; 952 break; 953 } 954 if (strcmp(arg, "-Wu,-save_args") == 0) { 955 newae(h, "-msave-args"); 956 break; 957 } 958#endif /* __x86 */ 959 error(arg); 960 break; 961 case 'X': 962 if (strcmp(arg, "-Xa") == 0 || 963 strcmp(arg, "-Xt") == 0) { 964 Xamode(h); 965 break; 966 } 967 if (strcmp(arg, "-Xc") == 0) { 968 Xcmode(h); 969 break; 970 } 971 if (strcmp(arg, "-Xs") == 0) { 972 Xsmode(h); 973 break; 974 } 975 error(arg); 976 break; 977 case 'x': 978 if (arglen == 1) 979 error(arg); 980 switch (arg[2]) { 981#if defined(__x86) 982 case '3': 983 if (strcmp(arg, "-x386") == 0) { 984 newae(h, "-march=i386"); 985 break; 986 } 987 error(arg); 988 break; 989 case '4': 990 if (strcmp(arg, "-x486") == 0) { 991 newae(h, "-march=i486"); 992 break; 993 } 994 error(arg); 995 break; 996#endif /* __x86 */ 997 case 'a': 998 if (strncmp(arg, "-xarch=", 7) == 0) { 999 xlate(h, arg + 7, xarch_tbl); 1000 break; 1001 } 1002 error(arg); 1003 break; 1004 case 'b': 1005 if (strncmp(arg, "-xbuiltin=", 10) == 0) { 1006 if (strcmp(arg + 10, "%all")) 1007 newae(h, "-fbuiltin"); 1008 break; 1009 } 1010 error(arg); 1011 break; 1012 case 'C': 1013 /* Accept C++ style comments -- ignore */ 1014 if (strcmp(arg, "-xCC") == 0) 1015 break; 1016 error(arg); 1017 break; 1018 case 'c': 1019 if (strncmp(arg, "-xc99=%all", 10) == 0) { 1020 newae(h, "-std=gnu99"); 1021 break; 1022 } 1023 if (strncmp(arg, "-xc99=%none", 11) == 0) { 1024 newae(h, "-std=gnu89"); 1025 break; 1026 } 1027 if (strncmp(arg, "-xchip=", 7) == 0) { 1028 xlate(h, arg + 7, xchip_tbl); 1029 break; 1030 } 1031 if (strncmp(arg, "-xcode=", 7) == 0) { 1032 xlate(h, arg + 7, xcode_tbl); 1033 if (strncmp(arg + 7, "pic", 3) == 0) 1034 pic = 1; 1035 break; 1036 } 1037 if (strncmp(arg, "-xcache=", 8) == 0) 1038 break; 1039 if (strncmp(arg, "-xcrossfile", 11) == 0) 1040 break; 1041 error(arg); 1042 break; 1043 case 'd': 1044 if (strcmp(arg, "-xdepend") == 0) 1045 break; 1046 if (strncmp(arg, "-xdebugformat=", 14) == 0) 1047 break; 1048 error(arg); 1049 break; 1050 case 'F': 1051 /* compile for mapfile reordering -- ignore */ 1052 if (strcmp(arg, "-xF") == 0) 1053 break; 1054 error(arg); 1055 break; 1056 case 'i': 1057 if (strncmp(arg, "-xinline", 8) == 0) 1058 /* No inlining; ignore */ 1059 break; 1060 if (strcmp(arg, "-xildon") == 0 || 1061 strcmp(arg, "-xildoff") == 0) 1062 /* No incremental linking; ignore */ 1063 break; 1064 error(arg); 1065 break; 1066 case 'M': 1067 if (strcmp(arg, "-xM") == 0) { 1068 newae(h, "-M"); 1069 break; 1070 } 1071 if (strcmp(arg, "-xM1") == 0) { 1072 newae(h, "-MM"); 1073 break; 1074 } 1075 error(arg); 1076 break; 1077 case 'n': 1078 if (strcmp(arg, "-xnolib") == 0) { 1079 nolibc = 1; 1080 break; 1081 } 1082 error(arg); 1083 break; 1084 case 'O': 1085 if (strncmp(arg, "-xO", 3) == 0) { 1086 size_t len = strlen(arg); 1087 char *s = malloc(len); 1088 int c = *(arg + 3); 1089 int level; 1090 1091 if (len != 4 || !isdigit(c)) 1092 error(arg); 1093 1094 level = atoi(arg + 3); 1095 if (level > 5) 1096 error(arg); 1097 if (level >= 2) { 1098 /* 1099 * For gcc-3.4.x at -O2 we 1100 * need to disable optimizations 1101 * that break ON. 1102 */ 1103 optim_disable(h, level); 1104 /* 1105 * limit -xO3 to -O2 as well. 1106 */ 1107 level = 2; 1108 } 1109 (void) snprintf(s, len, "-O%d", level); 1110 newae(h, s); 1111 free(s); 1112 break; 1113 } 1114 error(arg); 1115 break; 1116 case 'p': 1117 if (strcmp(arg, "-xpentium") == 0) { 1118 newae(h, "-march=pentium"); 1119 break; 1120 } 1121 if (strcmp(arg, "-xpg") == 0) { 1122 newae(h, "-pg"); 1123 break; 1124 } 1125 error(arg); 1126 break; 1127 case 'r': 1128 if (strncmp(arg, "-xregs=", 7) == 0) { 1129 xlate(h, arg + 7, xregs_tbl); 1130 break; 1131 } 1132 error(arg); 1133 break; 1134 case 's': 1135 if (strcmp(arg, "-xs") == 0 || 1136 strcmp(arg, "-xspace") == 0 || 1137 strcmp(arg, "-xstrconst") == 0) 1138 break; 1139 error(arg); 1140 break; 1141 case 't': 1142 if (strcmp(arg, "-xtransition") == 0) { 1143 newae(h, "-Wtransition"); 1144 break; 1145 } 1146 if (strcmp(arg, "-xtrigraphs=yes") == 0) { 1147 newae(h, "-trigraphs"); 1148 break; 1149 } 1150 if (strcmp(arg, "-xtrigraphs=no") == 0) { 1151 newae(h, "-notrigraphs"); 1152 break; 1153 } 1154 if (strncmp(arg, "-xtarget=", 9) == 0) { 1155 xlate(h, arg + 9, xtarget_tbl); 1156 break; 1157 } 1158 error(arg); 1159 break; 1160 case 'e': 1161 case 'h': 1162 case 'l': 1163 default: 1164 error(arg); 1165 break; 1166 } 1167 break; 1168 case 'Y': 1169 if (arglen == 1) { 1170 if ((arg = *++argv) == NULL || *arg == '\0') 1171 error("-Y"); 1172 argc--; 1173 arglen = strlen(arg + 1); 1174 } else { 1175 arg += 2; 1176 } 1177 /* Just ignore -YS,... for now */ 1178 if (strncmp(arg, "S,", 2) == 0) 1179 break; 1180 if (strncmp(arg, "l,", 2) == 0) { 1181 char *s = strdup(arg); 1182 s[0] = '-'; 1183 s[1] = 'B'; 1184 newae(h, s); 1185 free(s); 1186 break; 1187 } 1188 if (strncmp(arg, "I,", 2) == 0) { 1189 char *s = strdup(arg); 1190 s[0] = '-'; 1191 s[1] = 'I'; 1192 newae(h, "-nostdinc"); 1193 newae(h, s); 1194 free(s); 1195 break; 1196 } 1197 error(arg); 1198 break; 1199 case 'Q': 1200 /* 1201 * We could map -Qy into -Wl,-Qy etc. 1202 */ 1203 default: 1204 error(arg); 1205 break; 1206 } 1207 } 1208 1209 if (model && !pic) 1210 newae(h, model); 1211 if (!nolibc) 1212 newae(h, "-lc"); 1213} 1214 1215/* ARGSUSED4 */ 1216static void 1217do_cc(const char *dir, const char *cmd, int argc, char **argv, 1218 struct aelist *h, int cplusplus) 1219{ 1220 char *program; 1221 size_t len = strlen(dir) + strlen(cmd) + 2; 1222 1223 program = malloc(len); 1224 (void) snprintf(program, len, "%s/%s", dir, cmd); 1225 1226 /* 1227 * This is pretty simple. 1228 * We just have to recognize -V, -_noecho, -_compiler, -_cc= and -_gcc= 1229 */ 1230 newae(h, program); 1231 1232 while (--argc > 0) { 1233 char *arg = *++argv; 1234 1235 if (*arg != '-') { 1236 newae(h, arg); 1237 } else if (*(arg + 1) != '_') { 1238 if (strcmp(arg, "-V") == 0) 1239 echo = 0; 1240 newae(h, arg); 1241 } else if (strcmp(arg, "-_noecho") == 0) { 1242 echo = 0; 1243 } else if (strcmp(arg, "-_compiler") == 0) { 1244 (void) printf("%s\n", program); 1245 exit(0); 1246 } else if (strncmp(arg, "-_cc=", 5) == 0 || 1247 strncmp(arg, "-_CC=", 5) == 0) { 1248 newae(h, arg + 5); 1249 } else if (strncmp(arg, "-_gcc=", 6) != 0 && 1250 strncmp(arg, "-_g++=", 6) != 0) { 1251 (void) fprintf(stderr, 1252 "%s: invalid argument '%s'\n", progname, arg); 1253 exit(2); 1254 } 1255 } 1256} 1257 1258int 1259main(int argc, char **argv) 1260{ 1261 struct aelist *h = newael(); 1262 const char *dir; 1263 int ac; 1264 char **newargv; 1265 struct ae *a; 1266 char cc_buf[MAXPATHLEN], gcc_buf[MAXPATHLEN]; 1267 1268 if ((progname = strrchr(argv[0], '/')) == NULL) 1269 progname = argv[0]; 1270 else 1271 progname++; 1272 1273 default_cc_dir = DEFAULT_CC_DIR; 1274 default_gcc_dir = DEFAULT_GCC_DIR; 1275 default_cplusplus_dir = DEFAULT_CPLUSPLUS_DIR; 1276 default_gplusplus_dir = DEFAULT_GPLUSPLUS_DIR; 1277 1278 /* 1279 * Figure out where to get our tools from. This depends on 1280 * the environment variables set at run time. 1281 */ 1282 if ((dir = getenv("SPRO_VROOT")) != NULL) { 1283 (void) snprintf(cc_buf, MAXPATHLEN, "%s/bin", dir); 1284 } else if ((dir = getenv("SPRO_ROOT")) != NULL) { 1285 (void) snprintf(cc_buf, MAXPATHLEN, "%s/SOS10/bin", dir); 1286 } else if ((dir = getenv("BUILD_TOOLS")) != NULL) { 1287 (void) snprintf(cc_buf, MAXPATHLEN, 1288 "%s/SUNWspro/SOS10/bin", dir); 1289 } 1290 if (dir != NULL) 1291 default_cc_dir = (char *)cc_buf; 1292 1293 if ((dir = getenv("GNU_ROOT")) != NULL) { 1294 (void) snprintf(gcc_buf, MAXPATHLEN, "%s/bin", dir); 1295 default_gcc_dir = (char *)gcc_buf; 1296 } 1297 1298 default_cplusplus_dir = default_cc_dir; 1299 default_gplusplus_dir = default_gcc_dir; 1300 1301 /* 1302 * The first argument must be one of "-_cc", "-_gcc", "-_CC", or "-_g++" 1303 */ 1304 if (argc == 1) 1305 usage(); 1306 argc--; 1307 argv++; 1308 if (strcmp(argv[0], "-_cc") == 0) { 1309 if ((dir = getenv("CW_CC_DIR")) == NULL) 1310 dir = default_cc_dir; 1311 do_cc(dir, "cc", argc, argv, h, 0); 1312 } else if (strcmp(argv[0], "-_gcc") == 0) { 1313 if ((dir = getenv("CW_GCC_DIR")) == NULL) 1314 dir = default_gcc_dir; 1315 do_gcc(dir, "gcc", argc, argv, h, 0); 1316 } else if (strcmp(argv[0], "-_CC") == 0) { 1317 if ((dir = getenv("CW_CPLUSPLUS_DIR")) == NULL) 1318 dir = default_cplusplus_dir; 1319 do_cc(dir, "CC", argc, argv, h, 1); 1320 } else if (strcmp(argv[0], "-_g++") == 0) { 1321 if ((dir = getenv("CW_GPLUSPLUS_DIR")) == NULL) 1322 dir = default_gplusplus_dir; 1323 do_gcc(dir, "g++", argc, argv, h, 1); 1324 } else { 1325 /* assume "-_gcc" by default */ 1326 argc++; 1327 argv--; 1328 if ((dir = getenv("CW_GCC_DIR")) == NULL) 1329 dir = default_gcc_dir; 1330 do_gcc(dir, "gcc", argc, argv, h, 0); 1331 } 1332 1333 newargv = calloc(sizeof (*newargv), newargc + 1); 1334 1335 if (echo) 1336 (void) printf("+ "); 1337 1338 for (ac = 0, a = h->ael_head; a; a = a->ae_next, ac++) { 1339 newargv[ac] = a->ae_arg; 1340 if (echo) 1341 (void) printf("%s ", a->ae_arg); 1342 if (a == h->ael_tail) 1343 break; 1344 } 1345 1346 if (echo) { 1347 (void) printf("\n"); 1348 (void) fflush(stdout); 1349 } 1350 1351 /* 1352 * Here goes .. 1353 */ 1354 (void) execvp(newargv[0], newargv); 1355 1356 /* 1357 * execvp() returns only on error. 1358 */ 1359 perror("execvp"); 1360 (void) fprintf(stderr, "%s: couldn't run %s\n", 1361 progname, newargv[0]); 1362 return (4); 1363} 1364