318 typedef enum cw_op {
319 CW_O_NONE = 0,
320 CW_O_PREPROCESS,
321 CW_O_COMPILE,
322 CW_O_LINK
323 } cw_op_t;
324
325 struct aelist {
326 struct ae {
327 struct ae *ae_next;
328 char *ae_arg;
329 } *ael_head, *ael_tail;
330 int ael_argc;
331 };
332
333 typedef enum {
334 GNU,
335 SUN
336 } compiler_style_t;
337
338 #define COMPILER_STYLE(comp) (comp->style == SUN ? "cc" : "gcc")
339
340 typedef struct {
341 char *name;
342 char *path;
343 compiler_style_t style;
344 } cw_compiler_t;
345
346 typedef struct cw_ictx {
347 cw_compiler_t *i_compiler;
348 struct aelist *i_ae;
349 uint32_t i_flags;
350 int i_oldargc;
351 char **i_oldargv;
352 pid_t i_pid;
353 char i_discard[MAXPATHLEN];
354 char *i_stderr;
355 } cw_ictx_t;
356
357 /*
358 * Status values to indicate which Studio compiler and associated
359 * flags are being used.
360 */
361 #define M32 0x01 /* -m32 - only on Studio 12 */
362 #define M64 0x02 /* -m64 - only on Studio 12 */
363 #define SS11 0x100 /* Studio 11 */
437 static const char *xtarget_tbl[] = {
438 #if defined(__x86)
439 "pentium_pro", "-march=pentiumpro", NULL,
440 #endif /* __x86 */
441 NULL, NULL
442 };
443
444 static const char *xregs_tbl[] = {
445 #if defined(__sparc)
446 "appl", "-mapp-regs", NULL,
447 "no%appl", "-mno-app-regs", NULL,
448 "float", "-mfpu", NULL,
449 "no%float", "-mno-fpu", NULL,
450 #endif /* __sparc */
451 NULL, NULL
452 };
453
454 static void
455 nomem(void)
456 {
457 (void) errx(1, "out of memory");
458 }
459
460 static void
461 newae(struct aelist *ael, const char *arg)
462 {
463 struct ae *ae;
464
465 if ((ae = calloc(sizeof (*ae), 1)) == NULL)
466 nomem();
467 ae->ae_arg = strdup(arg);
468 if (ael->ael_tail == NULL)
469 ael->ael_head = ae;
470 else
471 ael->ael_tail->ae_next = ae;
472 ael->ael_tail = ae;
473 ael->ael_argc++;
474 }
475
476 static cw_ictx_t *
477 newictx(void)
506 /*
507 * Enable as many warnings as exist, then disable those that we never
508 * ever want.
509 */
510 newae(h, "-Wall");
511 newae(h, "-Wextra");
512 }
513
514 static void
515 optim_disable(struct aelist *h, int level)
516 {
517 if (level >= 2) {
518 newae(h, "-fno-strict-aliasing");
519 newae(h, "-fno-unit-at-a-time");
520 newae(h, "-fno-optimize-sibling-calls");
521 }
522 }
523
524 /* ARGSUSED */
525 static void
526 Xamode(struct aelist *h __attribute__((__unused__)))
527 {
528 }
529
530 static void
531 Xcmode(struct aelist *h)
532 {
533 static int xconce;
534
535 if (xconce++)
536 return;
537
538 newae(h, "-ansi");
539 newae(h, "-pedantic-errors");
540 }
541
542 static void
543 Xsmode(struct aelist *h)
544 {
545 static int xsonce;
546
641 /*
642 * The SPARC ldd and std instructions require 8-byte alignment of
643 * their address operand. gcc correctly uses them only when the
644 * ABI requires 8-byte alignment; unfortunately we have a number of
645 * pieces of buggy code that doesn't conform to the ABI. This
646 * flag makes gcc work more like Studio with -xmemalign=4.
647 */
648 newae(ctx->i_ae, "-mno-integer-ldd-std");
649 #endif
650
651 /*
652 * This is needed because 'u' is defined
653 * under a conditional on 'sun'. Should
654 * probably just remove the conditional,
655 * or make it be dependent on '__sun'.
656 *
657 * -Dunix is also missing in enhanced ANSI mode
658 */
659 newae(ctx->i_ae, "-D__sun");
660
661 if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->name) == -1)
662 nomem();
663
664 /*
665 * Walk the argument list, translating as we go ..
666 */
667 while (--ctx->i_oldargc > 0) {
668 char *arg = *++ctx->i_oldargv;
669 size_t arglen = strlen(arg);
670
671 if (*arg == '-') {
672 arglen--;
673 } else {
674 /*
675 * Discard inline files that gcc doesn't grok
676 */
677 if (!in_output && arglen > 3 &&
678 strcmp(arg + arglen - 3, ".il") == 0)
679 continue;
680
681 if (!in_output && arglen > 2 &&
1390 newae(ctx->i_ae, s);
1391 free(s);
1392 break;
1393 }
1394 error(arg);
1395 break;
1396 case 'Q':
1397 /*
1398 * We could map -Qy into -Wl,-Qy etc.
1399 */
1400 default:
1401 error(arg);
1402 break;
1403 }
1404 }
1405
1406 free(nameflag);
1407
1408 if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1409 op != CW_O_PREPROCESS) {
1410 (void) errx(2, "multiple source files are "
1411 "allowed only with -E or -P");
1412 }
1413
1414 /*
1415 * Make sure that we do not have any unintended interactions between
1416 * the xarch options passed in and the version of the Studio compiler
1417 * used.
1418 */
1419 if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1420 (void) errx(2,
1421 "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1422 }
1423
1424 switch (mflag) {
1425 case 0:
1426 /* FALLTHROUGH */
1427 case M32:
1428 #if defined(__sparc)
1429 /*
1430 * Only -m32 is defined and so put in the missing xarch
1431 * translation.
1432 */
1433 newae(ctx->i_ae, "-mcpu=v8");
1434 newae(ctx->i_ae, "-mno-v8plus");
1435 #endif
1436 break;
1437 case M64:
1438 #if defined(__sparc)
1439 /*
1440 * Only -m64 is defined and so put in the missing xarch
1481 if (!nolibc)
1482 newae(ctx->i_ae, "-lc");
1483 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1484 newae(ctx->i_ae, "-o");
1485 newae(ctx->i_ae, ctx->i_discard);
1486 }
1487 }
1488
1489 static void
1490 do_cc(cw_ictx_t *ctx)
1491 {
1492 int in_output = 0, seen_o = 0;
1493 cw_op_t op = CW_O_LINK;
1494 char *nameflag;
1495
1496 if (ctx->i_flags & CW_F_PROG) {
1497 newae(ctx->i_ae, "-V");
1498 return;
1499 }
1500
1501 if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->name) == -1)
1502 nomem();
1503
1504 while (--ctx->i_oldargc > 0) {
1505 char *arg = *++ctx->i_oldargv;
1506
1507 if (strncmp(arg, "-_CC=", 5) == 0) {
1508 newae(ctx->i_ae, strchr(arg, '=') + 1);
1509 continue;
1510 }
1511
1512 if (*arg != '-') {
1513 if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1514 newae(ctx->i_ae, arg);
1515 } else {
1516 in_output = 0;
1517 newae(ctx->i_ae, ctx->i_discard);
1518 }
1519 continue;
1520 }
1521 switch (*(arg + 1)) {
1557 default:
1558 newae(ctx->i_ae, arg);
1559 }
1560 }
1561
1562 free(nameflag);
1563
1564 if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1565 (ctx->i_flags & CW_F_SHADOW))
1566 exit(0);
1567
1568 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1569 newae(ctx->i_ae, "-o");
1570 newae(ctx->i_ae, ctx->i_discard);
1571 }
1572 }
1573
1574 static void
1575 prepctx(cw_ictx_t *ctx)
1576 {
1577 newae(ctx->i_ae, ctx->i_compiler->path);
1578
1579 if (ctx->i_flags & CW_F_PROG) {
1580 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1581 "shadow" : "primary", ctx->i_compiler->path);
1582 (void) fflush(stdout);
1583 }
1584
1585 if (!(ctx->i_flags & CW_F_XLATE))
1586 return;
1587
1588 switch (ctx->i_compiler->style) {
1589 case SUN:
1590 do_cc(ctx);
1591 break;
1592 case GNU:
1593 do_gcc(ctx);
1594 break;
1595 }
1596 }
1597
1598 static int
1599 invoke(cw_ictx_t *ctx)
1600 {
1601 char **newargv;
1602 int ac;
1603 struct ae *a;
1604
1605 if ((newargv = calloc(sizeof (*newargv), ctx->i_ae->ael_argc + 1)) ==
1606 NULL)
1607 nomem();
1608
1741 prepctx(ctx);
1742 exit(invoke(ctx));
1743 }
1744
1745 if (ctx->i_pid < 0) {
1746 err(1, "fork failed");
1747 }
1748
1749 if (block)
1750 return (reap(ctx));
1751
1752 return (0);
1753 }
1754
1755 static int
1756 parse_compiler(const char *spec, cw_compiler_t *compiler)
1757 {
1758 char *tspec, *token;
1759
1760 if ((tspec = strdup(spec)) == NULL)
1761 err(1, "out of memory");
1762
1763 if ((token = strsep(&tspec, ",")) == NULL)
1764 errx(1, "Compiler is missing a name: %s", spec);
1765 compiler->name = token;
1766
1767 if ((token = strsep(&tspec, ",")) == NULL)
1768 errx(1, "Compiler is missing a path: %s", spec);
1769 compiler->path = token;
1770
1771 if ((token = strsep(&tspec, ",")) == NULL)
1772 errx(1, "Compiler is missing a style: %s", spec);
1773
1774 if ((strcasecmp(token, "gnu") == 0) ||
1775 (strcasecmp(token, "gcc") == 0))
1776 compiler->style = GNU;
1777 else if ((strcasecmp(token, "sun") == 0) ||
1778 (strcasecmp(token, "cc") == 0))
1779 compiler->style = SUN;
1780 else
1781 errx(1, "unknown compiler style: %s", token);
1782
1783 if (tspec != NULL)
1784 errx(1, "Excess tokens in compiler: %s", spec);
1785
1786 return (0);
1787 }
1788
1789 int
1790 main(int argc, char **argv)
1791 {
1792 int ch;
1793 cw_compiler_t primary = { NULL, NULL, 0 };
1794 cw_compiler_t shadows[10];
1795 int nshadows = 0;
1796 int ret = 0;
1797 boolean_t do_serial = B_FALSE;
1798 boolean_t do_exec = B_FALSE;
1799 boolean_t vflg = B_FALSE;
1800 boolean_t Cflg = B_FALSE;
1801 boolean_t cflg = B_FALSE;
1802 boolean_t nflg = B_FALSE;
1803
1804 cw_ictx_t *main_ctx = newictx();
1805
1806 static struct option longopts[] = {
1807 { "compiler", no_argument, NULL, 'c' },
1808 { "noecho", no_argument, NULL ,'n' },
1809 { "primary", required_argument, NULL, 'p' },
1810 { "shadow", required_argument, NULL, 's' },
1811 { "versions", no_argument, NULL, 'v' },
1812 { NULL, 0, NULL, 0 },
1813 };
1814
1815 while ((ch = getopt_long(argc, argv, "C", longopts, NULL)) != -1) {
1816 switch (ch) {
1817 case 'c':
1818 cflg = B_TRUE;
1819 break;
1820 case 'C':
1821 Cflg = B_TRUE;
1822 break;
1823 case 'n':
1824 nflg = B_TRUE;
1825 break;
1826 case 'p':
1827 if (primary.path != NULL) {
1828 warnx("Only one primary compiler may be specified");
1829 usage();
1830 }
1831
1832 if (parse_compiler(optarg, &primary) != 0)
1833 errx(1, "Couldn't parse %s as a compiler spec", optarg);
1834 break;
1835 case 's':
1836 if (nshadows >= 10)
1837 errx(1, "May only use 10 shadows at the moment");
1838 if (parse_compiler(optarg, &shadows[nshadows]) != 0)
1839 errx(1, "Couldn't parse %s as a compiler spec", optarg);
1840 nshadows++;
1841 break;
1842 case 'v':
1843 vflg = B_TRUE;
1844 break;
1845 default:
1846 fprintf(stderr, "Did you forget '--'?\n");
1847 usage();
1848 }
1849 }
1850
1851 if (primary.path == NULL) {
1852 warnx("A primary compiler must be specified");
1853 usage();
1854 }
1855
1856 do_serial = (getenv("CW_SHADOW_SERIAL") == NULL) ? B_FALSE : B_TRUE;
1857 do_exec = (getenv("CW_NO_EXEC") == NULL) ? B_TRUE : B_FALSE;
1858
1859 /* Leave room for argv[0] */
1860 argc -= (optind - 1);
1861 argv += (optind - 1);
1862
1863 if (main_ctx == NULL)
1864 nomem();
1865
1866 main_ctx->i_oldargc = argc;
1867 main_ctx->i_oldargv = argv;
1868 main_ctx->i_flags = CW_F_XLATE;
1869 if (nflg == 0)
1870 main_ctx->i_flags |= CW_F_ECHO;
1871 if (do_exec)
1872 main_ctx->i_flags |= CW_F_EXEC;
1873 if (Cflg)
1874 main_ctx->i_flags |= CW_F_CXX;
1875 main_ctx->i_compiler = &primary;
1876
1877 if (cflg) {
1878 fputs(primary.path, stdout);
1879 }
1880
1881 if (vflg) {
1882 (void) printf("cw version %s\n", CW_VERSION);
1883 (void) fflush(stdout);
1884 main_ctx->i_flags &= ~CW_F_ECHO;
1885 main_ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
1886 do_serial = 1;
1887 }
1888
1889 ret |= exec_ctx(main_ctx, do_serial);
1890
1891 for (int i = 0; i < nshadows; i++) {
1892 cw_ictx_t *shadow_ctx = newictx();
1893
1894 if (shadow_ctx == NULL)
1895 nomem();
1896
1897 memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
1898
1899 shadow_ctx->i_flags |= CW_F_SHADOW;
1900 shadow_ctx->i_compiler = &shadows[i];
1901
1902 /* XXX: Would be nice to run these parallel, too */
1903 ret |= exec_ctx(shadow_ctx, 1);
1904 }
1905
1906 if (!do_serial)
1907 ret |= reap(main_ctx);
1908
1909 return (ret);
1910 }
|
318 typedef enum cw_op {
319 CW_O_NONE = 0,
320 CW_O_PREPROCESS,
321 CW_O_COMPILE,
322 CW_O_LINK
323 } cw_op_t;
324
325 struct aelist {
326 struct ae {
327 struct ae *ae_next;
328 char *ae_arg;
329 } *ael_head, *ael_tail;
330 int ael_argc;
331 };
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
344 typedef struct cw_ictx {
345 cw_compiler_t *i_compiler;
346 struct aelist *i_ae;
347 uint32_t i_flags;
348 int i_oldargc;
349 char **i_oldargv;
350 pid_t i_pid;
351 char i_discard[MAXPATHLEN];
352 char *i_stderr;
353 } cw_ictx_t;
354
355 /*
356 * Status values to indicate which Studio compiler and associated
357 * flags are being used.
358 */
359 #define M32 0x01 /* -m32 - only on Studio 12 */
360 #define M64 0x02 /* -m64 - only on Studio 12 */
361 #define SS11 0x100 /* Studio 11 */
435 static const char *xtarget_tbl[] = {
436 #if defined(__x86)
437 "pentium_pro", "-march=pentiumpro", NULL,
438 #endif /* __x86 */
439 NULL, NULL
440 };
441
442 static const char *xregs_tbl[] = {
443 #if defined(__sparc)
444 "appl", "-mapp-regs", NULL,
445 "no%appl", "-mno-app-regs", NULL,
446 "float", "-mfpu", NULL,
447 "no%float", "-mno-fpu", NULL,
448 #endif /* __sparc */
449 NULL, NULL
450 };
451
452 static void
453 nomem(void)
454 {
455 errx(1, "out of memory");
456 }
457
458 static void
459 newae(struct aelist *ael, const char *arg)
460 {
461 struct ae *ae;
462
463 if ((ae = calloc(sizeof (*ae), 1)) == NULL)
464 nomem();
465 ae->ae_arg = strdup(arg);
466 if (ael->ael_tail == NULL)
467 ael->ael_head = ae;
468 else
469 ael->ael_tail->ae_next = ae;
470 ael->ael_tail = ae;
471 ael->ael_argc++;
472 }
473
474 static cw_ictx_t *
475 newictx(void)
504 /*
505 * Enable as many warnings as exist, then disable those that we never
506 * ever want.
507 */
508 newae(h, "-Wall");
509 newae(h, "-Wextra");
510 }
511
512 static void
513 optim_disable(struct aelist *h, int level)
514 {
515 if (level >= 2) {
516 newae(h, "-fno-strict-aliasing");
517 newae(h, "-fno-unit-at-a-time");
518 newae(h, "-fno-optimize-sibling-calls");
519 }
520 }
521
522 /* ARGSUSED */
523 static void
524 Xamode(struct aelist __unused *h)
525 {
526 }
527
528 static void
529 Xcmode(struct aelist *h)
530 {
531 static int xconce;
532
533 if (xconce++)
534 return;
535
536 newae(h, "-ansi");
537 newae(h, "-pedantic-errors");
538 }
539
540 static void
541 Xsmode(struct aelist *h)
542 {
543 static int xsonce;
544
639 /*
640 * The SPARC ldd and std instructions require 8-byte alignment of
641 * their address operand. gcc correctly uses them only when the
642 * ABI requires 8-byte alignment; unfortunately we have a number of
643 * pieces of buggy code that doesn't conform to the ABI. This
644 * flag makes gcc work more like Studio with -xmemalign=4.
645 */
646 newae(ctx->i_ae, "-mno-integer-ldd-std");
647 #endif
648
649 /*
650 * This is needed because 'u' is defined
651 * under a conditional on 'sun'. Should
652 * probably just remove the conditional,
653 * or make it be dependent on '__sun'.
654 *
655 * -Dunix is also missing in enhanced ANSI mode
656 */
657 newae(ctx->i_ae, "-D__sun");
658
659 if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
660 nomem();
661
662 /*
663 * Walk the argument list, translating as we go ..
664 */
665 while (--ctx->i_oldargc > 0) {
666 char *arg = *++ctx->i_oldargv;
667 size_t arglen = strlen(arg);
668
669 if (*arg == '-') {
670 arglen--;
671 } else {
672 /*
673 * Discard inline files that gcc doesn't grok
674 */
675 if (!in_output && arglen > 3 &&
676 strcmp(arg + arglen - 3, ".il") == 0)
677 continue;
678
679 if (!in_output && arglen > 2 &&
1388 newae(ctx->i_ae, s);
1389 free(s);
1390 break;
1391 }
1392 error(arg);
1393 break;
1394 case 'Q':
1395 /*
1396 * We could map -Qy into -Wl,-Qy etc.
1397 */
1398 default:
1399 error(arg);
1400 break;
1401 }
1402 }
1403
1404 free(nameflag);
1405
1406 if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1407 op != CW_O_PREPROCESS) {
1408 errx(2, "multiple source files are "
1409 "allowed only with -E or -P");
1410 }
1411
1412 /*
1413 * Make sure that we do not have any unintended interactions between
1414 * the xarch options passed in and the version of the Studio compiler
1415 * used.
1416 */
1417 if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1418 errx(2,
1419 "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1420 }
1421
1422 switch (mflag) {
1423 case 0:
1424 /* FALLTHROUGH */
1425 case M32:
1426 #if defined(__sparc)
1427 /*
1428 * Only -m32 is defined and so put in the missing xarch
1429 * translation.
1430 */
1431 newae(ctx->i_ae, "-mcpu=v8");
1432 newae(ctx->i_ae, "-mno-v8plus");
1433 #endif
1434 break;
1435 case M64:
1436 #if defined(__sparc)
1437 /*
1438 * Only -m64 is defined and so put in the missing xarch
1479 if (!nolibc)
1480 newae(ctx->i_ae, "-lc");
1481 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1482 newae(ctx->i_ae, "-o");
1483 newae(ctx->i_ae, ctx->i_discard);
1484 }
1485 }
1486
1487 static void
1488 do_cc(cw_ictx_t *ctx)
1489 {
1490 int in_output = 0, seen_o = 0;
1491 cw_op_t op = CW_O_LINK;
1492 char *nameflag;
1493
1494 if (ctx->i_flags & CW_F_PROG) {
1495 newae(ctx->i_ae, "-V");
1496 return;
1497 }
1498
1499 if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1500 nomem();
1501
1502 while (--ctx->i_oldargc > 0) {
1503 char *arg = *++ctx->i_oldargv;
1504
1505 if (strncmp(arg, "-_CC=", 5) == 0) {
1506 newae(ctx->i_ae, strchr(arg, '=') + 1);
1507 continue;
1508 }
1509
1510 if (*arg != '-') {
1511 if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1512 newae(ctx->i_ae, arg);
1513 } else {
1514 in_output = 0;
1515 newae(ctx->i_ae, ctx->i_discard);
1516 }
1517 continue;
1518 }
1519 switch (*(arg + 1)) {
1555 default:
1556 newae(ctx->i_ae, arg);
1557 }
1558 }
1559
1560 free(nameflag);
1561
1562 if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1563 (ctx->i_flags & CW_F_SHADOW))
1564 exit(0);
1565
1566 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1567 newae(ctx->i_ae, "-o");
1568 newae(ctx->i_ae, ctx->i_discard);
1569 }
1570 }
1571
1572 static void
1573 prepctx(cw_ictx_t *ctx)
1574 {
1575 newae(ctx->i_ae, ctx->i_compiler->c_path);
1576
1577 if (ctx->i_flags & CW_F_PROG) {
1578 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1579 "shadow" : "primary", ctx->i_compiler->c_path);
1580 (void) fflush(stdout);
1581 }
1582
1583 if (!(ctx->i_flags & CW_F_XLATE))
1584 return;
1585
1586 switch (ctx->i_compiler->c_style) {
1587 case SUN:
1588 do_cc(ctx);
1589 break;
1590 case GNU:
1591 do_gcc(ctx);
1592 break;
1593 }
1594 }
1595
1596 static int
1597 invoke(cw_ictx_t *ctx)
1598 {
1599 char **newargv;
1600 int ac;
1601 struct ae *a;
1602
1603 if ((newargv = calloc(sizeof (*newargv), ctx->i_ae->ael_argc + 1)) ==
1604 NULL)
1605 nomem();
1606
1739 prepctx(ctx);
1740 exit(invoke(ctx));
1741 }
1742
1743 if (ctx->i_pid < 0) {
1744 err(1, "fork failed");
1745 }
1746
1747 if (block)
1748 return (reap(ctx));
1749
1750 return (0);
1751 }
1752
1753 static int
1754 parse_compiler(const char *spec, cw_compiler_t *compiler)
1755 {
1756 char *tspec, *token;
1757
1758 if ((tspec = strdup(spec)) == NULL)
1759 nomem();
1760
1761 if ((token = strsep(&tspec, ",")) == NULL)
1762 errx(1, "Compiler is missing a name: %s", spec);
1763 compiler->c_name = token;
1764
1765 if ((token = strsep(&tspec, ",")) == NULL)
1766 errx(1, "Compiler is missing a path: %s", spec);
1767 compiler->c_path = token;
1768
1769 if ((token = strsep(&tspec, ",")) == NULL)
1770 errx(1, "Compiler is missing a style: %s", spec);
1771
1772 if ((strcasecmp(token, "gnu") == 0) ||
1773 (strcasecmp(token, "gcc") == 0))
1774 compiler->c_style = GNU;
1775 else if ((strcasecmp(token, "sun") == 0) ||
1776 (strcasecmp(token, "cc") == 0))
1777 compiler->c_style = SUN;
1778 else
1779 errx(1, "unknown compiler style: %s", token);
1780
1781 if (tspec != NULL)
1782 errx(1, "Excess tokens in compiler: %s", spec);
1783
1784 return (0);
1785 }
1786
1787 int
1788 main(int argc, char **argv)
1789 {
1790 int ch;
1791 cw_compiler_t primary = { NULL, NULL, 0 };
1792 cw_compiler_t shadows[10];
1793 int nshadows = 0;
1794 int ret = 0;
1795 boolean_t do_serial = B_FALSE;
1796 boolean_t do_exec = B_FALSE;
1797 boolean_t vflg = B_FALSE;
1798 boolean_t Cflg = B_FALSE;
1799 boolean_t cflg = B_FALSE;
1800 boolean_t nflg = B_FALSE;
1801
1802 cw_ictx_t *main_ctx;
1803
1804 static struct option longopts[] = {
1805 { "compiler", no_argument, NULL, 'c' },
1806 { "noecho", no_argument, NULL, 'n' },
1807 { "primary", required_argument, NULL, 'p' },
1808 { "shadow", required_argument, NULL, 's' },
1809 { "versions", no_argument, NULL, 'v' },
1810 { NULL, 0, NULL, 0 },
1811 };
1812
1813
1814 if ((main_ctx = newictx()) == NULL)
1815 nomem();
1816
1817
1818 while ((ch = getopt_long(argc, argv, "C", longopts, NULL)) != -1) {
1819 switch (ch) {
1820 case 'c':
1821 cflg = B_TRUE;
1822 break;
1823 case 'C':
1824 Cflg = B_TRUE;
1825 break;
1826 case 'n':
1827 nflg = B_TRUE;
1828 break;
1829 case 'p':
1830 if (primary.c_path != NULL) {
1831 warnx("Only one primary compiler may "
1832 "be specified");
1833 usage();
1834 }
1835
1836 if (parse_compiler(optarg, &primary) != 0)
1837 errx(1, "Couldn't parse %s as a compiler spec",
1838 optarg);
1839 break;
1840 case 's':
1841 if (nshadows >= 10)
1842 errx(1, "May only use 10 shadows at "
1843 "the moment");
1844 if (parse_compiler(optarg, &shadows[nshadows]) != 0)
1845 errx(1, "Couldn't parse %s as a compiler spec",
1846 optarg);
1847 nshadows++;
1848 break;
1849 case 'v':
1850 vflg = B_TRUE;
1851 break;
1852 default:
1853 (void) fprintf(stderr, "Did you forget '--'?\n");
1854 usage();
1855 }
1856 }
1857
1858 if (primary.c_path == NULL) {
1859 warnx("A primary compiler must be specified");
1860 usage();
1861 }
1862
1863 do_serial = (getenv("CW_SHADOW_SERIAL") == NULL) ? B_FALSE : B_TRUE;
1864 do_exec = (getenv("CW_NO_EXEC") == NULL) ? B_TRUE : B_FALSE;
1865
1866 /* Leave room for argv[0] */
1867 argc -= (optind - 1);
1868 argv += (optind - 1);
1869
1870 main_ctx->i_oldargc = argc;
1871 main_ctx->i_oldargv = argv;
1872 main_ctx->i_flags = CW_F_XLATE;
1873 if (nflg == 0)
1874 main_ctx->i_flags |= CW_F_ECHO;
1875 if (do_exec)
1876 main_ctx->i_flags |= CW_F_EXEC;
1877 if (Cflg)
1878 main_ctx->i_flags |= CW_F_CXX;
1879 main_ctx->i_compiler = &primary;
1880
1881 if (cflg) {
1882 (void) fputs(primary.c_path, stdout);
1883 }
1884
1885 if (vflg) {
1886 (void) printf("cw version %s\n", CW_VERSION);
1887 (void) fflush(stdout);
1888 main_ctx->i_flags &= ~CW_F_ECHO;
1889 main_ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
1890 do_serial = 1;
1891 }
1892
1893 ret |= exec_ctx(main_ctx, do_serial);
1894
1895 for (int i = 0; i < nshadows; i++) {
1896 cw_ictx_t *shadow_ctx;
1897
1898 if ((shadow_ctx = newictx()) == NULL)
1899 nomem();
1900
1901 memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
1902
1903 shadow_ctx->i_flags |= CW_F_SHADOW;
1904 shadow_ctx->i_compiler = &shadows[i];
1905
1906 /* XXX: Would be nice to run these parallel, too */
1907 ret |= exec_ctx(shadow_ctx, 1);
1908 }
1909
1910 if (!do_serial)
1911 ret |= reap(main_ctx);
1912
1913 return (ret);
1914 }
|