commit 3ff2026

shrub  ·  2026-04-12 09:11:15 +0000 UTC
parent 3165e81
make filter-out tests pass
3 files changed,  +45, -19
+10, -10
 1@@ -320,20 +320,20 @@ expandstr(struct Env *env, const char *s)
 2 			memcpy(out + len, val, k);
 3 			len += k;
 4 			free(val);
 5-		} else if (j - i - 3 >= 6 &&
 6-		           memcmp(s + i + 2, "filter", 6) == 0) {
 7+		} else if (j - i - 3 >= 10 &&
 8+		           memcmp(s + i + 2, "filter-out", 10) == 0) {
 9 			char *args_raw, *pat_raw, *text_raw;
10 			char *pat_exp, *text_exp, *val;
11 			size_t astart;
12 			ptrdiff_t comma;
13 
14-			astart = i + 8;
15+			astart = i + 12;
16 			while (astart < j - 1 && isspace((unsigned char)s[astart]))
17 				astart++;
18 			args_raw = xstrndup(s + astart, j - 1 - astart);
19 			comma = findargcomma(args_raw, strlen(args_raw));
20 			if (comma < 0) {
21-				evalerr("malformed function arguments", "$(filter)");
22+				evalerr("malformed function arguments", "$(filter-out)");
23 				free(args_raw);
24 				val = xstrdup("");
25 			} else {
26@@ -344,7 +344,7 @@ expandstr(struct Env *env, const char *s)
27 				text_exp = expandstr(env, text_raw);
28 				free(pat_raw);
29 				free(text_raw);
30-				val = fnfilter(pat_exp, text_exp);
31+				val = fnfilterout(pat_exp, text_exp);
32 				free(pat_exp);
33 				free(text_exp);
34 			}
35@@ -356,20 +356,20 @@ expandstr(struct Env *env, const char *s)
36 			memcpy(out + len, val, k);
37 			len += k;
38 			free(val);
39-		} else if (j - i - 3 >= 10 &&
40-		           memcmp(s + i + 2, "filter-out", 10) == 0) {
41+		} else if (j - i - 3 >= 6 &&
42+		           memcmp(s + i + 2, "filter", 6) == 0) {
43 			char *args_raw, *pat_raw, *text_raw;
44 			char *pat_exp, *text_exp, *val;
45 			size_t astart;
46 			ptrdiff_t comma;
47 
48-			astart = i + 12;
49+			astart = i + 8;
50 			while (astart < j - 1 && isspace((unsigned char)s[astart]))
51 				astart++;
52 			args_raw = xstrndup(s + astart, j - 1 - astart);
53 			comma = findargcomma(args_raw, strlen(args_raw));
54 			if (comma < 0) {
55-				evalerr("malformed function arguments", "$(filter-out)");
56+				evalerr("malformed function arguments", "$(filter)");
57 				free(args_raw);
58 				val = xstrdup("");
59 			} else {
60@@ -380,7 +380,7 @@ expandstr(struct Env *env, const char *s)
61 				text_exp = expandstr(env, text_raw);
62 				free(pat_raw);
63 				free(text_raw);
64-				val = fnfilterout(pat_exp, text_exp);
65+				val = fnfilter(pat_exp, text_exp);
66 				free(pat_exp);
67 				free(text_exp);
68 			}
+33, -9
 1@@ -15,8 +15,10 @@ matchword(const char *patterns, const char *word, size_t nword)
 2 	size_t p0, p1;
 3 
 4 	for (p0 = 0; patterns[p0];) {
 5-		const char *pat, *pct;
 6-		size_t npat, pre, suf;
 7+		const char *pat;
 8+		char *cooked;
 9+		size_t npat, i, n, pct, pre, suf;
10+		int haspct;
11 
12 		while (patterns[p0] && isspace((unsigned char)patterns[p0]))
13 			p0++;
14@@ -27,19 +29,41 @@ matchword(const char *patterns, const char *word, size_t nword)
15 			p1++;
16 		pat = patterns + p0;
17 		npat = p1 - p0;
18-		pct = memchr(pat, '%', npat);
19-		if (!pct) {
20-			if (npat == nword && memcmp(pat, word, npat) == 0)
21+		cooked = xmalloc(npat + 1);
22+		n = 0;
23+		pct = 0;
24+		haspct = 0;
25+		for (i = 0; i < npat; i++) {
26+			if (pat[i] == '\\' && i + 1 < npat && (pat[i + 1] == '\\' || pat[i + 1] == '%')) {
27+				cooked[n++] = pat[++i];
28+				continue;
29+			}
30+			if (pat[i] == '%' && !haspct) {
31+				pct = n;
32+				haspct = 1;
33+				continue;
34+			}
35+			cooked[n++] = pat[i];
36+		}
37+		cooked[n] = 0;
38+		if (!haspct) {
39+			if (n == nword && memcmp(cooked, word, n) == 0) {
40+				free(cooked);
41 				return 1;
42+			}
43+			free(cooked);
44 			p0 = p1;
45 			continue;
46 		}
47-		pre = (size_t)(pct - pat);
48-		suf = npat - pre - 1;
49+		pre = pct;
50+		suf = n - pre;
51 		if (nword >= pre + suf &&
52-		    memcmp(pat, word, pre) == 0 &&
53-		    memcmp(pct + 1, word + nword - suf, suf) == 0)
54+		    memcmp(cooked, word, pre) == 0 &&
55+		    memcmp(cooked + pre, word + nword - suf, suf) == 0) {
56+			free(cooked);
57 			return 1;
58+		}
59+		free(cooked);
60 		p0 = p1;
61 	}
62 	return 0;
+2, -0
1@@ -1,2 +1,4 @@
2 .test-result
3 work
4+*/build.ninja
5+*/.ninja_*