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