commit 8775424
default
·
2023-09-21 09:37:51 +0000 UTC
parent 8698b3f
Backport from xs.
2 files changed,
+58,
-36
+57,
-35
1@@ -17,50 +17,72 @@ int xs_match(const char *str, const char *spec);
2
3 int xs_match(const char *str, const char *spec)
4 {
5- const char *o_str = str;
6+ const char *b_str;
7+ const char *b_spec = NULL;
8+ const char *o_str = str;
9
10-again:
11- if (*spec == '*') {
12- spec++; /* wildcard */
13+retry:
14
15- do {
16- if (xs_match(str, spec))
17- return 1;
18- str++;
19- } while (*str);
20+ for (;;) {
21+ char c = *str++;
22+ char p = *spec++;
23
24- return 0;
25- }
26+ if (c == '\0') {
27+ /* end of string; also end of spec? */
28+ if (p == '\0' || p == '|')
29+ return 1;
30+ else
31+ break;
32+ }
33+ else
34+ if (p == '?') {
35+ /* match anything except the end */
36+ if (c == '\0')
37+ return 0;
38+ }
39+ else
40+ if (p == '*') {
41+ /* end of spec? match */
42+ if (*spec == '\0')
43+ return 1;
44
45- if (*spec == '?' && *str) {
46- spec++; /* any character */
47- str++;
48- goto again;
49+ /* store spec for later */
50+ b_spec = spec;
51+
52+ /* back one char */
53+ b_str = --str;
54+ }
55+ else {
56+ if (p == '\\')
57+ p = *spec++;
58+
59+ if (c != p) {
60+ /* mismatch; do we have a backtrack? */
61+ if (b_spec) {
62+ /* continue where we left, one char forward */
63+ spec = b_spec;
64+ str = ++b_str;
65+ }
66+ else
67+ break;
68+ }
69+ }
70 }
71
72- if (*spec == '|')
73- return 1; /* alternative separator? positive match */
74-
75- if (!*spec)
76- return 1; /* end of spec? positive match */
77-
78- if (*spec == '\\')
79- spec++; /* escaped char */
80+ /* try to find an alternative mark */
81+ while (*spec) {
82+ char p = *spec++;
83
84- if (*spec == *str) {
85- spec++; /* matched 1 char */
86- str++;
87- goto again;
88- }
89+ if (p == '\\')
90+ p = *spec++;
91
92- /* not matched; are there any alternatives? */
93- while (*spec) {
94- if (*spec == '|')
95- return xs_match(o_str, spec + 1); /* try next alternative */
96+ if (p == '|') {
97+ /* no backtrack spec, restart str from the beginning */
98+ b_spec = NULL;
99+ str = o_str;
100
101- if (*spec == '\\')
102- spec++; /* escaped char */
103- spec++;
104+ goto retry;
105+ }
106 }
107
108 return 0;
+1,
-1
1@@ -1 +1 @@
2-/* 06767a70773865042a70680aef50f7ecb077681a */
3+/* 263e97c8ac21ff8524e3c890fe4310c696d01056 */