mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-05 21:00:05 +00:00
Update.
2001-03-15 Ulrich Drepper <drepper@redhat.com> * posix/fnmatch.h (FNM_EXTMATCH): Define. * posix/fnmatch.c (NO_LEADING_PERIOD): Define. (posixly_correct): Move global variable here. (INT, EXT, END): Name new functions defined in fnmatch_loop.c. (fnmatch): Pretty printing. * posix/fnmatch_loop.c: Add code to handle FNM_EXTMATCH. * posix/tst-fnmatch.c: Recognize EXTMATCH flag. * posix/tst-fnmatch.input: Add tests for extended matching. * posix/testfnm.c: Add test for patterns with multiple ** before /. * posix/fnmatch_loop.c: Fix problem with the test above.
This commit is contained in:
parent
0493a6d7e8
commit
955994e131
14
ChangeLog
14
ChangeLog
@ -1,3 +1,17 @@
|
||||
2001-03-15 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* posix/fnmatch.h (FNM_EXTMATCH): Define.
|
||||
* posix/fnmatch.c (NO_LEADING_PERIOD): Define.
|
||||
(posixly_correct): Move global variable here.
|
||||
(INT, EXT, END): Name new functions defined in fnmatch_loop.c.
|
||||
(fnmatch): Pretty printing.
|
||||
* posix/fnmatch_loop.c: Add code to handle FNM_EXTMATCH.
|
||||
* posix/tst-fnmatch.c: Recognize EXTMATCH flag.
|
||||
* posix/tst-fnmatch.input: Add tests for extended matching.
|
||||
|
||||
* posix/testfnm.c: Add test for patterns with multiple ** before /.
|
||||
* posix/fnmatch_loop.c: Fix problem with the test above.
|
||||
|
||||
2001-03-14 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/ieee754/dbl-64/e_sqrt.c (__ieee754_sqrt): Remove
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991-1993, 1996-1999, 2000 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991-1993,1996-1999,2000,2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
@ -61,6 +61,10 @@
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
#endif
|
||||
|
||||
/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
|
||||
#define NO_LEADING_PERIOD(flags) \
|
||||
((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
@ -153,6 +157,9 @@ extern char *getenv ();
|
||||
extern int errno;
|
||||
# endif
|
||||
|
||||
/* Global variable. */
|
||||
static int posixly_correct;
|
||||
|
||||
/* This function doesn't exist on most systems. */
|
||||
|
||||
# if !defined HAVE___STRCHRNUL && !defined _LIBC
|
||||
@ -195,15 +202,18 @@ __wcschrnul (s, c)
|
||||
# endif
|
||||
# define CHAR char
|
||||
# define UCHAR unsigned char
|
||||
# define INT int
|
||||
# define FCT internal_fnmatch
|
||||
# define EXT ext_match
|
||||
# define END end_pattern
|
||||
# define L(CS) CS
|
||||
# ifdef _LIBC
|
||||
# define BTOWC(C) __btowc (C)
|
||||
# else
|
||||
# define BTOWC(C) btowc (C)
|
||||
# endif
|
||||
# define STRCHR(S, C) strchr (S, C)
|
||||
# define STRCHRNUL(S, C) __strchrnul (S, C)
|
||||
# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
|
||||
# define MEMCHR(S, C, N) memchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) strcoll (S1, S2)
|
||||
# include "fnmatch_loop.c"
|
||||
|
||||
@ -217,11 +227,14 @@ __wcschrnul (s, c)
|
||||
# endif
|
||||
# define CHAR wchar_t
|
||||
# define UCHAR wint_t
|
||||
# define INT wint_t
|
||||
# define FCT internal_fnwmatch
|
||||
# define EXT ext_wmatch
|
||||
# define END end_wpattern
|
||||
# define L(CS) L##CS
|
||||
# define BTOWC(C) (C)
|
||||
# define STRCHR(S, C) wcschr (S, C)
|
||||
# define STRCHRNUL(S, C) __wcschrnul (S, C)
|
||||
# define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
|
||||
# define MEMCHR(S, C, N) wmemchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) wcscoll (S1, S2)
|
||||
# define WIDE_CHAR_VERSION 1
|
||||
|
||||
@ -303,42 +316,43 @@ fnmatch (pattern, string, flags)
|
||||
int flags;
|
||||
{
|
||||
# if HANDLE_MULTIBYTE
|
||||
mbstate_t ps;
|
||||
size_t n;
|
||||
wchar_t *wpattern;
|
||||
wchar_t *wstring;
|
||||
if (__builtin_expect (MB_CUR_MAX, 1) != 1)
|
||||
{
|
||||
mbstate_t ps;
|
||||
size_t n;
|
||||
wchar_t *wpattern;
|
||||
wchar_t *wstring;
|
||||
|
||||
if (MB_CUR_MAX == 1)
|
||||
/* This is an optimization for 8-bit character set. */
|
||||
return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
|
||||
/* Convert the strings into wide characters. */
|
||||
memset (&ps, '\0', sizeof (ps));
|
||||
n = mbsrtowcs (NULL, &pattern, 0, &ps);
|
||||
if (__builtin_expect (n, 0) == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
|
||||
|
||||
/* Convert the strings into wide characters. */
|
||||
memset (&ps, '\0', sizeof (ps));
|
||||
n = mbsrtowcs (NULL, &pattern, 0, &ps);
|
||||
if (n == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
|
||||
assert (mbsinit (&ps));
|
||||
n = mbsrtowcs (NULL, &string, 0, &ps);
|
||||
if (__builtin_expect (n, 0) == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wstring, &string, n + 1, &ps);
|
||||
|
||||
assert (mbsinit (&ps));
|
||||
n = mbsrtowcs (NULL, &string, 0, &ps);
|
||||
if (n == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wstring, &string, n + 1, &ps);
|
||||
|
||||
return internal_fnwmatch (wpattern, wstring, flags & FNM_PERIOD, flags);
|
||||
# else
|
||||
return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
|
||||
return internal_fnwmatch (wpattern, wstring, wstring + n,
|
||||
flags & FNM_PERIOD, flags);
|
||||
}
|
||||
# endif /* mbstate_t and mbsrtowcs or _LIBC. */
|
||||
|
||||
return internal_fnmatch (pattern, string, string + strlen (string),
|
||||
flags & FNM_PERIOD, flags);
|
||||
}
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991,92,93,96,97,98,99,2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -59,6 +59,7 @@ extern "C" {
|
||||
# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
|
||||
#endif
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
|
@ -19,13 +19,19 @@
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, nonzero if not. */
|
||||
static int FCT (const CHAR *pattern, const CHAR *string,
|
||||
int no_leading_period, int flags) internal_function;
|
||||
const CHAR *string_end, int no_leading_period, int flags)
|
||||
internal_function;
|
||||
static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
|
||||
const CHAR *string_end, int no_leading_period, int flags)
|
||||
internal_function;
|
||||
static const CHAR *END (const CHAR *patternp) internal_function;
|
||||
|
||||
static int
|
||||
internal_function
|
||||
FCT (pattern, string, no_leading_period, flags)
|
||||
FCT (pattern, string, string_end, no_leading_period, flags)
|
||||
const CHAR *pattern;
|
||||
const CHAR *string;
|
||||
const CHAR *string_end;
|
||||
int no_leading_period;
|
||||
int flags;
|
||||
{
|
||||
@ -43,18 +49,27 @@ FCT (pattern, string, no_leading_period, flags)
|
||||
|
||||
while ((c = *p++) != L('\0'))
|
||||
{
|
||||
int new_no_leading_period = 0;
|
||||
c = FOLD (c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case L('?'):
|
||||
if (*n == L('\0'))
|
||||
if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
|
||||
{
|
||||
int res;
|
||||
|
||||
res = EXT (c, p, n, string_end, no_leading_period,
|
||||
flags);
|
||||
if (res != -1)
|
||||
return res;
|
||||
}
|
||||
|
||||
if (n == string_end)
|
||||
return FNM_NOMATCH;
|
||||
else if (*n == L('/') && (flags & FNM_FILE_NAME))
|
||||
return FNM_NOMATCH;
|
||||
else if (*n == L('.') && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
|
||||
else if (*n == L('.') && no_leading_period)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
@ -67,27 +82,48 @@ FCT (pattern, string, no_leading_period, flags)
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (FOLD ((UCHAR) *n) != c)
|
||||
if (n == string_end || FOLD ((UCHAR) *n) != c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case L('*'):
|
||||
if (*n == L('.') && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
|
||||
if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
|
||||
{
|
||||
int res;
|
||||
|
||||
res = EXT (c, p, n, string_end, no_leading_period,
|
||||
flags);
|
||||
if (res != -1)
|
||||
return res;
|
||||
}
|
||||
|
||||
if (n != string_end && *n == L('.') && no_leading_period)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
for (c = *p++; c == L('?') || c == L('*'); c = *p++)
|
||||
{
|
||||
if (*n == L('/') && (flags & FNM_FILE_NAME))
|
||||
/* A slash does not match a wildcard under FNM_FILE_NAME. */
|
||||
return FNM_NOMATCH;
|
||||
else if (c == L('?'))
|
||||
if (*p == L('(') && (flags & FNM_EXTMATCH) != 0)
|
||||
{
|
||||
const CHAR *endp = END (p);
|
||||
if (endp != p)
|
||||
{
|
||||
/* This is a pattern. Skip over it. */
|
||||
p = endp;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == L('?'))
|
||||
{
|
||||
/* A ? needs to match one character. */
|
||||
if (*n == L('\0'))
|
||||
if (n == string_end)
|
||||
/* There isn't another character; no match. */
|
||||
return FNM_NOMATCH;
|
||||
else if (*n == L('/')
|
||||
&& __builtin_expect (flags & FNM_FILE_NAME, 0))
|
||||
/* A slash does not match a wildcard under
|
||||
FNM_FILE_NAME. */
|
||||
return FNM_NOMATCH;
|
||||
else
|
||||
/* One character of the string is consumed in matching
|
||||
this ? wildcard, so *??? won't match if there are
|
||||
@ -110,7 +146,7 @@ FCT (pattern, string, no_leading_period, flags)
|
||||
result = 0;
|
||||
else
|
||||
{
|
||||
if (STRCHR (n, L('/')) == NULL)
|
||||
if (MEMCHR (n, L('/'), string_end - n) == NULL)
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
@ -121,44 +157,47 @@ FCT (pattern, string, no_leading_period, flags)
|
||||
{
|
||||
const CHAR *endp;
|
||||
|
||||
endp = STRCHRNUL (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'));
|
||||
endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'),
|
||||
string_end - n);
|
||||
if (endp == NULL)
|
||||
endp = string_end;
|
||||
|
||||
if (c == L('['))
|
||||
if (c == L('[')
|
||||
|| (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
|
||||
/* XXX Do we have to add '!'? */
|
||||
&& (c == L('@') || c == L('+')) && *p == L('(')))
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
int no_leading_period2 = no_leading_period;
|
||||
|
||||
for (--p; n < endp; ++n)
|
||||
if (FCT (p, n, (no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/')
|
||||
&& (flags & FNM_FILE_NAME)))),
|
||||
flags2) == 0)
|
||||
for (--p; n < endp; ++n, no_leading_period2 = 0)
|
||||
if (FCT (p, n, string_end, no_leading_period2, flags2)
|
||||
== 0)
|
||||
return 0;
|
||||
}
|
||||
else if (c == L('/') && (flags & FNM_FILE_NAME))
|
||||
{
|
||||
while (*n != L('\0') && *n != L('/'))
|
||||
while (n < string_end && *n != L('/'))
|
||||
++n;
|
||||
if (*n == L('/')
|
||||
&& (FCT (p, n + 1, flags & FNM_PERIOD, flags) == 0))
|
||||
if (n < string_end && *n == L('/')
|
||||
&& (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags)
|
||||
== 0))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
int no_leading_period2 = no_leading_period;
|
||||
|
||||
if (c == L('\\') && !(flags & FNM_NOESCAPE))
|
||||
c = *p;
|
||||
c = FOLD (c);
|
||||
for (--p; n < endp; ++n)
|
||||
for (--p; n < endp; ++n, no_leading_period2 = 0)
|
||||
if (FOLD ((UCHAR) *n) == c
|
||||
&& (FCT (p, n, (no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/')
|
||||
&& (flags & FNM_FILE_NAME)))),
|
||||
flags2) == 0))
|
||||
&& (FCT (p, n, string_end, no_leading_period2, flags2)
|
||||
== 0))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -168,20 +207,18 @@ FCT (pattern, string, no_leading_period, flags)
|
||||
|
||||
case L('['):
|
||||
{
|
||||
static int posixly_correct;
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
register int not;
|
||||
CHAR cold;
|
||||
UCHAR fn;
|
||||
|
||||
if (posixly_correct == 0)
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
|
||||
|
||||
if (*n == L('\0'))
|
||||
if (n == string_end)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (*n == L('.') && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
|
||||
if (*n == L('.') && no_leading_period)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (*n == L('/') && (flags & FNM_FILE_NAME))
|
||||
@ -192,11 +229,11 @@ FCT (pattern, string, no_leading_period, flags)
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
fn = FOLD ((UCHAR) *n);
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
UCHAR fn = FOLD ((UCHAR) *n);
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
|
||||
{
|
||||
if (*p == L('\0'))
|
||||
@ -878,30 +915,275 @@ FCT (pattern, string, no_leading_period, flags)
|
||||
}
|
||||
break;
|
||||
|
||||
case L('+'):
|
||||
case L('@'):
|
||||
case L('!'):
|
||||
if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
|
||||
{
|
||||
int res;
|
||||
|
||||
res = EXT (c, p, n, string_end, no_leading_period, flags);
|
||||
if (res != -1)
|
||||
return res;
|
||||
}
|
||||
goto normal_match;
|
||||
|
||||
case L('/'):
|
||||
if (NO_LEADING_PERIOD (flags))
|
||||
{
|
||||
if (n == string_end || c != *n)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
new_no_leading_period = 1;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (c != FOLD ((UCHAR) *n))
|
||||
normal_match:
|
||||
if (n == string_end || c != FOLD ((UCHAR) *n))
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
no_leading_period = new_no_leading_period;
|
||||
++n;
|
||||
}
|
||||
|
||||
if (*n == '\0')
|
||||
if (n == string_end)
|
||||
return 0;
|
||||
|
||||
if ((flags & FNM_LEADING_DIR) && *n == L('/'))
|
||||
if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/'))
|
||||
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
|
||||
return 0;
|
||||
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
|
||||
static const CHAR *
|
||||
internal_function
|
||||
END (const CHAR *pattern)
|
||||
{
|
||||
const CHAR *p = pattern;
|
||||
|
||||
while (1)
|
||||
if (*++p == L('\0'))
|
||||
/* This is an invalid pattern. */
|
||||
return pattern;
|
||||
else if (*p == L('['))
|
||||
{
|
||||
/* Handle brackets special. */
|
||||
if (posixly_correct == 0)
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
|
||||
|
||||
/* Skip the not sign. We have to recognize it because of a possibly
|
||||
following ']'. */
|
||||
if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
|
||||
++p;
|
||||
/* A leading ']' is recognized as such. */
|
||||
if (*p == L(']'))
|
||||
++p;
|
||||
/* Skip over all characters of the list. */
|
||||
while (*p != L(']'))
|
||||
if (*p++ == L('\0'))
|
||||
/* This is no valid pattern. */
|
||||
return pattern;
|
||||
}
|
||||
else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
|
||||
|| *p == L('!')) && p[1] == L('('))
|
||||
p = END (p + 1);
|
||||
else if (*p == L(')'))
|
||||
break;
|
||||
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
internal_function
|
||||
EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
|
||||
int no_leading_period, int flags)
|
||||
{
|
||||
const CHAR *startp;
|
||||
int level;
|
||||
struct patternlist
|
||||
{
|
||||
struct patternlist *next;
|
||||
CHAR str[0];
|
||||
} *list = NULL;
|
||||
struct patternlist **lastp = &list;
|
||||
const CHAR *p;
|
||||
const CHAR *rs;
|
||||
|
||||
/* Parse the pattern. Store the individual parts in the list. */
|
||||
level = 0;
|
||||
for (startp = p = pattern + 1; level >= 0; ++p)
|
||||
if (*p == L('\0'))
|
||||
/* This is an invalid pattern. */
|
||||
return -1;
|
||||
else if (*p == L('['))
|
||||
{
|
||||
/* Handle brackets special. */
|
||||
if (posixly_correct == 0)
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
|
||||
|
||||
/* Skip the not sign. We have to recognize it because of a possibly
|
||||
following ']'. */
|
||||
if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
|
||||
++p;
|
||||
/* A leading ']' is recognized as such. */
|
||||
if (*p == L(']'))
|
||||
++p;
|
||||
/* Skip over all characters of the list. */
|
||||
while (*p != L(']'))
|
||||
if (*p++ == L('\0'))
|
||||
/* This is no valid pattern. */
|
||||
return -1;
|
||||
}
|
||||
else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
|
||||
|| *p == L('!')) && p[1] == L('('))
|
||||
/* Remember the nesting level. */
|
||||
++level;
|
||||
else if (*p == L(')'))
|
||||
{
|
||||
if (level-- == 0)
|
||||
{
|
||||
/* This means we found the end of the pattern. */
|
||||
#define NEW_PATTERN \
|
||||
struct patternlist *newp = alloca (sizeof (struct patternlist) \
|
||||
+ ((p - startp + 1) \
|
||||
* sizeof (CHAR))); \
|
||||
*((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
|
||||
newp->next = NULL; \
|
||||
*lastp = newp; \
|
||||
lastp = &newp->next
|
||||
NEW_PATTERN;
|
||||
}
|
||||
}
|
||||
else if (*p == L('|'))
|
||||
{
|
||||
if (level == 0)
|
||||
{
|
||||
NEW_PATTERN;
|
||||
startp = p + 1;
|
||||
}
|
||||
}
|
||||
assert (list != NULL);
|
||||
assert (p[-1] == L(')'));
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case L('*'):
|
||||
if (FCT (p, string, string_end, no_leading_period, flags) == 0)
|
||||
return 0;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case L('+'):
|
||||
do
|
||||
{
|
||||
for (rs = string; rs <= string_end; ++rs)
|
||||
/* First match the prefix with the current pattern with the
|
||||
current pattern. */
|
||||
if (FCT (list->str, string, rs, no_leading_period,
|
||||
flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0
|
||||
/* This was successful. Now match the rest with the rest
|
||||
of the pattern. */
|
||||
&& (FCT (p, rs, string_end,
|
||||
rs == string
|
||||
? no_leading_period
|
||||
: rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
|
||||
flags & FNM_FILE_NAME
|
||||
? flags : flags & ~FNM_PERIOD) == 0
|
||||
/* This didn't work. Try the whole pattern. */
|
||||
|| (rs != string
|
||||
&& FCT (pattern - 1, rs, string_end,
|
||||
rs == string
|
||||
? no_leading_period
|
||||
: (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
|
||||
? 1 : 0),
|
||||
flags & FNM_FILE_NAME
|
||||
? flags : flags & ~FNM_PERIOD) == 0)))
|
||||
/* It worked. Signal success. */
|
||||
return 0;
|
||||
}
|
||||
while ((list = list->next) != NULL);
|
||||
|
||||
/* None of the patterns lead to a match. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
case L('?'):
|
||||
if (FCT (p, string, string_end, no_leading_period, flags) == 0)
|
||||
return 0;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case L('@'):
|
||||
do
|
||||
{
|
||||
for (rs = string; rs <= string_end; ++rs)
|
||||
/* First match the prefix with the current pattern with the
|
||||
current pattern. */
|
||||
if (FCT (list->str, string, rs, no_leading_period,
|
||||
flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0
|
||||
/* This was successful. Now match the rest of the strings
|
||||
with the rest of the pattern. */
|
||||
&& (FCT (p, rs, string_end,
|
||||
rs == string
|
||||
? no_leading_period
|
||||
: (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
|
||||
? 1 : 0),
|
||||
flags & FNM_FILE_NAME
|
||||
? flags : flags & ~FNM_PERIOD) == 0))
|
||||
/* It worked. Signal success. */
|
||||
return 0;
|
||||
}
|
||||
while ((list = list->next) != NULL);
|
||||
|
||||
/* None of the patterns lead to a match. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
case L('!'):
|
||||
for (rs = string; rs <= string_end; ++rs)
|
||||
{
|
||||
struct patternlist *runp;
|
||||
|
||||
for (runp = list; runp != NULL; runp = runp->next)
|
||||
if (FCT (runp->str, string, rs, no_leading_period,
|
||||
flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
|
||||
break;
|
||||
|
||||
/* If none of the patterns matched see whether the rest does. */
|
||||
if (runp == NULL
|
||||
&& (FCT (p, rs, string_end,
|
||||
rs == string
|
||||
? no_leading_period
|
||||
: rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
|
||||
flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
|
||||
== 0))
|
||||
/* This is successful. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* None of the patterns together with the rest of the pattern
|
||||
lead to a match. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
default:
|
||||
assert (! "Invalid extended matching operator");
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#undef FOLD
|
||||
#undef CHAR
|
||||
#undef UCHAR
|
||||
#undef INT
|
||||
#undef FCT
|
||||
#undef STRCHR
|
||||
#undef STRCHRNUL
|
||||
#undef EXT
|
||||
#undef END
|
||||
#undef MEMPCPY
|
||||
#undef MEMCHR
|
||||
#undef STRCOLL
|
||||
#undef L
|
||||
#undef BTOWC
|
||||
|
@ -54,6 +54,9 @@ struct {
|
||||
{ "a/b", "*a*", FNM_PATHNAME|FNM_LEADING_DIR, 0 },
|
||||
{ "ab/c", "*a?", FNM_PATHNAME|FNM_LEADING_DIR, 0 },
|
||||
{ "ab/c", "a?", FNM_PATHNAME|FNM_LEADING_DIR, 0 },
|
||||
{ "a/b", "?*/?", FNM_PATHNAME, 0 },
|
||||
{ "/b", "*/?", FNM_PATHNAME, 0 },
|
||||
{ "/b", "**/?", FNM_PATHNAME, 0 },
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Tests for fnmatch function.
|
||||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -263,6 +263,12 @@ convert_flags (const char *str)
|
||||
result |= FNM_CASEFOLD;
|
||||
len = 8;
|
||||
}
|
||||
else if (strncasecmp (str, "EXTMATCH", 8) == 0
|
||||
&& (str[8] == '|' || str[8] == '\0'))
|
||||
{
|
||||
result |= FNM_EXTMATCH;
|
||||
len = 8;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
@ -315,6 +321,13 @@ flag_output (int flags)
|
||||
cp = stpcpy (cp, "FNM_CASEFOLD");
|
||||
first = 0;
|
||||
}
|
||||
if (flags & FNM_EXTMATCH)
|
||||
{
|
||||
if (! first)
|
||||
*cp++ = '|';
|
||||
cp = stpcpy (cp, "FNM_EXTMATCH");
|
||||
first = 0;
|
||||
}
|
||||
if (cp == buf)
|
||||
*cp++ = '0';
|
||||
*cp = '\0';
|
||||
|
@ -348,7 +348,7 @@ C "\\/\\$" "\\/\\$" 0 NOESCAPE
|
||||
|
||||
# B.6 033(C)
|
||||
C ".asd" ".*" 0 PERIOD
|
||||
C "/.asd" "*" 0 PERIOD
|
||||
C "/.asd" "*" 0 PERIOD
|
||||
C "/as/.df" "*/?*f" 0 PERIOD
|
||||
C "..asd" ".[!a-z]*" 0 PERIOD
|
||||
|
||||
@ -370,6 +370,17 @@ C "/." "/[!a-z]" NOMATCH PATHNAME|PERIOD
|
||||
C "/a./.b." "/*/*" NOMATCH PATHNAME|PERIOD
|
||||
C "/a./.b." "/??/???" NOMATCH PATHNAME|PERIOD
|
||||
|
||||
# Some home-grown tests.
|
||||
C "foobar" "foo*[abc]z" NOMATCH
|
||||
C "foobaz" "foo*[abc][xyz]" 0
|
||||
C "foobaz" "foo?*[abc][xyz]" 0
|
||||
C "foobaz" "foo?*[abc][x/yz]" 0
|
||||
C "foobaz" "foo?*[abc]/[xyz]" NOMATCH PATHNAME
|
||||
C "a" "a/" NOMATCH PATHNAME
|
||||
C "a/" "a" NOMATCH PATHNAME
|
||||
C "//a" "/a" NOMATCH PATHNAME
|
||||
C "/a" "//a" NOMATCH PATHNAME
|
||||
|
||||
# Following are tests outside the scope of IEEE 2003.2 since they are using
|
||||
# locales other than the C locale. The main focus of the tests is on the
|
||||
# handling of ranges and the recognition of character (vs bytes).
|
||||
@ -578,3 +589,128 @@ C "x/y/z" "x/y" 0 PATHNAME|LEADING_DIR
|
||||
C "x" "x?y" NOMATCH PATHNAME|LEADING_DIR
|
||||
C "x/y" "x?y" NOMATCH PATHNAME|LEADING_DIR
|
||||
C "x/y/z" "x?y" NOMATCH PATHNAME|LEADING_DIR
|
||||
|
||||
# ksh style matching.
|
||||
C "abcd" "?@(a|b)*@(c)d" 0 EXTMATCH
|
||||
C "/dev/udp/129.22.8.102/45" "/dev/@(tcp|udp)/*/*" 0 PATHNAME|EXTMATCH
|
||||
C "12" "[1-9]*([0-9])" 0 EXTMATCH
|
||||
C "12abc" "[1-9]*([0-9])" NOMATCH EXTMATCH
|
||||
C "1" "[1-9]*([0-9])" 0 EXTMATCH
|
||||
C "07" "+([0-7])" 0 EXTMATCH
|
||||
C "0377" "+([0-7])" 0 EXTMATCH
|
||||
C "09" "+([0-7])" NOMATCH EXTMATCH
|
||||
C "paragraph" "para@(chute|graph)" 0 EXTMATCH
|
||||
C "paramour" "para@(chute|graph)" NOMATCH EXTMATCH
|
||||
C "para991" "para?([345]|99)1" 0 EXTMATCH
|
||||
C "para381" "para?([345]|99)1" NOMATCH EXTMATCH
|
||||
C "paragraph" "para*([0-9])" NOMATCH EXTMATCH
|
||||
C "para" "para*([0-9])" 0 EXTMATCH
|
||||
C "para13829383746592" "para*([0-9])" 0 EXTMATCH
|
||||
C "paragraph" "para+([0-9])" NOMATCH EXTMATCH
|
||||
C "para" "para+([0-9])" NOMATCH EXTMATCH
|
||||
C "para987346523" "para+([0-9])" 0 EXTMATCH
|
||||
C "paragraph" "para!(*.[0-9])" 0 EXTMATCH
|
||||
C "para.38" "para!(*.[0-9])" 0 EXTMATCH
|
||||
C "para.graph" "para!(*.[0-9])" 0 EXTMATCH
|
||||
C "para39" "para!(*.[0-9])" 0 EXTMATCH
|
||||
C "" "*(0|1|3|5|7|9)" 0 EXTMATCH
|
||||
C "137577991" "*(0|1|3|5|7|9)" 0 EXTMATCH
|
||||
C "2468" "*(0|1|3|5|7|9)" NOMATCH EXTMATCH
|
||||
C "1358" "*(0|1|3|5|7|9)" NOMATCH EXTMATCH
|
||||
C "file.c" "*.c?(c)" 0 EXTMATCH
|
||||
C "file.C" "*.c?(c)" NOMATCH EXTMATCH
|
||||
C "file.cc" "*.c?(c)" 0 EXTMATCH
|
||||
C "file.ccc" "*.c?(c)" NOMATCH EXTMATCH
|
||||
C "parse.y" "!(*.c|*.h|Makefile.in|config*|README)" 0 EXTMATCH
|
||||
C "shell.c" "!(*.c|*.h|Makefile.in|config*|README)" NOMATCH EXTMATCH
|
||||
C "Makefile" "!(*.c|*.h|Makefile.in|config*|README)" 0 EXTMATCH
|
||||
C "VMS.FILE;1" "*\;[1-9]*([0-9])" 0 EXTMATCH
|
||||
C "VMS.FILE;0" "*\;[1-9]*([0-9])" NOMATCH EXTMATCH
|
||||
C "VMS.FILE;" "*\;[1-9]*([0-9])" NOMATCH EXTMATCH
|
||||
C "VMS.FILE;139" "*\;[1-9]*([0-9])" 0 EXTMATCH
|
||||
C "VMS.FILE;1N" "*\;[1-9]*([0-9])" NOMATCH EXTMATCH
|
||||
C "abcfefg" "ab**(e|f)" 0 EXTMATCH
|
||||
C "abcfefg" "ab**(e|f)g" 0 EXTMATCH
|
||||
C "ab" "ab*+(e|f)" NOMATCH EXTMATCH
|
||||
C "abef" "ab***ef" 0 EXTMATCH
|
||||
C "abef" "ab**" 0 EXTMATCH
|
||||
C "fofo" "*(f*(o))" 0 EXTMATCH
|
||||
C "ffo" "*(f*(o))" 0 EXTMATCH
|
||||
C "foooofo" "*(f*(o))" 0 EXTMATCH
|
||||
C "foooofof" "*(f*(o))" 0 EXTMATCH
|
||||
C "fooofoofofooo" "*(f*(o))" 0 EXTMATCH
|
||||
C "foooofof" "*(f+(o))" NOMATCH EXTMATCH
|
||||
C "xfoooofof" "*(f*(o))" NOMATCH EXTMATCH
|
||||
C "foooofofx" "*(f*(o))" NOMATCH EXTMATCH
|
||||
C "ofxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH
|
||||
C "ofooofoofofooo" "*(f*(o))" NOMATCH EXTMATCH
|
||||
C "foooxfooxfoxfooox" "*(f*(o)x)" 0 EXTMATCH
|
||||
C "foooxfooxofoxfooox" "*(f*(o)x)" NOMATCH EXTMATCH
|
||||
C "foooxfooxfxfooox" "*(f*(o)x)" 0 EXTMATCH
|
||||
C "ofxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH
|
||||
C "ofoooxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH
|
||||
C "ofoooxoofxoofoooxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH
|
||||
C "ofoooxoofxoofoooxoofxoo" "*(*(of*(o)x)o)" 0 EXTMATCH
|
||||
C "ofoooxoofxoofoooxoofxofo" "*(*(of*(o)x)o)" NOMATCH EXTMATCH
|
||||
C "ofoooxoofxoofoooxoofxooofxofxo" "*(*(of*(o)x)o)" 0 EXTMATCH
|
||||
C "aac" "*(@(a))a@(c)" 0 EXTMATCH
|
||||
C "ac" "*(@(a))a@(c)" 0 EXTMATCH
|
||||
C "c" "*(@(a))a@(c)" NOMATCH EXTMATCH
|
||||
C "aaac" "*(@(a))a@(c)" 0 EXTMATCH
|
||||
C "baaac" "*(@(a))a@(c)" NOMATCH EXTMATCH
|
||||
C "abcd" "?@(a|b)*@(c)d" 0 EXTMATCH
|
||||
C "abcd" "@(ab|a*@(b))*(c)d" 0 EXTMATCH
|
||||
C "acd" "@(ab|a*(b))*(c)d" 0 EXTMATCH
|
||||
C "abbcd" "@(ab|a*(b))*(c)d" 0 EXTMATCH
|
||||
C "effgz" "@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
|
||||
C "efgz" "@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
|
||||
C "egz" "@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
|
||||
C "egzefffgzbcdij" "*(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
|
||||
C "egz" "@(b+(c)d|e+(f)g?|?(h)i@(j|k))" NOMATCH EXTMATCH
|
||||
C "ofoofo" "*(of+(o))" 0 EXTMATCH
|
||||
C "oxfoxoxfox" "*(oxf+(ox))" 0 EXTMATCH
|
||||
C "oxfoxfox" "*(oxf+(ox))" NOMATCH EXTMATCH
|
||||
C "ofoofo" "*(of+(o)|f)" 0 EXTMATCH
|
||||
C "foofoofo" "@(foo|f|fo)*(f|of+(o))" 0 EXTMATCH
|
||||
C "oofooofo" "*(of|oof+(o))" 0 EXTMATCH
|
||||
C "fffooofoooooffoofffooofff" "*(*(f)*(o))" 0 EXTMATCH
|
||||
C "fofoofoofofoo" "*(fo|foo)" 0 EXTMATCH
|
||||
C "foo" "!(x)" 0 EXTMATCH
|
||||
C "foo" "!(x)*" 0 EXTMATCH
|
||||
C "foo" "!(foo)" NOMATCH EXTMATCH
|
||||
C "foo" "!(foo)*" 0 EXTMATCH
|
||||
C "foobar" "!(foo)" 0 EXTMATCH
|
||||
C "foobar" "!(foo)*" 0 EXTMATCH
|
||||
C "moo.cow" "!(*.*).!(*.*)" 0 EXTMATCH
|
||||
C "mad.moo.cow" "!(*.*).!(*.*)" NOMATCH EXTMATCH
|
||||
C "mucca.pazza" "mu!(*(c))?.pa!(*(z))?" NOMATCH EXTMATCH
|
||||
C "fff" "!(f)" 0 EXTMATCH
|
||||
C "fff" "*(!(f))" 0 EXTMATCH
|
||||
C "fff" "+(!(f))" 0 EXTMATCH
|
||||
C "ooo" "!(f)" 0 EXTMATCH
|
||||
C "ooo" "*(!(f))" 0 EXTMATCH
|
||||
C "ooo" "+(!(f))" 0 EXTMATCH
|
||||
C "foo" "!(f)" 0 EXTMATCH
|
||||
C "foo" "*(!(f))" 0 EXTMATCH
|
||||
C "foo" "+(!(f))" 0 EXTMATCH
|
||||
C "f" "!(f)" NOMATCH EXTMATCH
|
||||
C "f" "*(!(f))" NOMATCH EXTMATCH
|
||||
C "f" "+(!(f))" NOMATCH EXTMATCH
|
||||
C "foot" "@(!(z*)|*x)" 0 EXTMATCH
|
||||
C "zoot" "@(!(z*)|*x)" NOMATCH EXTMATCH
|
||||
C "foox" "@(!(z*)|*x)" 0 EXTMATCH
|
||||
C "zoox" "@(!(z*)|*x)" 0 EXTMATCH
|
||||
C "foo" "*(!(foo)) 0 EXTMATCH
|
||||
C "foob" "!(foo)b*" NOMATCH EXTMATCH
|
||||
C "foobb" "!(foo)b*" 0 EXTMATCH
|
||||
C "[" "*([a[])" 0 EXTMATCH
|
||||
C "]" "*([]a[])" 0 EXTMATCH
|
||||
C "a" "*([]a[])" 0 EXTMATCH
|
||||
C "b" "*([!]a[])" 0 EXTMATCH
|
||||
C "[" "*([!]a[]|[[])" 0 EXTMATCH
|
||||
C "]" "*([!]a[]|[]])" 0 EXTMATCH
|
||||
C "[" "!([!]a[])" 0 EXTMATCH
|
||||
C "]" "!([!]a[])" 0 EXTMATCH
|
||||
C ")" "*([)])" 0 EXTMATCH
|
||||
C "*" "*([*(])" 0 EXTMATCH
|
||||
C "abcd" "*!(|a)cd" NOMATCH EXTMATCH
|
||||
|
Loading…
Reference in New Issue
Block a user