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