diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-04-14 02:01:15 +0200 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-10 18:39:17 +1000 |
commit | 3a9514cceca86f1c33c82fb879396789defb8f51 (patch) | |
tree | bedd1a5c54943a805a5515220118122f9c7f5edb | |
parent | b20cb1eb2037673a74a99649984901fc14ac7ad8 (diff) | |
download | busybox-w32-3a9514cceca86f1c33c82fb879396789defb8f51.tar.gz busybox-w32-3a9514cceca86f1c33c82fb879396789defb8f51.tar.bz2 busybox-w32-3a9514cceca86f1c33c82fb879396789defb8f51.zip |
win32: Import fnmatch source
This was extracted from commit e56b799d6ad8afba4168fffa7218d44c041a72d2
in Git repository.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | Makefile.flags | 3 | ||||
-rw-r--r-- | win32/Kbuild | 7 | ||||
-rw-r--r-- | win32/fnmatch.c | 488 |
4 files changed, 498 insertions, 1 deletions
@@ -481,6 +481,7 @@ libs-y := \ | |||
481 | sysklogd/ \ | 481 | sysklogd/ \ |
482 | util-linux/ \ | 482 | util-linux/ \ |
483 | util-linux/volume_id/ \ | 483 | util-linux/volume_id/ \ |
484 | win32/ \ | ||
484 | 485 | ||
485 | endif # KBUILD_EXTMOD | 486 | endif # KBUILD_EXTMOD |
486 | 487 | ||
diff --git a/Makefile.flags b/Makefile.flags index 0b5eea43b..920fee322 100644 --- a/Makefile.flags +++ b/Makefile.flags | |||
@@ -98,7 +98,8 @@ CFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_CFLAGS))) | |||
98 | endif | 98 | endif |
99 | 99 | ||
100 | ifeq ($(CONFIG_PLATFORM_MINGW32),y) | 100 | ifeq ($(CONFIG_PLATFORM_MINGW32),y) |
101 | CFLAGS += -Iwin32 | 101 | # These defintions are not strictly needed, but they help shut up fnmatch.c warnings |
102 | CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 | ||
102 | EXEEXT = .exe | 103 | EXEEXT = .exe |
103 | else | 104 | else |
104 | LDLIBS += m crypt | 105 | LDLIBS += m crypt |
diff --git a/win32/Kbuild b/win32/Kbuild new file mode 100644 index 000000000..df4fcb18d --- /dev/null +++ b/win32/Kbuild | |||
@@ -0,0 +1,7 @@ | |||
1 | # Makefile for busybox | ||
2 | # | ||
3 | # Licensed under the GPL v2, see the file LICENSE in this tarball. | ||
4 | |||
5 | lib-y:= | ||
6 | |||
7 | lib-$(CONFIG_PLATFORM_MINGW32) += fnmatch.o | ||
diff --git a/win32/fnmatch.c b/win32/fnmatch.c new file mode 100644 index 000000000..1f4ead5f9 --- /dev/null +++ b/win32/fnmatch.c | |||
@@ -0,0 +1,488 @@ | |||
1 | /* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. | ||
2 | This file is part of the GNU C Library. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Library General Public License as | ||
6 | published by the Free Software Foundation; either version 2 of the | ||
7 | License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public | ||
15 | License along with this library; see the file COPYING.LIB. If not, | ||
16 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
17 | Boston, MA 02111-1307, USA. */ | ||
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 <fnmatch.h> | ||
30 | #include <ctype.h> | ||
31 | |||
32 | #if HAVE_STRING_H || defined _LIBC | ||
33 | # include <string.h> | ||
34 | #else | ||
35 | # include <strings.h> | ||
36 | #endif | ||
37 | |||
38 | #if defined STDC_HEADERS || defined _LIBC | ||
39 | # include <stdlib.h> | ||
40 | #endif | ||
41 | |||
42 | /* For platform which support the ISO C amendement 1 functionality we | ||
43 | support user defined character classes. */ | ||
44 | #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | ||
45 | /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ | ||
46 | # include <wchar.h> | ||
47 | # include <wctype.h> | ||
48 | #endif | ||
49 | |||
50 | /* Comment out all this code if we are using the GNU C Library, and are not | ||
51 | actually compiling the library itself. This code is part of the GNU C | ||
52 | Library, but also included in many other GNU distributions. Compiling | ||
53 | and linking in this code is a waste when using the GNU C library | ||
54 | (especially if it is a shared library). Rather than having every GNU | ||
55 | program understand `configure --with-gnu-libc' and omit the object files, | ||
56 | it is simpler to just do this in the source for each such file. */ | ||
57 | |||
58 | #if defined _LIBC || !defined __GNU_LIBRARY__ | ||
59 | |||
60 | |||
61 | # if defined STDC_HEADERS || !defined isascii | ||
62 | # define ISASCII(c) 1 | ||
63 | # else | ||
64 | # define ISASCII(c) isascii(c) | ||
65 | # endif | ||
66 | |||
67 | # ifdef isblank | ||
68 | # define ISBLANK(c) (ISASCII (c) && isblank (c)) | ||
69 | # else | ||
70 | # define ISBLANK(c) ((c) == ' ' || (c) == '\t') | ||
71 | # endif | ||
72 | # ifdef isgraph | ||
73 | # define ISGRAPH(c) (ISASCII (c) && isgraph (c)) | ||
74 | # else | ||
75 | # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) | ||
76 | # endif | ||
77 | |||
78 | # define ISPRINT(c) (ISASCII (c) && isprint (c)) | ||
79 | # define ISDIGIT(c) (ISASCII (c) && isdigit (c)) | ||
80 | # define ISALNUM(c) (ISASCII (c) && isalnum (c)) | ||
81 | # define ISALPHA(c) (ISASCII (c) && isalpha (c)) | ||
82 | # define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) | ||
83 | # define ISLOWER(c) (ISASCII (c) && islower (c)) | ||
84 | # define ISPUNCT(c) (ISASCII (c) && ispunct (c)) | ||
85 | # define ISSPACE(c) (ISASCII (c) && isspace (c)) | ||
86 | # define ISUPPER(c) (ISASCII (c) && isupper (c)) | ||
87 | # define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) | ||
88 | |||
89 | # define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) | ||
90 | |||
91 | # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | ||
92 | /* The GNU C library provides support for user-defined character classes | ||
93 | and the functions from ISO C amendement 1. */ | ||
94 | # ifdef CHARCLASS_NAME_MAX | ||
95 | # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX | ||
96 | # else | ||
97 | /* This shouldn't happen but some implementation might still have this | ||
98 | problem. Use a reasonable default value. */ | ||
99 | # define CHAR_CLASS_MAX_LENGTH 256 | ||
100 | # endif | ||
101 | |||
102 | # ifdef _LIBC | ||
103 | # define IS_CHAR_CLASS(string) __wctype (string) | ||
104 | # else | ||
105 | # define IS_CHAR_CLASS(string) wctype (string) | ||
106 | # endif | ||
107 | # else | ||
108 | # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ | ||
109 | |||
110 | # define IS_CHAR_CLASS(string) \ | ||
111 | (STREQ (string, "alpha") || STREQ (string, "upper") \ | ||
112 | || STREQ (string, "lower") || STREQ (string, "digit") \ | ||
113 | || STREQ (string, "alnum") || STREQ (string, "xdigit") \ | ||
114 | || STREQ (string, "space") || STREQ (string, "print") \ | ||
115 | || STREQ (string, "punct") || STREQ (string, "graph") \ | ||
116 | || STREQ (string, "cntrl") || STREQ (string, "blank")) | ||
117 | # endif | ||
118 | |||
119 | /* Avoid depending on library functions or files | ||
120 | whose names are inconsistent. */ | ||
121 | |||
122 | # if !defined _LIBC && !defined getenv | ||
123 | extern char *getenv (); | ||
124 | # endif | ||
125 | |||
126 | # ifndef errno | ||
127 | extern int errno; | ||
128 | # endif | ||
129 | |||
130 | /* This function doesn't exist on most systems. */ | ||
131 | |||
132 | # if !defined HAVE___STRCHRNUL && !defined _LIBC | ||
133 | static char * | ||
134 | __strchrnul (s, c) | ||
135 | const char *s; | ||
136 | int c; | ||
137 | { | ||
138 | char *result = strchr (s, c); | ||
139 | if (result == NULL) | ||
140 | result = strchr (s, '\0'); | ||
141 | return result; | ||
142 | } | ||
143 | # endif | ||
144 | |||
145 | # ifndef internal_function | ||
146 | /* Inside GNU libc we mark some function in a special way. In other | ||
147 | environments simply ignore the marking. */ | ||
148 | # define internal_function | ||
149 | # endif | ||
150 | |||
151 | /* Match STRING against the filename pattern PATTERN, returning zero if | ||
152 | it matches, nonzero if not. */ | ||
153 | static int internal_fnmatch __P ((const char *pattern, const char *string, | ||
154 | int no_leading_period, int flags)) | ||
155 | internal_function; | ||
156 | static int | ||
157 | internal_function | ||
158 | internal_fnmatch (pattern, string, no_leading_period, flags) | ||
159 | const char *pattern; | ||
160 | const char *string; | ||
161 | int no_leading_period; | ||
162 | int flags; | ||
163 | { | ||
164 | register const char *p = pattern, *n = string; | ||
165 | register unsigned char c; | ||
166 | |||
167 | /* Note that this evaluates C many times. */ | ||
168 | # ifdef _LIBC | ||
169 | # define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) | ||
170 | # else | ||
171 | # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) | ||
172 | # endif | ||
173 | |||
174 | while ((c = *p++) != '\0') | ||
175 | { | ||
176 | c = FOLD (c); | ||
177 | |||
178 | switch (c) | ||
179 | { | ||
180 | case '?': | ||
181 | if (*n == '\0') | ||
182 | return FNM_NOMATCH; | ||
183 | else if (*n == '/' && (flags & FNM_FILE_NAME)) | ||
184 | return FNM_NOMATCH; | ||
185 | else if (*n == '.' && no_leading_period | ||
186 | && (n == string | ||
187 | || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) | ||
188 | return FNM_NOMATCH; | ||
189 | break; | ||
190 | |||
191 | case '\\': | ||
192 | if (!(flags & FNM_NOESCAPE)) | ||
193 | { | ||
194 | c = *p++; | ||
195 | if (c == '\0') | ||
196 | /* Trailing \ loses. */ | ||
197 | return FNM_NOMATCH; | ||
198 | c = FOLD (c); | ||
199 | } | ||
200 | if (FOLD ((unsigned char) *n) != c) | ||
201 | return FNM_NOMATCH; | ||
202 | break; | ||
203 | |||
204 | case '*': | ||
205 | if (*n == '.' && no_leading_period | ||
206 | && (n == string | ||
207 | || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) | ||
208 | return FNM_NOMATCH; | ||
209 | |||
210 | for (c = *p++; c == '?' || c == '*'; c = *p++) | ||
211 | { | ||
212 | if (*n == '/' && (flags & FNM_FILE_NAME)) | ||
213 | /* A slash does not match a wildcard under FNM_FILE_NAME. */ | ||
214 | return FNM_NOMATCH; | ||
215 | else if (c == '?') | ||
216 | { | ||
217 | /* A ? needs to match one character. */ | ||
218 | if (*n == '\0') | ||
219 | /* There isn't another character; no match. */ | ||
220 | return FNM_NOMATCH; | ||
221 | else | ||
222 | /* One character of the string is consumed in matching | ||
223 | this ? wildcard, so *??? won't match if there are | ||
224 | less than three characters. */ | ||
225 | ++n; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | if (c == '\0') | ||
230 | /* The wildcard(s) is/are the last element of the pattern. | ||
231 | If the name is a file name and contains another slash | ||
232 | this does mean it cannot match. */ | ||
233 | return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL | ||
234 | ? FNM_NOMATCH : 0); | ||
235 | else | ||
236 | { | ||
237 | const char *endp; | ||
238 | |||
239 | endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); | ||
240 | |||
241 | if (c == '[') | ||
242 | { | ||
243 | int flags2 = ((flags & FNM_FILE_NAME) | ||
244 | ? flags : (flags & ~FNM_PERIOD)); | ||
245 | |||
246 | for (--p; n < endp; ++n) | ||
247 | if (internal_fnmatch (p, n, | ||
248 | (no_leading_period | ||
249 | && (n == string | ||
250 | || (n[-1] == '/' | ||
251 | && (flags | ||
252 | & FNM_FILE_NAME)))), | ||
253 | flags2) | ||
254 | == 0) | ||
255 | return 0; | ||
256 | } | ||
257 | else if (c == '/' && (flags & FNM_FILE_NAME)) | ||
258 | { | ||
259 | while (*n != '\0' && *n != '/') | ||
260 | ++n; | ||
261 | if (*n == '/' | ||
262 | && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, | ||
263 | flags) == 0)) | ||
264 | return 0; | ||
265 | } | ||
266 | else | ||
267 | { | ||
268 | int flags2 = ((flags & FNM_FILE_NAME) | ||
269 | ? flags : (flags & ~FNM_PERIOD)); | ||
270 | |||
271 | if (c == '\\' && !(flags & FNM_NOESCAPE)) | ||
272 | c = *p; | ||
273 | c = FOLD (c); | ||
274 | for (--p; n < endp; ++n) | ||
275 | if (FOLD ((unsigned char) *n) == c | ||
276 | && (internal_fnmatch (p, n, | ||
277 | (no_leading_period | ||
278 | && (n == string | ||
279 | || (n[-1] == '/' | ||
280 | && (flags | ||
281 | & FNM_FILE_NAME)))), | ||
282 | flags2) == 0)) | ||
283 | return 0; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* If we come here no match is possible with the wildcard. */ | ||
288 | return FNM_NOMATCH; | ||
289 | |||
290 | case '[': | ||
291 | { | ||
292 | /* Nonzero if the sense of the character class is inverted. */ | ||
293 | static int posixly_correct; | ||
294 | register int not; | ||
295 | char cold; | ||
296 | |||
297 | if (posixly_correct == 0) | ||
298 | posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; | ||
299 | |||
300 | if (*n == '\0') | ||
301 | return FNM_NOMATCH; | ||
302 | |||
303 | if (*n == '.' && no_leading_period && (n == string | ||
304 | || (n[-1] == '/' | ||
305 | && (flags | ||
306 | & FNM_FILE_NAME)))) | ||
307 | return FNM_NOMATCH; | ||
308 | |||
309 | if (*n == '/' && (flags & FNM_FILE_NAME)) | ||
310 | /* `/' cannot be matched. */ | ||
311 | return FNM_NOMATCH; | ||
312 | |||
313 | not = (*p == '!' || (posixly_correct < 0 && *p == '^')); | ||
314 | if (not) | ||
315 | ++p; | ||
316 | |||
317 | c = *p++; | ||
318 | for (;;) | ||
319 | { | ||
320 | unsigned char fn = FOLD ((unsigned char) *n); | ||
321 | |||
322 | if (!(flags & FNM_NOESCAPE) && c == '\\') | ||
323 | { | ||
324 | if (*p == '\0') | ||
325 | return FNM_NOMATCH; | ||
326 | c = FOLD ((unsigned char) *p); | ||
327 | ++p; | ||
328 | |||
329 | if (c == fn) | ||
330 | goto matched; | ||
331 | } | ||
332 | else if (c == '[' && *p == ':') | ||
333 | { | ||
334 | /* Leave room for the null. */ | ||
335 | char str[CHAR_CLASS_MAX_LENGTH + 1]; | ||
336 | size_t c1 = 0; | ||
337 | # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | ||
338 | wctype_t wt; | ||
339 | # endif | ||
340 | const char *startp = p; | ||
341 | |||
342 | for (;;) | ||
343 | { | ||
344 | if (c1 == CHAR_CLASS_MAX_LENGTH) | ||
345 | /* The name is too long and therefore the pattern | ||
346 | is ill-formed. */ | ||
347 | return FNM_NOMATCH; | ||
348 | |||
349 | c = *++p; | ||
350 | if (c == ':' && p[1] == ']') | ||
351 | { | ||
352 | p += 2; | ||
353 | break; | ||
354 | } | ||
355 | if (c < 'a' || c >= 'z') | ||
356 | { | ||
357 | /* This cannot possibly be a character class name. | ||
358 | Match it as a normal range. */ | ||
359 | p = startp; | ||
360 | c = '['; | ||
361 | goto normal_bracket; | ||
362 | } | ||
363 | str[c1++] = c; | ||
364 | } | ||
365 | str[c1] = '\0'; | ||
366 | |||
367 | # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | ||
368 | wt = IS_CHAR_CLASS (str); | ||
369 | if (wt == 0) | ||
370 | /* Invalid character class name. */ | ||
371 | return FNM_NOMATCH; | ||
372 | |||
373 | if (__iswctype (__btowc ((unsigned char) *n), wt)) | ||
374 | goto matched; | ||
375 | # else | ||
376 | if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) | ||
377 | || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) | ||
378 | || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) | ||
379 | || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) | ||
380 | || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) | ||
381 | || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) | ||
382 | || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) | ||
383 | || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) | ||
384 | || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) | ||
385 | || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) | ||
386 | || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) | ||
387 | || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) | ||
388 | goto matched; | ||
389 | # endif | ||
390 | } | ||
391 | else if (c == '\0') | ||
392 | /* [ (unterminated) loses. */ | ||
393 | return FNM_NOMATCH; | ||
394 | else | ||
395 | { | ||
396 | normal_bracket: | ||
397 | if (FOLD (c) == fn) | ||
398 | goto matched; | ||
399 | |||
400 | cold = c; | ||
401 | c = *p++; | ||
402 | |||
403 | if (c == '-' && *p != ']') | ||
404 | { | ||
405 | /* It is a range. */ | ||
406 | unsigned char cend = *p++; | ||
407 | if (!(flags & FNM_NOESCAPE) && cend == '\\') | ||
408 | cend = *p++; | ||
409 | if (cend == '\0') | ||
410 | return FNM_NOMATCH; | ||
411 | |||
412 | if (cold <= fn && fn <= FOLD (cend)) | ||
413 | goto matched; | ||
414 | |||
415 | c = *p++; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | if (c == ']') | ||
420 | break; | ||
421 | } | ||
422 | |||
423 | if (!not) | ||
424 | return FNM_NOMATCH; | ||
425 | break; | ||
426 | |||
427 | matched: | ||
428 | /* Skip the rest of the [...] that already matched. */ | ||
429 | while (c != ']') | ||
430 | { | ||
431 | if (c == '\0') | ||
432 | /* [... (unterminated) loses. */ | ||
433 | return FNM_NOMATCH; | ||
434 | |||
435 | c = *p++; | ||
436 | if (!(flags & FNM_NOESCAPE) && c == '\\') | ||
437 | { | ||
438 | if (*p == '\0') | ||
439 | return FNM_NOMATCH; | ||
440 | /* XXX 1003.2d11 is unclear if this is right. */ | ||
441 | ++p; | ||
442 | } | ||
443 | else if (c == '[' && *p == ':') | ||
444 | { | ||
445 | do | ||
446 | if (*++p == '\0') | ||
447 | return FNM_NOMATCH; | ||
448 | while (*p != ':' || p[1] == ']'); | ||
449 | p += 2; | ||
450 | c = *p; | ||
451 | } | ||
452 | } | ||
453 | if (not) | ||
454 | return FNM_NOMATCH; | ||
455 | } | ||
456 | break; | ||
457 | |||
458 | default: | ||
459 | if (c != FOLD ((unsigned char) *n)) | ||
460 | return FNM_NOMATCH; | ||
461 | } | ||
462 | |||
463 | ++n; | ||
464 | } | ||
465 | |||
466 | if (*n == '\0') | ||
467 | return 0; | ||
468 | |||
469 | if ((flags & FNM_LEADING_DIR) && *n == '/') | ||
470 | /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ | ||
471 | return 0; | ||
472 | |||
473 | return FNM_NOMATCH; | ||
474 | |||
475 | # undef FOLD | ||
476 | } | ||
477 | |||
478 | |||
479 | int | ||
480 | fnmatch (pattern, string, flags) | ||
481 | const char *pattern; | ||
482 | const char *string; | ||
483 | int flags; | ||
484 | { | ||
485 | return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); | ||
486 | } | ||
487 | |||
488 | #endif /* _LIBC or not __GNU_LIBRARY__. */ | ||