the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
-
+
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
-
+
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#include <config.h>
#include <stdio.h> /* for debugging */
-
+
#include "fnmatch.h"
#include "collsyms.h"
#include <ctype.h>
#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
#endif
-/* We don't use strcoll(3) for range comparisons in bracket expressions,
- even if we have it, since it can have unwanted side effects in locales
+/* We use strcoll(3) for range comparisons in bracket expressions,
+ even though it can have unwanted side effects in locales
other than POSIX or US. For instance, in the de locale, [A-Z] matches
- all characters. So, for ranges we use ASCII collation, and for
- collating symbol equivalence we use strcoll(). The casts to int are
- to handle tests that use unsigned chars. */
-
-#define rangecmp(c1, c2) ((int)(c1) - (int)(c2))
+ all characters. */
#if defined (HAVE_STRCOLL)
/* Helper function for collating symbol equivalence. */
-static int rangecmp2 (c1, c2)
+static int rangecmp (c1, c2)
int c1, c2;
{
static char s1[2] = { ' ', '\0' };
return (c1 - c2);
}
#else /* !HAVE_STRCOLL */
-# define rangecmp2(c1, c2) ((int)(c1) - (int)(c2))
+# define rangecmp(c1, c2) ((int)(c1) - (int)(c2))
#endif /* !HAVE_STRCOLL */
#if defined (HAVE_STRCOLL)
static int collequiv (c1, c2)
int c1, c2;
{
- return (rangecmp2 (c1, c2) == 0);
+ return (rangecmp (c1, c2) == 0);
}
#else
# define collequiv(c1, c2) ((c1) == (c2))
for (csp = posix_collsyms; csp->name; csp++)
{
if (STREQN(csp->name, s, len) && csp->name[len] == '\0')
- return (csp->code);
+ return (csp->code);
}
if (len == 1)
return s[0];
if (string == 0 || pattern == 0)
return FNM_NOMATCH;
+#if DEBUG_MATCHING
+fprintf(stderr, "gmatch: string = %s; se = %s\n", string, se);
+fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
+#endif
+
while (p < pe)
{
c = *p++;
}
#endif
if (p == pe)
- break;
+ break;
}
/* If we've hit the end of the pattern and the last character of
/* Only call fnmatch if the first character indicates a
possible match. We can check the first character if
we're not doing an extended glob match. */
- if ((flags & FNM_EXTMATCH) == 0 && c != '[' && FOLD (*n) != c1)
+ if ((flags & FNM_EXTMATCH) == 0 && c != '[' && FOLD (*n) != c1) /*]*/
continue;
/* If we're doing an extended glob match and the pattern is not
one of the extended glob patterns, we can check the first
character. */
if ((flags & FNM_EXTMATCH) && p[1] != '(' && /*)*/
- strchr ("?*+@!", *p) == 0 && c != '[' && FOLD (*n) != c1)
+ strchr ("?*+@!", *p) == 0 && c != '[' && FOLD (*n) != c1) /*]*/
continue;
/* Otherwise, we just recurse. */
if ((flags & FNM_LEADING_DIR) && *n == '/')
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
return 0;
-
+
return (FNM_NOMATCH);
}
int val;
p++; /* move past the `.' */
-
+
for (pc = 0; p[pc]; pc++)
if (p[pc] == '.' && p[pc+1] == ']')
break;
/* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the
circumflex (`^') in its role in a `nonmatching list'. A bracket
- expression starging with an unquoted circumflex character produces
+ expression starting with an unquoted circumflex character produces
unspecified results. This implementation treats the two identically. */
if (not = (*p == '!' || *p == '^'))
++p;
pc = FOLD (p[1]);
p += 4;
if (collequiv (test, pc))
- goto matched;
+ {
+/*[*/ /* Move past the closing `]', since the first thing we do at
+ the `matched:' label is back p up one. */
+ p++;
+ goto matched;
+ }
else
{
c = *p++;
if (c == '\0')
- return ((test == '[') ? savep : (char *)0);
+ return ((test == '[') ? savep : (char *)0); /*]*/
c = FOLD (c);
continue;
}
- }
+ }
/* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */
- if (c == '[' && *p == ':')
+ if (c == '[' && *p == ':') /*]*/
{
pc = 0; /* make sure invalid char classes don't match. */
if (STREQN (p+1, "alnum:]", 7))
else if (STREQN (p+1, "ascii:]", 7))
{ pc = isascii (test); p += 8; }
if (pc)
+ {
+/*[*/ /* Move past the closing `]', since the first thing we do at
+ the `matched:' label is back p up one. */
+ p++;
goto matched;
+ }
else
{
/* continue the loop here, since this expression can't be
if (c == '\0')
return ((test == '[') ? savep : (char *)0);
else if (c == ']')
- break;
+ break;
c = FOLD (c);
continue;
}
if (rangecmp (cstart, cend) > 0)
{
if (c == ']')
- break;
+ break;
c = FOLD (c);
continue;
}
matched:
/* Skip the rest of the [...] that already matched. */
+#if 0
brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.'));
+#else
+ c = *--p;
+ brcnt = 1;
+#endif
while (brcnt > 0)
{
/* A `[' without a matching `]' is just another character to match. */
c = *p++;
if (c == '[' && (*p == '=' || *p == ':' || *p == '.'))
- brcnt++;
+ brcnt++;
else if (c == ']')
- brcnt--;
+ brcnt--;
else if (!(flags & FNM_NOESCAPE) && c == '\\')
{
if (*p == '\0')
char *string, *end;
int delim;
{
- int pnest, bnest;
- char *s, c;
+ int pnest, bnest, cchar;
+ char *s, c, *bfirst;
- pnest = bnest = 0;
+ pnest = bnest = cchar = 0;
+ bfirst = 0;
for (s = string; c = *s; s++)
{
if (s >= end)
- return (s);
+ return (s);
switch (c)
{
case '\0':
return ((char *)0);
+
+ /* `[' is not special inside a bracket expression, but it may
+ introduce one of the special POSIX bracket expressions
+ ([.SYM.], [=c=], [: ... :]) that needs special handling. */
case '[':
- bnest++;
+ if (bnest == 0)
+ {
+ bfirst = s + 1;
+ if (*bfirst == '!' || *bfirst == '^')
+ bfirst++;
+ bnest++;
+ }
+ else if (s[1] == ':' || s[1] == '.' || s[1] == '=')
+ cchar = s[1];
break;
+
+ /* `]' is not special if it's the first char (after a leading `!'
+ or `^') in a bracket expression or if it's part of one of the
+ special POSIX bracket expressions ([.SYM.], [=c=], [: ... :]) */
case ']':
if (bnest)
- bnest--;
+ {
+ if (cchar && s[-1] == cchar)
+ cchar = 0;
+ else if (s != bfirst)
+ {
+ bnest--;
+ bfirst = 0;
+ }
+ }
break;
+
case '(':
if (bnest == 0)
pnest++;
break;
+
case ')':
#if 0
if (bnest == 0)
return ++s;
#endif
break;
+
case '|':
if (bnest == 0 && pnest == 0 && delim == '|')
return ++s;
char *srest; /* pointer to rest of string */
int m1, m2;
-#if 0
+#if DEBUG_MATCHING
fprintf(stderr, "extmatch: xc = %c\n", xc);
fprintf(stderr, "extmatch: s = %s; se = %s\n", s, se);
fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
return 0;
/* OK, we have to do this the hard way. First, we make sure one of
- the subpatterns matches, then we try to match the rest of the
- string. */
+ the subpatterns matches, then we try to match the rest of the
+ string. */
for (psub = p + 1; ; psub = pnext)
{
pnext = patscan (psub, pe, '|');
m2 = (gmatch (srest, se, prest, pe, flags) == 0) ||
(s != srest && gmatch (srest, se, p - 1, pe, flags) == 0);
if (m1 && m2)
- return (0);
+ return (0);
}
if (pnext == prest)
break;
break;
}
if (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0)
- return (0);
+ return (0);
}
return (FNM_NOMATCH);
}