]> git.saurik.com Git - apple/libc.git/blame - gen/FreeBSD/fnmatch.c.patch
Libc-763.11.tar.gz
[apple/libc.git] / gen / FreeBSD / fnmatch.c.patch
CommitLineData
1f2f436a
A
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.
3d9156a7 4 #include <sys/cdefs.h>
1f2f436a 5 __FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.19 2010/04/16 22:29:24 jilles Exp $");
3d9156a7
A
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.
1f2f436a 12@@ -62,13 +64,16 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/fnm
224c7076
A
13
14 #define EOS '\0'
15
224c7076 16+#define RETURN_ERROR 2 /* neither 0 or FNM_NOMATCH */
224c7076 17 #define RANGE_MATCH 1
3d9156a7
A
18 #define RANGE_NOMATCH 0
19 #define RANGE_ERROR (-1)
20
21-static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
1f2f436a
A
22+#define RECURSION_MAX 64
23+
224c7076 24+__private_extern__ int rangematch(const char *, wchar_t, const char *, int, char **, char **, mbstate_t *, mbstate_t *, locale_t);
1f2f436a
A
25 static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
26- mbstate_t);
27+ mbstate_t, locale_t, int);
3d9156a7
A
28
29 int
30 fnmatch(pattern, string, flags)
1f2f436a
A
31@@ -76,27 +81,38 @@ fnmatch(pattern, string, flags)
32 int flags;
3d9156a7
A
33 {
34 static const mbstate_t initial;
1f2f436a
A
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 */
3d9156a7
A
42 }
43
44 static int
1f2f436a
A
45-fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
46+fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs, loc, recursion)
47 const char *pattern, *string, *stringstart;
3d9156a7
A
48 int flags;
49 mbstate_t patmbs, strmbs;
50+ locale_t loc;
1f2f436a 51+ int recursion;
3d9156a7 52 {
224c7076
A
53- char *newp;
54+ char *newp, *news;
55 char c;
56 wchar_t pc, sc;
3d9156a7
A
57 size_t pclen, sclen;
58
1f2f436a
A
59+ if (recursion-- <= 0)
60+ return RETURN_ERROR;
61 for (;;) {
3d9156a7
A
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)
224c7076
A
65+#if __DARWIN_UNIX03
66+ return (RETURN_ERROR);
67+#else /* !__DARWIN_UNIX03 */
3d9156a7 68 return (FNM_NOMATCH);
224c7076 69+#endif /* __DARWIN_UNIX03 */
3d9156a7
A
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;
1f2f436a
A
76@@ -144,12 +160,13 @@ fnmatch1(pattern, string, stringstart, f
77 }
78
3d9156a7 79 /* General case, use recursion. */
1f2f436a 80+ int ret;
3d9156a7 81 while (sc != EOS) {
1f2f436a
A
82- if (!fnmatch1(pattern, string, stringstart,
83- flags, patmbs, strmbs))
84- return (0);
3d9156a7
A
85- sclen = mbrtowc(&sc, string, MB_LEN_MAX,
86- &strmbs);
1f2f436a
A
87+ if ((ret = fnmatch1(pattern, string, stringstart,
88+ flags, patmbs, strmbs, loc, recursion)) != FNM_NOMATCH)
89+ return (ret);
3d9156a7
A
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;
1f2f436a 95@@ -171,35 +188,45 @@ fnmatch1(pattern, string, stringstart, f
224c7076 96 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
3d9156a7
A
97 return (FNM_NOMATCH);
98
224c7076 99- switch (rangematch(pattern, sc, flags, &newp,
3d9156a7 100- &patmbs)) {
224c7076
A
101+ switch (rangematch(pattern, sc, string + sclen, flags,
102+ &newp, &news, &patmbs, &strmbs, loc)) {
3d9156a7 103 case RANGE_ERROR:
224c7076
A
104+#if __DARWIN_UNIX03
105+ return (RETURN_ERROR);
106+#else /* !__DARWIN_UNIX03 */
3d9156a7 107 goto norm;
224c7076 108+#endif /* __DARWIN_UNIX03 */
3d9156a7 109 case RANGE_MATCH:
224c7076
A
110 pattern = newp;
111+ string = news;
112 break;
113 case RANGE_NOMATCH:
114 return (FNM_NOMATCH);
115 }
116- string += sclen;
3d9156a7
A
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)
224c7076
A
125+#if __DARWIN_UNIX03
126+ return (RETURN_ERROR);
127+#else /* !__DARWIN_UNIX03 */
3d9156a7 128 return (FNM_NOMATCH);
224c7076 129+#endif /* __DARWIN_UNIX03 */
3d9156a7 130 if (pclen == 0)
224c7076
A
131 pc = '\\';
132 pattern += pclen;
133 }
134 /* FALLTHROUGH */
135 default:
136+#if !__DARWIN_UNIX03
137 norm:
138+#endif /* !__DARWIN_UNIX03 */
3d9156a7
A
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);
1f2f436a 147@@ -210,18 +237,22 @@ fnmatch1(pattern, string, stringstart, f
224c7076 148 /* NOTREACHED */
3d9156a7
A
149 }
150
224c7076 151-static int
3d9156a7 152-rangematch(pattern, test, flags, newp, patmbs)
224c7076
A
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;
3d9156a7
A
158 wchar_t test;
159 int flags;
224c7076
A
160- char **newp;
161- mbstate_t *patmbs;
162+ char **newp, **news;
163+ mbstate_t *patmbs, *strmbs;
3d9156a7
A
164+ locale_t loc;
165 {
224c7076
A
166- int negate, ok;
167+ int negate, ok, special;
3d9156a7 168 wchar_t c, c2;
224c7076
A
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
1f2f436a 178@@ -234,7 +265,7 @@ rangematch(pattern, test, flags, newp, p
3d9156a7
A
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
1f2f436a 187@@ -244,8 +275,8 @@ rangematch(pattern, test, flags, newp, p
224c7076
A
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);
1f2f436a 197@@ -253,39 +284,188 @@ rangematch(pattern, test, flags, newp, p
3d9156a7
A
198 return (RANGE_NOMATCH);
199 } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE))
200 pattern++;
201- pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs);
224c7076
A
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+ }
3d9156a7
A
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)
224c7076
A
320- return (RANGE_NOMATCH);
321+ return (RANGE_ERROR);
3d9156a7 322 pattern += pclen;
224c7076 323 if (c2 == EOS)
3d9156a7
A
324 return (RANGE_ERROR);
325
224c7076
A
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+
3d9156a7
A
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
224c7076 355- )
3d9156a7
A
356+ __collate_range_cmp(c, test, loc) <= 0
357+ && __collate_range_cmp(test, c2, loc) <= 0
224c7076 358+ ) {
3d9156a7 359 ok = 1;
224c7076
A
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 */