1999-04-26  Ulrich Drepper  <drepper@cygnus.com>

	* posix/fnmatch.c (internal_fnmatch): Renamed from fnmatch.  Take
	extra parameter.  Fix several more bugs involving wildcard and
	ranges.
	(fnmatch): New function.  Call internal_fnmatch.

	* posix/testfnm.c: More test cases.
This commit is contained in:
Ulrich Drepper 1999-04-26 23:21:01 +00:00
parent 80127c749b
commit d8aaef00a7
3 changed files with 108 additions and 30 deletions

View File

@ -1,3 +1,12 @@
1999-04-26 Ulrich Drepper <drepper@cygnus.com>
* posix/fnmatch.c (internal_fnmatch): Renamed from fnmatch. Take
extra parameter. Fix several more bugs involving wildcard and
ranges.
(fnmatch): New function. Call internal_fnmatch.
* posix/testfnm.c: More test cases.
1999-04-03 Andreas Jaeger <aj@arthur.rhein-neckar.de> 1999-04-03 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* manual/install.texi (Configuring and compiling): Explain that * manual/install.texi (Configuring and compiling): Explain that

View File

@ -129,11 +129,10 @@ extern int errno;
/* Match STRING against the filename pattern PATTERN, returning zero if /* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */ it matches, nonzero if not. */
int static int
fnmatch (pattern, string, flags) internal_function
const char *pattern; internal_fnmatch (const char *pattern, const char *string,
const char *string; int no_leading_period, int flags)
int flags;
{ {
register const char *p = pattern, *n = string; register const char *p = pattern, *n = string;
register unsigned char c; register unsigned char c;
@ -156,8 +155,7 @@ fnmatch (pattern, string, flags)
return FNM_NOMATCH; return FNM_NOMATCH;
else if (*n == '/' && (flags & FNM_FILE_NAME)) else if (*n == '/' && (flags & FNM_FILE_NAME))
return FNM_NOMATCH; return FNM_NOMATCH;
else if (*n == '.' && (flags & FNM_PERIOD) && else if (*n == '.' && no_leading_period)
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH; return FNM_NOMATCH;
break; break;
@ -175,8 +173,7 @@ fnmatch (pattern, string, flags)
break; break;
case '*': case '*':
if (*n == '.' && (flags & FNM_PERIOD) && if (*n == '.' && no_leading_period)
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH; return FNM_NOMATCH;
for (c = *p++; c == '?' || c == '*'; c = *p++) for (c = *p++; c == '?' || c == '*'; c = *p++)
@ -214,9 +211,22 @@ fnmatch (pattern, string, flags)
if (c == '[') if (c == '[')
{ {
for (--p; n < endp; ++n) for (--p; n < endp; ++n)
if (fnmatch (p, n, flags & ~FNM_PERIOD) == 0) if (internal_fnmatch (p, n,
(n == string) && no_leading_period,
((flags & FNM_FILE_NAME)
? flags : (flags & ~FNM_PERIOD)))
== 0)
return 0; return 0;
} }
else if (c == '/' && (flags & FNM_FILE_NAME))
{
while (*n != '\0' && *n != '/')
++n;
if (*n == '/'
&& (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
flags) == 0))
return 0;
}
else else
{ {
if (c == '\\' && !(flags & FNM_NOESCAPE)) if (c == '\\' && !(flags & FNM_NOESCAPE))
@ -224,7 +234,13 @@ fnmatch (pattern, string, flags)
c = FOLD (c); c = FOLD (c);
for (--p; n < endp; ++n) for (--p; n < endp; ++n)
if (FOLD ((unsigned char) *n) == c if (FOLD ((unsigned char) *n) == c
&& fnmatch (p, n, flags & ~FNM_PERIOD) == 0) && (internal_fnmatch (p, n,
((n == string)
&& no_leading_period),
((flags & FNM_FILE_NAME)
? flags
: (flags & ~FNM_PERIOD)))
== 0))
return 0; return 0;
} }
} }
@ -245,8 +261,7 @@ fnmatch (pattern, string, flags)
if (*n == '\0') if (*n == '\0')
return FNM_NOMATCH; return FNM_NOMATCH;
if (*n == '.' && (flags & FNM_PERIOD) && if (*n == '.' && no_leading_period)
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH; return FNM_NOMATCH;
if (*n == '/' && (flags & FNM_FILE_NAME)) if (*n == '/' && (flags & FNM_FILE_NAME))
@ -294,7 +309,15 @@ fnmatch (pattern, string, flags)
p += 2; p += 2;
break; break;
} }
str[c1++] = 'c'; if (c < 'a' || c >= 'z')
{
/* This cannot possibly be a character class name.
Match it as a normal range. */
--p;
c = '[';
goto normal_bracket;
}
str[c1++] = c;
} }
str[c1] = '\0'; str[c1] = '\0';
@ -325,26 +348,31 @@ fnmatch (pattern, string, flags)
else if (c == '\0') else if (c == '\0')
/* [ (unterminated) loses. */ /* [ (unterminated) loses. */
return FNM_NOMATCH; return FNM_NOMATCH;
else if (FOLD (c) == fn) else
goto matched;
cold = c;
c = *p++;
if (c == '-' && *p != ']')
{ {
/* It is a range. */ normal_bracket:
unsigned char cend = *p++; if (FOLD (c) == fn)
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return FNM_NOMATCH;
if (cold <= fn && fn <= FOLD (cend))
goto matched; goto matched;
cold = c;
c = *p++; c = *p++;
if (c == '-' && *p != ']')
{
/* It is a range. */
unsigned char cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return FNM_NOMATCH;
if (cold <= fn && fn <= FOLD (cend))
goto matched;
c = *p++;
}
} }
if (c == ']') if (c == ']')
break; break;
} }
@ -404,4 +432,14 @@ fnmatch (pattern, string, flags)
# undef FOLD # undef FOLD
} }
int
fnmatch (pattern, string, flags)
const char *pattern;
const char *string;
int flags;
{
return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */ #endif /* _LIBC or not __GNU_LIBRARY__. */

View File

@ -15,7 +15,38 @@ struct {
{ "a/b", "[a-z]/[a-z]", 0, 0 }, { "a/b", "[a-z]/[a-z]", 0, 0 },
{ "a/b", "*", FNM_FILE_NAME, FNM_NOMATCH }, { "a/b", "*", FNM_FILE_NAME, FNM_NOMATCH },
{ "a/b", "*[/]b", FNM_FILE_NAME, FNM_NOMATCH }, { "a/b", "*[/]b", FNM_FILE_NAME, FNM_NOMATCH },
{ "a/b", "*[b]", FNM_FILE_NAME, FNM_NOMATCH } { "a/b", "*[b]", FNM_FILE_NAME, FNM_NOMATCH },
{ "a/b", "[*]/b", 0, FNM_NOMATCH },
{ "*/b", "[*]/b", 0, 0 },
{ "a/b", "[?]/b", 0, FNM_NOMATCH },
{ "?/b", "[?]/b", 0, 0 },
{ "a/b", "[[a]/b", 0, 0 },
{ "[/b", "[[a]/b", 0, 0 },
{ "a/b", "\\*/b", 0, FNM_NOMATCH },
{ "*/b", "\\*/b", 0, 0 },
{ "a/b", "\\?/b", 0, FNM_NOMATCH },
{ "?/b", "\\?/b", 0, 0 },
{ "[/b", "[/b", 0, FNM_NOMATCH },
{ "[/b", "\\[/b", 0, 0 },
{ "aa/b", "??/b", 0, 0 },
{ "aa/b", "???b", 0, 0 },
{ "aa/b", "???b", FNM_PATHNAME, FNM_NOMATCH },
{ ".a/b", "?a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
{ "a/.b", "a/?b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
{ ".a/b", "*a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
{ "a/.b", "a/*b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
{ ".a/b", "[.]a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
{ "a/.b", "a/[.]b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
{ "a/b", "*/?", FNM_PATHNAME|FNM_PERIOD, 0 },
{ "a/b", "?/*", FNM_PATHNAME|FNM_PERIOD, 0 },
{ ".a/b", ".*/?", FNM_PATHNAME|FNM_PERIOD, 0 },
{ "a/.b", "*/.?", FNM_PATHNAME|FNM_PERIOD, 0 },
{ "a/.b", "*/*", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
{ "a/.b", "*?*/*", FNM_PERIOD, 0 },
{ "a./b", "*[.]/b", FNM_PATHNAME|FNM_PERIOD, 0 },
{ "a/b", "*[[:alpha:]]/*[[:alnum:]]", FNM_PATHNAME, 0 },
{ "a/b", "*[![:digit:]]*/[![:d-d]", FNM_PATHNAME, 0 },
{ "a/[", "*[![:digit:]]*/[![:d-d]", FNM_PATHNAME, FNM_NOMATCH },
}; };
int int