]>
sourceware.org Git - 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 /* The following code is glibc specific but does
260 there a good job in sppeding up the code since
261 we can avoid the btowc() call. The
262 IS_CHAR_CLASS call will return a bit mask for
263 the 32-bit table. We have to convert it to a
264 bitmask for the __ctype_b table. This has to
265 be done based on the byteorder as can be seen
266 below. In any case we will fall back on the
267 code using btowc() if the class is not one of
268 the standard classes. */
269 # if defined _LIBC && ! WIDE_CHAR_VERSION
270 # if __BYTE_ORDER == __LITTLE_ENDIAN
271 if ((wt
& 0xf0ffff) == 0)
274 if ((__ctype_b
[(UCHAR
) *n
] & wt
) != 0)
280 if ((__ctype_b
[(UCHAR
) *n
] & wt
) != 0)
286 if (ISWCTYPE (BTOWC ((UCHAR
) *n
), wt
))
289 if ((STREQ (str
, L("alnum")) && ISALNUM ((UCHAR
) *n
))
290 || (STREQ (str
, L("alpha")) && ISALPHA ((UCHAR
) *n
))
291 || (STREQ (str
, L("blank")) && ISBLANK ((UCHAR
) *n
))
292 || (STREQ (str
, L("cntrl")) && ISCNTRL ((UCHAR
) *n
))
293 || (STREQ (str
, L("digit")) && ISDIGIT ((UCHAR
) *n
))
294 || (STREQ (str
, L("graph")) && ISGRAPH ((UCHAR
) *n
))
295 || (STREQ (str
, L("lower")) && ISLOWER ((UCHAR
) *n
))
296 || (STREQ (str
, L("print")) && ISPRINT ((UCHAR
) *n
))
297 || (STREQ (str
, L("punct")) && ISPUNCT ((UCHAR
) *n
))
298 || (STREQ (str
, L("space")) && ISSPACE ((UCHAR
) *n
))
299 || (STREQ (str
, L("upper")) && ISUPPER ((UCHAR
) *n
))
300 || (STREQ (str
, L("xdigit")) && ISXDIGIT ((UCHAR
) *n
)))
306 else if (c
== L('[') && *p
== L('='))
310 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
311 const CHAR
*startp
= p
;
323 if (c
!= L('=') || p
[1] != L(']'))
333 if ((UCHAR
) *n
== str
[0])
338 const int32_t *table
;
339 # if WIDE_CHAR_VERSION
340 const int32_t *weights
;
341 const int32_t *extra
;
343 const unsigned char *weights
;
344 const unsigned char *extra
;
346 const int32_t *indirect
;
348 const UCHAR
*cp
= (const UCHAR
*) str
;
350 /* This #include defines a local function! */
351 # if WIDE_CHAR_VERSION
352 # include <locale/weightwc.h>
354 # include <locale/weight.h>
357 # if WIDE_CHAR_VERSION
358 table
= (const int32_t *)
359 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEWC
);
360 weights
= (const int32_t *)
361 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTWC
);
362 extra
= (const int32_t *)
363 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAWC
);
364 indirect
= (const int32_t *)
365 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTWC
);
367 table
= (const int32_t *)
368 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEMB
);
369 weights
= (const unsigned char *)
370 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTMB
);
371 extra
= (const unsigned char *)
372 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAMB
);
373 indirect
= (const int32_t *)
374 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTMB
);
380 /* We found a table entry. Now see whether the
381 character we are currently at has the same
382 equivalance class value. */
383 # if !WIDE_CHAR_VERSION
384 int len
= weights
[idx
];
387 const UCHAR
*np
= (const UCHAR
*) n
;
389 idx2
= findidx (&np
);
390 # if !WIDE_CHAR_VERSION
391 if (idx2
!= 0 && len
== weights
[idx2
])
396 && (weights
[idx
+ 1 + cnt
]
397 == weights
[idx2
+ 1 + cnt
]))
404 if (idx2
!= 0 && weights
[idx
] == weights
[idx2
])
413 else if (c
== L('\0'))
414 /* [ (unterminated) loses. */
426 if (c
== L('-') && *p
!= L(']'))
429 /* We have to find the collation sequence
430 value for C. Collation sequence is nothing
431 we can regularly access. The sequence
432 value is defined by the order in which the
433 definitions of the collation values for the
434 various characters appear in the source
435 file. A strange concept, nowhere
440 # ifdef WIDE_CHAR_VERSION
444 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
449 # ifdef WIDE_CHAR_VERSION
450 /* Search in the `names' array for the characters. */
453 while (names
[fseqidx
] != fn
)
456 /* XXX We don't know anything about
457 the character we are supposed to
458 match. This means we are failing. */
459 goto range_not_matched
;
463 lseqidx
= cold
% size
;
465 while (names
[lseqidx
] != cold
)
479 /* XXX It is not entirely clear to me how to handle
480 characters which are not mentioned in the
481 collation specification. */
483 # ifdef WIDE_CHAR_VERSION
486 collseq
[lseqidx
] <= collseq
[fseqidx
])
488 /* We have to look at the upper bound. */
492 # ifdef WIDE_CHAR_VERSION
493 hseqidx
= cend
% size
;
495 while (names
[hseqidx
] != cend
)
499 /* Hum, no information about the upper
500 bound. The matching succeeds if the
501 lower bound is matched exactly. */
502 if (lseqidx
== -1 || cold
!= fn
)
503 goto range_not_matched
;
513 # ifdef WIDE_CHAR_VERSION
515 && collseq
[fseqidx
] == collseq
[hseqidx
]) ||
517 collseq
[fseqidx
] <= collseq
[hseqidx
])
520 # ifdef WIDE_CHAR_VERSION
524 /* We use a boring value comparison of the character
525 values. This is better than comparing using
526 `strcoll' since the latter would have surprising
527 and sometimes fatal consequences. */
530 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
536 if (cold
<= fc
&& fc
<= c
)
553 /* Skip the rest of the [...] that already matched. */
559 /* [... (unterminated) loses. */
562 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
566 /* XXX 1003.2d11 is unclear if this is right. */
569 else if (c
== L('[') && *p
== L(':'))
574 while (*p
!= L(':') || p
[1] == L(']'));
586 if (c
!= FOLD ((UCHAR
) *n
))
596 if ((flags
& FNM_LEADING_DIR
) && *n
== L('/'))
597 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
This page took 0.067111 seconds and 5 git commands to generate.