commit fa3993a
shrub
·
2026-05-14 20:30:33 +0000 UTC
parent ab67d72
eval: correctly expand substitution refs on automatic vars and add test for it
4 files changed,
+67,
-4
+41,
-4
1@@ -167,7 +167,7 @@ issubstref(const char *s, size_t n, size_t *colon, size_t *eq)
2 *colon = i;
3 break;
4 }
5- if (!(isalnum((unsigned char)s[i]) || s[i] == '_'))
6+ if (isspace((unsigned char)s[i]))
7 return 0;
8 }
9 if (i == 0 || i >= n)
10@@ -364,6 +364,8 @@ expandsubstref(struct EvalCtx *ctx, const char *s, size_t colon, size_t eq, size
11 {
12 char *name, *from, *to, *val;
13 struct Var *v;
14+ char *base;
15+ int auto_name;
16
17 {
18 char *nameraw, *toraw, *fromraw;
19@@ -378,14 +380,49 @@ expandsubstref(struct EvalCtx *ctx, const char *s, size_t colon, size_t eq, size
20 free(fromraw);
21 free(toraw);
22 v = findvar(ctx->env, name);
23- free(name);
24 }
25+ base = 0;
26+ auto_name = 0;
27 if (v) {
28- char *base;
29-
30 base = expandstr(ctx, v->val);
31+ } else if (name[0] && name[1] == 0) {
32+ /* we handle some substitution refs on automatic vars like $(@:.o=.c). */
33+ switch (name[0]) {
34+ case '@':
35+ auto_name = 1;
36+ if (ctx->auto_target)
37+ base = xstrdup(ctx->auto_target);
38+ break;
39+ case '<':
40+ auto_name = 1;
41+ if (ctx->auto_prereqs && ctx->auto_prereqs->n > 0)
42+ base = xstrdup(ctx->auto_prereqs->v[0]);
43+ break;
44+ case '^':
45+ case '+':
46+ case '?':
47+ auto_name = 1;
48+ if (ctx->auto_prereqs)
49+ base = autoprereqsval(ctx->auto_prereqs, name[0]);
50+ break;
51+ case '*':
52+ auto_name = 1;
53+ if (ctx->auto_stem)
54+ base = xstrdup(ctx->auto_stem);
55+ break;
56+ }
57+ }
58+ free(name);
59+
60+ if (base) {
61 val = substval(base, from, to);
62 free(base);
63+ } else if (auto_name) {
64+ char *inner;
65+
66+ inner = xstrndup(s, n);
67+ val = cat3("$(", inner, ")");
68+ free(inner);
69 } else {
70 val = xstrdup("");
71 }
+8,
-0
1@@ -0,0 +1,8 @@
2+OBJ = foo.o bar.o
3+
4+all: $(OBJ)
5+
6+bar.o: foo.o
7+
8+$(OBJ):
9+ @echo src=$(@:.o=.c)
+2,
-0
1@@ -0,0 +1,2 @@
2+src=foo.c
3+src=bar.c
+16,
-0
1@@ -0,0 +1,16 @@
2+{
3+ "case": "t002",
4+ "category": "variables",
5+ "compare_output": true,
6+ "description": "substitution refs work on automatic target variable",
7+ "details": "",
8+ "env": {},
9+ "expected_exit": 0,
10+ "options": "",
11+ "options_mode": "argv",
12+ "output_mode": "exact",
13+ "setup": [],
14+ "stdin": "",
15+ "suite": "shin",
16+ "timeout_seconds": 60
17+}