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");
|