Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libc/gen/fnmatch.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libc/gen/fnmatch.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.9 retrieving revision 1.26 diff -u -p -r1.9 -r1.26 --- src/lib/libc/gen/fnmatch.c 1993/11/11 19:04:25 1.9 +++ src/lib/libc/gen/fnmatch.c 2014/10/12 22:32:33 1.26 @@ -1,5 +1,7 @@ +/* $NetBSD: fnmatch.c,v 1.26 2014/10/12 22:32:33 christos Exp $ */ + /* - * Copyright (c) 1989, 1993 + * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,9 +32,13 @@ * SUCH DAMAGE. */ +#include #if defined(LIBC_SCCS) && !defined(lint) -/* from: static char sccsid[] = "@(#)fnmatch.c 8.1 (Berkeley) 6/4/93"; */ -static char *rcsid = "$Id: fnmatch.c,v 1.9 1993/11/11 19:04:25 jtc Exp $"; +#if 0 +static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; +#else +__RCSID("$NetBSD: fnmatch.c,v 1.26 2014/10/12 22:32:33 christos Exp $"); +#endif #endif /* LIBC_SCCS and not lint */ /* @@ -44,136 +46,177 @@ static char *rcsid = "$Id: fnmatch.c,v 1 * Compares a filename or pathname to a pattern. */ +#include "namespace.h" + +#include +#include #include #include +#ifdef __weak_alias +__weak_alias(fnmatch,_fnmatch) +#endif + #define EOS '\0' -static const char *rangematch __P((const char *, int, int)); +static inline int +foldcase(int ch, int flags) +{ -int -fnmatch(pattern, string, flags) - register const char *pattern, *string; - int flags; + if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) + return tolower(ch); + return ch; +} + +#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) + +static const char * +rangematch(const char *pattern, int test, int flags) +{ + int negate, ok, need; + char c, c2; + + _DIAGASSERT(pattern != NULL); + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^')) != 0) + ++pattern; + + need = 1; + for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']' || need;) { + need = 0; + if (c == '/') + return (void *)-1; + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = FOLDCASE(*pattern++, flags); + if (c == EOS) + return NULL; + if (*pattern == '-' + && (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS && + c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = FOLDCASE(*pattern++, flags); + if (c2 == EOS) + return NULL; + if (c <= test && test <= c2) + ok = 1; + } else if (c == test) + ok = 1; + } + return ok == negate ? NULL : pattern; +} + + +static int +fnmatchx(const char *pattern, const char *string, int flags, size_t recursion) { - const char *stringstart = string; - register char c; - char test; + const char *stringstart, *r; + char c, test; + + _DIAGASSERT(pattern != NULL); + _DIAGASSERT(string != NULL); - for (;;) - switch (c = *pattern++) { + if (recursion-- == 0) + return FNM_NORES; + + for (stringstart = string;;) { + switch (c = FOLDCASE(*pattern++, flags)) { case EOS: - return (*string == EOS ? 0 : FNM_NOMATCH); + if ((flags & FNM_LEADING_DIR) && *string == '/') + return 0; + return *string == EOS ? 0 : FNM_NOMATCH; case '?': if (*string == EOS) - return (FNM_NOMATCH); + return FNM_NOMATCH; if (*string == '/' && (flags & FNM_PATHNAME)) - return (FNM_NOMATCH); + return FNM_NOMATCH; if (*string == '.' && (flags & FNM_PERIOD) && - (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return FNM_NOMATCH; ++string; break; case '*': - c = *pattern; + c = FOLDCASE(*pattern, flags); /* Collapse multiple stars. */ while (c == '*') - c = *++pattern; + c = FOLDCASE(*++pattern, flags); if (*string == '.' && (flags & FNM_PERIOD) && - (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return FNM_NOMATCH; /* Optimize for pattern with * at end or before /. */ - if (c == EOS) + if (c == EOS) { if (flags & FNM_PATHNAME) - return (index(string, '/') == NULL ? - 0 : FNM_NOMATCH); + return (flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH; else - return (0); - else if (c == '/' && flags & FNM_PATHNAME) { - if ((string = index(string, '/')) == NULL) - return (FNM_NOMATCH); + return 0; + } else if (c == '/' && flags & FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) + return FNM_NOMATCH; break; } /* General case, use recursion. */ - while ((test = *string) != EOS) { - if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) - return (0); + while ((test = FOLDCASE(*string, flags)) != EOS) { + int e; + switch ((e = fnmatchx(pattern, string, + flags & ~FNM_PERIOD, recursion))) { + case FNM_NOMATCH: + break; + default: + return e; + } if (test == '/' && flags & FNM_PATHNAME) break; ++string; } - return (FNM_NOMATCH); + return FNM_NOMATCH; case '[': if (*string == EOS) - return (FNM_NOMATCH); + return FNM_NOMATCH; if (*string == '/' && flags & FNM_PATHNAME) - return (FNM_NOMATCH); - if ((pattern = rangematch(pattern, *string, flags)) == NULL) - return (FNM_NOMATCH); + return FNM_NOMATCH; + if ((r = rangematch(pattern, + FOLDCASE(*string, flags), flags)) == NULL) + return FNM_NOMATCH; + if (r == (void *)-1) { + if (*string != '[') + return FNM_NOMATCH; + } else + pattern = r; ++string; break; case '\\': if (!(flags & FNM_NOESCAPE)) { - if ((c = *pattern++) == EOS) { - c = '\\'; + if ((c = FOLDCASE(*pattern++, flags)) == EOS) { + c = '\0'; --pattern; } } /* FALLTHROUGH */ default: - if (c != *string++) - return (FNM_NOMATCH); + if (c != FOLDCASE(*string++, flags)) + return FNM_NOMATCH; break; } + } /* NOTREACHED */ } -static const char * -rangematch(pattern, test, flags) - register const char *pattern; - register int test; - int flags; +int +fnmatch(const char *pattern, const char *string, int flags) { - register char c, c2; - int negate, ok; - - /* A bracket expression starting with an unquoted circumflex - * character produces unspecified results (IEEE 1003.2-1992, - * 3.13.2). I have chosen to treat it like '!', for - * consistancy with regular expression syntax. - */ - if (negate = (*pattern == '!' || *pattern == '^')) { - pattern++; - } - - for (ok = 0; (c = *pattern++) != ']';) { - if (c == '\\' && !(flags & FNM_NOESCAPE)) { - c = *pattern++; - } - if (c == EOS) { - return (NULL); - } - - if (*pattern == '-' - && (c2 = *(pattern+1)) != EOS && c2 != ']') { - pattern += 2; - if (c2 == '\\' && !(flags & FNM_NOESCAPE)) { - c2 = *pattern++; - } - if (c2 == EOS) { - return (NULL); - } - - if (c <= test && test <= c2) { - ok = 1; - } - } else if (c == test) { - ok = 1; - } - } - - return (ok == negate ? NULL : pattern); + return fnmatchx(pattern, string, flags, 64); }