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