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