From 62e648e148b3cb9f96dcce808c55c02b7ccb4486 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 20 Jan 1999 04:59:39 +0000 Subject: ruby 1.3 cycle git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/RUBY@372 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- fnmatch.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 15 deletions(-) (limited to 'fnmatch.c') diff --git a/fnmatch.c b/fnmatch.c index 0847f5cafb..f031749c3d 100644 --- a/fnmatch.c +++ b/fnmatch.c @@ -20,6 +20,10 @@ Cambridge, MA 02139, USA. */ #include #include "fnmatch.h" +#ifdef USE_CWGUSI +#include +#endif + #if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS) # if !defined (errno) extern int errno; @@ -51,15 +55,23 @@ fnmatch (pattern, string, flags) if (*n == '\0') return (FNM_NOMATCH); else if ((flags & FNM_PATHNAME) && *n == '/') + /* If we are matching a pathname, `?' can never match a `/'. */ return (FNM_NOMATCH); else if ((flags & FNM_PERIOD) && *n == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + /* `?' cannot match a `.' if it is the first character of the + string or if it is the first character following a slash and + we are matching a pathname. */ return (FNM_NOMATCH); break; case '\\': if (!(flags & FNM_NOESCAPE)) - c = *p++; + { + c = *p++; + if (c == '\0') + return (FNM_NOMATCH); + } if (*n != c) return (FNM_NOMATCH); break; @@ -67,19 +79,38 @@ fnmatch (pattern, string, flags) case '*': if ((flags & FNM_PERIOD) && *n == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + /* `*' cannot match a `.' if it is the first character of the + string or if it is the first character following a slash and + we are matching a pathname. */ return (FNM_NOMATCH); - for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) - if (((flags & FNM_PATHNAME) && *n == '/') || - (c == '?' && *n == '\0')) - return (FNM_NOMATCH); + /* Collapse multiple consecutive, `*' and `?', but make sure that + one character of the string is consumed for each `?'. */ + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if ((flags & FNM_PATHNAME) && *n == '/') + /* A slash does not match a wildcard under FNM_PATHNAME. */ + return (FNM_NOMATCH); + else if (c == '?') + { + if (*n == '\0') + return (FNM_NOMATCH); + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + fewer than three characters. */ + n++; + } + } if (c == '\0') return (0); + /* General case, use recursion. */ { char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; for (--p; *n != '\0'; ++n) + /* Only call fnmatch if the first character indicates a + possible match. */ if ((c == '[' || *n == c1) && fnmatch (p, n, flags & ~FNM_PERIOD) == 0) return (0); @@ -94,22 +125,30 @@ fnmatch (pattern, string, flags) if (*n == '\0') return (FNM_NOMATCH); + /* A character class cannot match a `.' if it is the first + character of the string or if it is the first character + following a slash and we are matching a pathname. */ if ((flags & FNM_PERIOD) && *n == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) return (FNM_NOMATCH); - /* Make sure there is a closing `]'. If there isn't, the `[' - is just a character to be matched. */ + /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that + is not preceded by a backslash and is not part of a bracket + expression produces undefined results.' This implementation + treats the `[' as just a character to be matched if there is + not a closing `]'. This code will have to be changed when + POSIX.2 character classes are implemented. */ { register char *np; - for (np = p; np && *np && *np != ']'; np++); + for (np = p; np && *np && *np != ']'; np++) + ; if (np && !*np) { if (*n != '[') return (FNM_NOMATCH); - goto next_char; + break; } } @@ -120,10 +159,18 @@ fnmatch (pattern, string, flags) c = *p++; for (;;) { - register char cstart = c, cend = c; + register char cstart, cend; + + /* Initialize cstart and cend in case `-' is the last + character of the pattern. */ + cstart = cend = c; if (!(flags & FNM_NOESCAPE) && c == '\\') - cstart = cend = *p++; + { + if (*p == '\0') + return FNM_NOMATCH; + cstart = cend = *p++; + } if (c == '\0') /* [ (unterminated) loses. */ @@ -135,6 +182,9 @@ fnmatch (pattern, string, flags) /* [/] can never match. */ return (FNM_NOMATCH); + /* This introduces a range, unless the `-' is the last + character of the class. Find the end of the range + and move past it. */ if (c == '-' && *p != ']') { cend = *p++; @@ -142,6 +192,7 @@ fnmatch (pattern, string, flags) cend = *p++; if (cend == '\0') return (FNM_NOMATCH); + c = *p++; } @@ -153,8 +204,6 @@ fnmatch (pattern, string, flags) } if (!not) return (FNM_NOMATCH); - - next_char: break; matched: @@ -167,8 +216,12 @@ fnmatch (pattern, string, flags) c = *p++; if (!(flags & FNM_NOESCAPE) && c == '\\') - /* 1003.2d11 is unclear if this is right. %%% */ - ++p; + { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } } if (not) return (FNM_NOMATCH); -- cgit v1.2.3