From 446ee5b1105cbb419bcccf8c09ad3514d3d66037 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sat, 5 Jul 2003 00:03:36 +0000 Subject: [PATCH] A new wildcard-matching routine to replace the fnmatch code. --- lib/wildmatch.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/wildmatch.h | 3 ++ 2 files changed, 99 insertions(+) create mode 100644 lib/wildmatch.c create mode 100644 lib/wildmatch.h diff --git a/lib/wildmatch.c b/lib/wildmatch.c new file mode 100644 index 00000000..bce9545e --- /dev/null +++ b/lib/wildmatch.c @@ -0,0 +1,96 @@ +/* +** Do shell-style pattern matching for ?, \, [], and * characters. +** It is 8bit clean. +** +** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. +** Rich $alz is now . +** +** Modified by Wayne Davison to special-case '/' matching and to fix +** the character-class code. +*/ + +#include "rsync.h" + +/* What character marks an inverted character class? */ +#define NEGATE_CLASS '!' + +#define false 0 +#define true 1 + +/* Look for pattern "p" in the "text" string. */ +int +wildmatch(const char *p, const char *text) +{ + int matched, special; + char ch, prev; + + for ( ; (ch = *p) != '\0'; text++, p++) { + if (*text == '\0' && ch != '*') + return false; + switch (ch) { + case '\\': + /* Literal match with following character. Note that the test + * in "default" handles the p[1] == '\0' failure case. */ + ch = *++p; + /* FALLTHROUGH */ + default: + if (*text != ch) + return false; + continue; + case '?': + /* Match anything but '/'. */ + if (*text == '/') + return false; + continue; + case '*': + if (*++p == '*') { + while (*++p == '*') {} + special = true; + } + else + special = false; + if (*p == '\0') { + /* Trailing "**" matches everything. */ + return special? true : strchr(text, '/') == 0; + } + for ( ; *text; text++) { + if (wildmatch(p, text)) + return true; + if (!special && *text == '/') + return false; + } + return false; + case '[': + special = *++p == NEGATE_CLASS ? true : false; + if (special) { + /* Inverted character class. */ + p++; + } + prev = 0; + matched = false; + ch = *p; + if (ch == ']' || ch == '-') { + if (*text == ch) + matched = true; + prev = ch; + ch = *++p; + } + for ( ; ch != ']'; prev = ch, ch = *++p) { + if (!ch) + return false; + if (ch == '-' && prev && p[1] && p[1] != ']') { + if (*text <= *++p && *text >= prev) + matched = true; + ch = 0; + } + else if (*text == ch) + matched = true; + } + if (matched == special) + return false; + continue; + } + } + + return *text == '\0'; +} diff --git a/lib/wildmatch.h b/lib/wildmatch.h new file mode 100644 index 00000000..c1225303 --- /dev/null +++ b/lib/wildmatch.h @@ -0,0 +1,3 @@ +/* wildmatch.h */ + +int wildmatch(const char *p, const char *text); -- 2.34.1