1 /* Pattern matching (globbing).
2 Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc.
4 This file is part of GNU Wget.
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* NOTE: Some Un*xes have their own fnmatch() -- yet, they are
21 reportedly unreliable and buggy. Thus I chose never to use it;
22 this version (from GNU Bash) is used unconditionally. */
30 /* Match STRING against the filename pattern PATTERN, returning zero
31 if it matches, FNM_NOMATCH if not. */
33 fnmatch (const char *pattern, const char *string, int flags)
35 register const char *p = pattern, *n = string;
38 if ((flags & ~__FNM_FLAGS) != 0)
44 while ((c = *p++) != '\0')
51 else if ((flags & FNM_PATHNAME) && *n == '/')
53 else if ((flags & FNM_PERIOD) && *n == '.' &&
54 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
59 if (!(flags & FNM_NOESCAPE))
66 if ((flags & FNM_PERIOD) && *n == '.' &&
67 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
70 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
71 if (((flags & FNM_PATHNAME) && *n == '/') ||
72 (c == '?' && *n == '\0'))
79 char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
80 for (--p; *n != '\0'; ++n)
81 if ((c == '[' || *n == c1) &&
82 fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
89 /* Nonzero if the sense of the character class is
96 if ((flags & FNM_PERIOD) && *n == '.' &&
97 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
100 /* Make sure there is a closing `]'. If there isn't,
101 the `[' is just a character to be matched. */
103 register const char *np;
105 for (np = p; np && *np && *np != ']'; np++);
110 return (FNM_NOMATCH);
115 not = (*p == '!' || *p == '^');
122 register char cstart = c, cend = c;
124 if (!(flags & FNM_NOESCAPE) && c == '\\')
125 cstart = cend = *p++;
128 /* [ (unterminated) loses. */
129 return (FNM_NOMATCH);
133 if ((flags & FNM_PATHNAME) && c == '/')
134 /* [/] can never match. */
135 return (FNM_NOMATCH);
137 if (c == '-' && *p != ']')
140 if (!(flags & FNM_NOESCAPE) && cend == '\\')
143 return (FNM_NOMATCH);
147 if (*n >= cstart && *n <= cend)
154 return (FNM_NOMATCH);
160 /* Skip the rest of the [...] that already matched. */
164 /* [... (unterminated) loses. */
165 return (FNM_NOMATCH);
168 if (!(flags & FNM_NOESCAPE) && c == '\\')
169 /* 1003.2d11 is unclear if this is right. %%% */
173 return (FNM_NOMATCH);
179 return (FNM_NOMATCH);
188 return (FNM_NOMATCH);
191 /* Return non-zero if S contains globbing wildcards (`*', `?', `[' or
194 has_wildcards_p (const char *s)
197 if (*s == '*' || *s == '?' || *s == '[' || *s == ']')