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