xref: /netbsd-src/external/gpl2/gmake/dist/glob/fnmatch.c (revision 69606e3f5c9388e52aed8c120ad63c049ca45d8f)
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