version 1.12, 1997/07/13 18:57:26 |
version 1.21, 2005/12/24 21:11:16 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* 3. Neither the name of the University nor the names of its contributors |
* 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 |
|
* may be used to endorse or promote products derived from this software |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* without specific prior written permission. |
* |
* |
Line 50 __RCSID("$NetBSD$"); |
|
Line 46 __RCSID("$NetBSD$"); |
|
* Compares a filename or pathname to a pattern. |
* Compares a filename or pathname to a pattern. |
*/ |
*/ |
|
|
|
#include "namespace.h" |
|
|
|
#include <assert.h> |
|
#include <ctype.h> |
#include <fnmatch.h> |
#include <fnmatch.h> |
#include <string.h> |
#include <string.h> |
|
|
|
#ifdef __weak_alias |
|
__weak_alias(fnmatch,_fnmatch) |
|
#endif |
|
|
#define EOS '\0' |
#define EOS '\0' |
|
|
static const char *rangematch __P((const char *, int, 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 |
int |
fnmatch(pattern, string, flags) |
fnmatch(pattern, string, flags) |
const char *pattern, *string; |
const char *pattern, *string; |
Line 65 fnmatch(pattern, string, flags) |
|
Line 80 fnmatch(pattern, string, flags) |
|
const char *stringstart; |
const char *stringstart; |
char c, test; |
char c, test; |
|
|
|
_DIAGASSERT(pattern != NULL); |
|
_DIAGASSERT(string != NULL); |
|
|
for (stringstart = string;;) |
for (stringstart = string;;) |
switch (c = *pattern++) { |
switch (c = FOLDCASE(*pattern++, flags)) { |
case EOS: |
case EOS: |
|
if ((flags & FNM_LEADING_DIR) && *string == '/') |
|
return (0); |
return (*string == EOS ? 0 : FNM_NOMATCH); |
return (*string == EOS ? 0 : FNM_NOMATCH); |
case '?': |
case '?': |
if (*string == EOS) |
if (*string == EOS) |
Line 81 fnmatch(pattern, string, flags) |
|
Line 101 fnmatch(pattern, string, flags) |
|
++string; |
++string; |
break; |
break; |
case '*': |
case '*': |
c = *pattern; |
c = FOLDCASE(*pattern, flags); |
/* Collapse multiple stars. */ |
/* Collapse multiple stars. */ |
while (c == '*') |
while (c == '*') |
c = *++pattern; |
c = FOLDCASE(*++pattern, flags); |
|
|
if (*string == '.' && (flags & FNM_PERIOD) && |
if (*string == '.' && (flags & FNM_PERIOD) && |
(string == stringstart || |
(string == stringstart || |
Line 92 fnmatch(pattern, string, flags) |
|
Line 112 fnmatch(pattern, string, flags) |
|
return (FNM_NOMATCH); |
return (FNM_NOMATCH); |
|
|
/* Optimize for pattern with * at end or before /. */ |
/* Optimize for pattern with * at end or before /. */ |
if (c == EOS) |
if (c == EOS) { |
if (flags & FNM_PATHNAME) |
if (flags & FNM_PATHNAME) |
return (strchr(string, '/') == NULL ? |
return ((flags & FNM_LEADING_DIR) || |
|
strchr(string, '/') == NULL ? |
0 : FNM_NOMATCH); |
0 : FNM_NOMATCH); |
else |
else |
return (0); |
return (0); |
else if (c == '/' && flags & FNM_PATHNAME) { |
} else if (c == '/' && flags & FNM_PATHNAME) { |
if ((string = strchr(string, '/')) == NULL) |
if ((string = strchr(string, '/')) == NULL) |
return (FNM_NOMATCH); |
return (FNM_NOMATCH); |
break; |
break; |
} |
} |
|
|
/* General case, use recursion. */ |
/* General case, use recursion. */ |
while ((test = *string) != EOS) { |
while ((test = FOLDCASE(*string, flags)) != EOS) { |
if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) |
if (!fnmatch(pattern, string, |
|
flags & ~FNM_PERIOD)) |
return (0); |
return (0); |
if (test == '/' && flags & FNM_PATHNAME) |
if (test == '/' && flags & FNM_PATHNAME) |
break; |
break; |
Line 119 fnmatch(pattern, string, flags) |
|
Line 141 fnmatch(pattern, string, flags) |
|
if (*string == '/' && flags & FNM_PATHNAME) |
if (*string == '/' && flags & FNM_PATHNAME) |
return (FNM_NOMATCH); |
return (FNM_NOMATCH); |
if ((pattern = |
if ((pattern = |
rangematch(pattern, *string, flags)) == NULL) |
rangematch(pattern, FOLDCASE(*string, flags), |
|
flags)) == NULL) |
return (FNM_NOMATCH); |
return (FNM_NOMATCH); |
++string; |
++string; |
break; |
break; |
case '\\': |
case '\\': |
if (!(flags & FNM_NOESCAPE)) { |
if (!(flags & FNM_NOESCAPE)) { |
if ((c = *pattern++) == EOS) { |
if ((c = FOLDCASE(*pattern++, flags)) == EOS) { |
c = '\\'; |
c = '\\'; |
--pattern; |
--pattern; |
} |
} |
} |
} |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
default: |
default: |
if (c != *string++) |
if (c != FOLDCASE(*string++, flags)) |
return (FNM_NOMATCH); |
return (FNM_NOMATCH); |
break; |
break; |
} |
} |
Line 147 rangematch(pattern, test, flags) |
|
Line 170 rangematch(pattern, test, flags) |
|
int negate, ok; |
int negate, ok; |
char c, c2; |
char c, c2; |
|
|
|
_DIAGASSERT(pattern != NULL); |
|
|
/* |
/* |
* A bracket expression starting with an unquoted circumflex |
* A bracket expression starting with an unquoted circumflex |
* character produces unspecified results (IEEE 1003.2-1992, |
* character produces unspecified results (IEEE 1003.2-1992, |
Line 157 rangematch(pattern, test, flags) |
|
Line 182 rangematch(pattern, test, flags) |
|
if ((negate = (*pattern == '!' || *pattern == '^')) != 0) |
if ((negate = (*pattern == '!' || *pattern == '^')) != 0) |
++pattern; |
++pattern; |
|
|
for (ok = 0; (c = *pattern++) != ']';) { |
for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) { |
if (c == '\\' && !(flags & FNM_NOESCAPE)) |
if (c == '\\' && !(flags & FNM_NOESCAPE)) |
c = *pattern++; |
c = FOLDCASE(*pattern++, flags); |
if (c == EOS) |
if (c == EOS) |
return (NULL); |
return (NULL); |
if (*pattern == '-' |
if (*pattern == '-' |
&& (c2 = *(pattern+1)) != EOS && c2 != ']') { |
&& (c2 = FOLDCASE(*(pattern+1), flags)) != EOS && |
|
c2 != ']') { |
pattern += 2; |
pattern += 2; |
if (c2 == '\\' && !(flags & FNM_NOESCAPE)) |
if (c2 == '\\' && !(flags & FNM_NOESCAPE)) |
c2 = *pattern++; |
c2 = FOLDCASE(*pattern++, flags); |
if (c2 == EOS) |
if (c2 == EOS) |
return (NULL); |
return (NULL); |
if (c <= test && test <= c2) |
if (c <= test && test <= c2) |