Merge branch 'dw/diff-no-index-doc'
[git] / compat / fnmatch / fnmatch.c
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 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 /* Enable GNU extensions in fnmatch.h.  */
24 #ifndef _GNU_SOURCE
25 # define _GNU_SOURCE    1
26 #endif
27
28 #include <stddef.h>
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 platforms which support the ISO C amendment 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 NO_FNMATCH || defined NO_FNMATCH_CASEFOLD || \
60     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 amendment 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
125 extern char *getenv (const char *name);
126 # endif
127
128 # ifndef errno
129 extern int errno;
130 # endif
131
132 # ifndef NULL
133 #  define NULL 0
134 # endif
135
136 /* This function doesn't exist on most systems.  */
137
138 # if !defined HAVE___STRCHRNUL && !defined _LIBC
139 static char *
140 __strchrnul (const char *s, int c)
141
142
143 {
144   char *result = strchr (s, c);
145   if (result == NULL)
146     result = strchr (s, '\0');
147   return result;
148 }
149 # endif
150
151 # ifndef internal_function
152 /* Inside GNU libc we mark some function in a special way.  In other
153    environments simply ignore the marking.  */
154 #  define internal_function
155 # endif
156
157 /* Match STRING against the filename pattern PATTERN, returning zero if
158    it matches, nonzero if not.  */
159 static int internal_fnmatch __P ((const char *pattern, const char *string,
160                                   int no_leading_period, int flags))
161      internal_function;
162 static int
163 internal_function
164 internal_fnmatch (const char *pattern, const char *string, int no_leading_period, int flags)
165
166
167
168
169 {
170   register const char *p = pattern, *n = string;
171   register unsigned char c;
172
173 /* Note that this evaluates C many times.  */
174 # ifdef _LIBC
175 #  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
176 # else
177 #  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
178 # endif
179
180   while ((c = *p++) != '\0')
181     {
182       c = FOLD (c);
183
184       switch (c)
185         {
186         case '?':
187           if (*n == '\0')
188             return FNM_NOMATCH;
189           else if (*n == '/' && (flags & FNM_FILE_NAME))
190             return FNM_NOMATCH;
191           else if (*n == '.' && no_leading_period
192                    && (n == string
193                        || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
194             return FNM_NOMATCH;
195           break;
196
197         case '\\':
198           if (!(flags & FNM_NOESCAPE))
199             {
200               c = *p++;
201               if (c == '\0')
202                 /* Trailing \ loses.  */
203                 return FNM_NOMATCH;
204               c = FOLD (c);
205             }
206           if (FOLD ((unsigned char) *n) != c)
207             return FNM_NOMATCH;
208           break;
209
210         case '*':
211           if (*n == '.' && no_leading_period
212               && (n == string
213                   || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
214             return FNM_NOMATCH;
215
216           for (c = *p++; c == '?' || c == '*'; c = *p++)
217             {
218               if (*n == '/' && (flags & FNM_FILE_NAME))
219                 /* A slash does not match a wildcard under FNM_FILE_NAME.  */
220                 return FNM_NOMATCH;
221               else if (c == '?')
222                 {
223                   /* A ? needs to match one character.  */
224                   if (*n == '\0')
225                     /* There isn't another character; no match.  */
226                     return FNM_NOMATCH;
227                   else
228                     /* One character of the string is consumed in matching
229                        this ? wildcard, so *??? won't match if there are
230                        less than three characters.  */
231                     ++n;
232                 }
233             }
234
235           if (c == '\0')
236             /* The wildcard(s) is/are the last element of the pattern.
237                If the name is a file name and contains another slash
238                this does mean it cannot match.  */
239             return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
240                     ? FNM_NOMATCH : 0);
241           else
242             {
243               const char *endp;
244
245               endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
246
247               if (c == '[')
248                 {
249                   int flags2 = ((flags & FNM_FILE_NAME)
250                                 ? flags : (flags & ~FNM_PERIOD));
251
252                   for (--p; n < endp; ++n)
253                     if (internal_fnmatch (p, n,
254                                           (no_leading_period
255                                            && (n == string
256                                                || (n[-1] == '/'
257                                                    && (flags
258                                                        & FNM_FILE_NAME)))),
259                                           flags2)
260                         == 0)
261                       return 0;
262                 }
263               else if (c == '/' && (flags & FNM_FILE_NAME))
264                 {
265                   while (*n != '\0' && *n != '/')
266                     ++n;
267                   if (*n == '/'
268                       && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
269                                             flags) == 0))
270                     return 0;
271                 }
272               else
273                 {
274                   int flags2 = ((flags & FNM_FILE_NAME)
275                                 ? flags : (flags & ~FNM_PERIOD));
276
277                   if (c == '\\' && !(flags & FNM_NOESCAPE))
278                     c = *p;
279                   c = FOLD (c);
280                   for (--p; n < endp; ++n)
281                     if (FOLD ((unsigned char) *n) == c
282                         && (internal_fnmatch (p, n,
283                                               (no_leading_period
284                                                && (n == string
285                                                    || (n[-1] == '/'
286                                                        && (flags
287                                                            & FNM_FILE_NAME)))),
288                                               flags2) == 0))
289                       return 0;
290                 }
291             }
292
293           /* If we come here no match is possible with the wildcard.  */
294           return FNM_NOMATCH;
295
296         case '[':
297           {
298             /* Nonzero if the sense of the character class is inverted.  */
299             static int posixly_correct;
300             register int not;
301             char cold;
302
303             if (posixly_correct == 0)
304               posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
305
306             if (*n == '\0')
307               return FNM_NOMATCH;
308
309             if (*n == '.' && no_leading_period && (n == string
310                                                    || (n[-1] == '/'
311                                                        && (flags
312                                                            & FNM_FILE_NAME))))
313               return FNM_NOMATCH;
314
315             if (*n == '/' && (flags & FNM_FILE_NAME))
316               /* `/' cannot be matched.  */
317               return FNM_NOMATCH;
318
319             not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
320             if (not)
321               ++p;
322
323             c = *p++;
324             for (;;)
325               {
326                 unsigned char fn = FOLD ((unsigned char) *n);
327
328                 if (!(flags & FNM_NOESCAPE) && c == '\\')
329                   {
330                     if (*p == '\0')
331                       return FNM_NOMATCH;
332                     c = FOLD ((unsigned char) *p);
333                     ++p;
334
335                     if (c == fn)
336                       goto matched;
337                   }
338                 else if (c == '[' && *p == ':')
339                   {
340                     /* Leave room for the null.  */
341                     char str[CHAR_CLASS_MAX_LENGTH + 1];
342                     size_t c1 = 0;
343 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
344                     wctype_t wt;
345 # endif
346                     const char *startp = p;
347
348                     for (;;)
349                       {
350                         if (c1 > CHAR_CLASS_MAX_LENGTH)
351                           /* The name is too long and therefore the pattern
352                              is ill-formed.  */
353                           return FNM_NOMATCH;
354
355                         c = *++p;
356                         if (c == ':' && p[1] == ']')
357                           {
358                             p += 2;
359                             break;
360                           }
361                         if (c < 'a' || c >= 'z')
362                           {
363                             /* This cannot possibly be a character class name.
364                                Match it as a normal range.  */
365                             p = startp;
366                             c = '[';
367                             goto normal_bracket;
368                           }
369                         str[c1++] = c;
370                       }
371                     str[c1] = '\0';
372
373 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
374                     wt = IS_CHAR_CLASS (str);
375                     if (wt == 0)
376                       /* Invalid character class name.  */
377                       return FNM_NOMATCH;
378
379                     if (__iswctype (__btowc ((unsigned char) *n), wt))
380                       goto matched;
381 # else
382                     if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
383                         || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
384                         || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
385                         || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
386                         || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
387                         || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
388                         || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
389                         || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
390                         || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
391                         || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
392                         || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
393                         || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
394                       goto matched;
395 # endif
396                   }
397                 else if (c == '\0')
398                   /* [ (unterminated) loses.  */
399                   return FNM_NOMATCH;
400                 else
401                   {
402                   normal_bracket:
403                     if (FOLD (c) == fn)
404                       goto matched;
405
406                     cold = c;
407                     c = *p++;
408
409                     if (c == '-' && *p != ']')
410                       {
411                         /* It is a range.  */
412                         unsigned char cend = *p++;
413                         if (!(flags & FNM_NOESCAPE) && cend == '\\')
414                           cend = *p++;
415                         if (cend == '\0')
416                           return FNM_NOMATCH;
417
418                         if (cold <= fn && fn <= FOLD (cend))
419                           goto matched;
420
421                         c = *p++;
422                       }
423                   }
424
425                 if (c == ']')
426                   break;
427               }
428
429             if (!not)
430               return FNM_NOMATCH;
431             break;
432
433           matched:
434             /* Skip the rest of the [...] that already matched.  */
435             while (c != ']')
436               {
437                 if (c == '\0')
438                   /* [... (unterminated) loses.  */
439                   return FNM_NOMATCH;
440
441                 c = *p++;
442                 if (!(flags & FNM_NOESCAPE) && c == '\\')
443                   {
444                     if (*p == '\0')
445                       return FNM_NOMATCH;
446                     /* XXX 1003.2d11 is unclear if this is right.  */
447                     ++p;
448                   }
449                 else if (c == '[' && *p == ':')
450                   {
451                     do
452                       if (*++p == '\0')
453                         return FNM_NOMATCH;
454                     while (*p != ':' || p[1] == ']');
455                     p += 2;
456                     c = *p;
457                   }
458               }
459             if (not)
460               return FNM_NOMATCH;
461           }
462           break;
463
464         default:
465           if (c != FOLD ((unsigned char) *n))
466             return FNM_NOMATCH;
467         }
468
469       ++n;
470     }
471
472   if (*n == '\0')
473     return 0;
474
475   if ((flags & FNM_LEADING_DIR) && *n == '/')
476     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
477     return 0;
478
479   return FNM_NOMATCH;
480
481 # undef FOLD
482 }
483
484
485 int
486 fnmatch (const char *pattern, const char *string, int flags)
487
488
489
490 {
491   return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
492 }
493
494 #endif  /* _LIBC or not __GNU_LIBRARY__.  */