diff options
author | default <nobody@localhost> | 2023-09-21 11:37:51 +0200 |
---|---|---|
committer | default <nobody@localhost> | 2023-09-21 11:37:51 +0200 |
commit | 8775424f1383ca9a6e97852029d244e4e51abfc4 (patch) | |
tree | aa6f7fe3e772667f30800d02582ab66fe74de38d | |
parent | 8698b3f59edd554024fc680325c98bdb388a511a (diff) |
Backport from xs.
-rw-r--r-- | xs_match.h | 92 | ||||
-rw-r--r-- | xs_version.h | 2 |
2 files changed, 58 insertions, 36 deletions
@@ -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 index f6c3412..1873039 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* 06767a70773865042a70680aef50f7ecb077681a */ +/* 263e97c8ac21ff8524e3c890fe4310c696d01056 */ |