From 8775424f1383ca9a6e97852029d244e4e51abfc4 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 21 Sep 2023 11:37:51 +0200 Subject: [PATCH] Backport from xs. --- xs_match.h | 94 ++++++++++++++++++++++++++++++++-------------------- xs_version.h | 2 +- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/xs_match.h b/xs_match.h index 9f12c15..dac7e2e 100644 --- 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)) + for (;;) { + char c = *str++; + char p = *spec++; + + 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; - str++; - } while (*str); - return 0; + /* 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 == '?' && *str) { - spec++; /* any character */ - str++; - goto again; - } - - if (*spec == '|') - return 1; /* alternative separator? positive match */ - - if (!*spec) - return 1; /* end of spec? positive match */ - - if (*spec == '\\') - spec++; /* escaped char */ - - if (*spec == *str) { - spec++; /* matched 1 char */ - str++; - goto again; - } - - /* not matched; are there any alternatives? */ + /* try to find an alternative mark */ while (*spec) { - if (*spec == '|') - return xs_match(o_str, spec + 1); /* try next alternative */ + char p = *spec++; - if (*spec == '\\') - spec++; /* escaped char */ - spec++; + if (p == '\\') + p = *spec++; + + if (p == '|') { + /* no backtrack spec, restart str from the beginning */ + b_spec = NULL; + str = o_str; + + 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 */