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