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