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++)