commit 3025f65

shrub  ·  2026-07-01 13:55:48 +0000 UTC
parent b9b99b8
handle comment in submake recipe + test
7 files changed,  +64, -1
+1, -0
1@@ -527,6 +527,7 @@ static const struct func funcs[] = {
2     {"subst",      FNEXP3, {.f3 = fnsubst}},
3     {"patsubst",   FNEXP3, {.f3 = fnpatsubst}},
4     {"if",         FNEXP3, {.f3 = fnif}},
5+    {"or",         FNCTX,  {.ctx = fnor}},
6     {"call",       FNCTX,  {.ctx = fncall}},
7     {"foreach",    FNCTX,  {.ctx = fnforeach}},
8     {"eval",       FNCTX,  {.ctx = fneval}},
+20, -0
 1@@ -1202,6 +1202,26 @@ fnabspath(const char *names)
 2 	return out;
 3 }
 4 
 5+char *
 6+fnor(struct EvalCtx *ctx, const char *args)
 7+{
 8+	char **raw;
 9+	char *val;
10+	size_t argc, i;
11+
12+	raw = splitargsraw(args, &argc);
13+	for (i = 0; i < argc; i++) {
14+		val = expandstr(ctx, raw[i]);
15+		if (val[0]) {
16+			freeargsraw(raw, argc);
17+			return val;
18+		}
19+		free(val);
20+	}
21+	freeargsraw(raw, argc);
22+	return xstrdup("");
23+}
24+
25 char *
26 fncall(struct EvalCtx *ctx, const char *args)
27 {
+1, -0
1@@ -107,6 +107,7 @@ char *fnbasename(const char *names);
2 char *fnsubst(const char *from, const char *to, const char *text);
3 char *fnpatsubst(const char *pattern, const char *replacement, const char *text);
4 char *fnif(const char *cond, const char *then, const char *otherwise);
5+char *fnor(struct EvalCtx *ctx, const char *args);
6 char *fnwords(const char *text);
7 char *fnword(const char *n, const char *list);
8 char *fnwordlist(const char *s, const char *e, const char *list);
+15, -1
 1@@ -4,7 +4,16 @@
 2 #include <stdlib.h>
 3 #include <string.h>
 4 
 5-/* recursive make handling */
 6+/* recursive make handling: sort of done naively, doesent always work.
 7+ *
 8+ * TODO:
 9+ * idea for a better implementation: create a new binary. shin replaces $(MAKE) with the 
10+ * name of this new binary that we create. this binary is a program that simply expands the 
11+ * graph of the submake and returns some sort of graph IR. shin pre-emptively runs all submake 
12+ * recipes with the new helper binary sibstituted in as $(MAKE), then it reads the output 
13+ * for each one and parses the graph IR into subgraphs. because we just shell out pre-emnptively,
14+ * we don't have to implement a small shell parser (like the one down below) and it will work
15+ * in 99% if not 100% of cases. */
16 
17 static void
18 tokview(const char *s, const char **out, size_t *n)
19@@ -140,6 +149,9 @@ tokenizecmd(struct StrList *out, const char *s)
20 			i++;
21 		if (!s[i])
22 			break;
23+		/* comment after recope shouldnt get parsed as a target*/
24+		if (s[i] == '#')
25+			break;
26 		if (s[i] == '&' && s[i + 1] == '&') {
27 			addtok(out, "&&", 2);
28 			i += 2;
29@@ -152,6 +164,8 @@ tokenizecmd(struct StrList *out, const char *s)
30 				break;
31 			if (!quote && s[i] == '&' && s[i + 1] == '&')
32 				break;
33+			if (!quote && s[i] == '#')
34+				break;
35 			if (s[i] == '\\' && s[i + 1]) {
36 				i += 2;
37 				continue;
+2, -0
1@@ -0,0 +1,2 @@
2+all:
3+	@$(MAKE) -f sub.mk show NAME=moon #_all
+1, -0
1@@ -0,0 +1 @@
2+name=moon
+24, -0
 1@@ -0,0 +1,24 @@
 2+{
 3+  "case": "t003",
 4+  "category": "recursion",
 5+  "compare_output": true,
 6+  "description": "recursive make ignores shell comments after submake arguments",
 7+  "details": "",
 8+  "env": {},
 9+  "expected_exit": 0,
10+  "options": "",
11+  "options_mode": "argv",
12+  "output_mode": "exact",
13+  "setup": [
14+    {
15+      "kind": "file",
16+      "mode": "0644",
17+      "mtime": 0,
18+      "path": "sub.mk",
19+      "content": "show:\n\t@echo name=$(NAME)\n"
20+    }
21+  ],
22+  "stdin": "",
23+  "suite": "shin",
24+  "timeout_seconds": 60
25+}