commit 38b7f57

shrub  ·  2026-05-04 18:40:25 +0000 UTC
parent 1beb2a2
implement !=
1 files changed,  +49, -1
+49, -1
 1@@ -58,6 +58,51 @@ copyenv(struct Env *dst, const struct Env *src)
 2 	dst->cap = src->n;
 3 }
 4 
 5+static char *
 6+runshellassign(const char *cmd)
 7+{
 8+	FILE *fp;
 9+	char buf[4096];
10+	char *out;
11+	size_t len, cap, nread, i;
12+
13+	fp = popen(cmd, "r");
14+	if (!fp)
15+		return xstrdup("");
16+
17+	cap = 64;
18+	len = 0;
19+	out = xmalloc(cap);
20+	out[0] = 0;
21+
22+	while ((nread = fread(buf, 1, sizeof(buf), fp)) > 0) {
23+		if (len + nread + 1 > cap) {
24+			while (cap < len + nread + 1)
25+				cap *= 2;
26+			out = xrealloc(out, cap);
27+		}
28+		memcpy(out + len, buf, nread);
29+		len += nread;
30+	}
31+	out[len] = 0;
32+	pclose(fp);
33+	if (len > 0 && out[len - 1] == '\n') {
34+		len--;
35+		if (len > 0 && out[len - 1] == '\r')
36+			len--;
37+		out[len] = 0;
38+	} else if (len > 0 && out[len - 1] == '\r') {
39+		len--;
40+		out[len] = 0;
41+	}
42+
43+	for (i = 0; i < len; i++) {
44+		if (out[i] == '\n' || out[i] == '\r')
45+			out[i] = ' ';
46+	}
47+	return out;
48+}
49+
50 void
51 evalassign(struct EvalCtx *ctx, const struct AssignNode *in)
52 {
53@@ -97,7 +142,10 @@ evalassign(struct EvalCtx *ctx, const struct AssignNode *in)
54 			v->exported = 1;
55 		break;
56 	case ASSIGN_BANG_EQ:
57-		envsetvar(env, in->lhs, expandstr(ctx, in->rhs), 1, o, in->exported);
58+		rhs = expandstr(ctx, in->rhs);
59+		joined = runshellassign(rhs);
60+		free(rhs);
61+		envsetvar(env, in->lhs, joined, 1, o, in->exported);
62 		break;
63 	}
64 }