1*a9fa9459Szrj /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
2*a9fa9459Szrj
3*a9fa9459Szrj NOTE: This source is derived from an old version taken from the GNU C
4*a9fa9459Szrj Library (glibc).
5*a9fa9459Szrj
6*a9fa9459Szrj This program is free software; you can redistribute it and/or modify it
7*a9fa9459Szrj under the terms of the GNU General Public License as published by the
8*a9fa9459Szrj Free Software Foundation; either version 2, or (at your option) any
9*a9fa9459Szrj later version.
10*a9fa9459Szrj
11*a9fa9459Szrj This program is distributed in the hope that it will be useful,
12*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
13*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*a9fa9459Szrj GNU General Public License for more details.
15*a9fa9459Szrj
16*a9fa9459Szrj You should have received a copy of the GNU General Public License
17*a9fa9459Szrj along with this program; if not, write to the Free Software
18*a9fa9459Szrj Foundation, 51 Franklin Street - Fifth Floor,
19*a9fa9459Szrj Boston, MA 02110-1301, USA. */
20*a9fa9459Szrj
21*a9fa9459Szrj #ifdef HAVE_CONFIG_H
22*a9fa9459Szrj #if defined (CONFIG_BROKETS)
23*a9fa9459Szrj /* We use <config.h> instead of "config.h" so that a compilation
24*a9fa9459Szrj using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
25*a9fa9459Szrj (which it would do because it found this file in $srcdir). */
26*a9fa9459Szrj #include <config.h>
27*a9fa9459Szrj #else
28*a9fa9459Szrj #include "config.h"
29*a9fa9459Szrj #endif
30*a9fa9459Szrj #endif
31*a9fa9459Szrj
32*a9fa9459Szrj
33*a9fa9459Szrj #ifndef _GNU_SOURCE
34*a9fa9459Szrj #define _GNU_SOURCE
35*a9fa9459Szrj #endif
36*a9fa9459Szrj
37*a9fa9459Szrj /* This code to undef const added in libiberty. */
38*a9fa9459Szrj #ifndef __STDC__
39*a9fa9459Szrj /* This is a separate conditional since some stdc systems
40*a9fa9459Szrj reject `defined (const)'. */
41*a9fa9459Szrj #ifndef const
42*a9fa9459Szrj #define const
43*a9fa9459Szrj #endif
44*a9fa9459Szrj #endif
45*a9fa9459Szrj
46*a9fa9459Szrj #include <errno.h>
47*a9fa9459Szrj #include <fnmatch.h>
48*a9fa9459Szrj #include <safe-ctype.h>
49*a9fa9459Szrj
50*a9fa9459Szrj /* Comment out all this code if we are using the GNU C Library, and are not
51*a9fa9459Szrj actually compiling the library itself. This code is part of the GNU C
52*a9fa9459Szrj Library, but also included in many other GNU distributions. Compiling
53*a9fa9459Szrj and linking in this code is a waste when using the GNU C library
54*a9fa9459Szrj (especially if it is a shared library). Rather than having every GNU
55*a9fa9459Szrj program understand `configure --with-gnu-libc' and omit the object files,
56*a9fa9459Szrj it is simpler to just do this in the source for each such file. */
57*a9fa9459Szrj
58*a9fa9459Szrj #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
59*a9fa9459Szrj
60*a9fa9459Szrj
61*a9fa9459Szrj #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
62*a9fa9459Szrj extern int errno;
63*a9fa9459Szrj #endif
64*a9fa9459Szrj
65*a9fa9459Szrj /* Match STRING against the filename pattern PATTERN, returning zero if
66*a9fa9459Szrj it matches, nonzero if not. */
67*a9fa9459Szrj int
fnmatch(const char * pattern,const char * string,int flags)68*a9fa9459Szrj fnmatch (const char *pattern, const char *string, int flags)
69*a9fa9459Szrj {
70*a9fa9459Szrj register const char *p = pattern, *n = string;
71*a9fa9459Szrj register unsigned char c;
72*a9fa9459Szrj
73*a9fa9459Szrj #define FOLD(c) ((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
74*a9fa9459Szrj
75*a9fa9459Szrj while ((c = *p++) != '\0')
76*a9fa9459Szrj {
77*a9fa9459Szrj c = FOLD (c);
78*a9fa9459Szrj
79*a9fa9459Szrj switch (c)
80*a9fa9459Szrj {
81*a9fa9459Szrj case '?':
82*a9fa9459Szrj if (*n == '\0')
83*a9fa9459Szrj return FNM_NOMATCH;
84*a9fa9459Szrj else if ((flags & FNM_FILE_NAME) && *n == '/')
85*a9fa9459Szrj return FNM_NOMATCH;
86*a9fa9459Szrj else if ((flags & FNM_PERIOD) && *n == '.' &&
87*a9fa9459Szrj (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
88*a9fa9459Szrj return FNM_NOMATCH;
89*a9fa9459Szrj break;
90*a9fa9459Szrj
91*a9fa9459Szrj case '\\':
92*a9fa9459Szrj if (!(flags & FNM_NOESCAPE))
93*a9fa9459Szrj {
94*a9fa9459Szrj c = *p++;
95*a9fa9459Szrj c = FOLD (c);
96*a9fa9459Szrj }
97*a9fa9459Szrj if (FOLD ((unsigned char)*n) != c)
98*a9fa9459Szrj return FNM_NOMATCH;
99*a9fa9459Szrj break;
100*a9fa9459Szrj
101*a9fa9459Szrj case '*':
102*a9fa9459Szrj if ((flags & FNM_PERIOD) && *n == '.' &&
103*a9fa9459Szrj (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
104*a9fa9459Szrj return FNM_NOMATCH;
105*a9fa9459Szrj
106*a9fa9459Szrj for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
107*a9fa9459Szrj if (((flags & FNM_FILE_NAME) && *n == '/') ||
108*a9fa9459Szrj (c == '?' && *n == '\0'))
109*a9fa9459Szrj return FNM_NOMATCH;
110*a9fa9459Szrj
111*a9fa9459Szrj if (c == '\0')
112*a9fa9459Szrj return 0;
113*a9fa9459Szrj
114*a9fa9459Szrj {
115*a9fa9459Szrj unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
116*a9fa9459Szrj c1 = FOLD (c1);
117*a9fa9459Szrj for (--p; *n != '\0'; ++n)
118*a9fa9459Szrj if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
119*a9fa9459Szrj fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
120*a9fa9459Szrj return 0;
121*a9fa9459Szrj return FNM_NOMATCH;
122*a9fa9459Szrj }
123*a9fa9459Szrj
124*a9fa9459Szrj case '[':
125*a9fa9459Szrj {
126*a9fa9459Szrj /* Nonzero if the sense of the character class is inverted. */
127*a9fa9459Szrj register int negate;
128*a9fa9459Szrj
129*a9fa9459Szrj if (*n == '\0')
130*a9fa9459Szrj return FNM_NOMATCH;
131*a9fa9459Szrj
132*a9fa9459Szrj if ((flags & FNM_PERIOD) && *n == '.' &&
133*a9fa9459Szrj (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
134*a9fa9459Szrj return FNM_NOMATCH;
135*a9fa9459Szrj
136*a9fa9459Szrj negate = (*p == '!' || *p == '^');
137*a9fa9459Szrj if (negate)
138*a9fa9459Szrj ++p;
139*a9fa9459Szrj
140*a9fa9459Szrj c = *p++;
141*a9fa9459Szrj for (;;)
142*a9fa9459Szrj {
143*a9fa9459Szrj register unsigned char cstart = c, cend = c;
144*a9fa9459Szrj
145*a9fa9459Szrj if (!(flags & FNM_NOESCAPE) && c == '\\')
146*a9fa9459Szrj cstart = cend = *p++;
147*a9fa9459Szrj
148*a9fa9459Szrj cstart = cend = FOLD (cstart);
149*a9fa9459Szrj
150*a9fa9459Szrj if (c == '\0')
151*a9fa9459Szrj /* [ (unterminated) loses. */
152*a9fa9459Szrj return FNM_NOMATCH;
153*a9fa9459Szrj
154*a9fa9459Szrj c = *p++;
155*a9fa9459Szrj c = FOLD (c);
156*a9fa9459Szrj
157*a9fa9459Szrj if ((flags & FNM_FILE_NAME) && c == '/')
158*a9fa9459Szrj /* [/] can never match. */
159*a9fa9459Szrj return FNM_NOMATCH;
160*a9fa9459Szrj
161*a9fa9459Szrj if (c == '-' && *p != ']')
162*a9fa9459Szrj {
163*a9fa9459Szrj cend = *p++;
164*a9fa9459Szrj if (!(flags & FNM_NOESCAPE) && cend == '\\')
165*a9fa9459Szrj cend = *p++;
166*a9fa9459Szrj if (cend == '\0')
167*a9fa9459Szrj return FNM_NOMATCH;
168*a9fa9459Szrj cend = FOLD (cend);
169*a9fa9459Szrj
170*a9fa9459Szrj c = *p++;
171*a9fa9459Szrj }
172*a9fa9459Szrj
173*a9fa9459Szrj if (FOLD ((unsigned char)*n) >= cstart
174*a9fa9459Szrj && FOLD ((unsigned char)*n) <= cend)
175*a9fa9459Szrj goto matched;
176*a9fa9459Szrj
177*a9fa9459Szrj if (c == ']')
178*a9fa9459Szrj break;
179*a9fa9459Szrj }
180*a9fa9459Szrj if (!negate)
181*a9fa9459Szrj return FNM_NOMATCH;
182*a9fa9459Szrj break;
183*a9fa9459Szrj
184*a9fa9459Szrj matched:;
185*a9fa9459Szrj /* Skip the rest of the [...] that already matched. */
186*a9fa9459Szrj while (c != ']')
187*a9fa9459Szrj {
188*a9fa9459Szrj if (c == '\0')
189*a9fa9459Szrj /* [... (unterminated) loses. */
190*a9fa9459Szrj return FNM_NOMATCH;
191*a9fa9459Szrj
192*a9fa9459Szrj c = *p++;
193*a9fa9459Szrj if (!(flags & FNM_NOESCAPE) && c == '\\')
194*a9fa9459Szrj /* XXX 1003.2d11 is unclear if this is right. */
195*a9fa9459Szrj ++p;
196*a9fa9459Szrj }
197*a9fa9459Szrj if (negate)
198*a9fa9459Szrj return FNM_NOMATCH;
199*a9fa9459Szrj }
200*a9fa9459Szrj break;
201*a9fa9459Szrj
202*a9fa9459Szrj default:
203*a9fa9459Szrj if (c != FOLD ((unsigned char)*n))
204*a9fa9459Szrj return FNM_NOMATCH;
205*a9fa9459Szrj }
206*a9fa9459Szrj
207*a9fa9459Szrj ++n;
208*a9fa9459Szrj }
209*a9fa9459Szrj
210*a9fa9459Szrj if (*n == '\0')
211*a9fa9459Szrj return 0;
212*a9fa9459Szrj
213*a9fa9459Szrj if ((flags & FNM_LEADING_DIR) && *n == '/')
214*a9fa9459Szrj /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
215*a9fa9459Szrj return 0;
216*a9fa9459Szrj
217*a9fa9459Szrj return FNM_NOMATCH;
218*a9fa9459Szrj }
219*a9fa9459Szrj
220*a9fa9459Szrj #endif /* _LIBC or not __GNU_LIBRARY__. */
221