Print this page
9899 cw(1onbld) should shadow more compilation
9888 cw shouldn't use __unused


 291 
 292 typedef enum {
 293         GNU,
 294         SUN
 295 } compiler_style_t;
 296 
 297 typedef struct {
 298         char *c_name;
 299         char *c_path;
 300         compiler_style_t c_style;
 301 } cw_compiler_t;
 302 
 303 typedef struct cw_ictx {
 304         struct cw_ictx  *i_next;
 305         cw_compiler_t   *i_compiler;
 306         struct aelist   *i_ae;
 307         uint32_t        i_flags;
 308         int             i_oldargc;
 309         char            **i_oldargv;
 310         pid_t           i_pid;
 311         char            i_discard[MAXPATHLEN];
 312         char            *i_stderr;
 313 } cw_ictx_t;
 314 
 315 /*
 316  * Status values to indicate which Studio compiler and associated
 317  * flags are being used.
 318  */
 319 #define M32             0x01    /* -m32 - only on Studio 12 */
 320 #define M64             0x02    /* -m64 - only on Studio 12 */
 321 #define SS11            0x100   /* Studio 11 */
 322 #define SS12            0x200   /* Studio 12 */
 323 
 324 #define TRANS_ENTRY     5
 325 /*
 326  * Translation table definition for the -xarch= flag. The "x_arg"
 327  * value is translated into the appropriate gcc flags according
 328  * to the values in x_trans[n]. The x_flags indicates what compiler
 329  * is being used and what flags have been set via the use of
 330  * "x_arg".
 331  */


 462                 return;
 463 
 464         /*
 465          * Enable as many warnings as exist, then disable those that we never
 466          * ever want.
 467          */
 468         newae(h, "-Wall");
 469         newae(h, "-Wextra");
 470 }
 471 
 472 static void
 473 optim_disable(struct aelist *h, int level)
 474 {
 475         if (level >= 2) {
 476                 newae(h, "-fno-strict-aliasing");
 477                 newae(h, "-fno-unit-at-a-time");
 478                 newae(h, "-fno-optimize-sibling-calls");
 479         }
 480 }
 481 
 482 /* ARGSUSED */
 483 static void
 484 Xamode(struct aelist __unused *h)
 485 {
 486 }
 487 
 488 static void
 489 Xsmode(struct aelist *h)
 490 {
 491         static int xsonce;
 492 
 493         if (xsonce++)
 494                 return;
 495 
 496         newae(h, "-traditional");
 497         newae(h, "-traditional-cpp");
 498 }
 499 
 500 static void
 501 usage()
 502 {
 503         extern char *__progname;
 504         (void) fprintf(stderr,
 505             "usage: %s [-C] [--versions] --primary <compiler> "
 506             "[--shadow <compiler>]... -- cflags...\n",
 507             __progname);


 542 static void
 543 xlate(struct aelist *h, const char *xarg, const char **table)
 544 {
 545         while (*table != NULL && strcmp(xarg, *table) != 0) {
 546                 while (*table != NULL)
 547                         table++;
 548                 table++;
 549         }
 550 
 551         if (*table == NULL)
 552                 error(xarg);
 553 
 554         table++;
 555 
 556         while (*table != NULL) {
 557                 newae(h, *table);
 558                 table++;
 559         }
 560 }
 561 





























 562 static void
 563 do_gcc(cw_ictx_t *ctx)
 564 {
 565         int c;
 566         int nolibc = 0;
 567         int in_output = 0, seen_o = 0, c_files = 0;
 568         cw_op_t op = CW_O_LINK;
 569         char *model = NULL;
 570         char *nameflag;
 571         int     mflag = 0;
 572 
 573         if (ctx->i_flags & CW_F_PROG) {
 574                 newae(ctx->i_ae, "--version");
 575                 return;
 576         }
 577 
 578         newae(ctx->i_ae, "-fident");
 579         newae(ctx->i_ae, "-finline");
 580         newae(ctx->i_ae, "-fno-inline-functions");
 581         newae(ctx->i_ae, "-fno-builtin");


 619                 } else {
 620                         /*
 621                          * Discard inline files that gcc doesn't grok
 622                          */
 623                         if (!in_output && arglen > 3 &&
 624                             strcmp(arg + arglen - 3, ".il") == 0)
 625                                 continue;
 626 
 627                         if (!in_output && arglen > 2 &&
 628                             arg[arglen - 2] == '.' &&
 629                             (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
 630                             arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
 631                                 c_files++;
 632 
 633                         /*
 634                          * Otherwise, filenames and partial arguments
 635                          * are passed through for gcc to chew on.  However,
 636                          * output is always discarded for the secondary
 637                          * compiler.
 638                          */
 639                         if ((ctx->i_flags & CW_F_SHADOW) && in_output)




 640                                 newae(ctx->i_ae, ctx->i_discard);
 641                         else
 642                                 newae(ctx->i_ae, arg);

 643                         in_output = 0;
 644                         continue;
 645                 }
 646 
 647                 if (ctx->i_flags & CW_F_CXX) {
 648                         if (strncmp(arg, "-_g++=", 6) == 0) {
 649                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
 650                                 continue;
 651                         }
 652                         if (strncmp(arg, "-compat=", 8) == 0) {
 653                                 /* discard -compat=4 and -compat=5 */
 654                                 continue;
 655                         }
 656                         if (strcmp(arg, "-Qoption") == 0) {
 657                                 /* discard -Qoption and its two arguments */
 658                                 if (ctx->i_oldargc < 3)
 659                                         error(arg);
 660                                 ctx->i_oldargc -= 2;
 661                                 ctx->i_oldargv += 2;
 662                                 continue;


 738                         break;
 739                 case 'A':
 740                 case 'h':
 741                 case 'I':
 742                 case 'i':
 743                 case 'L':
 744                 case 'l':
 745                 case 'R':
 746                 case 'U':
 747                 case 'u':
 748                 case 'w':
 749                         newae(ctx->i_ae, arg);
 750                         break;
 751                 case 'o':
 752                         seen_o = 1;
 753                         if (arglen == 1) {
 754                                 in_output = 1;
 755                                 newae(ctx->i_ae, arg);
 756                         } else if (ctx->i_flags & CW_F_SHADOW) {
 757                                 newae(ctx->i_ae, "-o");




 758                                 newae(ctx->i_ae, ctx->i_discard);
 759                         } else {
 760                                 newae(ctx->i_ae, arg);
 761                         }
 762                         break;
 763                 case 'D':
 764                         newae(ctx->i_ae, arg);
 765                         /*
 766                          * XXX  Clearly a hack ... do we need _KADB too?
 767                          */
 768                         if (strcmp(arg, "-D_KERNEL") == 0 ||
 769                             strcmp(arg, "-D_BOOT") == 0)
 770                                 newae(ctx->i_ae, "-ffreestanding");
 771                         break;
 772                 case 'd':
 773                         if (arglen == 2) {
 774                                 if (strcmp(arg, "-dy") == 0) {
 775                                         newae(ctx->i_ae, "-Wl,-dy");
 776                                         break;
 777                                 }


 979                                 break;
 980                         }
 981                         if (strcmp(arg, "-Wc,-Qassembler-ounrefsym=0") == 0) {
 982                                 /*
 983                                  * Prevents optimizing away of static variables.
 984                                  * gcc does not do this, so it's not needed.
 985                                  */
 986                                 break;
 987                         }
 988 #if defined(__x86)
 989                         if (strcmp(arg, "-Wu,-save_args") == 0) {
 990                                 newae(ctx->i_ae, "-msave-args");
 991                                 break;
 992                         }
 993 #endif  /* __x86 */
 994                         error(arg);
 995                         break;
 996                 case 'X':
 997                         if (strcmp(arg, "-Xa") == 0 ||
 998                             strcmp(arg, "-Xt") == 0) {
 999                                 Xamode(ctx->i_ae);
1000                                 break;
1001                         }
1002                         if (strcmp(arg, "-Xs") == 0) {
1003                                 Xsmode(ctx->i_ae);
1004                                 break;
1005                         }
1006                         error(arg);
1007                         break;
1008                 case 'x':
1009                         if (arglen == 1)
1010                                 error(arg);
1011                         switch (arg[2]) {
1012                         case 'a':
1013                                 if (strncmp(arg, "-xarch=", 7) == 0) {
1014                                         mflag |= xlate_xtb(ctx->i_ae, arg + 7);
1015                                         break;
1016                                 }
1017                                 error(arg);
1018                                 break;
1019                         case 'b':


1177                                 s[1] = 'I';
1178                                 newae(ctx->i_ae, "-nostdinc");
1179                                 newae(ctx->i_ae, s);
1180                                 free(s);
1181                                 break;
1182                         }
1183                         error(arg);
1184                         break;
1185                 case 'Q':
1186                         /*
1187                          * We could map -Qy into -Wl,-Qy etc.
1188                          */
1189                 default:
1190                         error(arg);
1191                         break;
1192                 }
1193         }
1194 
1195         free(nameflag);
1196 
1197         if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1198             op != CW_O_PREPROCESS) {








1199                 errx(2, "multiple source files are "
1200                     "allowed only with -E or -P");
1201         }
1202 
1203         /*
1204          * Make sure that we do not have any unintended interactions between
1205          * the xarch options passed in and the version of the Studio compiler
1206          * used.
1207          */
1208         if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1209                 errx(2,
1210                     "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1211         }
1212 
1213         switch (mflag) {
1214         case 0:
1215                 /* FALLTHROUGH */
1216         case M32:
1217 #if defined(__sparc)
1218                 /*


1246                 break;
1247         case (SS12|M32):
1248 #if defined(__sparc)
1249                 /*
1250                  * Need to add in further 32 bit options because with SS12
1251                  * the xarch=sparcvis option can be applied to 32 or 64
1252                  * bit, and so the translatation table (xtbl) cannot handle
1253                  * that.
1254                  */
1255                 newae(ctx->i_ae, "-mv8plus");
1256 #endif
1257                 break;
1258         case (SS12|M64):
1259                 break;
1260         default:
1261                 (void) fprintf(stderr,
1262                     "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1263                 exit(2);
1264         }
1265 
1266         if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1267             (ctx->i_flags & CW_F_SHADOW))


1268                 exit(0);

1269 
1270         if (model != NULL)
1271                 newae(ctx->i_ae, model);
1272         if (!nolibc)
1273                 newae(ctx->i_ae, "-lc");
1274         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {




1275                 newae(ctx->i_ae, "-o");
1276                 newae(ctx->i_ae, ctx->i_discard);
1277         }
1278 }
1279 
1280 static void
1281 do_cc(cw_ictx_t *ctx)
1282 {
1283         int in_output = 0, seen_o = 0;
1284         cw_op_t op = CW_O_LINK;
1285         char *nameflag;
1286 
1287         if (ctx->i_flags & CW_F_PROG) {
1288                 newae(ctx->i_ae, "-V");
1289                 return;
1290         }
1291 
1292         if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1293                 nomem();
1294 
1295         while (--ctx->i_oldargc > 0) {
1296                 char *arg = *++ctx->i_oldargv;

1297 
1298                 if (strncmp(arg, "-_CC=", 5) == 0) {
1299                         newae(ctx->i_ae, strchr(arg, '=') + 1);
1300                         continue;
1301                 }
1302 
1303                 if (*arg != '-') {






1304                         if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1305                                 newae(ctx->i_ae, arg);
1306                         } else {
1307                                 in_output = 0;



1308                                 newae(ctx->i_ae, ctx->i_discard);
1309                         }
1310                         continue;
1311                 }
1312                 switch (*(arg + 1)) {
1313                 case '_':
1314                         if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
1315                             (strncmp(arg, "-_cc=", 5) == 0) ||
1316                             (strncmp(arg, "-_sun=", 6) == 0)) {
1317                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
1318                         }
1319                         break;
1320 
1321                 case 'V':
1322                         ctx->i_flags &= ~CW_F_ECHO;
1323                         newae(ctx->i_ae, arg);
1324                         break;
1325                 case 'o':
1326                         seen_o = 1;
1327                         if (strlen(arg) == 2) {
1328                                 in_output = 1;
1329                                 newae(ctx->i_ae, arg);
1330                         } else if (ctx->i_flags & CW_F_SHADOW) {
1331                                 newae(ctx->i_ae, "-o");



1332                                 newae(ctx->i_ae, ctx->i_discard);
1333                         } else {
1334                                 newae(ctx->i_ae, arg);
1335                         }
1336                         break;
1337                 case 'c':
1338                 case 'S':
1339                         if (strlen(arg) == 2)
1340                                 op = CW_O_COMPILE;
1341                         newae(ctx->i_ae, arg);
1342                         break;
1343                 case 'E':
1344                 case 'P':
1345                         if (strlen(arg) == 2)
1346                                 op = CW_O_PREPROCESS;
1347                 /*FALLTHROUGH*/
1348                 default:
1349                         newae(ctx->i_ae, arg);
1350                 }
1351         }
1352 
1353         free(nameflag);
1354 
1355         if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1356             (ctx->i_flags & CW_F_SHADOW))






1357                 exit(0);



1358 
1359         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1360                 newae(ctx->i_ae, "-o");




1361                 newae(ctx->i_ae, ctx->i_discard);
1362         }
1363 }
1364 
1365 static void
1366 prepctx(cw_ictx_t *ctx)
1367 {
1368         newae(ctx->i_ae, ctx->i_compiler->c_path);
1369 
1370         if (ctx->i_flags & CW_F_PROG) {
1371                 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1372                     "shadow" : "primary", ctx->i_compiler->c_path);
1373                 (void) fflush(stdout);
1374         }
1375 
1376         if (!(ctx->i_flags & CW_F_XLATE))
1377                 return;
1378 
1379         switch (ctx->i_compiler->c_style) {
1380         case SUN:


1450         if (ctx->i_pid <= 0)
1451                 return (-1);
1452 
1453         do {
1454                 if (waitpid(ctx->i_pid, &status, 0) < 0) {
1455                         warn("cannot reap child");
1456                         return (-1);
1457                 }
1458                 if (status != 0) {
1459                         if (WIFSIGNALED(status)) {
1460                                 ret = -WTERMSIG(status);
1461                                 break;
1462                         } else if (WIFEXITED(status)) {
1463                                 ret = WEXITSTATUS(status);
1464                                 break;
1465                         }
1466                 }
1467         } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1468 
1469         (void) unlink(ctx->i_discard);

1470 
1471         if (stat(ctx->i_stderr, &s) < 0) {
1472                 warn("stat failed on child cleanup");
1473                 return (-1);
1474         }
1475         if (s.st_size != 0) {
1476                 FILE *f;
1477 
1478                 if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1479                         while (fgets(buf, sizeof (buf), f))
1480                                 (void) fprintf(stderr, "%s", buf);
1481                         (void) fflush(stderr);
1482                         (void) fclose(f);
1483                 }
1484         }
1485         (void) unlink(ctx->i_stderr);
1486         free(ctx->i_stderr);
1487 
1488         /*
1489          * cc returns an error code when given -V; we want that to succeed.
1490          */
1491         if (ctx->i_flags & CW_F_PROG)
1492                 return (0);
1493 
1494         return (ret);
1495 }
1496 
1497 static int
1498 exec_ctx(cw_ictx_t *ctx, int block)
1499 {
1500         char *file;
1501 
1502         /*
1503          * To avoid offending cc's sensibilities, the name of its output
1504          * file must end in '.o'.
1505          */
1506         if ((file = tempnam(NULL, ".cw")) == NULL) {
1507                 nomem();
1508                 return (-1);
1509         }
1510         (void) strlcpy(ctx->i_discard, file, MAXPATHLEN);
1511         (void) strlcat(ctx->i_discard, ".o", MAXPATHLEN);
1512         free(file);
1513 
1514         if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
1515                 nomem();
1516                 return (-1);
1517         }
1518 
1519         if ((ctx->i_pid = fork()) == 0) {
1520                 int fd;
1521 
1522                 (void) fclose(stderr);
1523                 if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1524                     0666)) < 0) {
1525                         err(1, "open failed for standard error");
1526                 }
1527                 if (dup2(fd, 2) < 0) {
1528                         err(1, "dup2 failed for standard error");
1529                 }
1530                 if (fd != 2)
1531                         (void) close(fd);
1532                 if (freopen("/dev/fd/2", "w", stderr) == NULL) {
1533                         err(1, "freopen failed for /dev/fd/2");




 291 
 292 typedef enum {
 293         GNU,
 294         SUN
 295 } compiler_style_t;
 296 
 297 typedef struct {
 298         char *c_name;
 299         char *c_path;
 300         compiler_style_t c_style;
 301 } cw_compiler_t;
 302 
 303 typedef struct cw_ictx {
 304         struct cw_ictx  *i_next;
 305         cw_compiler_t   *i_compiler;
 306         struct aelist   *i_ae;
 307         uint32_t        i_flags;
 308         int             i_oldargc;
 309         char            **i_oldargv;
 310         pid_t           i_pid;
 311         char            *i_discard;
 312         char            *i_stderr;
 313 } cw_ictx_t;
 314 
 315 /*
 316  * Status values to indicate which Studio compiler and associated
 317  * flags are being used.
 318  */
 319 #define M32             0x01    /* -m32 - only on Studio 12 */
 320 #define M64             0x02    /* -m64 - only on Studio 12 */
 321 #define SS11            0x100   /* Studio 11 */
 322 #define SS12            0x200   /* Studio 12 */
 323 
 324 #define TRANS_ENTRY     5
 325 /*
 326  * Translation table definition for the -xarch= flag. The "x_arg"
 327  * value is translated into the appropriate gcc flags according
 328  * to the values in x_trans[n]. The x_flags indicates what compiler
 329  * is being used and what flags have been set via the use of
 330  * "x_arg".
 331  */


 462                 return;
 463 
 464         /*
 465          * Enable as many warnings as exist, then disable those that we never
 466          * ever want.
 467          */
 468         newae(h, "-Wall");
 469         newae(h, "-Wextra");
 470 }
 471 
 472 static void
 473 optim_disable(struct aelist *h, int level)
 474 {
 475         if (level >= 2) {
 476                 newae(h, "-fno-strict-aliasing");
 477                 newae(h, "-fno-unit-at-a-time");
 478                 newae(h, "-fno-optimize-sibling-calls");
 479         }
 480 }
 481 






 482 static void
 483 Xsmode(struct aelist *h)
 484 {
 485         static int xsonce;
 486 
 487         if (xsonce++)
 488                 return;
 489 
 490         newae(h, "-traditional");
 491         newae(h, "-traditional-cpp");
 492 }
 493 
 494 static void
 495 usage()
 496 {
 497         extern char *__progname;
 498         (void) fprintf(stderr,
 499             "usage: %s [-C] [--versions] --primary <compiler> "
 500             "[--shadow <compiler>]... -- cflags...\n",
 501             __progname);


 536 static void
 537 xlate(struct aelist *h, const char *xarg, const char **table)
 538 {
 539         while (*table != NULL && strcmp(xarg, *table) != 0) {
 540                 while (*table != NULL)
 541                         table++;
 542                 table++;
 543         }
 544 
 545         if (*table == NULL)
 546                 error(xarg);
 547 
 548         table++;
 549 
 550         while (*table != NULL) {
 551                 newae(h, *table);
 552                 table++;
 553         }
 554 }
 555 
 556 /*
 557  * The compiler wants the output file to end in appropriate extension.  If
 558  * we're generating a name from whole cloth (path == NULL), we assume that
 559  * extension to be .o, otherwise we match the extension of the caller.
 560  */
 561 static char *
 562 discard_file_name(const char *path)
 563 {
 564         char *ret, *ext, *file;
 565 
 566         if (path == NULL) {
 567                 ext = ".o";
 568         } else {
 569                 ext = strrchr(path, '.');
 570         }
 571 
 572         if ((ret = calloc(MAXPATHLEN, sizeof (char))) == NULL)
 573                 nomem();
 574 
 575         if ((file = tempnam(NULL, ".cw")) == NULL)
 576                 nomem();
 577 
 578         (void) strlcpy(ret, file, MAXPATHLEN);
 579         if (ext != NULL)
 580                 (void) strlcat(ret, ext, MAXPATHLEN);
 581         free(file);
 582         return (ret);
 583 }
 584 
 585 static void
 586 do_gcc(cw_ictx_t *ctx)
 587 {
 588         int c;
 589         int nolibc = 0;
 590         int in_output = 0, seen_o = 0, c_files = 0;
 591         cw_op_t op = CW_O_LINK;
 592         char *model = NULL;
 593         char *nameflag;
 594         int mflag = 0;
 595 
 596         if (ctx->i_flags & CW_F_PROG) {
 597                 newae(ctx->i_ae, "--version");
 598                 return;
 599         }
 600 
 601         newae(ctx->i_ae, "-fident");
 602         newae(ctx->i_ae, "-finline");
 603         newae(ctx->i_ae, "-fno-inline-functions");
 604         newae(ctx->i_ae, "-fno-builtin");


 642                 } else {
 643                         /*
 644                          * Discard inline files that gcc doesn't grok
 645                          */
 646                         if (!in_output && arglen > 3 &&
 647                             strcmp(arg + arglen - 3, ".il") == 0)
 648                                 continue;
 649 
 650                         if (!in_output && arglen > 2 &&
 651                             arg[arglen - 2] == '.' &&
 652                             (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
 653                             arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
 654                                 c_files++;
 655 
 656                         /*
 657                          * Otherwise, filenames and partial arguments
 658                          * are passed through for gcc to chew on.  However,
 659                          * output is always discarded for the secondary
 660                          * compiler.
 661                          */
 662                         if ((ctx->i_flags & CW_F_SHADOW) && in_output) {
 663                                 ctx->i_discard = discard_file_name(arg);
 664 
 665                                 if (ctx->i_discard == NULL)
 666                                         nomem();
 667                                 newae(ctx->i_ae, ctx->i_discard);
 668                         } else {
 669                                 newae(ctx->i_ae, arg);
 670                         }
 671                         in_output = 0;
 672                         continue;
 673                 }
 674 
 675                 if (ctx->i_flags & CW_F_CXX) {
 676                         if (strncmp(arg, "-_g++=", 6) == 0) {
 677                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
 678                                 continue;
 679                         }
 680                         if (strncmp(arg, "-compat=", 8) == 0) {
 681                                 /* discard -compat=4 and -compat=5 */
 682                                 continue;
 683                         }
 684                         if (strcmp(arg, "-Qoption") == 0) {
 685                                 /* discard -Qoption and its two arguments */
 686                                 if (ctx->i_oldargc < 3)
 687                                         error(arg);
 688                                 ctx->i_oldargc -= 2;
 689                                 ctx->i_oldargv += 2;
 690                                 continue;


 766                         break;
 767                 case 'A':
 768                 case 'h':
 769                 case 'I':
 770                 case 'i':
 771                 case 'L':
 772                 case 'l':
 773                 case 'R':
 774                 case 'U':
 775                 case 'u':
 776                 case 'w':
 777                         newae(ctx->i_ae, arg);
 778                         break;
 779                 case 'o':
 780                         seen_o = 1;
 781                         if (arglen == 1) {
 782                                 in_output = 1;
 783                                 newae(ctx->i_ae, arg);
 784                         } else if (ctx->i_flags & CW_F_SHADOW) {
 785                                 newae(ctx->i_ae, "-o");
 786                                 ctx->i_discard = discard_file_name(arg);
 787                                 if (ctx->i_discard == NULL)
 788                                         nomem();
 789 
 790                                 newae(ctx->i_ae, ctx->i_discard);
 791                         } else {
 792                                 newae(ctx->i_ae, arg);
 793                         }
 794                         break;
 795                 case 'D':
 796                         newae(ctx->i_ae, arg);
 797                         /*
 798                          * XXX  Clearly a hack ... do we need _KADB too?
 799                          */
 800                         if (strcmp(arg, "-D_KERNEL") == 0 ||
 801                             strcmp(arg, "-D_BOOT") == 0)
 802                                 newae(ctx->i_ae, "-ffreestanding");
 803                         break;
 804                 case 'd':
 805                         if (arglen == 2) {
 806                                 if (strcmp(arg, "-dy") == 0) {
 807                                         newae(ctx->i_ae, "-Wl,-dy");
 808                                         break;
 809                                 }


1011                                 break;
1012                         }
1013                         if (strcmp(arg, "-Wc,-Qassembler-ounrefsym=0") == 0) {
1014                                 /*
1015                                  * Prevents optimizing away of static variables.
1016                                  * gcc does not do this, so it's not needed.
1017                                  */
1018                                 break;
1019                         }
1020 #if defined(__x86)
1021                         if (strcmp(arg, "-Wu,-save_args") == 0) {
1022                                 newae(ctx->i_ae, "-msave-args");
1023                                 break;
1024                         }
1025 #endif  /* __x86 */
1026                         error(arg);
1027                         break;
1028                 case 'X':
1029                         if (strcmp(arg, "-Xa") == 0 ||
1030                             strcmp(arg, "-Xt") == 0) {

1031                                 break;
1032                         }
1033                         if (strcmp(arg, "-Xs") == 0) {
1034                                 Xsmode(ctx->i_ae);
1035                                 break;
1036                         }
1037                         error(arg);
1038                         break;
1039                 case 'x':
1040                         if (arglen == 1)
1041                                 error(arg);
1042                         switch (arg[2]) {
1043                         case 'a':
1044                                 if (strncmp(arg, "-xarch=", 7) == 0) {
1045                                         mflag |= xlate_xtb(ctx->i_ae, arg + 7);
1046                                         break;
1047                                 }
1048                                 error(arg);
1049                                 break;
1050                         case 'b':


1208                                 s[1] = 'I';
1209                                 newae(ctx->i_ae, "-nostdinc");
1210                                 newae(ctx->i_ae, s);
1211                                 free(s);
1212                                 break;
1213                         }
1214                         error(arg);
1215                         break;
1216                 case 'Q':
1217                         /*
1218                          * We could map -Qy into -Wl,-Qy etc.
1219                          */
1220                 default:
1221                         error(arg);
1222                         break;
1223                 }
1224         }
1225 
1226         free(nameflag);
1227 
1228         /*
1229          * When compiling multiple source files in a single invocation some
1230          * compilers output objects into the current directory with
1231          * predictable and conventional names.
1232          *
1233          * We prevent any attempt to compile multiple files at once so that
1234          * any such objects created by a shadow can't escape into a later
1235          * link-edit.
1236          */
1237         if (c_files > 1 && op != CW_O_PREPROCESS) {
1238                 errx(2, "multiple source files are "
1239                     "allowed only with -E or -P");
1240         }
1241 
1242         /*
1243          * Make sure that we do not have any unintended interactions between
1244          * the xarch options passed in and the version of the Studio compiler
1245          * used.
1246          */
1247         if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1248                 errx(2,
1249                     "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1250         }
1251 
1252         switch (mflag) {
1253         case 0:
1254                 /* FALLTHROUGH */
1255         case M32:
1256 #if defined(__sparc)
1257                 /*


1285                 break;
1286         case (SS12|M32):
1287 #if defined(__sparc)
1288                 /*
1289                  * Need to add in further 32 bit options because with SS12
1290                  * the xarch=sparcvis option can be applied to 32 or 64
1291                  * bit, and so the translatation table (xtbl) cannot handle
1292                  * that.
1293                  */
1294                 newae(ctx->i_ae, "-mv8plus");
1295 #endif
1296                 break;
1297         case (SS12|M64):
1298                 break;
1299         default:
1300                 (void) fprintf(stderr,
1301                     "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1302                 exit(2);
1303         }
1304 
1305         if (ctx->i_flags & CW_F_SHADOW) {
1306                 if (op == CW_O_PREPROCESS)
1307                         exit(0);
1308                 else if (op == CW_O_LINK && c_files == 0)
1309                         exit(0);
1310         }
1311 
1312         if (model != NULL)
1313                 newae(ctx->i_ae, model);
1314         if (!nolibc)
1315                 newae(ctx->i_ae, "-lc");
1316         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1317                 ctx->i_discard = discard_file_name(NULL);
1318 
1319                 if (ctx->i_discard == NULL)
1320                         nomem();
1321                 newae(ctx->i_ae, "-o");
1322                 newae(ctx->i_ae, ctx->i_discard);
1323         }
1324 }
1325 
1326 static void
1327 do_cc(cw_ictx_t *ctx)
1328 {
1329         int in_output = 0, seen_o = 0, c_files = 0;
1330         cw_op_t op = CW_O_LINK;
1331         char *nameflag;
1332 
1333         if (ctx->i_flags & CW_F_PROG) {
1334                 newae(ctx->i_ae, "-V");
1335                 return;
1336         }
1337 
1338         if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1339                 nomem();
1340 
1341         while (--ctx->i_oldargc > 0) {
1342                 char *arg = *++ctx->i_oldargv;
1343                 size_t arglen = strlen(arg);
1344 
1345                 if (strncmp(arg, "-_CC=", 5) == 0) {
1346                         newae(ctx->i_ae, strchr(arg, '=') + 1);
1347                         continue;
1348                 }
1349 
1350                 if (*arg != '-') {
1351                         if (!in_output && arglen > 2 &&
1352                             arg[arglen - 2] == '.' &&
1353                             (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
1354                             arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
1355                                 c_files++;
1356 
1357                         if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1358                                 newae(ctx->i_ae, arg);
1359                         } else {
1360                                 in_output = 0;
1361                                 ctx->i_discard = discard_file_name(arg);
1362                                 if (ctx->i_discard == NULL)
1363                                         nomem();
1364                                 newae(ctx->i_ae, ctx->i_discard);
1365                         }
1366                         continue;
1367                 }
1368                 switch (*(arg + 1)) {
1369                 case '_':
1370                         if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
1371                             (strncmp(arg, "-_cc=", 5) == 0) ||
1372                             (strncmp(arg, "-_sun=", 6) == 0)) {
1373                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
1374                         }
1375                         break;
1376 
1377                 case 'V':
1378                         ctx->i_flags &= ~CW_F_ECHO;
1379                         newae(ctx->i_ae, arg);
1380                         break;
1381                 case 'o':
1382                         seen_o = 1;
1383                         if (strlen(arg) == 2) {
1384                                 in_output = 1;
1385                                 newae(ctx->i_ae, arg);
1386                         } else if (ctx->i_flags & CW_F_SHADOW) {
1387                                 newae(ctx->i_ae, "-o");
1388                                 ctx->i_discard = discard_file_name(arg);
1389                                 if (ctx->i_discard == NULL)
1390                                         nomem();
1391                                 newae(ctx->i_ae, ctx->i_discard);
1392                         } else {
1393                                 newae(ctx->i_ae, arg);
1394                         }
1395                         break;
1396                 case 'c':
1397                 case 'S':
1398                         if (strlen(arg) == 2)
1399                                 op = CW_O_COMPILE;
1400                         newae(ctx->i_ae, arg);
1401                         break;
1402                 case 'E':
1403                 case 'P':
1404                         if (strlen(arg) == 2)
1405                                 op = CW_O_PREPROCESS;
1406                 /*FALLTHROUGH*/
1407                 default:
1408                         newae(ctx->i_ae, arg);
1409                 }
1410         }
1411 
1412         free(nameflag);
1413 
1414         /* See the comment on this same code in do_gcc() */
1415         if (c_files > 1 && op != CW_O_PREPROCESS) {
1416                 errx(2, "multiple source files are "
1417                     "allowed only with -E or -P");
1418         }
1419 
1420         if (ctx->i_flags & CW_F_SHADOW) {
1421                 if (op == CW_O_PREPROCESS)
1422                         exit(0);
1423                 else if (op == CW_O_LINK && c_files == 0)
1424                         exit(0);
1425         }
1426 
1427         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1428                 newae(ctx->i_ae, "-o");
1429                 ctx->i_discard = discard_file_name(NULL);
1430 
1431                 if (ctx->i_discard == NULL)
1432                         nomem();
1433                 newae(ctx->i_ae, ctx->i_discard);
1434         }
1435 }
1436 
1437 static void
1438 prepctx(cw_ictx_t *ctx)
1439 {
1440         newae(ctx->i_ae, ctx->i_compiler->c_path);
1441 
1442         if (ctx->i_flags & CW_F_PROG) {
1443                 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1444                     "shadow" : "primary", ctx->i_compiler->c_path);
1445                 (void) fflush(stdout);
1446         }
1447 
1448         if (!(ctx->i_flags & CW_F_XLATE))
1449                 return;
1450 
1451         switch (ctx->i_compiler->c_style) {
1452         case SUN:


1522         if (ctx->i_pid <= 0)
1523                 return (-1);
1524 
1525         do {
1526                 if (waitpid(ctx->i_pid, &status, 0) < 0) {
1527                         warn("cannot reap child");
1528                         return (-1);
1529                 }
1530                 if (status != 0) {
1531                         if (WIFSIGNALED(status)) {
1532                                 ret = -WTERMSIG(status);
1533                                 break;
1534                         } else if (WIFEXITED(status)) {
1535                                 ret = WEXITSTATUS(status);
1536                                 break;
1537                         }
1538                 }
1539         } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1540 
1541         (void) unlink(ctx->i_discard);
1542         free(ctx->i_discard);
1543 
1544         if (stat(ctx->i_stderr, &s) < 0) {
1545                 warn("stat failed on child cleanup");
1546                 return (-1);
1547         }
1548         if (s.st_size != 0) {
1549                 FILE *f;
1550 
1551                 if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1552                         while (fgets(buf, sizeof (buf), f))
1553                                 (void) fprintf(stderr, "%s", buf);
1554                         (void) fflush(stderr);
1555                         (void) fclose(f);
1556                 }
1557         }
1558         (void) unlink(ctx->i_stderr);
1559         free(ctx->i_stderr);
1560 
1561         /*
1562          * cc returns an error code when given -V; we want that to succeed.
1563          */
1564         if (ctx->i_flags & CW_F_PROG)
1565                 return (0);
1566 
1567         return (ret);
1568 }
1569 
1570 static int
1571 exec_ctx(cw_ictx_t *ctx, int block)
1572 {














1573         if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
1574                 nomem();
1575                 return (-1);
1576         }
1577 
1578         if ((ctx->i_pid = fork()) == 0) {
1579                 int fd;
1580 
1581                 (void) fclose(stderr);
1582                 if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1583                     0666)) < 0) {
1584                         err(1, "open failed for standard error");
1585                 }
1586                 if (dup2(fd, 2) < 0) {
1587                         err(1, "dup2 failed for standard error");
1588                 }
1589                 if (fd != 2)
1590                         (void) close(fd);
1591                 if (freopen("/dev/fd/2", "w", stderr) == NULL) {
1592                         err(1, "freopen failed for /dev/fd/2");