]>
git.ipfire.org Git - thirdparty/glibc.git/blob - 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.
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.
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.
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. */
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
;
26 FCT (pattern
, string
, no_leading_period
, flags
)
29 int no_leading_period
;
32 register const CHAR
*p
= pattern
, *n
= string
;
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
);
45 while ((c
= *p
++) != L('\0'))
54 else if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
56 else if (*n
== L('.') && no_leading_period
58 || (n
[-1] == L('/') && (flags
& FNM_FILE_NAME
))))
63 if (!(flags
& FNM_NOESCAPE
))
67 /* Trailing \ loses. */
71 if (FOLD ((UCHAR
) *n
) != c
)
76 if (*n
== L('.') && no_leading_period
78 || (n
[-1] == L('/') && (flags
& FNM_FILE_NAME
))))
81 for (c
= *p
++; c
== L('?') || c
== L('*'); c
= *p
++)
83 if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
84 /* A slash does not match a wildcard under FNM_FILE_NAME. */
88 /* A ? needs to match one character. */
90 /* There isn't another character; no match. */
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. */
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
107 int result
= (flags
& FNM_FILE_NAME
) == 0 ? 0 : FNM_NOMATCH
;
109 if (flags
& FNM_FILE_NAME
)
111 const CHAR
*slashp
= STRCHR (n
, L('/'));
113 if (flags
& FNM_LEADING_DIR
)
116 && STRCHR (slashp
+ 1, L('/')) == NULL
)
132 endp
= STRCHRNUL (n
, (flags
& FNM_FILE_NAME
) ? L('/') : L('\0'));
136 int flags2
= ((flags
& FNM_FILE_NAME
)
137 ? flags
: (flags
& ~FNM_PERIOD
));
139 for (--p
; n
< endp
; ++n
)
140 if (FCT (p
, n
, (no_leading_period
143 && (flags
& FNM_FILE_NAME
)))),
147 else if (c
== L('/') && (flags
& FNM_FILE_NAME
))
149 while (*n
!= L('\0') && *n
!= L('/'))
152 && (FCT (p
, n
+ 1, flags
& FNM_PERIOD
, flags
) == 0))
157 int flags2
= ((flags
& FNM_FILE_NAME
)
158 ? flags
: (flags
& ~FNM_PERIOD
));
160 if (c
== L('\\') && !(flags
& FNM_NOESCAPE
))
163 for (--p
; n
< endp
; ++n
)
164 if (FOLD ((UCHAR
) *n
) == c
165 && (FCT (p
, n
, (no_leading_period
168 && (flags
& FNM_FILE_NAME
)))),
174 /* If we come here no match is possible with the wildcard. */
179 static int posixly_correct
;
180 /* Nonzero if the sense of the character class is inverted. */
184 if (posixly_correct
== 0)
185 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
190 if (*n
== L('.') && no_leading_period
192 || (n
[-1] == L('/') && (flags
& FNM_FILE_NAME
))))
195 if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
196 /* `/' cannot be matched. */
199 not = (*p
== L('!') || (posixly_correct
< 0 && *p
== L('^')));
206 UCHAR fn
= FOLD ((UCHAR
) *n
);
208 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
212 c
= FOLD ((UCHAR
) *p
);
218 else if (c
== L('[') && *p
== L(':'))
220 /* Leave room for the null. */
221 CHAR str
[CHAR_CLASS_MAX_LENGTH
+ 1];
223 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
226 const CHAR
*startp
= p
;
230 if (c1
== CHAR_CLASS_MAX_LENGTH
)
231 /* The name is too long and therefore the pattern
236 if (c
== L(':') && p
[1] == L(']'))
241 if (c
< L('a') || c
>= L('z'))
243 /* This cannot possibly be a character class name.
244 Match it as a normal range. */
253 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
254 wt
= IS_CHAR_CLASS (str
);
256 /* Invalid character class name. */
259 if (ISWCTYPE (BTOWC ((UCHAR
) *n
), wt
))
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
)))
278 else if (c
== L('\0'))
279 /* [ (unterminated) loses. */
291 if (c
== L('-') && *p
!= L(']'))
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
305 # ifdef WIDE_CHAR_VERSION
309 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
314 # ifdef WIDE_CHAR_VERSION
315 /* Search in the `names' array for the characters. */
318 while (names
[fseqidx
] != fn
)
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
;
328 lseqidx
= cold
% size
;
330 while (names
[lseqidx
] != cold
)
344 /* XXX It is not entirely clear to me how to handle
345 characters which are not mentioned in the
346 collation specification. */
348 # ifdef WIDE_CHAR_VERSION
351 collseq
[lseqidx
] <= collseq
[fseqidx
])
353 /* We have to look at the upper bound. */
357 # ifdef WIDE_CHAR_VERSION
358 hseqidx
= cend
% size
;
360 while (names
[hseqidx
] != cend
)
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
;
378 # ifdef WIDE_CHAR_VERSION
380 && collseq
[fseqidx
] == collseq
[hseqidx
]) ||
382 collseq
[fseqidx
] <= collseq
[hseqidx
])
385 # ifdef WIDE_CHAR_VERSION
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. */
395 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
401 if (cold
<= fc
&& fc
<= c
)
418 /* Skip the rest of the [...] that already matched. */
424 /* [... (unterminated) loses. */
427 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
431 /* XXX 1003.2d11 is unclear if this is right. */
434 else if (c
== L('[') && *p
== L(':'))
439 while (*p
!= L(':') || p
[1] == L(']'));
451 if (c
!= FOLD ((UCHAR
) *n
))
461 if ((flags
& FNM_LEADING_DIR
) && *n
== L('/'))
462 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */