]> git.saurik.com Git - apple/libc.git/blob - gen/FreeBSD/fnmatch.c.patch
b45f0ea26a99ed2f78b4e1abefd4a95b625bf9a4
[apple/libc.git] / gen / FreeBSD / fnmatch.c.patch
1 --- fnmatch.c.orig 2011-02-17 17:11:04.000000000 -0800
2 +++ fnmatch.c 2011-02-18 12:00:31.000000000 -0800
3 @@ -36,6 +36,8 @@ static char sccsid[] = "@(#)fnmatch.c 8.
4 #include <sys/cdefs.h>
5 __FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.19 2010/04/16 22:29:24 jilles Exp $");
6
7 +#include "xlocale_private.h"
8 +
9 /*
10 * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
11 * Compares a filename or pathname to a pattern.
12 @@ -62,13 +64,16 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/fnm
13
14 #define EOS '\0'
15
16 +#define RETURN_ERROR 2 /* neither 0 or FNM_NOMATCH */
17 #define RANGE_MATCH 1
18 #define RANGE_NOMATCH 0
19 #define RANGE_ERROR (-1)
20
21 -static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
22 +#define RECURSION_MAX 64
23 +
24 +__private_extern__ int rangematch(const char *, wchar_t, const char *, int, char **, char **, mbstate_t *, mbstate_t *, locale_t);
25 static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
26 - mbstate_t);
27 + mbstate_t, locale_t, int);
28
29 int
30 fnmatch(pattern, string, flags)
31 @@ -76,27 +81,38 @@ fnmatch(pattern, string, flags)
32 int flags;
33 {
34 static const mbstate_t initial;
35 -
36 - return (fnmatch1(pattern, string, string, flags, initial, initial));
37 +#if __DARWIN_UNIX03
38 + return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX));
39 +#else /* !__DARWIN_UNIX03 */
40 + return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX) != 0 ? FNM_NOMATCH : 0);
41 +#endif /* __DARWIN_UNIX03 */
42 }
43
44 static int
45 -fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
46 +fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs, loc, recursion)
47 const char *pattern, *string, *stringstart;
48 int flags;
49 mbstate_t patmbs, strmbs;
50 + locale_t loc;
51 + int recursion;
52 {
53 - char *newp;
54 + char *newp, *news;
55 char c;
56 wchar_t pc, sc;
57 size_t pclen, sclen;
58
59 + if (recursion-- <= 0)
60 + return RETURN_ERROR;
61 for (;;) {
62 - pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
63 + pclen = mbrtowc_l(&pc, pattern, MB_LEN_MAX, &patmbs, loc);
64 if (pclen == (size_t)-1 || pclen == (size_t)-2)
65 +#if __DARWIN_UNIX03
66 + return (RETURN_ERROR);
67 +#else /* !__DARWIN_UNIX03 */
68 return (FNM_NOMATCH);
69 +#endif /* __DARWIN_UNIX03 */
70 pattern += pclen;
71 - sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs);
72 + sclen = mbrtowc_l(&sc, string, MB_LEN_MAX, &strmbs, loc);
73 if (sclen == (size_t)-1 || sclen == (size_t)-2) {
74 sc = (unsigned char)*string;
75 sclen = 1;
76 @@ -144,12 +160,13 @@ fnmatch1(pattern, string, stringstart, f
77 }
78
79 /* General case, use recursion. */
80 + int ret;
81 while (sc != EOS) {
82 - if (!fnmatch1(pattern, string, stringstart,
83 - flags, patmbs, strmbs))
84 - return (0);
85 - sclen = mbrtowc(&sc, string, MB_LEN_MAX,
86 - &strmbs);
87 + if ((ret = fnmatch1(pattern, string, stringstart,
88 + flags, patmbs, strmbs, loc, recursion)) != FNM_NOMATCH)
89 + return (ret);
90 + sclen = mbrtowc_l(&sc, string, MB_LEN_MAX,
91 + &strmbs, loc);
92 if (sclen == (size_t)-1 ||
93 sclen == (size_t)-2) {
94 sc = (unsigned char)*string;
95 @@ -171,35 +188,45 @@ fnmatch1(pattern, string, stringstart, f
96 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
97 return (FNM_NOMATCH);
98
99 - switch (rangematch(pattern, sc, flags, &newp,
100 - &patmbs)) {
101 + switch (rangematch(pattern, sc, string + sclen, flags,
102 + &newp, &news, &patmbs, &strmbs, loc)) {
103 case RANGE_ERROR:
104 +#if __DARWIN_UNIX03
105 + return (RETURN_ERROR);
106 +#else /* !__DARWIN_UNIX03 */
107 goto norm;
108 +#endif /* __DARWIN_UNIX03 */
109 case RANGE_MATCH:
110 pattern = newp;
111 + string = news;
112 break;
113 case RANGE_NOMATCH:
114 return (FNM_NOMATCH);
115 }
116 - string += sclen;
117 break;
118 case '\\':
119 if (!(flags & FNM_NOESCAPE)) {
120 - pclen = mbrtowc(&pc, pattern, MB_LEN_MAX,
121 - &patmbs);
122 + pclen = mbrtowc_l(&pc, pattern, MB_LEN_MAX,
123 + &patmbs, loc);
124 if (pclen == (size_t)-1 || pclen == (size_t)-2)
125 +#if __DARWIN_UNIX03
126 + return (RETURN_ERROR);
127 +#else /* !__DARWIN_UNIX03 */
128 return (FNM_NOMATCH);
129 +#endif /* __DARWIN_UNIX03 */
130 if (pclen == 0)
131 pc = '\\';
132 pattern += pclen;
133 }
134 /* FALLTHROUGH */
135 default:
136 +#if !__DARWIN_UNIX03
137 norm:
138 +#endif /* !__DARWIN_UNIX03 */
139 if (pc == sc)
140 ;
141 else if ((flags & FNM_CASEFOLD) &&
142 - (towlower(pc) == towlower(sc)))
143 + (towlower_l(pc, loc) == towlower_l(sc, loc)))
144 ;
145 else
146 return (FNM_NOMATCH);
147 @@ -210,18 +237,22 @@ fnmatch1(pattern, string, stringstart, f
148 /* NOTREACHED */
149 }
150
151 -static int
152 -rangematch(pattern, test, flags, newp, patmbs)
153 - const char *pattern;
154 +#ifndef BUILDING_VARIANT
155 +__private_extern__ int
156 +rangematch(pattern, test, string, flags, newp, news, patmbs, strmbs, loc)
157 + const char *pattern, *string;
158 wchar_t test;
159 int flags;
160 - char **newp;
161 - mbstate_t *patmbs;
162 + char **newp, **news;
163 + mbstate_t *patmbs, *strmbs;
164 + locale_t loc;
165 {
166 - int negate, ok;
167 + int negate, ok, special;
168 wchar_t c, c2;
169 - size_t pclen;
170 - const char *origpat;
171 + wchar_t buf[STR_LEN]; /* STR_LEN defined in collate.h */
172 + size_t pclen, sclen, len;
173 + const char *origpat, *cp, *savestring;
174 + mbstate_t save;
175
176 /*
177 * A bracket expression starting with an unquoted circumflex
178 @@ -234,7 +265,7 @@ rangematch(pattern, test, flags, newp, p
179 ++pattern;
180
181 if (flags & FNM_CASEFOLD)
182 - test = towlower(test);
183 + test = towlower_l(test, loc);
184
185 /*
186 * A right bracket shall lose its special meaning and represent
187 @@ -244,8 +275,8 @@ rangematch(pattern, test, flags, newp, p
188 ok = 0;
189 origpat = pattern;
190 for (;;) {
191 + c = 0;
192 if (*pattern == ']' && pattern > origpat) {
193 - pattern++;
194 break;
195 } else if (*pattern == '\0') {
196 return (RANGE_ERROR);
197 @@ -253,39 +284,188 @@ rangematch(pattern, test, flags, newp, p
198 return (RANGE_NOMATCH);
199 } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE))
200 pattern++;
201 - pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs);
202 - if (pclen == (size_t)-1 || pclen == (size_t)-2)
203 - return (RANGE_NOMATCH);
204 - pattern += pclen;
205 + else if (*pattern == '[' && ((special = *(pattern + 1)) == '.' || special == '=' || special == ':')) {
206 + cp = (pattern += 2);
207 + while(cp = strchr(cp, special)) {
208 + if (*(cp + 1) == ']')
209 + break;
210 + cp++;
211 + }
212 + if (!cp)
213 + return (RANGE_ERROR);
214 + if (special == '.') {
215 +treat_like_collating_symbol:
216 + len = __collate_collating_symbol(buf, STR_LEN, pattern, cp - pattern, patmbs, loc);
217 + if (len == (size_t)-1 || len == 0)
218 + return (RANGE_ERROR);
219 + pattern = cp + 2;
220 + if (len > 1) {
221 + wchar_t *wp, sc;
222 + /* no multi-character collation symbols as start of range */
223 + if (*(cp + 2) == '-' && *(cp + 3) != EOS
224 + && *(cp + 3) != ']')
225 + return (RANGE_ERROR);
226 + wp = buf;
227 + if (test != *wp++)
228 + continue;
229 + if (len == 1) {
230 + ok = 1;
231 + break;
232 + }
233 + memcpy(&save, strmbs, sizeof(save));
234 + savestring = string;
235 + while (--len > 0) {
236 + sclen = mbrtowc_l(&sc, string, MB_LEN_MAX, strmbs, loc);
237 + if (sclen == (size_t)-1 || sclen == (size_t)-2) {
238 + sc = (unsigned char)*string;
239 + sclen = 1;
240 + memset(&strmbs, 0, sizeof(strmbs));
241 + }
242 + if (sc != *wp++) {
243 + memcpy(strmbs, &save, sizeof(save));
244 + string = savestring;
245 + break;
246 + }
247 + string += sclen;
248 + }
249 + if (len == 0) {
250 + ok = 1;
251 + break;
252 + }
253 + continue; /* no match */
254 + }
255 + c = *buf;
256 + } else if (special == '=') {
257 + int ec;
258 + memcpy(&save, patmbs, sizeof(save));
259 + ec = __collate_equiv_class(pattern, cp - pattern, patmbs, loc);
260 + if (ec < 0)
261 + return (RANGE_ERROR);
262 + if (ec == 0) {
263 + memcpy(patmbs, &save, sizeof(save));
264 + goto treat_like_collating_symbol;
265 + }
266 + pattern = cp + 2;
267 + /* no equivalence classes as start of range */
268 + if (*(cp + 2) == '-' && *(cp + 3) != EOS &&
269 + *(cp + 3) != ']')
270 + return (RANGE_ERROR);
271 + len = __collate_equiv_match(ec, NULL, 0, test, string, strlen(string), strmbs, &sclen, loc);
272 + if (len < 0)
273 + return (RANGE_ERROR);
274 + if (len > 0) {
275 + ok = 1;
276 + string += sclen;
277 + break;
278 + }
279 + continue;
280 + } else { /* special == ':' */
281 + wctype_t charclass;
282 + char name[CHARCLASS_NAME_MAX + 1];
283 + /* no character classes as start of range */
284 + if (*(cp + 2) == '-' && *(cp + 3) != EOS &&
285 + *(cp + 3) != ']')
286 + return (RANGE_ERROR);
287 + /* assume character class names are ascii */
288 + if (cp - pattern > CHARCLASS_NAME_MAX)
289 + return (RANGE_ERROR);
290 + strlcpy(name, pattern, cp - pattern + 1);
291 + pattern = cp + 2;
292 + if ((charclass = wctype(name)) == 0)
293 + return (RANGE_ERROR);
294 + if (iswctype_l(test, charclass, loc)) {
295 + ok = 1;
296 + break;
297 + }
298 + continue;
299 + }
300 + }
301 + if (!c) {
302 + pclen = mbrtowc_l(&c, pattern, MB_LEN_MAX, patmbs, loc);
303 + if (pclen == (size_t)-1 || pclen == (size_t)-2)
304 + return (RANGE_ERROR);
305 + pattern += pclen;
306 + }
307
308 if (flags & FNM_CASEFOLD)
309 - c = towlower(c);
310 + c = towlower_l(c, loc);
311
312 if (*pattern == '-' && *(pattern + 1) != EOS &&
313 *(pattern + 1) != ']') {
314 if (*++pattern == '\\' && !(flags & FNM_NOESCAPE))
315 if (*pattern != EOS)
316 pattern++;
317 - pclen = mbrtowc(&c2, pattern, MB_LEN_MAX, patmbs);
318 + pclen = mbrtowc_l(&c2, pattern, MB_LEN_MAX, patmbs, loc);
319 if (pclen == (size_t)-1 || pclen == (size_t)-2)
320 - return (RANGE_NOMATCH);
321 + return (RANGE_ERROR);
322 pattern += pclen;
323 if (c2 == EOS)
324 return (RANGE_ERROR);
325
326 + if (c2 == '[' && (special = *pattern) == '.' || special == '=' || special == ':') {
327 + /* no equivalence classes or character classes as end of range */
328 + if (special == '=' || special == ':')
329 + return (RANGE_ERROR);
330 + cp = ++pattern;
331 + while(cp = strchr(cp, special)) {
332 + if (*(cp + 1) == ']')
333 + break;
334 + cp++;
335 + }
336 + if (!cp)
337 + return (RANGE_ERROR);
338 + len = __collate_collating_symbol(buf, STR_LEN, pattern, cp - pattern, patmbs, loc);
339 + /* no multi-character collation symbols as end of range */
340 + if (len != 1)
341 + return (RANGE_ERROR);
342 + pattern = cp + 2;
343 + c2 = *buf;
344 + }
345 +
346 if (flags & FNM_CASEFOLD)
347 - c2 = towlower(c2);
348 + c2 = towlower_l(c2, loc);
349
350 - if (__collate_load_error ?
351 + if (loc->__collate_load_error ?
352 c <= test && test <= c2 :
353 - __collate_range_cmp(c, test) <= 0
354 - && __collate_range_cmp(test, c2) <= 0
355 - )
356 + __collate_range_cmp(c, test, loc) <= 0
357 + && __collate_range_cmp(test, c2, loc) <= 0
358 + ) {
359 ok = 1;
360 - } else if (c == test)
361 + break;
362 + }
363 + } else if (c == test) {
364 ok = 1;
365 + break;
366 + }
367 }
368 + /* go to end of bracket expression */
369 + special = 0;
370 + while(*pattern != ']') {
371 + if (*pattern == 0)
372 + return (RANGE_ERROR);
373 + if (*pattern == special) {
374 + if (*++pattern == ']') {
375 + special = 0;
376 + pattern++;
377 + }
378 + continue;
379 + }
380 + if (!special && *pattern == '[') {
381 + special = *++pattern;
382 + if (special != '.' && special != '=' && special != ':')
383 + special = 0;
384 + else
385 + pattern++;
386 + continue;
387 + }
388 + pclen = mbrtowc_l(&c, pattern, MB_LEN_MAX, patmbs, loc);
389 + if (pclen == (size_t)-1 || pclen == (size_t)-2)
390 + return (RANGE_ERROR);
391 + pattern += pclen;
392 + }
393
394 - *newp = (char *)pattern;
395 + *newp = (char *)++pattern;
396 + *news = (char *)string;
397 return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
398 }
399 +#endif /* BUILDING_VARIANT */