aboutsummaryrefslogtreecommitdiff
path: root/win32/fnmatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/fnmatch.c')
-rw-r--r--win32/fnmatch.c484
1 files changed, 484 insertions, 0 deletions
diff --git a/win32/fnmatch.c b/win32/fnmatch.c
new file mode 100644
index 000000000..de456e526
--- /dev/null
+++ b/win32/fnmatch.c
@@ -0,0 +1,484 @@
1/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18
19#include <platform.h>
20
21#if HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25/* Enable GNU extensions in fnmatch.h. */
26#ifndef _GNU_SOURCE
27# define _GNU_SOURCE 1
28#endif
29
30#include <errno.h>
31#include <fnmatch.h>
32#include <ctype.h>
33
34#if HAVE_STRING_H || defined _LIBC
35# include <string.h>
36#else
37# include <strings.h>
38#endif
39
40#if defined STDC_HEADERS || defined _LIBC
41# include <stdlib.h>
42#endif
43
44/* For platform which support the ISO C amendement 1 functionality we
45 support user defined character classes. */
46#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
47/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
48# include <wchar.h>
49# include <wctype.h>
50#endif
51
52/* Comment out all this code if we are using the GNU C Library, and are not
53 actually compiling the library itself. This code is part of the GNU C
54 Library, but also included in many other GNU distributions. Compiling
55 and linking in this code is a waste when using the GNU C library
56 (especially if it is a shared library). Rather than having every GNU
57 program understand `configure --with-gnu-libc' and omit the object files,
58 it is simpler to just do this in the source for each such file. */
59
60#if defined _LIBC || !defined __GNU_LIBRARY__
61
62
63# if defined STDC_HEADERS || !defined isascii
64# define ISASCII(c) 1
65# else
66# define ISASCII(c) isascii(c)
67# endif
68
69# ifdef isblank
70# define ISBLANK(c) (ISASCII (c) && isblank (c))
71# else
72# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
73# endif
74# ifdef isgraph
75# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
76# else
77# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
78# endif
79
80# define ISPRINT(c) (ISASCII (c) && isprint (c))
81# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
82# define ISALNUM(c) (ISASCII (c) && isalnum (c))
83# define ISALPHA(c) (ISASCII (c) && isalpha (c))
84# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
85# define ISLOWER(c) (ISASCII (c) && islower (c))
86# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
87# define ISSPACE(c) (ISASCII (c) && isspace (c))
88# define ISUPPER(c) (ISASCII (c) && isupper (c))
89# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
90
91# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
92
93# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
94/* The GNU C library provides support for user-defined character classes
95 and the functions from ISO C amendement 1. */
96# ifdef CHARCLASS_NAME_MAX
97# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
98# else
99/* This shouldn't happen but some implementation might still have this
100 problem. Use a reasonable default value. */
101# define CHAR_CLASS_MAX_LENGTH 256
102# endif
103
104# ifdef _LIBC
105# define IS_CHAR_CLASS(string) __wctype (string)
106# else
107# define IS_CHAR_CLASS(string) wctype (string)
108# endif
109# else
110# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
111
112# define IS_CHAR_CLASS(string) \
113 (STREQ (string, "alpha") || STREQ (string, "upper") \
114 || STREQ (string, "lower") || STREQ (string, "digit") \
115 || STREQ (string, "alnum") || STREQ (string, "xdigit") \
116 || STREQ (string, "space") || STREQ (string, "print") \
117 || STREQ (string, "punct") || STREQ (string, "graph") \
118 || STREQ (string, "cntrl") || STREQ (string, "blank"))
119# endif
120
121/* Avoid depending on library functions or files
122 whose names are inconsistent. */
123
124# if !defined _LIBC && !defined getenv
125extern char *getenv (const char *);
126# endif
127
128# ifndef errno
129extern int errno;
130# endif
131
132/* This function doesn't exist on most systems. */
133
134# if !defined HAVE___STRCHRNUL && !defined _LIBC && 0
135static char *
136__strchrnul (const char *s, int c)
137{
138 char *result = strchr (s, c);
139 if (result == NULL)
140 result = strchr (s, '\0');
141 return result;
142}
143# else
144# define __strchrnul strchrnul
145# endif
146
147# ifndef internal_function
148/* Inside GNU libc we mark some function in a special way. In other
149 environments simply ignore the marking. */
150# define internal_function
151# endif
152
153/* Match STRING against the filename pattern PATTERN, returning zero if
154 it matches, nonzero if not. */
155static int internal_fnmatch __P ((const char *pattern, const char *string,
156 int no_leading_period, int flags))
157 internal_function;
158static int
159internal_function
160internal_fnmatch (const char *pattern, const char *string,
161 int no_leading_period, int flags)
162{
163 register const char *p = pattern, *n = string;
164 register unsigned char c;
165
166/* Note that this evaluates C many times. */
167# ifdef _LIBC
168# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
169# else
170# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
171# endif
172
173 while ((c = *p++) != '\0')
174 {
175 c = FOLD (c);
176
177 switch (c)
178 {
179 case '?':
180 if (*n == '\0')
181 return FNM_NOMATCH;
182 else if (*n == '/' && (flags & FNM_FILE_NAME))
183 return FNM_NOMATCH;
184 else if (*n == '.' && no_leading_period
185 && (n == string
186 || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
187 return FNM_NOMATCH;
188 break;
189
190 case '\\':
191 if (!(flags & FNM_NOESCAPE))
192 {
193 c = *p++;
194 if (c == '\0')
195 /* Trailing \ loses. */
196 return FNM_NOMATCH;
197 c = FOLD (c);
198 }
199 if (FOLD ((unsigned char) *n) != c)
200 return FNM_NOMATCH;
201 break;
202
203 case '*':
204 if (*n == '.' && no_leading_period
205 && (n == string
206 || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
207 return FNM_NOMATCH;
208
209 for (c = *p++; c == '?' || c == '*'; c = *p++)
210 {
211 if (*n == '/' && (flags & FNM_FILE_NAME))
212 /* A slash does not match a wildcard under FNM_FILE_NAME. */
213 return FNM_NOMATCH;
214 else if (c == '?')
215 {
216 /* A ? needs to match one character. */
217 if (*n == '\0')
218 /* There isn't another character; no match. */
219 return FNM_NOMATCH;
220 else
221 /* One character of the string is consumed in matching
222 this ? wildcard, so *??? won't match if there are
223 less than three characters. */
224 ++n;
225 }
226 }
227
228 if (c == '\0')
229 /* The wildcard(s) is/are the last element of the pattern.
230 If the name is a file name and contains another slash
231 this does mean it cannot match. */
232 return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
233 ? FNM_NOMATCH : 0);
234 else
235 {
236 const char *endp;
237
238 endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
239
240 if (c == '[')
241 {
242 int flags2 = ((flags & FNM_FILE_NAME)
243 ? flags : (flags & ~FNM_PERIOD));
244
245 for (--p; n < endp; ++n)
246 if (internal_fnmatch (p, n,
247 (no_leading_period
248 && (n == string
249 || (n[-1] == '/'
250 && (flags
251 & FNM_FILE_NAME)))),
252 flags2)
253 == 0)
254 return 0;
255 }
256 else if (c == '/' && (flags & FNM_FILE_NAME))
257 {
258 while (*n != '\0' && *n != '/')
259 ++n;
260 if (*n == '/'
261 && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
262 flags) == 0))
263 return 0;
264 }
265 else
266 {
267 int flags2 = ((flags & FNM_FILE_NAME)
268 ? flags : (flags & ~FNM_PERIOD));
269
270 if (c == '\\' && !(flags & FNM_NOESCAPE))
271 c = *p;
272 c = FOLD (c);
273 for (--p; n < endp; ++n)
274 if (FOLD ((unsigned char) *n) == c
275 && (internal_fnmatch (p, n,
276 (no_leading_period
277 && (n == string
278 || (n[-1] == '/'
279 && (flags
280 & FNM_FILE_NAME)))),
281 flags2) == 0))
282 return 0;
283 }
284 }
285
286 /* If we come here no match is possible with the wildcard. */
287 return FNM_NOMATCH;
288
289 case '[':
290 {
291 /* Nonzero if the sense of the character class is inverted. */
292 static int posixly_correct;
293 register int not;
294 char cold;
295
296 if (posixly_correct == 0)
297 posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
298
299 if (*n == '\0')
300 return FNM_NOMATCH;
301
302 if (*n == '.' && no_leading_period && (n == string
303 || (n[-1] == '/'
304 && (flags
305 & FNM_FILE_NAME))))
306 return FNM_NOMATCH;
307
308 if (*n == '/' && (flags & FNM_FILE_NAME))
309 /* `/' cannot be matched. */
310 return FNM_NOMATCH;
311
312 not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
313 if (not)
314 ++p;
315
316 c = *p++;
317 for (;;)
318 {
319 unsigned char fn = FOLD ((unsigned char) *n);
320
321 if (!(flags & FNM_NOESCAPE) && c == '\\')
322 {
323 if (*p == '\0')
324 return FNM_NOMATCH;
325 c = FOLD ((unsigned char) *p);
326 ++p;
327
328 if (c == fn)
329 goto matched;
330 }
331 else if (c == '[' && *p == ':')
332 {
333 /* Leave room for the null. */
334 char str[CHAR_CLASS_MAX_LENGTH + 1];
335 size_t c1 = 0;
336# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
337 wctype_t wt;
338# endif
339 const char *startp = p;
340
341 for (;;)
342 {
343 if (c1 == CHAR_CLASS_MAX_LENGTH)
344 /* The name is too long and therefore the pattern
345 is ill-formed. */
346 return FNM_NOMATCH;
347
348 c = *++p;
349 if (c == ':' && p[1] == ']')
350 {
351 p += 2;
352 break;
353 }
354 if (c < 'a' || c >= 'z')
355 {
356 /* This cannot possibly be a character class name.
357 Match it as a normal range. */
358 p = startp;
359 c = '[';
360 goto normal_bracket;
361 }
362 str[c1++] = c;
363 }
364 str[c1] = '\0';
365
366# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
367 wt = IS_CHAR_CLASS (str);
368 if (wt == 0)
369 /* Invalid character class name. */
370 return FNM_NOMATCH;
371
372 if (__iswctype (__btowc ((unsigned char) *n), wt))
373 goto matched;
374# else
375 if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
376 || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
377 || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
378 || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
379 || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
380 || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
381 || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
382 || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
383 || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
384 || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
385 || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
386 || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
387 goto matched;
388# endif
389 }
390 else if (c == '\0')
391 /* [ (unterminated) loses. */
392 return FNM_NOMATCH;
393 else
394 {
395 normal_bracket:
396 if (FOLD (c) == fn)
397 goto matched;
398
399 cold = c;
400 c = *p++;
401
402 if (c == '-' && *p != ']')
403 {
404 /* It is a range. */
405 unsigned char cend = *p++;
406 if (!(flags & FNM_NOESCAPE) && cend == '\\')
407 cend = *p++;
408 if (cend == '\0')
409 return FNM_NOMATCH;
410
411 if (cold <= fn && fn <= FOLD (cend))
412 goto matched;
413
414 c = *p++;
415 }
416 }
417
418 if (c == ']')
419 break;
420 }
421
422 if (!not)
423 return FNM_NOMATCH;
424 break;
425
426 matched:
427 /* Skip the rest of the [...] that already matched. */
428 while (c != ']')
429 {
430 if (c == '\0')
431 /* [... (unterminated) loses. */
432 return FNM_NOMATCH;
433
434 c = *p++;
435 if (!(flags & FNM_NOESCAPE) && c == '\\')
436 {
437 if (*p == '\0')
438 return FNM_NOMATCH;
439 /* XXX 1003.2d11 is unclear if this is right. */
440 ++p;
441 }
442 else if (c == '[' && *p == ':')
443 {
444 do
445 if (*++p == '\0')
446 return FNM_NOMATCH;
447 while (*p != ':' || p[1] == ']');
448 p += 2;
449 c = *p;
450 }
451 }
452 if (not)
453 return FNM_NOMATCH;
454 }
455 break;
456
457 default:
458 if (c != FOLD ((unsigned char) *n))
459 return FNM_NOMATCH;
460 }
461
462 ++n;
463 }
464
465 if (*n == '\0')
466 return 0;
467
468 if ((flags & FNM_LEADING_DIR) && *n == '/')
469 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
470 return 0;
471
472 return FNM_NOMATCH;
473
474# undef FOLD
475}
476
477
478int
479fnmatch (const char *pattern, const char *string, int flags)
480{
481 return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
482}
483
484#endif /* _LIBC or not __GNU_LIBRARY__. */