commit aa0aab8

shrub  ·  2026-07-05 22:38:56 +0000 UTC
parent 47989f3
escape properly (fixes kati/recipe_var test)
1 files changed,  +54, -24
+54, -24
  1@@ -60,21 +60,21 @@ shellquote(const char *s)
  2 }
  3 
  4 static char *
  5-escapeninja(const char *s)
  6+escapeninja(const char *s, int path)
  7 {
  8-	size_t i, n, ndollar, j;
  9+	size_t i, n, nescc, j;
 10 	char *out;
 11 
 12 	n = strlen(s);
 13-	ndollar = 0;
 14+	nescc = 0;
 15 	for (i = 0; i < n; i++) {
 16-		if (s[i] == '$')
 17-			ndollar++;
 18+		if (s[i] == '$' || (path && (s[i] == ' ' || s[i] == ':')))
 19+			nescc++;
 20 	}
 21-	out = xmalloc(n + ndollar + 1);
 22+	out = xmalloc(n + nescc + 1);
 23 	j = 0;
 24 	for (i = 0; i < n; i++) {
 25-		if (s[i] == '$')
 26+		if (s[i] == '$' || (path && (s[i] == ' ' || s[i] == ':')))
 27 			out[j++] = '$';
 28 		out[j++] = s[i];
 29 	}
 30@@ -191,7 +191,7 @@ rulecmd(const struct Target *t)
 31 	cmd = joinrecipes(t);
 32 	env = exportenv(t);
 33 	full = cat3(env, cmd, "");
 34-	escaped = escapeninja(full);
 35+	escaped = escapeninja(full, 0);
 36 	free(full);
 37 	free(env);
 38 	free(cmd);
 39@@ -272,6 +272,7 @@ genninjafile(const struct Graph *graph, const char *path, const char *prefix, in
 40 	int ruleid;
 41 	struct Rule *rules;
 42 	size_t nrules;
 43+	char *escaped;
 44 
 45 	for (i = 0; i < graph->nsubs; i++) {
 46 		if (!emitgraphsub(graph, i))
 47@@ -325,17 +326,30 @@ genninjafile(const struct Graph *graph, const char *path, const char *prefix, in
 48 			} else {
 49 				free(cmd);
 50 			}
 51-			fprintf(fp, "build %s: r%d", graph->v[i].name, id);
 52+			escaped = escapeninja(graph->v[i].name, 1);
 53+			fputs("build ", fp);
 54+			fputs(escaped, fp);
 55+			fprintf(fp, ": r%d", id);
 56+			free(escaped);
 57 			if (graph->v[i].phony)
 58 				fprintf(fp, " __shin_always_build__");
 59-			for (j = 0; j < graph->v[i].impprereqs.n; j++)
 60-				fprintf(fp, " %s", graph->v[i].impprereqs.v[j]);
 61-			for (j = 0; j < graph->v[i].prereqs.n; j++)
 62-				fprintf(fp, " %s", graph->v[i].prereqs.v[j]);
 63+			for (j = 0; j < graph->v[i].impprereqs.n; j++) {
 64+				escaped = escapeninja(graph->v[i].impprereqs.v[j], 1);
 65+				fprintf(fp, " %s", escaped);
 66+				free(escaped);
 67+			}
 68+			for (j = 0; j < graph->v[i].prereqs.n; j++) {
 69+				escaped = escapeninja(graph->v[i].prereqs.v[j], 1);
 70+				fprintf(fp, " %s", escaped);
 71+				free(escaped);
 72+			}
 73 			if (graph->v[i].order_only.n) {
 74 				fprintf(fp, " ||");
 75-				for (j = 0; j < graph->v[i].order_only.n; j++)
 76-					fprintf(fp, " %s", graph->v[i].order_only.v[j]);
 77+				for (j = 0; j < graph->v[i].order_only.n; j++) {
 78+					escaped = escapeninja(graph->v[i].order_only.v[j], 1);
 79+					fprintf(fp, " %s", escaped);
 80+					free(escaped);
 81+				}
 82 			}
 83 			fprintf(fp, "\n");
 84 			if (prefix && prefix[0])
 85@@ -344,23 +358,39 @@ genninjafile(const struct Graph *graph, const char *path, const char *prefix, in
 86 				fprintf(fp, "  description = build %s\n\n", graph->v[i].name);
 87 		} else if (graph->v[i].defined || graph->v[i].prereqs.n > 0 ||
 88 		           graph->v[i].impprereqs.n > 0 || graph->v[i].order_only.n > 0) {
 89-			fprintf(fp, "build %s: phony", graph->v[i].name);
 90+			escaped = escapeninja(graph->v[i].name, 1);
 91+			fputs("build ", fp);
 92+			fputs(escaped, fp);
 93+			fputs(": phony", fp);
 94+			free(escaped);
 95 			if (graph->v[i].phony)
 96 				fprintf(fp, " __shin_always_build__");
 97-			for (j = 0; j < graph->v[i].impprereqs.n; j++)
 98-				fprintf(fp, " %s", graph->v[i].impprereqs.v[j]);
 99-			for (j = 0; j < graph->v[i].prereqs.n; j++)
100-				fprintf(fp, " %s", graph->v[i].prereqs.v[j]);
101+			for (j = 0; j < graph->v[i].impprereqs.n; j++) {
102+				escaped = escapeninja(graph->v[i].impprereqs.v[j], 1);
103+				fprintf(fp, " %s", escaped);
104+				free(escaped);
105+			}
106+			for (j = 0; j < graph->v[i].prereqs.n; j++) {
107+				escaped = escapeninja(graph->v[i].prereqs.v[j], 1);
108+				fprintf(fp, " %s", escaped);
109+				free(escaped);
110+			}
111 			if (graph->v[i].order_only.n) {
112 				fprintf(fp, " ||");
113-				for (j = 0; j < graph->v[i].order_only.n; j++)
114-					fprintf(fp, " %s", graph->v[i].order_only.v[j]);
115+				for (j = 0; j < graph->v[i].order_only.n; j++) {
116+					escaped = escapeninja(graph->v[i].order_only.v[j], 1);
117+					fprintf(fp, " %s", escaped);
118+					free(escaped);
119+				}
120 			}
121 			fprintf(fp, "\n\n");
122 		}
123 	}
124-	if (root && wanteddefault(graph, prefix))
125-		fprintf(fp, "default %s\n", wanteddefault(graph, prefix)->name);
126+	if (root && wanteddefault(graph, prefix)) {
127+		escaped = escapeninja(wanteddefault(graph, prefix)->name, 1);
128+		fprintf(fp, "default %s\n", escaped);
129+		free(escaped);
130+	}
131 
132 	fclose(fp);
133 	for (i = 0; i < nrules; i++)