1169695Skan/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
2169695Skan
3169695SkanNOTE: This source is derived from an old version taken from the GNU C
4169695SkanLibrary (glibc).
5169695Skan
6169695SkanThis program is free software; you can redistribute it and/or modify it
7169695Skanunder the terms of the GNU General Public License as published by the
8169695SkanFree Software Foundation; either version 2, or (at your option) any
9169695Skanlater version.
10169695Skan
11169695SkanThis program is distributed in the hope that it will be useful,
12169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
13169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14169695SkanGNU General Public License for more details.
15169695Skan
16169695SkanYou should have received a copy of the GNU General Public License
17169695Skanalong with this program; if not, write to the Free Software
18169695SkanFoundation, 51 Franklin Street - Fifth Floor,
19169695SkanBoston, MA 02110-1301, USA.  */
20169695Skan
21169695Skan#ifdef HAVE_CONFIG_H
22169695Skan#if defined (CONFIG_BROKETS)
23169695Skan/* We use <config.h> instead of "config.h" so that a compilation
24169695Skan   using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
25169695Skan   (which it would do because it found this file in $srcdir).  */
26169695Skan#include <config.h>
27169695Skan#else
28169695Skan#include "config.h"
29169695Skan#endif
30169695Skan#endif
31169695Skan
32169695Skan
33169695Skan#ifndef _GNU_SOURCE
34169695Skan#define _GNU_SOURCE
35169695Skan#endif
36169695Skan
37169695Skan/* This code to undef const added in libiberty.  */
38169695Skan#ifndef __STDC__
39169695Skan/* This is a separate conditional since some stdc systems
40169695Skan   reject `defined (const)'.  */
41169695Skan#ifndef const
42169695Skan#define const
43169695Skan#endif
44169695Skan#endif
45169695Skan
46169695Skan#include <errno.h>
47169695Skan#include <fnmatch.h>
48169695Skan#include <safe-ctype.h>
49169695Skan
50169695Skan/* Comment out all this code if we are using the GNU C Library, and are not
51169695Skan   actually compiling the library itself.  This code is part of the GNU C
52169695Skan   Library, but also included in many other GNU distributions.  Compiling
53169695Skan   and linking in this code is a waste when using the GNU C library
54169695Skan   (especially if it is a shared library).  Rather than having every GNU
55169695Skan   program understand `configure --with-gnu-libc' and omit the object files,
56169695Skan   it is simpler to just do this in the source for each such file.  */
57169695Skan
58169695Skan#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
59169695Skan
60169695Skan
61169695Skan#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
62169695Skanextern int errno;
63169695Skan#endif
64169695Skan
65169695Skan/* Match STRING against the filename pattern PATTERN, returning zero if
66169695Skan   it matches, nonzero if not.  */
67169695Skanint
68169695Skanfnmatch (const char *pattern, const char *string, int flags)
69169695Skan{
70169695Skan  register const char *p = pattern, *n = string;
71169695Skan  register unsigned char c;
72169695Skan
73169695Skan#define FOLD(c)	((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
74169695Skan
75169695Skan  while ((c = *p++) != '\0')
76169695Skan    {
77169695Skan      c = FOLD (c);
78169695Skan
79169695Skan      switch (c)
80169695Skan	{
81169695Skan	case '?':
82169695Skan	  if (*n == '\0')
83169695Skan	    return FNM_NOMATCH;
84169695Skan	  else if ((flags & FNM_FILE_NAME) && *n == '/')
85169695Skan	    return FNM_NOMATCH;
86169695Skan	  else if ((flags & FNM_PERIOD) && *n == '.' &&
87169695Skan		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
88169695Skan	    return FNM_NOMATCH;
89169695Skan	  break;
90169695Skan
91169695Skan	case '\\':
92169695Skan	  if (!(flags & FNM_NOESCAPE))
93169695Skan	    {
94169695Skan	      c = *p++;
95169695Skan	      c = FOLD (c);
96169695Skan	    }
97169695Skan	  if (FOLD ((unsigned char)*n) != c)
98169695Skan	    return FNM_NOMATCH;
99169695Skan	  break;
100169695Skan
101169695Skan	case '*':
102169695Skan	  if ((flags & FNM_PERIOD) && *n == '.' &&
103169695Skan	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
104169695Skan	    return FNM_NOMATCH;
105169695Skan
106169695Skan	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
107169695Skan	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
108169695Skan		(c == '?' && *n == '\0'))
109169695Skan	      return FNM_NOMATCH;
110169695Skan
111169695Skan	  if (c == '\0')
112169695Skan	    return 0;
113169695Skan
114169695Skan	  {
115169695Skan	    unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
116169695Skan	    c1 = FOLD (c1);
117169695Skan	    for (--p; *n != '\0'; ++n)
118169695Skan	      if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
119169695Skan		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
120169695Skan		return 0;
121169695Skan	    return FNM_NOMATCH;
122169695Skan	  }
123169695Skan
124169695Skan	case '[':
125169695Skan	  {
126169695Skan	    /* Nonzero if the sense of the character class is inverted.  */
127169695Skan	    register int negate;
128169695Skan
129169695Skan	    if (*n == '\0')
130169695Skan	      return FNM_NOMATCH;
131169695Skan
132169695Skan	    if ((flags & FNM_PERIOD) && *n == '.' &&
133169695Skan		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
134169695Skan	      return FNM_NOMATCH;
135169695Skan
136169695Skan	    negate = (*p == '!' || *p == '^');
137169695Skan	    if (negate)
138169695Skan	      ++p;
139169695Skan
140169695Skan	    c = *p++;
141169695Skan	    for (;;)
142169695Skan	      {
143169695Skan		register unsigned char cstart = c, cend = c;
144169695Skan
145169695Skan		if (!(flags & FNM_NOESCAPE) && c == '\\')
146169695Skan		  cstart = cend = *p++;
147169695Skan
148169695Skan		cstart = cend = FOLD (cstart);
149169695Skan
150169695Skan		if (c == '\0')
151169695Skan		  /* [ (unterminated) loses.  */
152169695Skan		  return FNM_NOMATCH;
153169695Skan
154169695Skan		c = *p++;
155169695Skan		c = FOLD (c);
156169695Skan
157169695Skan		if ((flags & FNM_FILE_NAME) && c == '/')
158169695Skan		  /* [/] can never match.  */
159169695Skan		  return FNM_NOMATCH;
160169695Skan
161169695Skan		if (c == '-' && *p != ']')
162169695Skan		  {
163169695Skan		    cend = *p++;
164169695Skan		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
165169695Skan		      cend = *p++;
166169695Skan		    if (cend == '\0')
167169695Skan		      return FNM_NOMATCH;
168169695Skan		    cend = FOLD (cend);
169169695Skan
170169695Skan		    c = *p++;
171169695Skan		  }
172169695Skan
173169695Skan		if (FOLD ((unsigned char)*n) >= cstart
174169695Skan		    && FOLD ((unsigned char)*n) <= cend)
175169695Skan		  goto matched;
176169695Skan
177169695Skan		if (c == ']')
178169695Skan		  break;
179169695Skan	      }
180169695Skan	    if (!negate)
181169695Skan	      return FNM_NOMATCH;
182169695Skan	    break;
183169695Skan
184169695Skan	  matched:;
185169695Skan	    /* Skip the rest of the [...] that already matched.  */
186169695Skan	    while (c != ']')
187169695Skan	      {
188169695Skan		if (c == '\0')
189169695Skan		  /* [... (unterminated) loses.  */
190169695Skan		  return FNM_NOMATCH;
191169695Skan
192169695Skan		c = *p++;
193169695Skan		if (!(flags & FNM_NOESCAPE) && c == '\\')
194169695Skan		  /* XXX 1003.2d11 is unclear if this is right.  */
195169695Skan		  ++p;
196169695Skan	      }
197169695Skan	    if (negate)
198169695Skan	      return FNM_NOMATCH;
199169695Skan	  }
200169695Skan	  break;
201169695Skan
202169695Skan	default:
203169695Skan	  if (c != FOLD ((unsigned char)*n))
204169695Skan	    return FNM_NOMATCH;
205169695Skan	}
206169695Skan
207169695Skan      ++n;
208169695Skan    }
209169695Skan
210169695Skan  if (*n == '\0')
211169695Skan    return 0;
212169695Skan
213169695Skan  if ((flags & FNM_LEADING_DIR) && *n == '/')
214169695Skan    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
215169695Skan    return 0;
216169695Skan
217169695Skan  return FNM_NOMATCH;
218169695Skan}
219169695Skan
220169695Skan#endif	/* _LIBC or not __GNU_LIBRARY__.  */
221