shithub: scc

Download patch

ref: a4548bb58265af4da12c28089a828afbecda2d0a
parent: c90d947dd33fb6163430eb47717b6c79db962221
author: Quentin Rameau <quinq@fifth.space>
date: Sat Jul 2 07:11:23 EDT 2016

[driver] keep l flags and operands ordered as given

We now supports file operands at any place on the command-line (as
stated by POSIX), and we process resulting objects and l-flags as the
user wants.

--- a/driver/posix/scc.c
+++ b/driver/posix/scc.c
@@ -200,12 +200,6 @@
 		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)
@@ -302,6 +296,7 @@
 			    !WIFEXITED(st) || WEXITSTATUS(st) != 0) {
 				failure = 1;
 				failed = tool;
+				unlink(objfile);
 				free(objfile);
 				objfile = NULL;
 			}
@@ -317,12 +312,10 @@
 	return failed == LAST_TOOL;
 }
 
-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) {
@@ -361,11 +354,42 @@
 		spawn(settool(inittool(tool), file, nexttool));
 	}
 
-	if (validatetools())
-		newitem(objs, objfile);
+	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]... "
@@ -382,6 +406,9 @@
 int
 main(int argc, char *argv[])
 {
+	struct items linkchain = { .n = 0, };
+	int link;
+
 	atexit(terminate);
 
 	arch = getenv("ARCH");
@@ -421,8 +448,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());
@@ -442,9 +469,12 @@
 		break;
 	default:
 		usage();
+	} ARGOPERAND {
+		newitem(&linkchain, ARGOP());
 	} ARGEND
 
-	if (Eflag && (Sflag || kflag) || argc > 1 && cflag && outfile || !argc)
+	if (Eflag && (Sflag || kflag) || linkchain.n == 0 ||
+	    linkchain.n > 1 && cflag && outfile)
 		usage();
 
 	if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])
@@ -451,14 +481,13 @@
 		tmpdir = ".";
 	tmpdirln = strlen(tmpdir);
 
-	for (; *argv; ++argv)
-		build(*argv);
+	build(&linkchain, (link = !(Eflag || Sflag || cflag)));
 
-	if (Eflag || Sflag)
+	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();
 	}