shithub: scc

Download patch

ref: 5407d759369b8652a397ccaf48ff6841d6230148
parent: 4b4f06be34425576458f964a3279ab9d579128d5
parent: 13e9450a9ff1d651e155841258a126f91c7a5e77
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Jul 5 04:38:51 EDT 2016

Merge remote-tracking branch 'origin/master'

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -382,8 +382,10 @@
 extern void expect(unsigned tok);
 extern void discard(void);
 extern int addinput(char *fname);
+extern void allocinput(char *fname, FILE *fp, char *line);
+extern void delinput(void);
 extern void setsafe(int type);
-extern void ilex(char *fname);
+extern void ilex(void);
 #define accept(t) ((yytoken == (t)) ? next() : 0)
 
 /* code.c */
@@ -418,7 +420,7 @@
 extern int expand(char *begin, Symbol *sym);
 extern void incdir(char *dir);
 extern void outcpp(void);
-extern Symbol *defmacro(char *s);
+extern void defdefine(char *macro, char *val);
 extern void undefmacro(char *s);
 
 /*
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -13,6 +13,7 @@
 
 static char *argp, *macroname;
 static unsigned arglen;
+static unsigned ncmdlines;
 static Symbol *symline, *symfile;
 static unsigned char ifstatus[NR_COND];
 static int ninclude;
@@ -21,30 +22,20 @@
 unsigned cppctx;
 int disexpand;
 
-Symbol *
-defmacro(char *s)
+void
+defdefine(char *macro, char *val)
 {
-	char *p, *q;
-	Symbol *sym;
-	char def[] = "=1";
+	char *def, *fmt = "#define %s %s";
 
-	if ((p = strchr(s, '=')) == NULL)
-		p = def;
-	*p++='\0';
-	q = xmalloc(strlen(p) + 4);
-	sprintf(q, "-1#%s", p);
+	if (!val)
+		val = "";
+	def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
 
-	sym = lookup(NS_CPP, s);
-	if (sym->flags & SDECLARED) {
-		warn("'%s' redefined");
-		free(sym->u.s);
-	} else {
-		install(NS_CPP, sym);
-		sym->flags |= SDECLARED|SSTRING;
-	}
-
-	sym->u.s = q;
-	return sym;
+	sprintf(def, fmt, macro, val);
+	allocinput("command-line", NULL, def);
+	input->nline = ++ncmdlines;
+	cpp();
+	delinput();
 }
 
 void
@@ -56,7 +47,7 @@
 void
 icpp(void)
 {
-	static char sdate[17], stime[14];
+	static char sdate[14], stime[11];
 	struct tm *tm;
 	time_t t;
 	static char **bp, *list[] = {
@@ -81,20 +72,25 @@
 		{NULL, 0, 0}
 	};
 
+	keywords(keys, NS_CPPCLAUSES);
+
 	t = time(NULL);
 	tm = localtime(&t);
-	strftime(sdate, sizeof(sdate), "-1#\"%b %d %Y\"", tm);
-	strftime(stime, sizeof(stime), "-1#\"%H:%M:%S\"", tm);
-	defmacro("__DATE__")->u.s = sdate;
-	defmacro("__TIME__")->u.s = stime;
+	strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
+	strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
+	defdefine("__DATE__", sdate);
+	defdefine("__TIME__", stime);
+	defdefine("__STDC_VERSION__", "199409L");
+	defdefine("__LINE__", NULL);
+	defdefine("__FILE__", NULL);
 
-	defmacro("__STDC_VERSION__")->u.s = "-1#199409L";
-	symline = defmacro("__LINE__");
-	symfile = defmacro("__FILE__");
+	symline = lookup(NS_CPP, "__LINE__");
+	symfile = lookup(NS_CPP, "__FILE__");
 
 	for (bp = list; *bp; ++bp)
-		defmacro(*bp)->u.s = "-1#1";
-	keywords(keys, NS_CPPCLAUSES);
+		defdefine(*bp, NULL);
+
+	ncmdlines = 0;
 }
 
 static void
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -22,16 +22,18 @@
 static int safe, eof;
 Input *input;
 
-static void
-allocinput(char *fname, FILE *fp)
+void
+allocinput(char *fname, FILE *fp, char *line)
 {
-	Input *ip;
+	Input *ip = xmalloc(sizeof(Input));
 
-	ip = xmalloc(sizeof(Input));
-	ip->fname = xstrdup(fname);
-	ip->p = ip->begin = ip->line = xmalloc(INPUTSIZ);
-	ip->p[0] = '\0';
+	if (!line) {
+		line = xmalloc(INPUTSIZ);
+		line[0] = '\0';
+	}
+	ip->p = ip->begin = ip->line = line;
 	ip->nline = 0;
+	ip->fname = xstrdup(fname);
 	ip->next = input;
 	ip->fp = fp;
 	input = ip;
@@ -38,7 +40,7 @@
 }
 
 void
-ilex(char *fname)
+ilex(void)
 {
 	static struct keyword keys[] = {
 		{"auto", SCLASS, AUTO},
@@ -78,18 +80,6 @@
 		{"while", WHILE, WHILE},
 		{NULL, 0, 0},
 	};
-	FILE *fp;
-
-	if (!fname) {
-		fp = stdin;
-		fname = "<stdin>";
-	} else {
-		if ((fp = fopen(fname, "r")) == NULL) {
-			die("error: failed to open input file '%s': %s",
-			    fname, strerror(errno));
-		}
-	}
-	allocinput(fname, fp);
 	keywords(keys, NS_KEYWORD);
 }
 
@@ -98,21 +88,29 @@
 {
 	FILE *fp;
 
-	if ((fp = fopen(fname, "r")) == NULL)
-		return 0;
-	allocinput(fname, fp);
+	if (fname) {
+		if ((fp = fopen(fname, "r")) == NULL)
+			return 0;
+	} else {
+		fp = stdin;
+		fname = "<stdin>";
+	}
+	allocinput(fname, fp, NULL);
 	return 1;
 }
 
-static void
+void
 delinput(void)
 {
 	Input *ip = input;
 
-	if (!ip->next)
-		eof = 1;
-	if (fclose(ip->fp))
-		die("error: failed to read from input file '%s'", ip->fname);
+	if (ip->fp) {
+		if (fclose(ip->fp))
+			die("error: failed to read from input file '%s'",
+			    ip->fname);
+		if (!ip->next)
+			eof = 1;
+	}
 	if (eof)
 		return;
 	input = ip->next;
@@ -130,14 +128,12 @@
 static int
 readchar(void)
 {
+	FILE *fp = input->fp;
 	int c;
-	FILE *fp;
 
-repeat:
-	if (eof)
+	if (eof || !fp)
 		return 0;
-	fp = input->fp;
-
+repeat:
 	switch (c = getc(fp)) {
 	case EOF:
 		c = '\0';
--- a/cc1/main.c
+++ b/cc1/main.c
@@ -29,6 +29,19 @@
 }
 
 static void
+defmacro(char *macro)
+{
+	char *p = strchr(macro, '=');
+
+	if (p)
+		*p++ = '\0';
+	else
+		p = "1";
+
+	defdefine(macro, p);
+}
+
+static void
 usage(void)
 {
 	die(!strcmp(name, "cpp") ?
@@ -46,6 +59,7 @@
 
 	atexit(clean);
 	icpp();
+	ilex();
 
 	/* if run as cpp, only run the preprocessor */
 	name = (cp = strrchr(*argv, '/')) ? cp + 1 : *argv;
@@ -88,7 +102,10 @@
 	for (i = 0; i < uflags.n; ++i)
 		undefmacro(uflags.s[i]);
 
-	ilex(*argv);
+	if (!addinput(*argv)) {
+		die("error: failed to open input file '%s': %s",
+		    *argv, strerror(errno));
+	}
 	if (onlycpp) {
 		outcpp();
 	} else {
--- a/driver/posix/Makefile
+++ b/driver/posix/Makefile
@@ -7,7 +7,7 @@
 
 all: scc
 
-$(OBJS): ../../inc/cc.h
+$(OBJS): ../../inc/cc.h ../../inc/arg.h
 
 ../../lib/libcc.a:
 	cd ../../lib && $(MAKE) -e
--- a/driver/posix/scc.c
+++ b/driver/posix/scc.c
@@ -1,5 +1,6 @@
 /* See LICENSE file for copyright and license details. */
 #define _POSIX_SOURCE
+#define _XOPEN_SOURCE 500
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -48,7 +49,9 @@
 };
 
 char *argv0;
-static char *arch, *outfile;
+static char *arch, *objfile, *outfile;
+static char *tmpdir;
+static size_t tmpdirln;
 static struct items objtmp, objout;
 static int Eflag, Sflag, cflag, kflag, sflag;
 
@@ -134,30 +137,35 @@
 }
 
 static char *
-outfilename(char *path, char *ext)
+outfname(char *path, char *type)
 {
-	char *new, *name, *dot;
-	size_t newsz, nameln;
-	int n;
+	char *new, sep, *p;
+	size_t newsz, pathln;
+	int tmpfd, n;
 
-	if (!(name = strrchr(path, '/')))
-		name = path;
-	else
-		++name;
+	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;
+	}
 
-	nameln = strlen(name);
-
-	if (!(dot = strrchr(name, '.')))
-		dot = &name[nameln];
-
-	nameln = nameln - strlen(dot);
-	newsz  = nameln + strlen(ext) + 1 + 1;
-
+	newsz = pathln + 1 + strlen(type) + 1;
 	new = xmalloc(newsz);
-
-	n = snprintf(new, newsz, "%.*s.%s", nameln, name, ext);
+	n = snprintf(new, newsz, "%.*s%c%s", pathln, path, sep, type);
 	if (n < 0 || n >= newsz)
 		die("scc: wrong output filename");
+	if ((tmpfd = mkstemp(new)) < 0 && errno != EINVAL)
+		die("scc: could not create output file '%s': %s",
+		    new, strerror(errno));
+	close(tmpfd);
 
 	return new;
 }
@@ -172,27 +180,27 @@
 
 	switch (tool) {
 	case TEEIR:
-		t->outfile = outfilename(infile, "ir");
+		t->outfile = outfname(infile, "ir");
 		addarg(tool, t->outfile);
 		break;
 	case TEEQBE:
-		t->outfile = outfilename(infile, "qbe");
+		t->outfile = outfname(infile, "qbe");
 		addarg(tool, t->outfile);
 		break;
 	case TEEAS:
-		t->outfile = outfilename(infile, "as");
+		t->outfile = outfname(infile, "as");
 		addarg(tool, t->outfile);
 		break;
 	case AS:
-		t->outfile = outfile ? outfile : outfilename(infile, "o");
+		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 LD:
-		for (i = 0; i < objtmp.n; ++i)
-			addarg(tool, xstrdup(objtmp.s[i]));
-		for (i = 0; i < objout.n; ++i)
-			addarg(tool, xstrdup(objout.s[i]));
-		break;
 	case STRIP:
 		if (cflag || kflag) {
 			for (i = 0; i < objout.n; ++i)
@@ -298,16 +306,20 @@
 			t->pid = 0;
 		}
 	}
+	if (failed < LAST_TOOL) {
+		unlink(objfile);
+		free(objfile);
+		objfile = NULL;
+		return 0;
+	}
 
-	return failed == LAST_TOOL;
+	return 1;
 }
 
-static void
-build(char *file)
+static int
+buildfile(char *file, int tool)
 {
-	int tool = toolfor(file), nexttool;
-	struct items *objs = (tool == LD || cflag || kflag) ?
-	                       &objout : &objtmp;
+	int nexttool;
 
 	for (; tool < LAST_TOOL; tool = nexttool) {
 		switch (tool) {
@@ -346,11 +358,42 @@
 		spawn(settool(inittool(tool), file, nexttool));
 	}
 
-	if (validatetools())
-		newitem(objs, outfilename(file, "o"));
+	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)
 {
 	die("usage: scc [-D def[=val]]... [-U def]... [-I dir]... "
@@ -367,6 +410,9 @@
 int
 main(int argc, char *argv[])
 {
+	struct items linkchain = { .n = 0, };
+	int link;
+
 	atexit(terminate);
 
 	arch = getenv("ARCH");
@@ -406,8 +452,8 @@
 		kflag = 1;
 		break;
 	case 'l':
-		addarg(LD, "-l");
-		addarg(LD, EARGF(usage()));
+		newitem(&linkchain, "-l");
+		newitem(&linkchain, EARGF(usage()));
 		break;
 	case 'm':
 		arch = EARGF(usage());
@@ -427,19 +473,29 @@
 		break;
 	default:
 		usage();
+	} ARGOPERAND {
+operand:
+		newitem(&linkchain, ARGOP());
 	} ARGEND
 
-	if (Eflag && (Sflag || kflag) || argc > 1 && cflag && outfile || !argc)
+	for (; *argv; --argc, ++argv)
+		goto operand;
+
+	if (Eflag && (Sflag || kflag) || linkchain.n == 0 ||
+	    linkchain.n > 1 && cflag && outfile)
 		usage();
 
-	for (; *argv; ++argv)
-		build(*argv);
+	if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])
+		tmpdir = ".";
+	tmpdirln = strlen(tmpdir);
 
-	if (Eflag || Sflag)
+	build(&linkchain, (link = !(Eflag || Sflag || cflag)));
+
+	if (!(link || cflag))
 		return failure;
 
-	if (!cflag && !failure) {
-		spawn(settool(inittool(LD), NULL, LAST_TOOL));
+	if (link && !failure) {
+		spawn(settool(LD, NULL, LAST_TOOL));
 		validatetools();
 	}
 
--- a/inc/arg.h
+++ b/inc/arg.h
@@ -9,57 +9,57 @@
 extern char *argv0;
 
 /* use main(int argc, char *argv[]) */
-#define ARGBEGIN	for (argv0 = *argv, argv++, argc--;\
-					argv[0] && argv[0][0] == '-'\
-					&& argv[0][1];\
-					argc--, argv++) {\
-				char argc_;\
-				char **argv_;\
-				int brk_;\
-				if (argv[0][1] == '-' && argv[0][2] == '\0') {\
-					argv++;\
-					argc--;\
-					break;\
-				}\
-				for (brk_ = 0, argv[0]++, argv_ = argv;\
-						argv[0][0] && !brk_;\
-						argv[0]++) {\
-					if (argv_ != argv)\
-						break;\
-					argc_ = argv[0][0];\
-					switch (argc_)
+#define ARGBEGIN \
+for (argv0 = *argv, argv++, argc--;\
+     argv[0];\
+     argc--, argv++) {\
+	if (argv[0][0] == '-') {\
+		char argc_;\
+		char **argv_;\
+		int brk_;\
+		if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+			argv++;\
+			argc--;\
+			break;\
+		}\
+		for (brk_ = 0, argv[0]++, argv_ = argv;\
+		     argv[0][0] && !brk_;\
+		     argv[0]++) {\
+			if (argv_ != argv)\
+				break;\
+			argc_ = argv[0][0];\
+			switch (argc_)
 
-/* Handles obsolete -NUM syntax */
-#define ARGNUM				case '0':\
-					case '1':\
-					case '2':\
-					case '3':\
-					case '4':\
-					case '5':\
-					case '6':\
-					case '7':\
-					case '8':\
-					case '9'
+#define ARGOPERAND \
+		}\
+	} else if (argv[0][0] != '\0') {\
+		{
 
-#define ARGEND			}\
-			}
+#define ARGEND \
+		}\
+	}\
+}
 
-#define ARGC()		argc_
+#define ARGC() argc_
 
-#define ARGNUMF()	(brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
+#define ARGOP() argv[0]
 
-#define EARGF(x)	((argv[0][1] == '\0' && argv[1] == NULL)?\
-				((x), abort(), (char *)0) :\
-				(brk_ = 1, (argv[0][1] != '\0')?\
-					(&argv[0][1]) :\
-					(argc--, argv++, argv[0])))
+#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
 
-#define ARGF()		((argv[0][1] == '\0' && argv[1] == NULL)?\
-				(char *)0 :\
-				(brk_ = 1, (argv[0][1] != '\0')?\
-					(&argv[0][1]) :\
-					(argc--, argv++, argv[0])))
+#define EARGF(x) \
+((argv[0][1] == '\0' && argv[1] == NULL) ?\
+    ((x), abort(), (char *)0) :\
+    (brk_ = 1, (argv[0][1] != '\0') ?\
+        (&argv[0][1]) :\
+        (argc--, argv++, argv[0])))
 
-#define LNGARG()	&argv[0][0]
+#define ARGF() \
+((argv[0][1] == '\0' && argv[1] == NULL)?\
+    (char *)0 :\
+    (brk_ = 1, (argv[0][1] != '\0')?\
+        (&argv[0][1]) :\
+        (argc--, argv++, argv[0])))
+
+#define LNGARG() &argv[0][0]
 
 #endif