commit edddaa3
shrub
·
2026-04-16 15:27:53 +0000 UTC
parent 30eeafb
handle double colon
4 files changed,
+34,
-22
+1,
-0
1@@ -195,6 +195,7 @@ evalnodes(const struct NodeList *in, struct NodeList *out, struct Env *env)
2 evalassign(env, &src->data.assign);
3 break;
4 case NODE_RULE:
5+ node.data.rule.dcolon = src->data.rule.dcolon;
6 copywords(&node.data.rule.targets, &src->data.rule.targets, env);
7 copywords(&node.data.rule.prereqs, &src->data.rule.prereqs, env);
8 copywords(&node.data.rule.order_only, &src->data.rule.order_only, env);
+19,
-11
1@@ -3,6 +3,7 @@
2 #include "posix.h"
3 #include "gnu/pattern.h"
4
5+#include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9@@ -168,7 +169,13 @@ addrule(struct GraphState *gs, const char *name, const struct RuleNode *rule)
10 t = &gs->graph->v[gs->graph->n++];
11 memset(t, 0, sizeof(*t));
12 t->name = xstrdup(name);
13+ t->dcolon = rule->dcolon;
14+ } else if (t->defined && t->dcolon != rule->dcolon) {
15+ fprintf(stderr, "target file `%s' has both : and :: entries, i can't handle that!\n", name);
16+ exit(1);
17 }
18+ t->defined = 1;
19+ t->dcolon = rule->dcolon;
20 addwords(&t->prereqs, &rule->prereqs);
21 addwords(&t->order_only, &rule->order_only);
22 targetenv(gs, &env, name);
23@@ -276,18 +283,19 @@ buildgraph(const struct Ast *ast, struct Graph *graph)
24 freeenv(&env);
25 }
26 nprereqs = t->prereqs.n;
27- for (j = 0; j < nprereqs; j++) {
28- const char *prereq = t->prereqs.v[j];
29-
30- if (!findtarget(graph, prereq)) {
31- struct Target *nt;
32-
33- graph->v = xrealloc(graph->v, (graph->n + 1) * sizeof(graph->v[0]));
34- nt = &graph->v[graph->n++];
35- memset(nt, 0, sizeof(*nt));
36- nt->name = xstrdup(prereq);
37+ for (j = 0; j < nprereqs; j++) {
38+ const char *prereq = t->prereqs.v[j];
39+
40+ if (!findtarget(graph, prereq)) {
41+ struct Target *nt;
42+
43+ graph->v = xrealloc(graph->v, (graph->n + 1) * sizeof(graph->v[0]));
44+ nt = &graph->v[graph->n++];
45+ memset(nt, 0, sizeof(*nt));
46+ nt->name = xstrdup(prereq);
47+ t = &graph->v[i];
48+ }
49 }
50- }
51 }
52 start = current_n;
53 }
+11,
-11
1@@ -599,10 +599,11 @@ parseassign(const struct PreLine *line, const char *s, size_t n, size_t base, st
2 }
3
4 static struct Node
5-parserule(const struct PreLine *line, const char *s, size_t n, size_t colon)
6+parserule(const struct PreLine *line, const char *s, size_t n, size_t colon, int dcolon)
7 {
8 struct Node state;
9 const char *rhs;
10+ size_t off;
11 size_t rhsn, split, semi;
12 char *recipe;
13
14@@ -610,11 +611,13 @@ parserule(const struct PreLine *line, const char *s, size_t n, size_t colon)
15 state.kind = NODE_RULE;
16 state.loc.line0 = line->line0;
17 state.loc.line1 = line->line1;
18+ state.data.rule.dcolon = dcolon;
19
20 splitwords(&state.data.rule.targets, s, colon);
21
22- rhs = s + colon + 1;
23- rhsn = n - colon - 1;
24+ off = dcolon ? 2 : 1;
25+ rhs = s + colon + off;
26+ rhsn = n - colon - off;
27 semi = (size_t)findtop(rhs, rhsn, ';');
28 if (semi != (size_t)-1) {
29 recipe = trimdup(rhs + semi + 1, rhsn - semi - 1);
30@@ -683,6 +686,7 @@ parseline(const struct PreLine *line)
31 struct Node state;
32 struct AssignScan as;
33 char *trim;
34+ int dcolon;
35 size_t n;
36 ptrdiff_t colon;
37
38@@ -731,10 +735,12 @@ parseline(const struct PreLine *line)
39 }
40
41 colon = findtop(trim, n, ':');
42+ dcolon = colon >= 0 && (size_t)colon + 1 < n && trim[colon + 1] == ':';
43 as = findassign(trim, n, 0);
44 if (colon >= 0 && as.ok && (size_t)colon < as.pos) {
45 /* some inline rule like 'all: ; @echo hi' */
46- ptrdiff_t semi = findtop(trim + colon + 1, as.pos - (size_t)colon - 1, ';');
47+ size_t off = dcolon ? 2 : 1;
48+ ptrdiff_t semi = findtop(trim + colon + off, as.pos - (size_t)colon - off, ';');
49 if (semi < 0) {
50 state = parseassign(line, trim, n, (size_t)colon + 1, as, 1, (size_t)colon);
51 free(trim);
52@@ -746,14 +752,8 @@ parseline(const struct PreLine *line)
53 free(trim);
54 return state;
55 }
56- if (colon >= 0 && (size_t)colon + 1 < n && trim[colon + 1] == ':') {
57- parseerr(line, "double-colon rule", trim);
58- state = blanknode(line);
59- free(trim);
60- return state;
61- }
62 if (colon >= 0) {
63- state = parserule(line, trim, n, (size_t)colon);
64+ state = parserule(line, trim, n, (size_t)colon, dcolon);
65 free(trim);
66 return state;
67 }
+3,
-0
1@@ -79,6 +79,7 @@ struct RuleNode {
2 struct StrList prereqs;
3 struct StrList order_only;
4 struct RecipeList recipes;
5+ int dcolon;
6 };
7
8 struct IncludeNode {
9@@ -128,6 +129,8 @@ struct Target {
10 struct StrList prereqs;
11 struct StrList order_only;
12 struct RecipeList recipes;
13+ int dcolon;
14+ int defined;
15 };
16
17 struct Graph {