Print this page
9128 cw(1onbld) should be able to run multiple shadows
9129 file-locking tests shouldn't build multiple source files in one compiler invocation
9130 DTrace tst.gcc.d isn't useful
9132 cw(1onbld) shouldn't shadow pure preprocessing
Reviewed by: Andy Fiddaman <omnios@citrus-it.net>

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   * CDDL HEADER START
   3    4   *
   4    5   * The contents of this file are subject to the terms of the
   5    6   * Common Development and Distribution License (the "License").
   6    7   * You may not use this file except in compliance with the License.
   7    8   *
   8    9   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9   10   * or http://www.opensolaris.org/os/licensing.
  10   11   * See the License for the specific language governing permissions
↓ open down ↓ 2 lines elided ↑ open up ↑
  13   14   * When distributing Covered Code, include this CDDL HEADER in each
  14   15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   16   * If applicable, add the following below this CDDL HEADER, with the
  16   17   * fields enclosed by brackets "[]" replaced with your own identifying
  17   18   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   19   *
  19   20   * CDDL HEADER END
  20   21   */
  21   22  
  22   23  /*
  23      - * Copyright 2011, Richard Lowe.
       24 + * Copyright 2018, Richard Lowe.
  24   25   */
  25   26  /*
  26   27   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  27   28   * Use is subject to license terms.
  28   29   */
  29   30  
  30   31  /*
  31   32   * Wrapper for the GNU C compiler to make it accept the Sun C compiler
  32   33   * arguments where possible.
  33   34   *
  34   35   * Since the translation is inexact, this is something of a work-in-progress.
  35   36   *
  36   37   */
  37   38  
  38   39  /* If you modify this file, you must increment CW_VERSION */
  39      -#define CW_VERSION      "1.30"
       40 +#define CW_VERSION      "2.0"
  40   41  
  41   42  /*
  42   43   * -#           Verbose mode
  43   44   * -###         Show compiler commands built by driver, no compilation
  44   45   * -A<name[(tokens)]>   Preprocessor predicate assertion
  45   46   * -B<[static|dynamic]> Specify dynamic or static binding
  46   47   * -C           Prevent preprocessor from removing comments
  47   48   * -c           Compile only - produce .o files, suppress linking
  48   49   * -cg92        Alias for -xtarget=ss1000
  49   50   * -D<name[=token]>     Associate name with token as if by #define
↓ open down ↓ 234 lines elided ↑ open up ↑
 284  285   * -xunroll=n                   error
 285  286   * -W0,-xdbggen=no%usedonly     -fno-eliminate-unused-debug-symbols
 286  287   *                              -fno-eliminate-unused-debug-types
 287  288   * -Y<c>,<dir>                  error
 288  289   * -YA,<dir>                    error
 289  290   * -YI,<dir>                    -nostdinc -I<dir>
 290  291   * -YP,<dir>                    error
 291  292   * -YS,<dir>                    error
 292  293   */
 293  294  
 294      -#include <stdio.h>
 295      -#include <sys/types.h>
 296      -#include <unistd.h>
 297      -#include <string.h>
 298      -#include <stdlib.h>
 299  295  #include <ctype.h>
 300      -#include <fcntl.h>
      296 +#include <err.h>
 301  297  #include <errno.h>
 302      -#include <stdarg.h>
 303      -#include <sys/utsname.h>
      298 +#include <fcntl.h>
      299 +#include <getopt.h>
      300 +#include <stdio.h>
      301 +#include <stdlib.h>
      302 +#include <string.h>
      303 +#include <unistd.h>
      304 +
 304  305  #include <sys/param.h>
 305      -#include <sys/isa_defs.h>
 306      -#include <sys/wait.h>
 307  306  #include <sys/stat.h>
      307 +#include <sys/types.h>
      308 +#include <sys/utsname.h>
      309 +#include <sys/wait.h>
 308  310  
 309  311  #define CW_F_CXX        0x01
 310  312  #define CW_F_SHADOW     0x02
 311  313  #define CW_F_EXEC       0x04
 312  314  #define CW_F_ECHO       0x08
 313  315  #define CW_F_XLATE      0x10
 314  316  #define CW_F_PROG       0x20
 315  317  
 316      -typedef enum cw_compiler {
 317      -        CW_C_CC = 0,
 318      -        CW_C_GCC
 319      -} cw_compiler_t;
 320      -
 321      -static const char *cmds[] = {
 322      -        "cc", "CC",
 323      -        "gcc", "g++"
 324      -};
 325      -
 326      -static char default_dir[2][MAXPATHLEN] = {
 327      -        DEFAULT_CC_DIR,
 328      -        DEFAULT_GCC_DIR,
 329      -};
 330      -
 331      -#define CC(ctx) \
 332      -        (((ctx)->i_flags & CW_F_SHADOW) ? \
 333      -            ((ctx)->i_compiler == CW_C_CC ? CW_C_GCC : CW_C_CC) : \
 334      -            (ctx)->i_compiler)
 335      -
 336      -#define CIDX(compiler, flags)   \
 337      -        ((int)(compiler) << 1) + ((flags) & CW_F_CXX ? 1 : 0)
 338      -
 339  318  typedef enum cw_op {
 340  319          CW_O_NONE = 0,
 341  320          CW_O_PREPROCESS,
 342  321          CW_O_COMPILE,
 343  322          CW_O_LINK
 344  323  } cw_op_t;
 345  324  
 346  325  struct aelist {
 347  326          struct ae {
 348  327                  struct ae *ae_next;
 349  328                  char *ae_arg;
 350  329          } *ael_head, *ael_tail;
 351  330          int ael_argc;
 352  331  };
 353  332  
      333 +typedef enum {
      334 +        GNU,
      335 +        SUN
      336 +} compiler_style_t;
      337 +
      338 +typedef struct {
      339 +        char *c_name;
      340 +        char *c_path;
      341 +        compiler_style_t c_style;
      342 +} cw_compiler_t;
      343 +
 354  344  typedef struct cw_ictx {
 355      -        cw_compiler_t   i_compiler;
      345 +        struct cw_ictx  *i_next;
      346 +        cw_compiler_t   *i_compiler;
 356  347          struct aelist   *i_ae;
 357  348          uint32_t        i_flags;
 358  349          int             i_oldargc;
 359  350          char            **i_oldargv;
 360  351          pid_t           i_pid;
 361  352          char            i_discard[MAXPATHLEN];
 362  353          char            *i_stderr;
 363  354  } cw_ictx_t;
 364  355  
 365  356  /*
↓ open down ↓ 17 lines elided ↑ open up ↑
 383  374          char    *x_arg;
 384  375          int     x_flags;
 385  376          char    *x_trans[TRANS_ENTRY];
 386  377  } xarch_table_t;
 387  378  
 388  379  /*
 389  380   * The translation table for the -xarch= flag used in the Studio compilers.
 390  381   */
 391  382  static const xarch_table_t xtbl[] = {
 392  383  #if defined(__x86)
 393      -        { "generic",    SS11 },
      384 +        { "generic",    SS11, {NULL} },
 394  385          { "generic64",  (SS11|M64), { "-m64", "-mtune=opteron" } },
 395  386          { "amd64",      (SS11|M64), { "-m64", "-mtune=opteron" } },
 396  387          { "386",        SS11,   { "-march=i386" } },
 397  388          { "pentium_pro", SS11,  { "-march=pentiumpro" } },
 398  389          { "sse",        SS11, { "-msse", "-mfpmath=sse" } },
 399  390          { "sse2",       SS11, { "-msse2", "-mfpmath=sse" } },
 400  391  #elif defined(__sparc)
 401  392          { "generic",    (SS11|M32), { "-m32", "-mcpu=v8" } },
 402  393          { "generic64",  (SS11|M64), { "-m64", "-mcpu=v9" } },
 403  394          { "v8",         (SS11|M32), { "-m32", "-mcpu=v8", "-mno-v8plus" } },
↓ open down ↓ 6 lines elided ↑ open up ↑
 410  401          { "v9a",        (SS11|M64), { "-m64", "-mcpu=ultrasparc", "-mvis" } },
 411  402          { "v9b",        (SS11|M64), { "-m64", "-mcpu=ultrasparc3", "-mvis" } },
 412  403          { "sparc",      SS12, { "-mcpu=v9", "-mv8plus" } },
 413  404          { "sparcvis",   SS12, { "-mcpu=ultrasparc", "-mvis" } },
 414  405          { "sparcvis2",  SS12, { "-mcpu=ultrasparc3", "-mvis" } }
 415  406  #endif
 416  407  };
 417  408  
 418  409  static int xtbl_size = sizeof (xtbl) / sizeof (xarch_table_t);
 419  410  
 420      -static const char *progname;
 421      -
 422  411  static const char *xchip_tbl[] = {
 423  412  #if defined(__x86)
 424  413          "386",          "-mtune=i386", NULL,
 425  414          "486",          "-mtune=i486", NULL,
 426  415          "pentium",      "-mtune=pentium", NULL,
 427  416          "pentium_pro",  "-mtune=pentiumpro", NULL,
 428  417  #elif defined(__sparc)
 429  418          "super",        "-mtune=supersparc", NULL,
 430  419          "ultra",        "-mtune=ultrasparc", NULL,
 431  420          "ultra3",       "-mtune=ultrasparc3", NULL,
↓ open down ↓ 25 lines elided ↑ open up ↑
 457  446          "no%appl",      "-mno-app-regs", NULL,
 458  447          "float",        "-mfpu", NULL,
 459  448          "no%float",     "-mno-fpu", NULL,
 460  449  #endif  /* __sparc */
 461  450          NULL,           NULL
 462  451  };
 463  452  
 464  453  static void
 465  454  nomem(void)
 466  455  {
 467      -        (void) fprintf(stderr, "%s: error: out of memory\n", progname);
 468      -        exit(1);
      456 +        errx(1, "out of memory");
 469  457  }
 470  458  
 471  459  static void
 472      -cw_perror(const char *fmt, ...)
 473      -{
 474      -        va_list ap;
 475      -        int saved_errno = errno;
 476      -
 477      -        (void) fprintf(stderr, "%s: error: ", progname);
 478      -
 479      -        va_start(ap, fmt);
 480      -        (void) vfprintf(stderr, fmt, ap);
 481      -        va_end(ap);
 482      -
 483      -        (void) fprintf(stderr, " (%s)\n", strerror(saved_errno));
 484      -}
 485      -
 486      -static void
 487  460  newae(struct aelist *ael, const char *arg)
 488  461  {
 489  462          struct ae *ae;
 490  463  
 491  464          if ((ae = calloc(sizeof (*ae), 1)) == NULL)
 492  465                  nomem();
 493  466          ae->ae_arg = strdup(arg);
 494  467          if (ael->ael_tail == NULL)
 495  468                  ael->ael_head = ae;
 496  469          else
↓ open down ↓ 11 lines elided ↑ open up ↑
 508  481                          free(ctx);
 509  482                          return (NULL);
 510  483                  }
 511  484  
 512  485          return (ctx);
 513  486  }
 514  487  
 515  488  static void
 516  489  error(const char *arg)
 517  490  {
 518      -        (void) fprintf(stderr,
 519      -            "%s: error: mapping failed at or near arg '%s'\n", progname, arg);
 520      -        exit(2);
      491 +        errx(2, "error: mapping failed at or near arg '%s'", arg);
 521  492  }
 522  493  
 523  494  /*
 524  495   * Add the current favourite set of warnings to the gcc invocation.
 525  496   */
 526  497  static void
 527  498  warnings(struct aelist *h)
 528  499  {
 529  500          static int warningsonce;
 530  501  
↓ open down ↓ 13 lines elided ↑ open up ↑
 544  515  {
 545  516          if (level >= 2) {
 546  517                  newae(h, "-fno-strict-aliasing");
 547  518                  newae(h, "-fno-unit-at-a-time");
 548  519                  newae(h, "-fno-optimize-sibling-calls");
 549  520          }
 550  521  }
 551  522  
 552  523  /* ARGSUSED */
 553  524  static void
 554      -Xamode(struct aelist *h)
      525 +Xamode(struct aelist __unused *h)
 555  526  {
 556  527  }
 557  528  
 558  529  static void
 559  530  Xcmode(struct aelist *h)
 560  531  {
 561  532          static int xconce;
 562  533  
 563  534          if (xconce++)
 564  535                  return;
↓ open down ↓ 10 lines elided ↑ open up ↑
 575  546          if (xsonce++)
 576  547                  return;
 577  548  
 578  549          newae(h, "-traditional");
 579  550          newae(h, "-traditional-cpp");
 580  551  }
 581  552  
 582  553  static void
 583  554  usage()
 584  555  {
      556 +        extern char *__progname;
 585  557          (void) fprintf(stderr,
 586      -            "usage: %s { -_cc | -_gcc | -_CC | -_g++ } [ -_compiler | ... ]\n",
 587      -            progname);
      558 +            "usage: %s [-C] [--versions] --primary <compiler> "
      559 +            "[--shadow <compiler>]... -- cflags...\n",
      560 +            __progname);
      561 +        (void) fprintf(stderr, "compilers take the form: name,path,style\n"
      562 +            " - name: a unique name usable in flag specifiers\n"
      563 +            " - path: path to the compiler binary\n"
      564 +            " - style: the style of flags expected: either sun or gnu\n");
 588  565          exit(2);
 589  566  }
 590  567  
 591  568  static int
 592  569  xlate_xtb(struct aelist *h, const char *xarg)
 593  570  {
 594  571          int     i, j;
 595  572  
 596  573          for (i = 0; i < xtbl_size; i++) {
 597  574                  if (strcmp(xtbl[i].x_arg, xarg) == 0)
↓ open down ↓ 38 lines elided ↑ open up ↑
 636  613  }
 637  614  
 638  615  static void
 639  616  do_gcc(cw_ictx_t *ctx)
 640  617  {
 641  618          int c;
 642  619          int pic = 0, nolibc = 0;
 643  620          int in_output = 0, seen_o = 0, c_files = 0;
 644  621          cw_op_t op = CW_O_LINK;
 645  622          char *model = NULL;
      623 +        char *nameflag;
 646  624          int     mflag = 0;
 647  625  
 648  626          if (ctx->i_flags & CW_F_PROG) {
 649  627                  newae(ctx->i_ae, "--version");
 650  628                  return;
 651  629          }
 652  630  
 653  631          newae(ctx->i_ae, "-fident");
 654  632          newae(ctx->i_ae, "-finline");
 655  633          newae(ctx->i_ae, "-fno-inline-functions");
↓ open down ↓ 16 lines elided ↑ open up ↑
 672  650          /*
 673  651           * This is needed because 'u' is defined
 674  652           * under a conditional on 'sun'.  Should
 675  653           * probably just remove the conditional,
 676  654           * or make it be dependent on '__sun'.
 677  655           *
 678  656           * -Dunix is also missing in enhanced ANSI mode
 679  657           */
 680  658          newae(ctx->i_ae, "-D__sun");
 681  659  
      660 +        if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
      661 +                nomem();
      662 +
 682  663          /*
 683  664           * Walk the argument list, translating as we go ..
 684  665           */
 685      -
 686  666          while (--ctx->i_oldargc > 0) {
 687  667                  char *arg = *++ctx->i_oldargv;
 688  668                  size_t arglen = strlen(arg);
 689  669  
 690  670                  if (*arg == '-') {
 691  671                          arglen--;
 692  672                  } else {
 693  673                          /*
 694  674                           * Discard inline files that gcc doesn't grok
 695  675                           */
↓ open down ↓ 15 lines elided ↑ open up ↑
 711  691                           */
 712  692                          if ((ctx->i_flags & CW_F_SHADOW) && in_output)
 713  693                                  newae(ctx->i_ae, ctx->i_discard);
 714  694                          else
 715  695                                  newae(ctx->i_ae, arg);
 716  696                          in_output = 0;
 717  697                          continue;
 718  698                  }
 719  699  
 720  700                  if (ctx->i_flags & CW_F_CXX) {
      701 +                        if (strncmp(arg, "-_g++=", 6) == 0) {
      702 +                                newae(ctx->i_ae, strchr(arg, '=') + 1);
      703 +                                continue;
      704 +                        }
 721  705                          if (strncmp(arg, "-compat=", 8) == 0) {
 722  706                                  /* discard -compat=4 and -compat=5 */
 723  707                                  continue;
 724  708                          }
 725  709                          if (strcmp(arg, "-Qoption") == 0) {
 726  710                                  /* discard -Qoption and its two arguments */
 727  711                                  if (ctx->i_oldargc < 3)
 728  712                                          error(arg);
 729  713                                  ctx->i_oldargc -= 2;
 730  714                                  ctx->i_oldargv += 2;
↓ open down ↓ 34 lines elided ↑ open up ↑
 765  749                          if (strcmp(arg, "-cg92") == 0) {
 766  750                                  mflag |= xlate_xtb(ctx->i_ae, "v8");
 767  751                                  xlate(ctx->i_ae, "super", xchip_tbl);
 768  752                                  continue;
 769  753                          }
 770  754  #endif  /* __sparc */
 771  755                  }
 772  756  
 773  757                  switch ((c = arg[1])) {
 774  758                  case '_':
 775      -                        if (strcmp(arg, "-_noecho") == 0)
 776      -                                ctx->i_flags &= ~CW_F_ECHO;
 777      -                        else if (strncmp(arg, "-_cc=", 5) == 0 ||
 778      -                            strncmp(arg, "-_CC=", 5) == 0)
 779      -                                /* EMPTY */;
 780      -                        else if (strncmp(arg, "-_gcc=", 6) == 0 ||
 781      -                            strncmp(arg, "-_g++=", 6) == 0)
 782      -                                newae(ctx->i_ae, arg + 6);
 783      -                        else
 784      -                                error(arg);
      759 +                        if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
      760 +                            (strncmp(arg, "-_gcc=", 6) == 0) ||
      761 +                            (strncmp(arg, "-_gnu=", 6) == 0)) {
      762 +                                newae(ctx->i_ae, strchr(arg, '=') + 1);
      763 +                        }
 785  764                          break;
 786  765                  case '#':
 787  766                          if (arglen == 1) {
 788  767                                  newae(ctx->i_ae, "-v");
 789  768                                  break;
 790  769                          }
 791  770                          error(arg);
 792  771                          break;
 793  772                  case 'g':
 794  773                          newae(ctx->i_ae, "-gdwarf-2");
↓ open down ↓ 619 lines elided ↑ open up ↑
1414 1393                  case 'Q':
1415 1394                          /*
1416 1395                           * We could map -Qy into -Wl,-Qy etc.
1417 1396                           */
1418 1397                  default:
1419 1398                          error(arg);
1420 1399                          break;
1421 1400                  }
1422 1401          }
1423 1402  
     1403 +        free(nameflag);
     1404 +
1424 1405          if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1425 1406              op != CW_O_PREPROCESS) {
1426      -                (void) fprintf(stderr, "%s: error: multiple source files are "
1427      -                    "allowed only with -E or -P\n", progname);
1428      -                exit(2);
     1407 +                errx(2, "multiple source files are "
     1408 +                    "allowed only with -E or -P");
1429 1409          }
1430 1410  
1431 1411          /*
1432 1412           * Make sure that we do not have any unintended interactions between
1433 1413           * the xarch options passed in and the version of the Studio compiler
1434 1414           * used.
1435 1415           */
1436 1416          if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1437      -                (void) fprintf(stderr,
     1417 +                errx(2,
1438 1418                      "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1439      -                exit(2);
1440 1419          }
1441 1420  
1442 1421          switch (mflag) {
1443 1422          case 0:
1444 1423                  /* FALLTHROUGH */
1445 1424          case M32:
1446 1425  #if defined(__sparc)
1447 1426                  /*
1448 1427                   * Only -m32 is defined and so put in the missing xarch
1449 1428                   * translation.
↓ open down ↓ 34 lines elided ↑ open up ↑
1484 1463                  newae(ctx->i_ae, "-mv8plus");
1485 1464  #endif
1486 1465                  break;
1487 1466          case (SS12|M64):
1488 1467                  break;
1489 1468          default:
1490 1469                  (void) fprintf(stderr,
1491 1470                      "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1492 1471                  exit(2);
1493 1472          }
1494      -        if (op == CW_O_LINK && (ctx->i_flags & CW_F_SHADOW))
     1473 +
     1474 +        if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
     1475 +            (ctx->i_flags & CW_F_SHADOW))
1495 1476                  exit(0);
1496 1477  
1497 1478          if (model && !pic)
1498 1479                  newae(ctx->i_ae, model);
1499 1480          if (!nolibc)
1500 1481                  newae(ctx->i_ae, "-lc");
1501 1482          if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1502 1483                  newae(ctx->i_ae, "-o");
1503 1484                  newae(ctx->i_ae, ctx->i_discard);
1504 1485          }
1505 1486  }
1506 1487  
1507 1488  static void
1508 1489  do_cc(cw_ictx_t *ctx)
1509 1490  {
1510 1491          int in_output = 0, seen_o = 0;
1511 1492          cw_op_t op = CW_O_LINK;
     1493 +        char *nameflag;
1512 1494  
1513 1495          if (ctx->i_flags & CW_F_PROG) {
1514 1496                  newae(ctx->i_ae, "-V");
1515 1497                  return;
1516 1498          }
1517 1499  
     1500 +        if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
     1501 +                nomem();
     1502 +
1518 1503          while (--ctx->i_oldargc > 0) {
1519 1504                  char *arg = *++ctx->i_oldargv;
1520 1505  
     1506 +                if (strncmp(arg, "-_CC=", 5) == 0) {
     1507 +                        newae(ctx->i_ae, strchr(arg, '=') + 1);
     1508 +                        continue;
     1509 +                }
     1510 +
1521 1511                  if (*arg != '-') {
1522 1512                          if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1523 1513                                  newae(ctx->i_ae, arg);
1524 1514                          } else {
1525 1515                                  in_output = 0;
1526 1516                                  newae(ctx->i_ae, ctx->i_discard);
1527 1517                          }
1528 1518                          continue;
1529 1519                  }
1530 1520                  switch (*(arg + 1)) {
1531 1521                  case '_':
1532      -                        if (strcmp(arg, "-_noecho") == 0) {
1533      -                                ctx->i_flags &= ~CW_F_ECHO;
1534      -                        } else if (strncmp(arg, "-_cc=", 5) == 0 ||
1535      -                            strncmp(arg, "-_CC=", 5) == 0) {
1536      -                                newae(ctx->i_ae, arg + 5);
1537      -                        } else if (strncmp(arg, "-_gcc=", 6) != 0 &&
1538      -                            strncmp(arg, "-_g++=", 6) != 0) {
1539      -                                (void) fprintf(stderr,
1540      -                                    "%s: invalid argument '%s'\n", progname,
1541      -                                    arg);
1542      -                                exit(2);
     1522 +                        if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
     1523 +                            (strncmp(arg, "-_cc=", 5) == 0) ||
     1524 +                            (strncmp(arg, "-_sun=", 6) == 0)) {
     1525 +                                newae(ctx->i_ae, strchr(arg, '=') + 1);
1543 1526                          }
1544 1527                          break;
     1528 +
1545 1529                  case 'V':
1546 1530                          ctx->i_flags &= ~CW_F_ECHO;
1547 1531                          newae(ctx->i_ae, arg);
1548 1532                          break;
1549 1533                  case 'o':
1550 1534                          seen_o = 1;
1551 1535                          if (strlen(arg) == 2) {
1552 1536                                  in_output = 1;
1553 1537                                  newae(ctx->i_ae, arg);
1554 1538                          } else if (ctx->i_flags & CW_F_SHADOW) {
↓ open down ↓ 12 lines elided ↑ open up ↑
1567 1551                  case 'E':
1568 1552                  case 'P':
1569 1553                          if (strlen(arg) == 2)
1570 1554                                  op = CW_O_PREPROCESS;
1571 1555                  /*FALLTHROUGH*/
1572 1556                  default:
1573 1557                          newae(ctx->i_ae, arg);
1574 1558                  }
1575 1559          }
1576 1560  
     1561 +        free(nameflag);
     1562 +
1577 1563          if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1578 1564              (ctx->i_flags & CW_F_SHADOW))
1579 1565                  exit(0);
1580 1566  
1581 1567          if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1582 1568                  newae(ctx->i_ae, "-o");
1583 1569                  newae(ctx->i_ae, ctx->i_discard);
1584 1570          }
1585 1571  }
1586 1572  
1587 1573  static void
1588 1574  prepctx(cw_ictx_t *ctx)
1589 1575  {
1590      -        const char *dir = NULL, *cmd;
1591      -        char *program = NULL;
1592      -        size_t len;
     1576 +        newae(ctx->i_ae, ctx->i_compiler->c_path);
1593 1577  
1594      -        switch (CIDX(CC(ctx), ctx->i_flags)) {
1595      -                case CIDX(CW_C_CC, 0):
1596      -                        program = getenv("CW_CC");
1597      -                        dir = getenv("CW_CC_DIR");
1598      -                        break;
1599      -                case CIDX(CW_C_CC, CW_F_CXX):
1600      -                        program = getenv("CW_CPLUSPLUS");
1601      -                        dir = getenv("CW_CPLUSPLUS_DIR");
1602      -                        break;
1603      -                case CIDX(CW_C_GCC, 0):
1604      -                        program = getenv("CW_GCC");
1605      -                        dir = getenv("CW_GCC_DIR");
1606      -                        break;
1607      -                case CIDX(CW_C_GCC, CW_F_CXX):
1608      -                        program = getenv("CW_GPLUSPLUS");
1609      -                        dir = getenv("CW_GPLUSPLUS_DIR");
1610      -                        break;
1611      -        }
1612      -
1613      -        if (program == NULL) {
1614      -                if (dir == NULL)
1615      -                        dir = default_dir[CC(ctx)];
1616      -                cmd = cmds[CIDX(CC(ctx), ctx->i_flags)];
1617      -                len = strlen(dir) + strlen(cmd) + 2;
1618      -                if ((program = malloc(len)) == NULL)
1619      -                        nomem();
1620      -                (void) snprintf(program, len, "%s/%s", dir, cmd);
1621      -        }
1622      -
1623      -        newae(ctx->i_ae, program);
1624      -
1625 1578          if (ctx->i_flags & CW_F_PROG) {
1626 1579                  (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1627      -                    "shadow" : "primary", program);
     1580 +                    "shadow" : "primary", ctx->i_compiler->c_path);
1628 1581                  (void) fflush(stdout);
1629 1582          }
1630 1583  
1631 1584          if (!(ctx->i_flags & CW_F_XLATE))
1632 1585                  return;
1633 1586  
1634      -        switch (CC(ctx)) {
1635      -        case CW_C_CC:
     1587 +        switch (ctx->i_compiler->c_style) {
     1588 +        case SUN:
1636 1589                  do_cc(ctx);
1637 1590                  break;
1638      -        case CW_C_GCC:
     1591 +        case GNU:
1639 1592                  do_gcc(ctx);
1640 1593                  break;
1641 1594          }
1642 1595  }
1643 1596  
1644 1597  static int
1645 1598  invoke(cw_ictx_t *ctx)
1646 1599  {
1647 1600          char **newargv;
1648 1601          int ac;
↓ open down ↓ 16 lines elided ↑ open up ↑
1665 1618  
1666 1619          if (ctx->i_flags & CW_F_ECHO) {
1667 1620                  (void) fprintf(stderr, "\n");
1668 1621                  (void) fflush(stderr);
1669 1622          }
1670 1623  
1671 1624          if (!(ctx->i_flags & CW_F_EXEC))
1672 1625                  return (0);
1673 1626  
1674 1627          /*
1675      -         * We must fix up the environment here so that the
1676      -         * dependency files are not trampled by the shadow compiler.
     1628 +         * We must fix up the environment here so that the dependency files are
     1629 +         * not trampled by the shadow compiler. Also take care of GCC
     1630 +         * environment variables that will throw off gcc. This assumes a primary
     1631 +         * gcc.
1677 1632           */
1678 1633          if ((ctx->i_flags & CW_F_SHADOW) &&
1679 1634              (unsetenv("SUNPRO_DEPENDENCIES") != 0 ||
1680      -            unsetenv("DEPENDENCIES_OUTPUT") != 0)) {
     1635 +            unsetenv("DEPENDENCIES_OUTPUT") != 0 ||
     1636 +            unsetenv("GCC_ROOT") != 0)) {
1681 1637                  (void) fprintf(stderr, "error: environment setup failed: %s\n",
1682 1638                      strerror(errno));
1683 1639                  return (-1);
1684 1640          }
1685 1641  
1686 1642          (void) execv(newargv[0], newargv);
1687      -        cw_perror("couldn't run %s", newargv[0]);
     1643 +        warn("couldn't run %s", newargv[0]);
1688 1644  
1689 1645          return (-1);
1690 1646  }
1691 1647  
1692 1648  static int
1693 1649  reap(cw_ictx_t *ctx)
1694 1650  {
1695 1651          int status, ret = 0;
1696 1652          char buf[1024];
1697 1653          struct stat s;
1698 1654  
1699 1655          /*
1700 1656           * Only wait for one specific child.
1701 1657           */
1702 1658          if (ctx->i_pid <= 0)
1703 1659                  return (-1);
1704 1660  
1705 1661          do {
1706 1662                  if (waitpid(ctx->i_pid, &status, 0) < 0) {
1707      -                        cw_perror("cannot reap child");
     1663 +                        warn("cannot reap child");
1708 1664                          return (-1);
1709 1665                  }
1710 1666                  if (status != 0) {
1711 1667                          if (WIFSIGNALED(status)) {
1712 1668                                  ret = -WTERMSIG(status);
1713 1669                                  break;
1714 1670                          } else if (WIFEXITED(status)) {
1715 1671                                  ret = WEXITSTATUS(status);
1716 1672                                  break;
1717 1673                          }
1718 1674                  }
1719 1675          } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1720 1676  
1721 1677          (void) unlink(ctx->i_discard);
1722 1678  
1723 1679          if (stat(ctx->i_stderr, &s) < 0) {
1724      -                cw_perror("stat failed on child cleanup");
     1680 +                warn("stat failed on child cleanup");
1725 1681                  return (-1);
1726 1682          }
1727 1683          if (s.st_size != 0) {
1728 1684                  FILE *f;
1729 1685  
1730 1686                  if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1731 1687                          while (fgets(buf, sizeof (buf), f))
1732 1688                                  (void) fprintf(stderr, "%s", buf);
1733 1689                          (void) fflush(stderr);
1734 1690                          (void) fclose(f);
↓ open down ↓ 32 lines elided ↑ open up ↑
1767 1723                  nomem();
1768 1724                  return (-1);
1769 1725          }
1770 1726  
1771 1727          if ((ctx->i_pid = fork()) == 0) {
1772 1728                  int fd;
1773 1729  
1774 1730                  (void) fclose(stderr);
1775 1731                  if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1776 1732                      0666)) < 0) {
1777      -                        cw_perror("open failed for standard error");
1778      -                        exit(1);
     1733 +                        err(1, "open failed for standard error");
1779 1734                  }
1780 1735                  if (dup2(fd, 2) < 0) {
1781      -                        cw_perror("dup2 failed for standard error");
1782      -                        exit(1);
     1736 +                        err(1, "dup2 failed for standard error");
1783 1737                  }
1784 1738                  if (fd != 2)
1785 1739                          (void) close(fd);
1786 1740                  if (freopen("/dev/fd/2", "w", stderr) == NULL) {
1787      -                        cw_perror("freopen failed for /dev/fd/2");
1788      -                        exit(1);
     1741 +                        err(1, "freopen failed for /dev/fd/2");
1789 1742                  }
     1743 +
1790 1744                  prepctx(ctx);
1791 1745                  exit(invoke(ctx));
1792 1746          }
1793 1747  
1794 1748          if (ctx->i_pid < 0) {
1795      -                cw_perror("fork failed");
1796      -                return (1);
     1749 +                err(1, "fork failed");
1797 1750          }
1798 1751  
1799 1752          if (block)
1800 1753                  return (reap(ctx));
1801 1754  
1802 1755          return (0);
1803 1756  }
1804 1757  
     1758 +static void
     1759 +parse_compiler(const char *spec, cw_compiler_t *compiler)
     1760 +{
     1761 +        char *tspec, *token;
     1762 +
     1763 +        if ((tspec = strdup(spec)) == NULL)
     1764 +                nomem();
     1765 +
     1766 +        if ((token = strsep(&tspec, ",")) == NULL)
     1767 +                errx(1, "Compiler is missing a name: %s", spec);
     1768 +        compiler->c_name = token;
     1769 +
     1770 +        if ((token = strsep(&tspec, ",")) == NULL)
     1771 +                errx(1, "Compiler is missing a path: %s", spec);
     1772 +        compiler->c_path = token;
     1773 +
     1774 +        if ((token = strsep(&tspec, ",")) == NULL)
     1775 +                errx(1, "Compiler is missing a style: %s", spec);
     1776 +
     1777 +        if ((strcasecmp(token, "gnu") == 0) ||
     1778 +            (strcasecmp(token, "gcc") == 0))
     1779 +                compiler->c_style = GNU;
     1780 +        else if ((strcasecmp(token, "sun") == 0) ||
     1781 +            (strcasecmp(token, "cc") == 0))
     1782 +                compiler->c_style = SUN;
     1783 +        else
     1784 +                errx(1, "unknown compiler style: %s", token);
     1785 +
     1786 +        if (tspec != NULL)
     1787 +                errx(1, "Excess tokens in compiler: %s", spec);
     1788 +}
     1789 +
1805 1790  int
1806 1791  main(int argc, char **argv)
1807 1792  {
1808      -        cw_ictx_t *ctx = newictx();
1809      -        cw_ictx_t *ctx_shadow = newictx();
1810      -        const char *dir;
1811      -        int do_serial, do_shadow;
     1793 +        int ch;
     1794 +        cw_compiler_t primary = { NULL, NULL, 0 };
     1795 +        cw_compiler_t shadows[10];
     1796 +        int nshadows = 0;
1812 1797          int ret = 0;
     1798 +        boolean_t do_serial = B_FALSE;
     1799 +        boolean_t do_exec = B_FALSE;
     1800 +        boolean_t vflg = B_FALSE;
     1801 +        boolean_t Cflg = B_FALSE;
     1802 +        boolean_t cflg = B_FALSE;
     1803 +        boolean_t nflg = B_FALSE;
1813 1804  
1814      -        if ((progname = strrchr(argv[0], '/')) == NULL)
1815      -                progname = argv[0];
1816      -        else
1817      -                progname++;
     1805 +        cw_ictx_t *main_ctx;
1818 1806  
1819      -        if (ctx == NULL || ctx_shadow == NULL)
     1807 +        static struct option longopts[] = {
     1808 +                { "compiler", no_argument, NULL, 'c' },
     1809 +                { "noecho", no_argument, NULL, 'n' },
     1810 +                { "primary", required_argument, NULL, 'p' },
     1811 +                { "shadow", required_argument, NULL, 's' },
     1812 +                { "versions", no_argument, NULL, 'v' },
     1813 +                { NULL, 0, NULL, 0 },
     1814 +        };
     1815 +
     1816 +
     1817 +        if ((main_ctx = newictx()) == NULL)
1820 1818                  nomem();
1821 1819  
1822      -        ctx->i_flags = CW_F_ECHO|CW_F_XLATE;
     1820 +        while ((ch = getopt_long(argc, argv, "C", longopts, NULL)) != -1) {
     1821 +                switch (ch) {
     1822 +                case 'c':
     1823 +                        cflg = B_TRUE;
     1824 +                        break;
     1825 +                case 'C':
     1826 +                        Cflg = B_TRUE;
     1827 +                        break;
     1828 +                case 'n':
     1829 +                        nflg = B_TRUE;
     1830 +                        break;
     1831 +                case 'p':
     1832 +                        if (primary.c_path != NULL) {
     1833 +                                warnx("Only one primary compiler may "
     1834 +                                    "be specified");
     1835 +                                usage();
     1836 +                        }
1823 1837  
1824      -        /*
1825      -         * Figure out where to get our tools from.  This depends on
1826      -         * the environment variables set at run time.
1827      -         */
1828      -        if ((dir = getenv("SPRO_VROOT")) != NULL) {
1829      -                (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN,
1830      -                    "%s/bin", dir);
1831      -        } else if ((dir = getenv("SPRO_ROOT")) != NULL) {
1832      -                (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN,
1833      -                    "%s/SS12/bin", dir);
1834      -        } else if ((dir = getenv("BUILD_TOOLS")) != NULL) {
1835      -                (void) snprintf(default_dir[CW_C_CC], MAXPATHLEN,
1836      -                    "%s/SUNWspro/SS12/bin", dir);
     1838 +                        parse_compiler(optarg, &primary);
     1839 +                        break;
     1840 +                case 's':
     1841 +                        if (nshadows >= 10)
     1842 +                                errx(1, "May only use 10 shadows at "
     1843 +                                    "the moment");
     1844 +                        parse_compiler(optarg, &shadows[nshadows]);
     1845 +                        nshadows++;
     1846 +                        break;
     1847 +                case 'v':
     1848 +                        vflg = B_TRUE;
     1849 +                        break;
     1850 +                default:
     1851 +                        (void) fprintf(stderr, "Did you forget '--'?\n");
     1852 +                        usage();
     1853 +                }
1837 1854          }
1838 1855  
1839      -        if ((dir = getenv("GNUC_ROOT")) != NULL) {
1840      -                (void) snprintf(default_dir[CW_C_GCC], MAXPATHLEN,
1841      -                    "%s/bin", dir);
     1856 +        if (primary.c_path == NULL) {
     1857 +                warnx("A primary compiler must be specified");
     1858 +                usage();
1842 1859          }
1843 1860  
1844      -        do_shadow = (getenv("CW_NO_SHADOW") ? 0 : 1);
1845      -        do_serial = (getenv("CW_SHADOW_SERIAL") ? 1 : 0);
     1861 +        do_serial = (getenv("CW_SHADOW_SERIAL") == NULL) ? B_FALSE : B_TRUE;
     1862 +        do_exec = (getenv("CW_NO_EXEC") == NULL) ? B_TRUE : B_FALSE;
1846 1863  
1847      -        if (getenv("CW_NO_EXEC") == NULL)
1848      -                ctx->i_flags |= CW_F_EXEC;
     1864 +        /* Leave room for argv[0] */
     1865 +        argc -= (optind - 1);
     1866 +        argv += (optind - 1);
1849 1867  
1850      -        /*
1851      -         * The first argument must be one of "-_cc", "-_gcc", "-_CC", or "-_g++"
1852      -         */
1853      -        if (argc == 1)
1854      -                usage();
1855      -        argc--;
1856      -        argv++;
1857      -        if (strcmp(argv[0], "-_cc") == 0) {
1858      -                ctx->i_compiler = CW_C_CC;
1859      -        } else if (strcmp(argv[0], "-_gcc") == 0) {
1860      -                ctx->i_compiler = CW_C_GCC;
1861      -        } else if (strcmp(argv[0], "-_CC") == 0) {
1862      -                ctx->i_compiler = CW_C_CC;
1863      -                ctx->i_flags |= CW_F_CXX;
1864      -        } else if (strcmp(argv[0], "-_g++") == 0) {
1865      -                ctx->i_compiler = CW_C_GCC;
1866      -                ctx->i_flags |= CW_F_CXX;
1867      -        } else {
1868      -                /* assume "-_gcc" by default */
1869      -                argc++;
1870      -                argv--;
1871      -                ctx->i_compiler = CW_C_GCC;
1872      -        }
     1868 +        main_ctx->i_oldargc = argc;
     1869 +        main_ctx->i_oldargv = argv;
     1870 +        main_ctx->i_flags = CW_F_XLATE;
     1871 +        if (nflg == 0)
     1872 +                main_ctx->i_flags |= CW_F_ECHO;
     1873 +        if (do_exec)
     1874 +                main_ctx->i_flags |= CW_F_EXEC;
     1875 +        if (Cflg)
     1876 +                main_ctx->i_flags |= CW_F_CXX;
     1877 +        main_ctx->i_compiler = &primary;
1873 1878  
1874      -        /*
1875      -         * -_compiler - tell us the path to the primary compiler only
1876      -         */
1877      -        if (argc > 1 && strcmp(argv[1], "-_compiler") == 0) {
1878      -                ctx->i_flags &= ~CW_F_XLATE;
1879      -                prepctx(ctx);
1880      -                (void) printf("%s\n", ctx->i_ae->ael_head->ae_arg);
1881      -                return (0);
     1879 +        if (cflg) {
     1880 +                (void) fputs(primary.c_path, stdout);
1882 1881          }
1883 1882  
1884      -        /*
1885      -         * -_versions - tell us the cw version, paths to all compilers, and
1886      -         *              ask each for its version if we know how.
1887      -         */
1888      -        if (argc > 1 && strcmp(argv[1], "-_versions") == 0) {
1889      -                (void) printf("cw version %s", CW_VERSION);
1890      -                if (!do_shadow)
1891      -                        (void) printf(" (SHADOW MODE DISABLED)");
1892      -                (void) printf("\n");
     1883 +        if (vflg) {
     1884 +                (void) printf("cw version %s\n", CW_VERSION);
1893 1885                  (void) fflush(stdout);
1894      -                ctx->i_flags &= ~CW_F_ECHO;
1895      -                ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
1896      -                argc--;
1897      -                argv++;
     1886 +                main_ctx->i_flags &= ~CW_F_ECHO;
     1887 +                main_ctx->i_flags |= CW_F_PROG | CW_F_EXEC;
1898 1888                  do_serial = 1;
1899 1889          }
1900 1890  
1901      -        ctx->i_oldargc = argc;
1902      -        ctx->i_oldargv = argv;
     1891 +        ret |= exec_ctx(main_ctx, do_serial);
1903 1892  
1904      -        ret |= exec_ctx(ctx, do_serial);
     1893 +        for (int i = 0; i < nshadows; i++) {
     1894 +                int r;
     1895 +                cw_ictx_t *shadow_ctx;
1905 1896  
1906      -        if (do_shadow) {
1907      -                (void) memcpy(ctx_shadow, ctx, sizeof (cw_ictx_t));
1908      -                ctx_shadow->i_flags |= CW_F_SHADOW;
1909      -                ret |= exec_ctx(ctx_shadow, 1);
     1897 +                if ((shadow_ctx = newictx()) == NULL)
     1898 +                        nomem();
     1899 +
     1900 +                memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
     1901 +
     1902 +                shadow_ctx->i_flags |= CW_F_SHADOW;
     1903 +                shadow_ctx->i_compiler = &shadows[i];
     1904 +
     1905 +                r = exec_ctx(shadow_ctx, do_serial);
     1906 +                if (r == 0) {
     1907 +                        shadow_ctx->i_next = main_ctx->i_next;
     1908 +                        main_ctx->i_next = shadow_ctx;
     1909 +                }
     1910 +                ret |= r;
1910 1911          }
1911 1912  
1912      -        if (!do_serial)
1913      -                ret |= reap(ctx);
     1913 +        if (!do_serial) {
     1914 +                cw_ictx_t *next = main_ctx;
     1915 +                while (next != NULL) {
     1916 +                        cw_ictx_t *toreap = next;
     1917 +                        next = next->i_next;
     1918 +                        ret |= reap(toreap);
     1919 +                }
     1920 +        }
1914 1921  
1915 1922          return (ret);
1916 1923  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX