Annotation of gforth/engine/fnmatch.c, revision 1.2
1.2 ! anton 1: /* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
1.1 anton 2:
1.2 ! anton 3: This program is free software; you can redistribute it and/or modify
! 4: it under the terms of the GNU General Public License as published by
! 5: the Free Software Foundation; either version 2, or (at your option)
! 6: any later version.
1.1 anton 7:
1.2 ! anton 8: This program is distributed in the hope that it will be useful,
1.1 anton 9: but WITHOUT ANY WARRANTY; without even the implied warranty of
1.2 ! anton 10: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 11: GNU General Public License for more details.
1.1 anton 12:
1.2 ! anton 13: You should have received a copy of the GNU General Public License
! 14: along with this program; if not, write to the Free Software Foundation,
! 15: Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1.1 anton 16:
17: #if HAVE_CONFIG_H
18: # include <config.h>
19: #endif
20:
21: /* Enable GNU extensions in fnmatch.h. */
22: #ifndef _GNU_SOURCE
23: # define _GNU_SOURCE 1
24: #endif
25:
26: #include <errno.h>
27: #include <fnmatch.h>
28: #include <ctype.h>
29:
30:
31: /* Comment out all this code if we are using the GNU C Library, and are not
32: actually compiling the library itself. This code is part of the GNU C
33: Library, but also included in many other GNU distributions. Compiling
34: and linking in this code is a waste when using the GNU C library
35: (especially if it is a shared library). Rather than having every GNU
36: program understand `configure --with-gnu-libc' and omit the object files,
37: it is simpler to just do this in the source for each such file. */
38:
39: #if defined _LIBC || !defined __GNU_LIBRARY__
40:
41:
42: # if defined STDC_HEADERS || !defined isascii
43: # define ISASCII(c) 1
44: # else
45: # define ISASCII(c) isascii(c)
46: # endif
47:
1.2 ! anton 48: # define ISUPPER(c) (ISASCII (c) && isupper (c))
1.1 anton 49:
50:
51: # ifndef errno
52: extern int errno;
53: # endif
54:
55: /* Match STRING against the filename pattern PATTERN, returning zero if
56: it matches, nonzero if not. */
1.2 ! anton 57: int
! 58: fnmatch (const char *pattern, const char *string, int flags)
1.1 anton 59: {
60: register const char *p = pattern, *n = string;
1.2 ! anton 61: register char c;
1.1 anton 62:
63: /* Note that this evaluates C many times. */
1.2 ! anton 64: # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
1.1 anton 65:
66: while ((c = *p++) != '\0')
67: {
68: c = FOLD (c);
69:
70: switch (c)
71: {
72: case '?':
73: if (*n == '\0')
74: return FNM_NOMATCH;
1.2 ! anton 75: else if ((flags & FNM_FILE_NAME) && *n == '/')
1.1 anton 76: return FNM_NOMATCH;
1.2 ! anton 77: else if ((flags & FNM_PERIOD) && *n == '.' &&
! 78: (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1.1 anton 79: return FNM_NOMATCH;
80: break;
81:
82: case '\\':
83: if (!(flags & FNM_NOESCAPE))
84: {
85: c = *p++;
86: if (c == '\0')
87: /* Trailing \ loses. */
88: return FNM_NOMATCH;
89: c = FOLD (c);
90: }
1.2 ! anton 91: if (FOLD (*n) != c)
1.1 anton 92: return FNM_NOMATCH;
93: break;
94:
95: case '*':
1.2 ! anton 96: if ((flags & FNM_PERIOD) && *n == '.' &&
! 97: (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1.1 anton 98: return FNM_NOMATCH;
99:
100: for (c = *p++; c == '?' || c == '*'; c = *p++)
101: {
1.2 ! anton 102: if ((flags & FNM_FILE_NAME) && *n == '/')
1.1 anton 103: /* A slash does not match a wildcard under FNM_FILE_NAME. */
104: return FNM_NOMATCH;
105: else if (c == '?')
106: {
107: /* A ? needs to match one character. */
108: if (*n == '\0')
109: /* There isn't another character; no match. */
110: return FNM_NOMATCH;
111: else
112: /* One character of the string is consumed in matching
113: this ? wildcard, so *??? won't match if there are
114: less than three characters. */
115: ++n;
116: }
117: }
118:
119: if (c == '\0')
1.2 ! anton 120: return 0;
1.1 anton 121:
1.2 ! anton 122: {
! 123: char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
! 124: c1 = FOLD (c1);
! 125: for (--p; *n != '\0'; ++n)
! 126: if ((c == '[' || FOLD (*n) == c1) &&
! 127: fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
! 128: return 0;
! 129: return FNM_NOMATCH;
! 130: }
1.1 anton 131:
132: case '[':
133: {
134: /* Nonzero if the sense of the character class is inverted. */
135: register int not;
136:
137: if (*n == '\0')
138: return FNM_NOMATCH;
139:
1.2 ! anton 140: if ((flags & FNM_PERIOD) && *n == '.' &&
! 141: (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1.1 anton 142: return FNM_NOMATCH;
143:
1.2 ! anton 144: not = (*p == '!' || *p == '^');
1.1 anton 145: if (not)
146: ++p;
147:
148: c = *p++;
149: for (;;)
150: {
1.2 ! anton 151: register char cstart = c, cend = c;
1.1 anton 152:
153: if (!(flags & FNM_NOESCAPE) && c == '\\')
154: {
155: if (*p == '\0')
156: return FNM_NOMATCH;
1.2 ! anton 157: cstart = cend = *p++;
1.1 anton 158: }
159:
1.2 ! anton 160: cstart = cend = FOLD (cstart);
1.1 anton 161:
1.2 ! anton 162: if (c == '\0')
1.1 anton 163: /* [ (unterminated) loses. */
164: return FNM_NOMATCH;
1.2 ! anton 165:
! 166: c = *p++;
! 167: c = FOLD (c);
! 168:
! 169: if ((flags & FNM_FILE_NAME) && c == '/')
! 170: /* [/] can never match. */
! 171: return FNM_NOMATCH;
! 172:
! 173: if (c == '-' && *p != ']')
1.1 anton 174: {
1.2 ! anton 175: cend = *p++;
! 176: if (!(flags & FNM_NOESCAPE) && cend == '\\')
! 177: cend = *p++;
! 178: if (cend == '\0')
! 179: return FNM_NOMATCH;
! 180: cend = FOLD (cend);
1.1 anton 181:
182: c = *p++;
1.2 ! anton 183: }
1.1 anton 184:
1.2 ! anton 185: if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
! 186: goto matched;
1.1 anton 187:
188: if (c == ']')
189: break;
190: }
191: if (!not)
192: return FNM_NOMATCH;
193: break;
194:
1.2 ! anton 195: matched:;
1.1 anton 196: /* Skip the rest of the [...] that already matched. */
197: while (c != ']')
198: {
199: if (c == '\0')
200: /* [... (unterminated) loses. */
201: return FNM_NOMATCH;
202:
203: c = *p++;
204: if (!(flags & FNM_NOESCAPE) && c == '\\')
205: {
206: if (*p == '\0')
207: return FNM_NOMATCH;
208: /* XXX 1003.2d11 is unclear if this is right. */
209: ++p;
210: }
211: }
212: if (not)
213: return FNM_NOMATCH;
214: }
215: break;
216:
217: default:
1.2 ! anton 218: if (c != FOLD (*n))
1.1 anton 219: return FNM_NOMATCH;
220: }
221:
222: ++n;
223: }
224:
225: if (*n == '\0')
226: return 0;
227:
228: if ((flags & FNM_LEADING_DIR) && *n == '/')
229: /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
230: return 0;
231:
232: return FNM_NOMATCH;
233:
234: # undef FOLD
235: }
236:
237: #endif /* _LIBC or not __GNU_LIBRARY__. */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>