?? fnmatch.c
字號:
goto matched;
}
else
{
c = *p++;
if (c == '\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 == ':')
{
pc = 0; /* make sure invalid char classes don't match. */
if (STREQN (p+1, "alnum:]", 7))
{ pc = isalnum (test); p += 8; }
else if (STREQN (p+1, "alpha:]", 7))
{ pc = isalpha (test); p += 8; }
else if (STREQN (p+1, "blank:]", 7))
{ pc = isblank (test); p += 8; }
else if (STREQN (p+1, "cntrl:]", 7))
{ pc = iscntrl (test); p += 8; }
else if (STREQN (p+1, "digit:]", 7))
{ pc = isdigit (test); p += 8; }
else if (STREQN (p+1, "graph:]", 7))
{ pc = isgraph (test); p += 8; }
else if (STREQN (p+1, "lower:]", 7))
{ pc = islower (test); p += 8; }
else if (STREQN (p+1, "print:]", 7))
{ pc = isprint (test); p += 8; }
else if (STREQN (p+1, "punct:]", 7))
{ pc = ispunct (test); p += 8; }
else if (STREQN (p+1, "space:]", 7))
{ pc = isspace (test); p += 8; }
else if (STREQN (p+1, "upper:]", 7))
{ pc = isupper (test); p += 8; }
else if (STREQN (p+1, "xdigit:]", 8))
{ pc = isxdigit (test); p += 9; }
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
the first part of a range expression. */
c = *p++;
if (c == '\0')
return ((test == '[') ? savep : (char *)0);
else if (c == ']')
break;
c = FOLD (c);
continue;
}
}
/* POSIX.2 collating symbols. See POSIX.2 2.8.3.2. Find the end of
the symbol name, make sure it is terminated by `.]', translate
the name to a character using the external table, and do the
comparison. */
if (c == '[' && *p == '.')
{
p = parse_collsym (p, &pc);
/* An invalid collating symbol cannot be the first point of a
range. If it is, we set cstart to one greater than `test',
so any comparisons later will fail. */
cstart = (pc == -1) ? test + 1 : pc;
}
if (!(flags & FNM_NOESCAPE) && c == '\\')
{
if (*p == '\0')
return (char *)0;
cstart = cend = *p++;
}
cstart = cend = FOLD (cstart);
/* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
is not preceded by a backslash and is not part of a bracket
expression produces undefined results.' This implementation
treats the `[' as just a character to be matched if there is
not a closing `]'. */
if (c == '\0')
return ((test == '[') ? savep : (char *)0);
c = *p++;
c = FOLD (c);
if ((flags & FNM_PATHNAME) && c == '/')
/* [/] can never match when matching a pathname. */
return (char *)0;
/* This introduces a range, unless the `-' is the last
character of the class. Find the end of the range
and move past it. */
if (c == '-' && *p != ']')
{
cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return (char *)0;
if (cend == '[' && *p == '.')
{
p = parse_collsym (p, &pc);
/* An invalid collating symbol cannot be the second part of a
range expression. If we get one, we set cend to one fewer
than the test character to make sure the range test fails. */
cend = (pc == -1) ? test - 1 : pc;
}
cend = FOLD (cend);
c = *p++;
/* POSIX.2 2.8.3.2: ``The ending range point shall collate
equal to or higher than the starting range point; otherwise
the expression shall be treated as invalid.'' Note that this
applies to only the range expression; the rest of the bracket
expression is still checked for matches. */
if (rangecmp (cstart, cend) > 0)
{
if (c == ']')
break;
c = FOLD (c);
continue;
}
}
if (rangecmp (test, cstart) >= 0 && rangecmp (test, cend) <= 0)
goto matched;
if (c == ']')
break;
}
/* No match. */
return (!not ? (char *)0 : p);
matched:
/* Skip the rest of the [...] that already matched. */
#if 0
#if 0
brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.'));
#else
c = *--p;
brcnt = 1;
#endif
#else
c = *--p;
brcnt = 1;
#endif
while (brcnt > 0)
{
/* A `[' without a matching `]' is just another character to match. */
if (c == '\0')
return ((test == '[') ? savep : (char *)0);
c = *p++;
if (c == '[' && (*p == '=' || *p == ':' || *p == '.'))
brcnt++;
else if (c == ']')
brcnt--;
else if (!(flags & FNM_NOESCAPE) && c == '\\')
{
if (*p == '\0')
return (char *)0;
/* XXX 1003.2d11 is unclear if this is right. */
++p;
}
}
return (not ? (char *)0 : p);
}
#if defined (EXTENDED_GLOB)
/* ksh-like extended pattern matching:
[?*+@!](pat-list)
where pat-list is a list of one or patterns separated by `|'. Operation
is as follows:
?(patlist) match zero or one of the given patterns
*(patlist) match zero or more of the given patterns
+(patlist) match one or more of the given patterns
@(patlist) match exactly one of the given patterns
!(patlist) match anything except one of the given patterns
*/
/* Scan a pattern starting at STRING and ending at END, keeping track of
embedded () and []. If DELIM is 0, we scan until a matching `)'
because we're scanning a `patlist'. Otherwise, we scan until we see
DELIM. In all cases, we never scan past END. The return value is the
first character after the matching DELIM. */
static char *
patscan (string, end, delim)
char *string, *end;
int delim;
{
int pnest, bnest;
char *s, c;
pnest = bnest = 0;
for (s = string; c = *s; s++)
{
if (s >= end)
return (s);
switch (c)
{
case '\0':
return ((char *)0);
case '[':
bnest++;
break;
case ']':
if (bnest)
bnest--;
break;
case '(':
if (bnest == 0)
pnest++;
break;
case ')':
#if 0
if (bnest == 0)
pnest--;
if (pnest <= 0)
return ++s;
#else
if (bnest == 0 && pnest-- <= 0)
return ++s;
#endif
break;
case '|':
if (bnest == 0 && pnest == 0 && delim == '|')
return ++s;
break;
}
}
return (char *)0;
}
/* Return 0 if dequoted pattern matches S in the current locale. */
static int
strcompare (p, pe, s, se)
char *p, *pe, *s, *se;
{
int ret;
char c1, c2;
c1 = *pe;
c2 = *se;
*pe = *se = '\0';
#if defined (HAVE_STRCOLL)
ret = strcoll (p, s);
#else
ret = strcmp (p, s);
#endif
*pe = c1;
*se = c2;
return (ret == 0 ? ret : FNM_NOMATCH);
}
/* Match a ksh extended pattern specifier. Return FNM_NOMATCH on failure or
0 on success. This is handed the entire rest of the pattern and string
the first time an extended pattern specifier is encountered, so it calls
gmatch recursively. */
static int
extmatch (xc, s, se, p, pe, flags)
int xc; /* select which operation */
char *s, *se;
char *p, *pe;
int flags;
{
char *prest; /* pointer to rest of pattern */
char *psub; /* pointer to sub-pattern */
char *pnext; /* pointer to next sub-pattern */
char *srest; /* pointer to rest of string */
int m1, m2;
#if 0
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);
#endif
prest = patscan (p + (*p == '('), pe, 0); /* ) */
if (prest == 0)
/* If PREST is 0, we failed to scan a valid pattern. In this
case, we just want to compare the two as strings. */
return (strcompare (p - 1, pe, s, se));
switch (xc)
{
case '+': /* match one or more occurrences */
case '*': /* match zero or more occurrences */
/* If we can get away with no matches, don't even bother. Just
call gmatch on the rest of the pattern and return success if
it succeeds. */
if (xc == '*' && (gmatch (s, se, prest, pe, flags) == 0))
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. */
for (psub = p + 1; ; psub = pnext)
{
pnext = patscan (psub, pe, '|');
for (srest = s; srest <= se; srest++)
{
/* Match this substring (S -> SREST) against this
subpattern (psub -> pnext - 1) */
m1 = gmatch (s, srest, psub, pnext - 1, flags) == 0;
/* OK, we matched a subpattern, so make sure the rest of the
string matches the rest of the pattern. Also handle
multiple matches of the pattern. */
if (m1)
m2 = (gmatch (srest, se, prest, pe, flags) == 0) ||
(s != srest && gmatch (srest, se, p - 1, pe, flags) == 0);
if (m1 && m2)
return (0);
}
if (pnext == prest)
break;
}
return (FNM_NOMATCH);
case '?': /* match zero or one of the patterns */
case '@': /* match exactly one of the patterns */
/* If we can get away with no matches, don't even bother. Just
call gmatch on the rest of the pattern and return success if
it succeeds. */
if (xc == '?' && (gmatch (s, se, prest, pe, flags) == 0))
return 0;
/* OK, we have to do this the hard way. First, we see if one of
the subpatterns matches, then, if it does, we try to match the
rest of the string. */
for (psub = p + 1; ; psub = pnext)
{
pnext = patscan (psub, pe, '|');
srest = (prest == pe) ? se : s;
for ( ; srest <= se; srest++)
{
if (gmatch (s, srest, psub, pnext - 1, flags) == 0 &&
gmatch (srest, se, prest, pe, flags) == 0)
return (0);
}
if (pnext == prest)
break;
}
return (FNM_NOMATCH);
case '!': /* match anything *except* one of the patterns */
for (srest = s; srest <= se; srest++)
{
m1 = 0;
for (psub = p + 1; ; psub = pnext)
{
pnext = patscan (psub, pe, '|');
/* If one of the patterns matches, just bail immediately. */
if (m1 = (gmatch (s, srest, psub, pnext - 1, flags) == 0))
break;
if (pnext == prest)
break;
}
if (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0)
return (0);
}
return (FNM_NOMATCH);
}
return (FNM_NOMATCH);
}
#endif /* EXTENDED_GLOB */
#ifdef TEST
main (c, v)
int c;
char **v;
{
char *string, *pat;
string = v[1];
pat = v[2];
if (fnmatch (pat, string, 0) == 0)
{
printf ("%s matches %s\n", string, pat);
exit (0);
}
else
{
printf ("%s does not match %s\n", string, pat);
exit (1);
}
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -