ref: ff5b36e280ae269eaa3835006f0f46fbe1bb2d2f
parent: a0ff31c2362324edf915883b2faa324377be1b4a
	author: Roberto E. Vargas Caballero <k0ga@shike2.com>
	date: Sun Oct  6 18:08:00 EDT 2019
	
[cc] Rename scc executable to cc
--- a/src/cmd/cc/posix/Makefile
+++ b/src/cmd/cc/posix/Makefile
@@ -12,12 +12,12 @@
i386-sysv-linux-elf\
amd64-sysv-openbsd-elf\
-TARGETS = $(BINDIR)/scc $(BINDIR)/cpp
+TARGETS = $(BINDIR)/cc $(BINDIR)/cpp
all: $(TARGETS)
-$(BINDIR)/scc: scc.o
- $(CC) $(SCC_LDFLAGS) scc.o -lscc -o $@
+$(BINDIR)/cc: cc.o
+ $(CC) $(SCC_LDFLAGS) cc.o -lscc -o $@
$(BINDIR)/cpp: cpp.sh
trap "rm -f $$$$.sh" 0 2 3;\
--- /dev/null
+++ b/src/cmd/cc/posix/cc.c
@@ -1,0 +1,658 @@
+#define _POSIX_SOURCE
+#define _XOPEN_SOURCE 500
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include <scc/arg.h>
+#include <scc/scc.h>
+#include <scc/syscrts.h>
+#include <scc/sysincludes.h>
+#include <scc/syslibs.h>
+#include <scc/ldflags.h>
+
+enum {+ CC1,
+ TEEIR,
+ CC2,
+ TEEQBE,
+ QBE,
+ TEEAS,
+ AS,
+ LD,
+ STRIP,
+ LAST_TOOL,
+};
+
+static struct tool {+ char cmd[PATH_MAX];
+ char bin[32];
+ char *outfile;
+ struct items args;
+ unsigned nparams;
+ int in, out, init;
+ pid_t pid;
+} tools[] = {+	[CC1]    = { .cmd = "cc1" },+	[TEEIR]  = { .bin = "tee",   .cmd = "tee", },+	[CC2]    = { .cmd = "cc2" },+	[TEEQBE] = { .bin = "tee",   .cmd = "tee", },+	[QBE]    = { .bin = "qbe",   .cmd = "qbe", },+	[TEEAS]  = { .bin = "tee",   .cmd = "tee", },+	[AS]     = { .bin = "as",    .cmd = "as", },+	[LD]     = { .bin = "ld",    .cmd = "ld", },+	[STRIP]  = { .bin = "strip", .cmd = "strip", },+};
+
+char *argv0;
+static char *arch, *sys, *abi, *format;
+static char *prefix, *objfile, *outfile;
+static char *tmpdir;
+static size_t tmpdirln;
+static struct items objtmp, objout;
+static int Mflag, Eflag, Sflag, Wflag,
+ cflag, dflag, kflag, sflag, Qflag = 1; /* TODO: Remove Qflag */
+static int devnullfd = -1;
+
+extern int failure;
+
+static void
+terminate(void)
+{+ unsigned i;
+
+	if (!kflag) {+ for (i = 0; i < objtmp.n; ++i)
+ unlink(objtmp.s[i]);
+ }
+}
+
+static char *
+path(char *s)
+{+ char *arg, buff[FILENAME_MAX];
+ size_t len, cnt;
+
+	for ( ; *s && cnt < FILENAME_MAX; ++s) {+		if (*s != '%') {+ buff[cnt++] = *s;
+ continue;
+ }
+
+		switch (*++s) {+ case 'a':
+ arg = arch;
+ break;
+ case 's':
+ arg = sys;
+ break;
+ case 'p':
+ arg = prefix;
+ break;
+ case 'b':
+ arg = abi;
+ break;
+ default:
+ buff[cnt++] = *s;
+ continue;
+ }
+
+ len = strlen(arg);
+ if (len + cnt >= FILENAME_MAX)
+ goto too_long;
+ memcpy(buff+cnt, arg, len);
+ cnt += len;
+ }
+
+ if (cnt != FILENAME_MAX)
+ return xstrdup(buff);
+
+too_long:
+	die("cc: too long pathname");+}
+
+static void
+addarg(int tool, char *arg)
+{+ struct tool *t = &tools[tool];
+
+ if (t->args.n < 1)
+ t->args.n = 1;
+
+ newitem(&t->args, arg);
+}
+
+static void
+setargv0(int tool, char *arg)
+{+ struct tool *t = &tools[tool];
+
+ if (t->args.n > 0)
+ t->args.s[0] = arg;
+ else
+ newitem(&t->args, arg);
+}
+
+static int
+qbe(int tool)
+{+ if (tool != CC2 || !Qflag)
+ return 0;
+ if (!strcmp(arch, "amd64") && !strcmp(abi, "sysv"))
+ return 1;
+ return 0;
+}
+
+static int
+inittool(int tool)
+{+ struct tool *t = &tools[tool];
+ char *crt, *fmt;
+ int n;
+
+ if (t->init)
+ return tool;
+
+	switch (tool) {+ case CC1:
+ if (Wflag)
+ addarg(tool, "-w");
+		for (n = 0; sysincludes[n]; ++n) {+ addarg(tool, "-I");
+ addarg(tool, path(sysincludes[n]));
+ }
+ case CC2:
+ fmt = (qbe(tool)) ? "%s-qbe_%s-%s" : "%s-%s-%s";
+ n = snprintf(t->bin, sizeof(t->bin), fmt, t->cmd, arch, abi);
+ if (n < 0 || n >= sizeof(t->bin))
+			die("cc: target tool name too long");+
+ n = snprintf(t->cmd, sizeof(t->cmd),
+ "%s/libexec/scc/%s", prefix, t->bin);
+ if (n < 0 || n >= sizeof(t->cmd))
+			die("cc: target tool path too long");+ break;
+ case LD:
+ for (n = 0; ldflags[n]; ++n)
+ addarg(tool, ldflags[n]);
+ addarg(tool, "-o");
+		t->outfile = outfile ? outfile : xstrdup("a.out");+ addarg(tool, t->outfile);
+		for (n = 0; syslibs[n]; ++n) {+ addarg(tool, "-L");
+ addarg(tool, path(syslibs[n]));
+ }
+ for (n = 0; syscrts[n]; ++n)
+ addarg(tool, path(syscrts[n]));
+ break;
+ case AS:
+ addarg(tool, "-o");
+ break;
+ default:
+ break;
+ }
+
+ setargv0(tool, t->bin);
+ t->nparams = t->args.n;
+ t->init = 1;
+
+ return tool;
+}
+
+static char *
+outfname(char *path, char *type)
+{+ char *new, sep, *p;
+ size_t newsz, pathln;
+ int tmpfd, n;
+
+	if (path) {+ sep = '.';
+ if (p = strrchr(path, '/'))
+ path = p + 1;
+ pathln = strlen(path);
+ if (p = strrchr(path, '.'))
+ pathln -= strlen(p);
+	} else {+ sep = '/';
+ type = "scc-XXXXXX";
+ path = tmpdir;
+ pathln = tmpdirln;
+ }
+
+ newsz = pathln + 1 + strlen(type) + 1;
+ new = xmalloc(newsz);
+ n = snprintf(new, newsz, "%.*s%c%s", (int)pathln, path, sep, type);
+ if (n < 0 || n >= newsz)
+		die("cc: wrong output filename");+	if (sep == '/') {+ if ((tmpfd = mkstemp(new)) < 0)
+			die("cc: could not create output file '%s': %s",+ new, strerror(errno));
+ close(tmpfd);
+ }
+
+ return new;
+}
+
+static int
+settool(int tool, char *infile, int nexttool)
+{+ struct tool *t = &tools[tool];
+ unsigned i;
+ int fds[2];
+ static int fdin = -1;
+
+	switch (tool) {+ case TEEIR:
+ t->outfile = outfname(infile, "ir");
+ addarg(tool, t->outfile);
+ break;
+ case TEEQBE:
+ t->outfile = outfname(infile, "qbe");
+ addarg(tool, t->outfile);
+ break;
+ case TEEAS:
+ t->outfile = outfname(infile, "s");
+ addarg(tool, t->outfile);
+ break;
+ case AS:
+		if (cflag && outfile) {+ objfile = outfile;
+		} else {+ objfile = (cflag || kflag) ? infile : NULL;
+ objfile = outfname(objfile, "o");
+ }
+ t->outfile = xstrdup(objfile);
+ addarg(tool, t->outfile);
+ break;
+ case STRIP:
+		if (cflag || kflag) {+ for (i = 0; i < objout.n; ++i)
+ addarg(tool, xstrdup(objout.s[i]));
+ }
+ if (!cflag && tools[LD].outfile)
+ addarg(tool, tools[LD].outfile);
+ break;
+ default:
+ break;
+ }
+
+	if (fdin > -1) {+ t->in = fdin;
+ fdin = -1;
+	} else {+ t->in = -1;
+ if (infile)
+ addarg(tool, xstrdup(infile));
+ }
+
+	if (nexttool < LAST_TOOL) {+ if (pipe(fds))
+			die("cc: pipe: %s", strerror(errno));+ t->out = fds[1];
+ fdin = fds[0];
+	} else {+ t->out = -1;
+ }
+
+ addarg(tool, NULL);
+
+ return tool;
+}
+
+static void
+spawn(int tool)
+{+ char **ap;
+ struct tool *t = &tools[tool];
+
+	switch (t->pid = fork()) {+ case -1:
+		die("cc: %s: %s", t->bin, strerror(errno));+ case 0:
+ if (t->out > -1)
+ dup2(t->out, 1);
+ if (t->in > -1)
+ dup2(t->in, 0);
+ if (!dflag && tool != CC1 && tool != LD)
+ dup2(devnullfd, 2);
+		if (dflag) {+ for (ap = t->args.s; *ap; ap++)
+ fprintf(stderr, " %s", *ap);
+			putc('\n', stderr);+ }
+ execvp(t->cmd, t->args.s);
+		if (dflag) {+ fprintf(stderr,
+ "scc: execvp %s: %s\n",
+ t->cmd,
+ strerror(errno));
+ }
+ abort();
+ default:
+ if (t->in > -1)
+ close(t->in);
+ if (t->out > -1)
+ close(t->out);
+ break;
+ }
+}
+
+static int
+toolfor(char *file)
+{+ char *dot = strrchr(file, '.');
+
+	if (dot) {+ if (!strcmp(dot, ".c"))
+ return CC1;
+ if (!strcmp(dot, ".ir"))
+ return CC2;
+ if (!strcmp(dot, ".qbe"))
+ return QBE;
+ if (!strcmp(dot, ".s"))
+ return AS;
+ if (!strcmp(dot, ".o"))
+ return LD;
+ if (!strcmp(dot, ".a"))
+ return LD;
+	} else if (!strcmp(file, "-")) {+ return CC1;
+ }
+
+	die("cc: do not recognize filetype of %s", file);+}
+
+static int
+valid(int tool, struct tool *t)
+{+ int st;
+
+ if (waitpid(t->pid, &st, 0) == -1 || WIFSIGNALED(st))
+ goto internal;
+ if (WIFEXITED(st) && WEXITSTATUS(st) == 0)
+ return 1;
+ if (!failure && (tool == CC1 || tool == LD))
+ goto fail;
+
+internal:
+ fprintf(stderr, "cc:%s: internal error\n", t->bin);
+fail:
+ failure = 1;
+ return 0;
+}
+
+static int
+validatetools(void)
+{+ struct tool *t;
+ unsigned i;
+ int tool, st, failed = LAST_TOOL;
+
+	for (tool = 0; tool < LAST_TOOL; ++tool) {+ t = &tools[tool];
+ if (!t->pid)
+ continue;
+ if (!valid(tool, t))
+ failed = tool;
+ if (tool >= failed && t->outfile)
+ unlink(t->outfile);
+ for (i = t->nparams; i < t->args.n; ++i)
+ free(t->args.s[i]);
+ t->args.n = t->nparams;
+ t->pid = 0;
+ }
+	if (failed < LAST_TOOL) {+ unlink(objfile);
+ free(objfile);
+ objfile = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+buildfile(char *file, int tool)
+{+ int nexttool;
+
+	for (; tool < LAST_TOOL; tool = nexttool) {+		switch (tool) {+ case CC1:
+ if (Eflag || Mflag)
+ nexttool = LAST_TOOL;
+ else
+ nexttool = kflag ? TEEIR : CC2;
+ break;
+ case TEEIR:
+ nexttool = CC2;
+ break;
+ case CC2:
+ if (Qflag)
+ nexttool = kflag ? TEEQBE : QBE;
+ else
+ nexttool = (Sflag || kflag) ? TEEAS : AS;
+ break;
+ case TEEQBE:
+ nexttool = QBE;
+ break;
+ case QBE:
+ nexttool = (Sflag || kflag) ? TEEAS : AS;
+ break;
+ case TEEAS:
+ nexttool = Sflag ? LAST_TOOL : AS;
+ break;
+ case AS:
+ nexttool = LAST_TOOL;
+ break;
+ default:
+ nexttool = LAST_TOOL;
+ continue;
+ }
+
+ spawn(settool(inittool(tool), file, nexttool));
+ }
+
+ return validatetools();
+}
+
+static void
+build(struct items *chain, int link)
+{+ int i, tool;
+
+ if (link)
+ inittool(LD);
+
+	for (i = 0; i < chain->n; ++i) {+		if (!strcmp(chain->s[i], "-l")) {+			if (link) {+ addarg(LD, xstrdup(chain->s[i++]));
+ addarg(LD, xstrdup(chain->s[i]));
+			} else {+ ++i;
+ }
+ continue;
+ }
+ tool = toolfor(chain->s[i]);
+		if (tool == LD) {+ if (link)
+ addarg(LD, xstrdup(chain->s[i]));
+ continue;
+ }
+		if (buildfile(chain->s[i], tool)) {+ if (link)
+ addarg(LD, xstrdup(objfile));
+ newitem((!link || kflag) ? &objout : &objtmp, objfile);
+ }
+ }
+}
+
+static void
+usage(void)
+{+	fputs("usage: scc [-D def[=val]]... [-U def]... [-I dir]... "+ "[-L dir]... [-l dir]...\n"
+ " [-dgksw] [-m arch] [-M|-E|-S] [-o outfile] file...\n"
+ " scc [-D def[=val]]... [-U def]... [-I dir]... "
+ "[-L dir]... [-l dir]...\n"
+ " [-dgksw] [-m arch] [-M|-E|-S] -c file...\n"
+ " scc [-D def[=val]]... [-U def]... [-I dir]... "
+ "[-L dir]... [-l dir]...\n"
+ " [-dgksw] [-m arch] -c -o outfile file\n", stderr);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{+	struct items linkchain = { .n = 0, };+ int link;
+
+ atexit(terminate);
+
+	if (!(arch = getenv("ARCH")))+ arch = ARCH;
+	if (!(sys = getenv("SYS")))+ sys = SYS;
+	if (!(abi = getenv("ABI")))+ abi = ABI;
+	if (!(format = getenv("FORMAT")))+ format = FORMAT;
+	if (!(prefix = getenv("SCCPREFIX")))+ prefix = PREFIX;
+
+	ARGBEGIN {+ case 'D':
+ addarg(CC1, "-D");
+ addarg(CC1, EARGF(usage()));
+ break;
+ case 'M':
+ Mflag = 1;
+ addarg(CC1, "-M");
+ break;
+ case 'E':
+ Eflag = 1;
+ addarg(CC1, "-E");
+ break;
+ case 'I':
+ addarg(CC1, "-I");
+ addarg(CC1, EARGF(usage()));
+ break;
+ case 'L':
+ addarg(LD, "-L");
+ addarg(LD, EARGF(usage()));
+ break;
+ case 'O':
+ EARGF(usage());
+ break;
+ case 'S':
+ Sflag = 1;
+ break;
+ case 'U':
+ addarg(CC1, "-U");
+ addarg(CC1, EARGF(usage()));
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'g':
+ addarg(AS, "-g");
+ addarg(LD, "-g");
+ break;
+ case 'k':
+ kflag = 1;
+ break;
+ case 'l':
+ newitem(&linkchain, "-l");
+ newitem(&linkchain, EARGF(usage()));
+ break;
+ case 'm':
+ arch = EARGF(usage());
+ break;
+ case 'o':
+ outfile = xstrdup(EARGF(usage()));
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 't':
+ sys = EARGF(usage());
+ break;
+ case 'w':
+ Wflag = 0;
+ break;
+ case 'W':
+ Wflag = 1;
+ break;
+ case 'q':
+ Qflag = 0;
+ break;
+ case 'Q':
+ Qflag = 1;
+ break;
+ case '-':
+ fprintf(stderr,
+ "scc: ignored parameter --%s\n", EARGF(usage()));
+ break;
+ default:
+ usage();
+	} ARGOPERAND {+operand:
+ newitem(&linkchain, ARGOP());
+ } ARGEND
+
+ for (; *argv; --argc, ++argv)
+ goto operand;
+
+ if (Eflag && linkchain.n == 0)
+ newitem(&linkchain, "-");
+
+ if (Eflag && Mflag ||
+ (Eflag || Mflag) && (Sflag || kflag) ||
+ linkchain.n == 0 ||
+ linkchain.n > 1 && cflag && outfile)
+ usage();
+
+	if (!dflag) {+		if ((devnullfd = open("/dev/null", O_WRONLY)) < 0)+			fputs("scc: could not open /dev/null\n", stderr);+ }
+
+	if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])+ tmpdir = ".";
+ tmpdirln = strlen(tmpdir);
+
+ build(&linkchain, (link = !(Mflag || Eflag || Sflag || cflag)));
+
+ if (!(link || cflag))
+ return failure;
+
+	if (link && !failure) {+		addarg(LD, xstrdup("-lc"));+		addarg(LD, xstrdup("-lcrt"));+ spawn(settool(LD, NULL, LAST_TOOL));
+ validatetools();
+ }
+
+	if (sflag) {+ spawn(settool(inittool(STRIP), NULL, LAST_TOOL));
+ validatetools();
+ }
+
+ return failure;
+}
--- a/src/cmd/cc/posix/cpp.sh
+++ b/src/cmd/cc/posix/cpp.sh
@@ -1,4 +1,4 @@
#!/bin/sh
 SCCPREFIX=${SCCPREFIX:-@PREFIX@}-${SCCPREFIX}/bin/scc -E $@+${SCCPREFIX}/bin/cc -E $@--- a/src/cmd/cc/posix/deps.mk
+++ b/src/cmd/cc/posix/deps.mk
@@ -1,8 +1,8 @@
#deps
-./scc.o: $(INCDIR)/scc/scc/arg.h
-./scc.o: $(INCDIR)/scc/scc/ldflags.h
-./scc.o: $(INCDIR)/scc/scc/scc.h
-./scc.o: $(INCDIR)/scc/scc/syscrts.h
-./scc.o: $(INCDIR)/scc/scc/sysincludes.h
-./scc.o: $(INCDIR)/scc/scc/syslibs.h
-./scc.o: ./config.h
+./cc.o: $(INCDIR)/scc/scc/arg.h
+./cc.o: $(INCDIR)/scc/scc/ldflags.h
+./cc.o: $(INCDIR)/scc/scc/scc.h
+./cc.o: $(INCDIR)/scc/scc/syscrts.h
+./cc.o: $(INCDIR)/scc/scc/sysincludes.h
+./cc.o: $(INCDIR)/scc/scc/syslibs.h
+./cc.o: ./config.h
--- a/src/cmd/cc/posix/scc.c
+++ /dev/null
@@ -1,658 +1,0 @@
-#define _POSIX_SOURCE
-#define _XOPEN_SOURCE 500
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include <scc/arg.h>
-#include <scc/scc.h>
-#include <scc/syscrts.h>
-#include <scc/sysincludes.h>
-#include <scc/syslibs.h>
-#include <scc/ldflags.h>
-
-enum {- CC1,
- TEEIR,
- CC2,
- TEEQBE,
- QBE,
- TEEAS,
- AS,
- LD,
- STRIP,
- LAST_TOOL,
-};
-
-static struct tool {- char cmd[PATH_MAX];
- char bin[32];
- char *outfile;
- struct items args;
- unsigned nparams;
- int in, out, init;
- pid_t pid;
-} tools[] = {-	[CC1]    = { .cmd = "cc1" },-	[TEEIR]  = { .bin = "tee",   .cmd = "tee", },-	[CC2]    = { .cmd = "cc2" },-	[TEEQBE] = { .bin = "tee",   .cmd = "tee", },-	[QBE]    = { .bin = "qbe",   .cmd = "qbe", },-	[TEEAS]  = { .bin = "tee",   .cmd = "tee", },-	[AS]     = { .bin = "as",    .cmd = "as", },-	[LD]     = { .bin = "ld",    .cmd = "ld", },-	[STRIP]  = { .bin = "strip", .cmd = "strip", },-};
-
-char *argv0;
-static char *arch, *sys, *abi, *format;
-static char *prefix, *objfile, *outfile;
-static char *tmpdir;
-static size_t tmpdirln;
-static struct items objtmp, objout;
-static int Mflag, Eflag, Sflag, Wflag,
- cflag, dflag, kflag, sflag, Qflag = 1; /* TODO: Remove Qflag */
-static int devnullfd = -1;
-
-extern int failure;
-
-static void
-terminate(void)
-{- unsigned i;
-
-	if (!kflag) {- for (i = 0; i < objtmp.n; ++i)
- unlink(objtmp.s[i]);
- }
-}
-
-static char *
-path(char *s)
-{- char *arg, buff[FILENAME_MAX];
- size_t len, cnt;
-
-	for ( ; *s && cnt < FILENAME_MAX; ++s) {-		if (*s != '%') {- buff[cnt++] = *s;
- continue;
- }
-
-		switch (*++s) {- case 'a':
- arg = arch;
- break;
- case 's':
- arg = sys;
- break;
- case 'p':
- arg = prefix;
- break;
- case 'b':
- arg = abi;
- break;
- default:
- buff[cnt++] = *s;
- continue;
- }
-
- len = strlen(arg);
- if (len + cnt >= FILENAME_MAX)
- goto too_long;
- memcpy(buff+cnt, arg, len);
- cnt += len;
- }
-
- if (cnt != FILENAME_MAX)
- return xstrdup(buff);
-
-too_long:
-	die("scc: too long pathname");-}
-
-static void
-addarg(int tool, char *arg)
-{- struct tool *t = &tools[tool];
-
- if (t->args.n < 1)
- t->args.n = 1;
-
- newitem(&t->args, arg);
-}
-
-static void
-setargv0(int tool, char *arg)
-{- struct tool *t = &tools[tool];
-
- if (t->args.n > 0)
- t->args.s[0] = arg;
- else
- newitem(&t->args, arg);
-}
-
-static int
-qbe(int tool)
-{- if (tool != CC2 || !Qflag)
- return 0;
- if (!strcmp(arch, "amd64") && !strcmp(abi, "sysv"))
- return 1;
- return 0;
-}
-
-static int
-inittool(int tool)
-{- struct tool *t = &tools[tool];
- char *crt, *fmt;
- int n;
-
- if (t->init)
- return tool;
-
-	switch (tool) {- case CC1:
- if (Wflag)
- addarg(tool, "-w");
-		for (n = 0; sysincludes[n]; ++n) {- addarg(tool, "-I");
- addarg(tool, path(sysincludes[n]));
- }
- case CC2:
- fmt = (qbe(tool)) ? "%s-qbe_%s-%s" : "%s-%s-%s";
- n = snprintf(t->bin, sizeof(t->bin), fmt, t->cmd, arch, abi);
- if (n < 0 || n >= sizeof(t->bin))
-			die("scc: target tool name too long");-
- n = snprintf(t->cmd, sizeof(t->cmd),
- "%s/libexec/scc/%s", prefix, t->bin);
- if (n < 0 || n >= sizeof(t->cmd))
-			die("scc: target tool path too long");- break;
- case LD:
- for (n = 0; ldflags[n]; ++n)
- addarg(tool, ldflags[n]);
- addarg(tool, "-o");
-		t->outfile = outfile ? outfile : xstrdup("a.out");- addarg(tool, t->outfile);
-		for (n = 0; syslibs[n]; ++n) {- addarg(tool, "-L");
- addarg(tool, path(syslibs[n]));
- }
- for (n = 0; syscrts[n]; ++n)
- addarg(tool, path(syscrts[n]));
- break;
- case AS:
- addarg(tool, "-o");
- break;
- default:
- break;
- }
-
- setargv0(tool, t->bin);
- t->nparams = t->args.n;
- t->init = 1;
-
- return tool;
-}
-
-static char *
-outfname(char *path, char *type)
-{- char *new, sep, *p;
- size_t newsz, pathln;
- int tmpfd, n;
-
-	if (path) {- sep = '.';
- if (p = strrchr(path, '/'))
- path = p + 1;
- pathln = strlen(path);
- if (p = strrchr(path, '.'))
- pathln -= strlen(p);
-	} else {- sep = '/';
- type = "scc-XXXXXX";
- path = tmpdir;
- pathln = tmpdirln;
- }
-
- newsz = pathln + 1 + strlen(type) + 1;
- new = xmalloc(newsz);
- n = snprintf(new, newsz, "%.*s%c%s", (int)pathln, path, sep, type);
- if (n < 0 || n >= newsz)
-		die("scc: wrong output filename");-	if (sep == '/') {- if ((tmpfd = mkstemp(new)) < 0)
-			die("scc: could not create output file '%s': %s",- new, strerror(errno));
- close(tmpfd);
- }
-
- return new;
-}
-
-static int
-settool(int tool, char *infile, int nexttool)
-{- struct tool *t = &tools[tool];
- unsigned i;
- int fds[2];
- static int fdin = -1;
-
-	switch (tool) {- case TEEIR:
- t->outfile = outfname(infile, "ir");
- addarg(tool, t->outfile);
- break;
- case TEEQBE:
- t->outfile = outfname(infile, "qbe");
- addarg(tool, t->outfile);
- break;
- case TEEAS:
- t->outfile = outfname(infile, "s");
- addarg(tool, t->outfile);
- break;
- case AS:
-		if (cflag && outfile) {- objfile = outfile;
-		} else {- objfile = (cflag || kflag) ? infile : NULL;
- objfile = outfname(objfile, "o");
- }
- t->outfile = xstrdup(objfile);
- addarg(tool, t->outfile);
- break;
- case STRIP:
-		if (cflag || kflag) {- for (i = 0; i < objout.n; ++i)
- addarg(tool, xstrdup(objout.s[i]));
- }
- if (!cflag && tools[LD].outfile)
- addarg(tool, tools[LD].outfile);
- break;
- default:
- break;
- }
-
-	if (fdin > -1) {- t->in = fdin;
- fdin = -1;
-	} else {- t->in = -1;
- if (infile)
- addarg(tool, xstrdup(infile));
- }
-
-	if (nexttool < LAST_TOOL) {- if (pipe(fds))
-			die("scc: pipe: %s", strerror(errno));- t->out = fds[1];
- fdin = fds[0];
-	} else {- t->out = -1;
- }
-
- addarg(tool, NULL);
-
- return tool;
-}
-
-static void
-spawn(int tool)
-{- char **ap;
- struct tool *t = &tools[tool];
-
-	switch (t->pid = fork()) {- case -1:
-		die("scc: %s: %s", t->bin, strerror(errno));- case 0:
- if (t->out > -1)
- dup2(t->out, 1);
- if (t->in > -1)
- dup2(t->in, 0);
- if (!dflag && tool != CC1 && tool != LD)
- dup2(devnullfd, 2);
-		if (dflag) {- for (ap = t->args.s; *ap; ap++)
- fprintf(stderr, " %s", *ap);
-			putc('\n', stderr);- }
- execvp(t->cmd, t->args.s);
-		if (dflag) {- fprintf(stderr,
- "scc: execvp %s: %s\n",
- t->cmd,
- strerror(errno));
- }
- abort();
- default:
- if (t->in > -1)
- close(t->in);
- if (t->out > -1)
- close(t->out);
- break;
- }
-}
-
-static int
-toolfor(char *file)
-{- char *dot = strrchr(file, '.');
-
-	if (dot) {- if (!strcmp(dot, ".c"))
- return CC1;
- if (!strcmp(dot, ".ir"))
- return CC2;
- if (!strcmp(dot, ".qbe"))
- return QBE;
- if (!strcmp(dot, ".s"))
- return AS;
- if (!strcmp(dot, ".o"))
- return LD;
- if (!strcmp(dot, ".a"))
- return LD;
-	} else if (!strcmp(file, "-")) {- return CC1;
- }
-
-	die("scc: do not recognize filetype of %s", file);-}
-
-static int
-valid(int tool, struct tool *t)
-{- int st;
-
- if (waitpid(t->pid, &st, 0) == -1 || WIFSIGNALED(st))
- goto internal;
- if (WIFEXITED(st) && WEXITSTATUS(st) == 0)
- return 1;
- if (!failure && (tool == CC1 || tool == LD))
- goto fail;
-
-internal:
- fprintf(stderr, "scc:%s: internal error\n", t->bin);
-fail:
- failure = 1;
- return 0;
-}
-
-static int
-validatetools(void)
-{- struct tool *t;
- unsigned i;
- int tool, st, failed = LAST_TOOL;
-
-	for (tool = 0; tool < LAST_TOOL; ++tool) {- t = &tools[tool];
- if (!t->pid)
- continue;
- if (!valid(tool, t))
- failed = tool;
- if (tool >= failed && t->outfile)
- unlink(t->outfile);
- for (i = t->nparams; i < t->args.n; ++i)
- free(t->args.s[i]);
- t->args.n = t->nparams;
- t->pid = 0;
- }
-	if (failed < LAST_TOOL) {- unlink(objfile);
- free(objfile);
- objfile = NULL;
- return 0;
- }
-
- return 1;
-}
-
-static int
-buildfile(char *file, int tool)
-{- int nexttool;
-
-	for (; tool < LAST_TOOL; tool = nexttool) {-		switch (tool) {- case CC1:
- if (Eflag || Mflag)
- nexttool = LAST_TOOL;
- else
- nexttool = kflag ? TEEIR : CC2;
- break;
- case TEEIR:
- nexttool = CC2;
- break;
- case CC2:
- if (Qflag)
- nexttool = kflag ? TEEQBE : QBE;
- else
- nexttool = (Sflag || kflag) ? TEEAS : AS;
- break;
- case TEEQBE:
- nexttool = QBE;
- break;
- case QBE:
- nexttool = (Sflag || kflag) ? TEEAS : AS;
- break;
- case TEEAS:
- nexttool = Sflag ? LAST_TOOL : AS;
- break;
- case AS:
- nexttool = LAST_TOOL;
- break;
- default:
- nexttool = LAST_TOOL;
- continue;
- }
-
- spawn(settool(inittool(tool), file, nexttool));
- }
-
- return validatetools();
-}
-
-static void
-build(struct items *chain, int link)
-{- int i, tool;
-
- if (link)
- inittool(LD);
-
-	for (i = 0; i < chain->n; ++i) {-		if (!strcmp(chain->s[i], "-l")) {-			if (link) {- addarg(LD, xstrdup(chain->s[i++]));
- addarg(LD, xstrdup(chain->s[i]));
-			} else {- ++i;
- }
- continue;
- }
- tool = toolfor(chain->s[i]);
-		if (tool == LD) {- if (link)
- addarg(LD, xstrdup(chain->s[i]));
- continue;
- }
-		if (buildfile(chain->s[i], tool)) {- if (link)
- addarg(LD, xstrdup(objfile));
- newitem((!link || kflag) ? &objout : &objtmp, objfile);
- }
- }
-}
-
-static void
-usage(void)
-{-	fputs("usage: scc [-D def[=val]]... [-U def]... [-I dir]... "- "[-L dir]... [-l dir]...\n"
- " [-dgksw] [-m arch] [-M|-E|-S] [-o outfile] file...\n"
- " scc [-D def[=val]]... [-U def]... [-I dir]... "
- "[-L dir]... [-l dir]...\n"
- " [-dgksw] [-m arch] [-M|-E|-S] -c file...\n"
- " scc [-D def[=val]]... [-U def]... [-I dir]... "
- "[-L dir]... [-l dir]...\n"
- " [-dgksw] [-m arch] -c -o outfile file\n", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{-	struct items linkchain = { .n = 0, };- int link;
-
- atexit(terminate);
-
-	if (!(arch = getenv("ARCH")))- arch = ARCH;
-	if (!(sys = getenv("SYS")))- sys = SYS;
-	if (!(abi = getenv("ABI")))- abi = ABI;
-	if (!(format = getenv("FORMAT")))- format = FORMAT;
-	if (!(prefix = getenv("SCCPREFIX")))- prefix = PREFIX;
-
-	ARGBEGIN {- case 'D':
- addarg(CC1, "-D");
- addarg(CC1, EARGF(usage()));
- break;
- case 'M':
- Mflag = 1;
- addarg(CC1, "-M");
- break;
- case 'E':
- Eflag = 1;
- addarg(CC1, "-E");
- break;
- case 'I':
- addarg(CC1, "-I");
- addarg(CC1, EARGF(usage()));
- break;
- case 'L':
- addarg(LD, "-L");
- addarg(LD, EARGF(usage()));
- break;
- case 'O':
- EARGF(usage());
- break;
- case 'S':
- Sflag = 1;
- break;
- case 'U':
- addarg(CC1, "-U");
- addarg(CC1, EARGF(usage()));
- break;
- case 'c':
- cflag = 1;
- break;
- case 'd':
- dflag = 1;
- break;
- case 'g':
- addarg(AS, "-g");
- addarg(LD, "-g");
- break;
- case 'k':
- kflag = 1;
- break;
- case 'l':
- newitem(&linkchain, "-l");
- newitem(&linkchain, EARGF(usage()));
- break;
- case 'm':
- arch = EARGF(usage());
- break;
- case 'o':
- outfile = xstrdup(EARGF(usage()));
- break;
- case 's':
- sflag = 1;
- break;
- case 't':
- sys = EARGF(usage());
- break;
- case 'w':
- Wflag = 0;
- break;
- case 'W':
- Wflag = 1;
- break;
- case 'q':
- Qflag = 0;
- break;
- case 'Q':
- Qflag = 1;
- break;
- case '-':
- fprintf(stderr,
- "scc: ignored parameter --%s\n", EARGF(usage()));
- break;
- default:
- usage();
-	} ARGOPERAND {-operand:
- newitem(&linkchain, ARGOP());
- } ARGEND
-
- for (; *argv; --argc, ++argv)
- goto operand;
-
- if (Eflag && linkchain.n == 0)
- newitem(&linkchain, "-");
-
- if (Eflag && Mflag ||
- (Eflag || Mflag) && (Sflag || kflag) ||
- linkchain.n == 0 ||
- linkchain.n > 1 && cflag && outfile)
- usage();
-
-	if (!dflag) {-		if ((devnullfd = open("/dev/null", O_WRONLY)) < 0)-			fputs("scc: could not open /dev/null\n", stderr);- }
-
-	if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])- tmpdir = ".";
- tmpdirln = strlen(tmpdir);
-
- build(&linkchain, (link = !(Mflag || Eflag || Sflag || cflag)));
-
- if (!(link || cflag))
- return failure;
-
-	if (link && !failure) {-		addarg(LD, xstrdup("-lc"));-		addarg(LD, xstrdup("-lcrt"));- spawn(settool(LD, NULL, LAST_TOOL));
- validatetools();
- }
-
-	if (sflag) {- spawn(settool(inittool(STRIP), NULL, LAST_TOOL));
- validatetools();
- }
-
- return failure;
-}
--
⑨