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.3 retrieving revision 1.20 diff -u -p -r1.3 -r1.20 --- src/lib/libc/gen/fnmatch.c 1993/06/16 17:16:13 1.3 +++ src/lib/libc/gen/fnmatch.c 2003/08/07 16:42:48 1.20 @@ -1,6 +1,8 @@ +/* $NetBSD: fnmatch.c,v 1.20 2003/08/07 16:42:48 agc Exp $ */ + /* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. + * 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 * Guido van Rossum. @@ -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,60 +32,103 @@ * SUCH DAMAGE. */ +#include #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)fnmatch.c 5.6 (Berkeley) 6/28/92"; +#if 0 +static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; +#else +__RCSID("$NetBSD: fnmatch.c,v 1.20 2003/08/07 16:42:48 agc Exp $"); +#endif #endif /* LIBC_SCCS and not lint */ /* - * Function fnmatch() as proposed in POSIX 1003.2 B.6 (D11.2). + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. * 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)); +static const char *rangematch __P((const char *, int, int)); +static __inline int +foldcase(int ch, int flags) +{ + + if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) + return (tolower(ch)); + return (ch); +} + +#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) + +int fnmatch(pattern, string, flags) - register const char *pattern, *string; + const char *pattern, *string; int flags; { - register char c; - char test; + const char *stringstart; + char c, test; + + _DIAGASSERT(pattern != NULL); + _DIAGASSERT(string != NULL); - for (;;) - switch (c = *pattern++) { + for (stringstart = string;;) + switch (c = FOLDCASE(*pattern++, flags)) { case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return (0); return (*string == EOS ? 0 : FNM_NOMATCH); case '?': - if ((test = *string++) == EOS || - test == '/' && flags & FNM_PATHNAME) + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (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); /* Optimize for pattern with * at end or before /. */ - if (c == EOS) + if (c == EOS) { if (flags & FNM_PATHNAME) - return (index(string, '/') == NULL ? + 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) + } 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)) + while ((test = FOLDCASE(*string, flags)) != EOS) { + if (!fnmatch(pattern, string, + flags & ~FNM_PERIOD)) return (0); if (test == '/' && flags & FNM_PATHNAME) break; @@ -95,25 +136,26 @@ fnmatch(pattern, string, flags) } return (FNM_NOMATCH); case '[': - if ((test = *string++) == EOS || - test == '/' && flags & FNM_PATHNAME) + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && flags & FNM_PATHNAME) return (FNM_NOMATCH); - if ((pattern = rangematch(pattern, test)) == NULL) + if ((pattern = + rangematch(pattern, FOLDCASE(*string, flags), + flags)) == NULL) return (FNM_NOMATCH); + ++string; break; case '\\': if (!(flags & FNM_NOESCAPE)) { - if ((c = *pattern++) == EOS) { + if ((c = FOLDCASE(*pattern++, flags)) == EOS) { c = '\\'; --pattern; } - if (c != *string++) - return (FNM_NOMATCH); - break; } /* FALLTHROUGH */ default: - if (c != *string++) + if (c != FOLDCASE(*string++, flags)) return (FNM_NOMATCH); break; } @@ -121,29 +163,41 @@ fnmatch(pattern, string, flags) } static const char * -rangematch(pattern, test) - register const char *pattern; - register int test; +rangematch(pattern, test, flags) + const char *pattern; + int test, flags; { - register char c, c2; int negate, ok; + char c, c2; - if (negate = (*pattern == '!')) - ++pattern; + _DIAGASSERT(pattern != NULL); /* - * XXX - * TO DO: quoting + * 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) */ - for (ok = 0; (c = *pattern++) != ']';) { + if ((negate = (*pattern == '!' || *pattern == '^')) != 0) + ++pattern; + + for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = FOLDCASE(*pattern++, flags); if (c == EOS) - return (NULL); /* Illegal pattern. */ - if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') { + 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; - pattern += 2; - } - else if (c == test) + } else if (c == test) ok = 1; } return (ok == negate ? NULL : pattern);