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