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