commit 8775424f1383ca9a6e97852029d244e4e51abfc4
parent 8698b3f59edd554024fc680325c98bdb388a511a
Author: default <nobody@localhost>
Date: Thu, 21 Sep 2023 11:37:51 +0200
Backport from xs.
Diffstat:
M | xs_match.h | | | 92 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
M | xs_version.h | | | 2 | +- |
2 files changed, 58 insertions(+), 36 deletions(-)
diff --git a/xs_match.h b/xs_match.h
@@ -17,50 +17,72 @@ int xs_match(const char *str, const char *spec);
int xs_match(const char *str, const char *spec)
{
- const char *o_str = str;
+ const char *b_str;
+ const char *b_spec = NULL;
+ const char *o_str = str;
-again:
- if (*spec == '*') {
- spec++; /* wildcard */
+retry:
- do {
- if (xs_match(str, spec))
- return 1;
- str++;
- } while (*str);
+ for (;;) {
+ char c = *str++;
+ char p = *spec++;
- return 0;
- }
+ if (c == '\0') {
+ /* end of string; also end of spec? */
+ if (p == '\0' || p == '|')
+ return 1;
+ else
+ break;
+ }
+ else
+ if (p == '?') {
+ /* match anything except the end */
+ if (c == '\0')
+ return 0;
+ }
+ else
+ if (p == '*') {
+ /* end of spec? match */
+ if (*spec == '\0')
+ return 1;
- if (*spec == '?' && *str) {
- spec++; /* any character */
- str++;
- goto again;
+ /* store spec for later */
+ b_spec = spec;
+
+ /* back one char */
+ b_str = --str;
+ }
+ else {
+ if (p == '\\')
+ p = *spec++;
+
+ if (c != p) {
+ /* mismatch; do we have a backtrack? */
+ if (b_spec) {
+ /* continue where we left, one char forward */
+ spec = b_spec;
+ str = ++b_str;
+ }
+ else
+ break;
+ }
+ }
}
- if (*spec == '|')
- return 1; /* alternative separator? positive match */
-
- if (!*spec)
- return 1; /* end of spec? positive match */
-
- if (*spec == '\\')
- spec++; /* escaped char */
+ /* try to find an alternative mark */
+ while (*spec) {
+ char p = *spec++;
- if (*spec == *str) {
- spec++; /* matched 1 char */
- str++;
- goto again;
- }
+ if (p == '\\')
+ p = *spec++;
- /* not matched; are there any alternatives? */
- while (*spec) {
- if (*spec == '|')
- return xs_match(o_str, spec + 1); /* try next alternative */
+ if (p == '|') {
+ /* no backtrack spec, restart str from the beginning */
+ b_spec = NULL;
+ str = o_str;
- if (*spec == '\\')
- spec++; /* escaped char */
- spec++;
+ goto retry;
+ }
}
return 0;
diff --git a/xs_version.h b/xs_version.h
@@ -1 +1 @@
-/* 06767a70773865042a70680aef50f7ecb077681a */
+/* 263e97c8ac21ff8524e3c890fe4310c696d01056 */