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 */