]> git.ipfire.org Git - thirdparty/glibc.git/blob - posix/fnmatch_loop.c
Update.
[thirdparty/glibc.git] / posix / fnmatch_loop.c
1 /* Copyright (C) 1991-1993, 1996-1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18
19 /* Match STRING against the filename pattern PATTERN, returning zero if
20 it matches, nonzero if not. */
21 static int FCT (const CHAR *pattern, const CHAR *string,
22 int no_leading_period, int flags) internal_function;
23
24 static int
25 internal_function
26 FCT (pattern, string, no_leading_period, flags)
27 const CHAR *pattern;
28 const CHAR *string;
29 int no_leading_period;
30 int flags;
31 {
32 register const CHAR *p = pattern, *n = string;
33 register UCHAR c;
34 #ifdef _LIBC
35 const UCHAR *collseq = (const UCHAR *)
36 _NL_CURRENT(LC_COLLATE, CONCAT(_NL_COLLATE_COLLSEQ,SUFFIX));
37 # ifdef WIDE_CHAR_VERSION
38 const wint_t *names = (const wint_t *)
39 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_NAMES);
40 size_t size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_HASH_SIZE);
41 size_t layers = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_HASH_LAYERS);
42 # endif
43 #endif
44
45 while ((c = *p++) != L('\0'))
46 {
47 c = FOLD (c);
48
49 switch (c)
50 {
51 case L('?'):
52 if (*n == L('\0'))
53 return FNM_NOMATCH;
54 else if (*n == L('/') && (flags & FNM_FILE_NAME))
55 return FNM_NOMATCH;
56 else if (*n == L('.') && no_leading_period
57 && (n == string
58 || (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
59 return FNM_NOMATCH;
60 break;
61
62 case L('\\'):
63 if (!(flags & FNM_NOESCAPE))
64 {
65 c = *p++;
66 if (c == L('\0'))
67 /* Trailing \ loses. */
68 return FNM_NOMATCH;
69 c = FOLD (c);
70 }
71 if (FOLD ((UCHAR) *n) != c)
72 return FNM_NOMATCH;
73 break;
74
75 case L('*'):
76 if (*n == L('.') && no_leading_period
77 && (n == string
78 || (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
79 return FNM_NOMATCH;
80
81 for (c = *p++; c == L('?') || c == L('*'); c = *p++)
82 {
83 if (*n == L('/') && (flags & FNM_FILE_NAME))
84 /* A slash does not match a wildcard under FNM_FILE_NAME. */
85 return FNM_NOMATCH;
86 else if (c == L('?'))
87 {
88 /* A ? needs to match one character. */
89 if (*n == L('\0'))
90 /* There isn't another character; no match. */
91 return FNM_NOMATCH;
92 else
93 /* One character of the string is consumed in matching
94 this ? wildcard, so *??? won't match if there are
95 less than three characters. */
96 ++n;
97 }
98 }
99
100 if (c == L('\0'))
101 /* The wildcard(s) is/are the last element of the pattern.
102 If the name is a file name and contains another slash
103 this does mean it cannot match. If the FNM_LEADING_DIR
104 flag is set and exactly one slash is following, we have
105 a match. */
106 {
107 int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
108
109 if (flags & FNM_FILE_NAME)
110 {
111 const CHAR *slashp = STRCHR (n, L('/'));
112
113 if (flags & FNM_LEADING_DIR)
114 {
115 if (slashp != NULL
116 && STRCHR (slashp + 1, L('/')) == NULL)
117 result = 0;
118 }
119 else
120 {
121 if (slashp == NULL)
122 result = 0;
123 }
124 }
125
126 return result;
127 }
128 else
129 {
130 const CHAR *endp;
131
132 endp = STRCHRNUL (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'));
133
134 if (c == L('['))
135 {
136 int flags2 = ((flags & FNM_FILE_NAME)
137 ? flags : (flags & ~FNM_PERIOD));
138
139 for (--p; n < endp; ++n)
140 if (FCT (p, n, (no_leading_period
141 && (n == string
142 || (n[-1] == L('/')
143 && (flags & FNM_FILE_NAME)))),
144 flags2) == 0)
145 return 0;
146 }
147 else if (c == L('/') && (flags & FNM_FILE_NAME))
148 {
149 while (*n != L('\0') && *n != L('/'))
150 ++n;
151 if (*n == L('/')
152 && (FCT (p, n + 1, flags & FNM_PERIOD, flags) == 0))
153 return 0;
154 }
155 else
156 {
157 int flags2 = ((flags & FNM_FILE_NAME)
158 ? flags : (flags & ~FNM_PERIOD));
159
160 if (c == L('\\') && !(flags & FNM_NOESCAPE))
161 c = *p;
162 c = FOLD (c);
163 for (--p; n < endp; ++n)
164 if (FOLD ((UCHAR) *n) == c
165 && (FCT (p, n, (no_leading_period
166 && (n == string
167 || (n[-1] == L('/')
168 && (flags & FNM_FILE_NAME)))),
169 flags2) == 0))
170 return 0;
171 }
172 }
173
174 /* If we come here no match is possible with the wildcard. */
175 return FNM_NOMATCH;
176
177 case L('['):
178 {
179 static int posixly_correct;
180 /* Nonzero if the sense of the character class is inverted. */
181 register int not;
182 CHAR cold;
183
184 if (posixly_correct == 0)
185 posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
186
187 if (*n == L('\0'))
188 return FNM_NOMATCH;
189
190 if (*n == L('.') && no_leading_period
191 && (n == string
192 || (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
193 return FNM_NOMATCH;
194
195 if (*n == L('/') && (flags & FNM_FILE_NAME))
196 /* `/' cannot be matched. */
197 return FNM_NOMATCH;
198
199 not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
200 if (not)
201 ++p;
202
203 c = *p++;
204 for (;;)
205 {
206 UCHAR fn = FOLD ((UCHAR) *n);
207
208 if (!(flags & FNM_NOESCAPE) && c == L('\\'))
209 {
210 if (*p == L('\0'))
211 return FNM_NOMATCH;
212 c = FOLD ((UCHAR) *p);
213 ++p;
214
215 if (c == fn)
216 goto matched;
217 }
218 else if (c == L('[') && *p == L(':'))
219 {
220 /* Leave room for the null. */
221 CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
222 size_t c1 = 0;
223 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
224 wctype_t wt;
225 #endif
226 const CHAR *startp = p;
227
228 for (;;)
229 {
230 if (c1 == CHAR_CLASS_MAX_LENGTH)
231 /* The name is too long and therefore the pattern
232 is ill-formed. */
233 return FNM_NOMATCH;
234
235 c = *++p;
236 if (c == L(':') && p[1] == L(']'))
237 {
238 p += 2;
239 break;
240 }
241 if (c < L('a') || c >= L('z'))
242 {
243 /* This cannot possibly be a character class name.
244 Match it as a normal range. */
245 p = startp;
246 c = L('[');
247 goto normal_bracket;
248 }
249 str[c1++] = c;
250 }
251 str[c1] = L('\0');
252
253 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
254 wt = IS_CHAR_CLASS (str);
255 if (wt == 0)
256 /* Invalid character class name. */
257 return FNM_NOMATCH;
258
259 if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
260 goto matched;
261 #else
262 if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n))
263 || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n))
264 || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n))
265 || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n))
266 || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n))
267 || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n))
268 || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n))
269 || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n))
270 || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n))
271 || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n))
272 || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n))
273 || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
274 goto matched;
275 #endif
276 c = *p++;
277 }
278 else if (c == L('\0'))
279 /* [ (unterminated) loses. */
280 return FNM_NOMATCH;
281 else
282 {
283 c = FOLD (c);
284 normal_bracket:
285 if (c == fn)
286 goto matched;
287
288 cold = c;
289 c = *p++;
290
291 if (c == L('-') && *p != L(']'))
292 {
293 #if _LIBC
294 /* We have to find the collation sequence
295 value for C. Collation sequence is nothing
296 we can regularly access. The sequence
297 value is defined by the order in which the
298 definitions of the collation values for the
299 various characters appear in the source
300 file. A strange concept, nowhere
301 documented. */
302 int32_t fseqidx;
303 int32_t lseqidx;
304 UCHAR cend = *p++;
305 # ifdef WIDE_CHAR_VERSION
306 size_t cnt;
307 # endif
308
309 if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
310 cend = *p++;
311 if (cend == L('\0'))
312 return FNM_NOMATCH;
313
314 # ifdef WIDE_CHAR_VERSION
315 /* Search in the `names' array for the characters. */
316 fseqidx = fn % size;
317 cnt = 0;
318 while (names[fseqidx] != fn)
319 {
320 if (++cnt == layers)
321 /* XXX We don't know anything about
322 the character we are supposed to
323 match. This means we are failing. */
324 goto range_not_matched;
325
326 fseqidx += size;
327 }
328 lseqidx = cold % size;
329 cnt = 0;
330 while (names[lseqidx] != cold)
331 {
332 if (++cnt == layers)
333 {
334 lseqidx = -1;
335 break;
336 }
337 lseqidx += size;
338 }
339 # else
340 fseqidx = fn;
341 lseqidx = cold;
342 # endif
343
344 /* XXX It is not entirely clear to me how to handle
345 characters which are not mentioned in the
346 collation specification. */
347 if (
348 # ifdef WIDE_CHAR_VERSION
349 lseqidx == -1 ||
350 # endif
351 collseq[lseqidx] <= collseq[fseqidx])
352 {
353 /* We have to look at the upper bound. */
354 int32_t hseqidx;
355
356 cend = FOLD (cend);
357 # ifdef WIDE_CHAR_VERSION
358 hseqidx = cend % size;
359 cnt = 0;
360 while (names[hseqidx] != cend)
361 {
362 if (++cnt == layers)
363 {
364 /* Hum, no information about the upper
365 bound. The matching succeeds if the
366 lower bound is matched exactly. */
367 if (lseqidx == -1 || cold != fn)
368 goto range_not_matched;
369
370 goto matched;
371 }
372 }
373 # else
374 hseqidx = cend;
375 # endif
376
377 if (
378 # ifdef WIDE_CHAR_VERSION
379 (lseqidx == -1
380 && collseq[fseqidx] == collseq[hseqidx]) ||
381 # endif
382 collseq[fseqidx] <= collseq[hseqidx])
383 goto matched;
384 }
385 # ifdef WIDE_CHAR_VERSION
386 range_not_matched:
387 # endif
388 #else
389 /* We use a boring value comparison of the character
390 values. This is better than comparing using
391 `strcoll' since the latter would have surprising
392 and sometimes fatal consequences. */
393 UCHAR cend = *p++;
394
395 if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
396 cend = *p++;
397 if (cend == L('\0'))
398 return FNM_NOMATCH;
399
400 /* It is a range. */
401 if (cold <= fc && fc <= c)
402 goto matched;
403 #endif
404
405 c = *p++;
406 }
407 }
408
409 if (c == L(']'))
410 break;
411 }
412
413 if (!not)
414 return FNM_NOMATCH;
415 break;
416
417 matched:
418 /* Skip the rest of the [...] that already matched. */
419 do
420 {
421 c = *p++;
422
423 if (c == L('\0'))
424 /* [... (unterminated) loses. */
425 return FNM_NOMATCH;
426
427 if (!(flags & FNM_NOESCAPE) && c == L('\\'))
428 {
429 if (*p == L('\0'))
430 return FNM_NOMATCH;
431 /* XXX 1003.2d11 is unclear if this is right. */
432 ++p;
433 }
434 else if (c == L('[') && *p == L(':'))
435 {
436 do
437 if (*++p == L('\0'))
438 return FNM_NOMATCH;
439 while (*p != L(':') || p[1] == L(']'));
440 p += 2;
441 c = *p;
442 }
443 }
444 while (c != L(']'));
445 if (not)
446 return FNM_NOMATCH;
447 }
448 break;
449
450 default:
451 if (c != FOLD ((UCHAR) *n))
452 return FNM_NOMATCH;
453 }
454
455 ++n;
456 }
457
458 if (*n == '\0')
459 return 0;
460
461 if ((flags & FNM_LEADING_DIR) && *n == L('/'))
462 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
463 return 0;
464
465 return FNM_NOMATCH;
466 }
467
468 #undef FOLD
469 #undef CHAR
470 #undef UCHAR
471 #undef FCT
472 #undef STRCHR
473 #undef STRCHRNUL
474 #undef STRCOLL
475 #undef L
476 #undef BTOWC
477 #undef SUFFIX