commit 77fb0bd
shrub
·
2026-05-14 00:10:28 +0000 UTC
parent 12b8673
fix some prefix stripping and lhs assignment edge cases
3 files changed,
+51,
-29
+0,
-1
1@@ -1,6 +1,5 @@
2 build.dot
3 *.o
4-shin
5 tests/runner/runner
6 tests/runner/testhelper
7 tests/work
+10,
-8
1@@ -137,28 +137,29 @@ evalassign(struct EvalCtx *ctx, const struct AssignNode *in)
2 {
3 struct Env *env;
4 struct Var *v;
5- char *rhs, *joined;
6+ char *lhs, *rhs, *joined;
7 enum Origin o;
8 int exported;
9
10 env = ctx->env;
11 o = in->origin ? in->origin : ORIGIN_FILE;
12 exported = assignexported(ctx, in);
13+ lhs = expandstr(ctx, in->lhs);
14 switch (in->op) {
15 case ASSIGN_EQ:
16- envsetvar(env, in->lhs, xstrdup(in->rhs), 0, o, exported);
17+ envsetvar(env, lhs, xstrdup(in->rhs), 0, o, exported);
18 break;
19 case ASSIGN_COLON_EQ:
20- envsetvar(env, in->lhs, expandstr(ctx, in->rhs), 1, o, exported);
21+ envsetvar(env, lhs, expandstr(ctx, in->rhs), 1, o, exported);
22 break;
23 case ASSIGN_QMARK_EQ:
24- if (!findvar(env, in->lhs))
25- envsetvar(env, in->lhs, xstrdup(in->rhs), 0, o, exported);
26+ if (!findvar(env, lhs))
27+ envsetvar(env, lhs, xstrdup(in->rhs), 0, o, exported);
28 break;
29 case ASSIGN_PLUS_EQ:
30- v = findvar(env, in->lhs);
31+ v = findvar(env, lhs);
32 if (!v) {
33- envsetvar(env, in->lhs, xstrdup(in->rhs), 0, o, in->exported);
34+ envsetvar(env, lhs, xstrdup(in->rhs), 0, o, in->exported);
35 break;
36 }
37 if ((int)o < (int)v->origin)
38@@ -176,9 +177,10 @@ evalassign(struct EvalCtx *ctx, const struct AssignNode *in)
39 rhs = expandstr(ctx, in->rhs);
40 joined = runshellassign(rhs);
41 free(rhs);
42- envsetvar(env, in->lhs, joined, 1, o, exported);
43+ envsetvar(env, lhs, joined, 1, o, exported);
44 break;
45 }
46+ free(lhs);
47 }
48
49 static void
+41,
-20
1@@ -400,27 +400,48 @@ expandgraph(struct Graph *graph)
2 struct Recipe *r = &t->recipes.v[k];
3 char *exp;
4
5- freestrs(&side_effects);
6- exp = expandstr(&ctx, r->body);
7- for (j = 0; j < side_effects.n; j++) {
8- struct Recipe *nr;
9-
10- new_recipes.v = xrealloc(new_recipes.v,
11- (new_recipes.n + 1) * sizeof(new_recipes.v[0]));
12- nr = &new_recipes.v[new_recipes.n++];
13- memset(nr, 0, sizeof(*nr));
14- nr->body = xstrdup(side_effects.v[j]);
15- nr->silent = r->silent;
16- nr->ignore = r->ignore;
17+ freestrs(&side_effects);
18+ exp = expandstr(&ctx, r->body);
19+ /* strip recipe prefixes that may have been
20+ * introduced by variable expansion, eg something like Q_CC = @echo ... */
21+ {
22+ const char *s = exp;
23+ while (*s == '@' || *s == '-' || *s == '+') {
24+ if (*s == '@')
25+ r->silent = 1;
26+ else if (*s == '-')
27+ r->ignore = 1;
28+ else if (*s == '+')
29+ r->recursive = 1;
30+ s++;
31+ while (*s == ' ' || *s == '\t')
32+ s++;
33 }
34- if (exp[0]) {
35- struct Recipe *nr;
36-
37- new_recipes.v = xrealloc(new_recipes.v,
38- (new_recipes.n + 1) * sizeof(new_recipes.v[0]));
39- nr = &new_recipes.v[new_recipes.n++];
40- *nr = *r;
41- nr->body = exp;
42+ if (s != exp) {
43+ char *trimmed = xstrdup(s);
44+ free(exp);
45+ exp = trimmed;
46+ }
47+ }
48+ for (j = 0; j < side_effects.n; j++) {
49+ struct Recipe *nr;
50+
51+ new_recipes.v = xrealloc(new_recipes.v,
52+ (new_recipes.n + 1) * sizeof(new_recipes.v[0]));
53+ nr = &new_recipes.v[new_recipes.n++];
54+ memset(nr, 0, sizeof(*nr));
55+ nr->body = xstrdup(side_effects.v[j]);
56+ nr->silent = r->silent;
57+ nr->ignore = r->ignore;
58+ }
59+ if (exp[0]) {
60+ struct Recipe *nr;
61+
62+ new_recipes.v = xrealloc(new_recipes.v,
63+ (new_recipes.n + 1) * sizeof(new_recipes.v[0]));
64+ nr = &new_recipes.v[new_recipes.n++];
65+ *nr = *r;
66+ nr->body = exp;
67 freesubmake(&nr->sm);
68 nr->submake = parsesubmake(&nr->sm, nr->body);
69 free(r->body);