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