]> git.ipfire.org Git - thirdparty/glibc.git/blame - posix/fnmatch_loop.c
Support Intel processor model 6 and model 0x2.
[thirdparty/glibc.git] / posix / fnmatch_loop.c
CommitLineData
f15ce4d8 1/* Copyright (C) 1991-1993,1996-2001,2003-2005,2007,2010
b7d1c5fa 2 Free Software Foundation, Inc.
1fc82a56
UD
3 This file is part of the GNU C Library.
4
41bdb6e2
AJ
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
1fc82a56 9
41bdb6e2 10 The GNU C Library is distributed in the hope that it will be useful,
1fc82a56
UD
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
1fc82a56 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
1fc82a56 19
9700b039
UD
20struct STRUCT
21{
22 const CHAR *pattern;
23 const CHAR *string;
24 int no_leading_period;
25};
26
1fc82a56
UD
27/* Match STRING against the filename pattern PATTERN, returning zero if
28 it matches, nonzero if not. */
29static int FCT (const CHAR *pattern, const CHAR *string,
9700b039 30 const CHAR *string_end, int no_leading_period, int flags,
f15ce4d8 31 struct STRUCT *ends, size_t alloca_used)
955994e1
UD
32 internal_function;
33static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
f15ce4d8
UD
34 const CHAR *string_end, int no_leading_period, int flags,
35 size_t alloca_used)
955994e1
UD
36 internal_function;
37static const CHAR *END (const CHAR *patternp) internal_function;
1fc82a56
UD
38
39static int
40internal_function
f15ce4d8 41FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
1fc82a56
UD
42 const CHAR *pattern;
43 const CHAR *string;
955994e1 44 const CHAR *string_end;
1fc82a56
UD
45 int no_leading_period;
46 int flags;
9700b039 47 struct STRUCT *ends;
f15ce4d8 48 size_t alloca_used;
1fc82a56
UD
49{
50 register const CHAR *p = pattern, *n = string;
51 register UCHAR c;
acb5ee2e 52#ifdef _LIBC
4c7d276e
UD
53# if WIDE_CHAR_VERSION
54 const char *collseq = (const char *)
55 _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
56# else
acb5ee2e 57 const UCHAR *collseq = (const UCHAR *)
4c7d276e 58 _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
acb5ee2e
UD
59# endif
60#endif
1fc82a56
UD
61
62 while ((c = *p++) != L('\0'))
63 {
955994e1 64 int new_no_leading_period = 0;
1fc82a56
UD
65 c = FOLD (c);
66
67 switch (c)
68 {
69 case L('?'):
955994e1
UD
70 if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
71 {
f15ce4d8
UD
72 int res = EXT (c, p, n, string_end, no_leading_period,
73 flags, alloca_used);
955994e1
UD
74 if (res != -1)
75 return res;
76 }
77
78 if (n == string_end)
1fc82a56
UD
79 return FNM_NOMATCH;
80 else if (*n == L('/') && (flags & FNM_FILE_NAME))
81 return FNM_NOMATCH;
955994e1 82 else if (*n == L('.') && no_leading_period)
1fc82a56
UD
83 return FNM_NOMATCH;
84 break;
85
86 case L('\\'):
87 if (!(flags & FNM_NOESCAPE))
88 {
89 c = *p++;
90 if (c == L('\0'))
91 /* Trailing \ loses. */
92 return FNM_NOMATCH;
93 c = FOLD (c);
94 }
955994e1 95 if (n == string_end || FOLD ((UCHAR) *n) != c)
1fc82a56
UD
96 return FNM_NOMATCH;
97 break;
98
99 case L('*'):
955994e1
UD
100 if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
101 {
f15ce4d8
UD
102 int res = EXT (c, p, n, string_end, no_leading_period,
103 flags, alloca_used);
955994e1
UD
104 if (res != -1)
105 return res;
106 }
9700b039
UD
107 else if (ends != NULL)
108 {
109 ends->pattern = p - 1;
110 ends->string = n;
111 ends->no_leading_period = no_leading_period;
112 return 0;
113 }
955994e1
UD
114
115 if (n != string_end && *n == L('.') && no_leading_period)
1fc82a56
UD
116 return FNM_NOMATCH;
117
118 for (c = *p++; c == L('?') || c == L('*'); c = *p++)
119 {
955994e1
UD
120 if (*p == L('(') && (flags & FNM_EXTMATCH) != 0)
121 {
122 const CHAR *endp = END (p);
123 if (endp != p)
124 {
125 /* This is a pattern. Skip over it. */
126 p = endp;
127 continue;
128 }
129 }
130
131 if (c == L('?'))
1fc82a56
UD
132 {
133 /* A ? needs to match one character. */
955994e1 134 if (n == string_end)
1fc82a56
UD
135 /* There isn't another character; no match. */
136 return FNM_NOMATCH;
955994e1
UD
137 else if (*n == L('/')
138 && __builtin_expect (flags & FNM_FILE_NAME, 0))
139 /* A slash does not match a wildcard under
140 FNM_FILE_NAME. */
141 return FNM_NOMATCH;
1fc82a56
UD
142 else
143 /* One character of the string is consumed in matching
144 this ? wildcard, so *??? won't match if there are
145 less than three characters. */
146 ++n;
147 }
148 }
149
150 if (c == L('\0'))
151 /* The wildcard(s) is/are the last element of the pattern.
152 If the name is a file name and contains another slash
a4607c1f
UD
153 this means it cannot match, unless the FNM_LEADING_DIR
154 flag is set. */
47924894
UD
155 {
156 int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
157
158 if (flags & FNM_FILE_NAME)
159 {
47924894 160 if (flags & FNM_LEADING_DIR)
a4607c1f 161 result = 0;
47924894
UD
162 else
163 {
955994e1 164 if (MEMCHR (n, L('/'), string_end - n) == NULL)
47924894
UD
165 result = 0;
166 }
167 }
168
169 return result;
170 }
1fc82a56
UD
171 else
172 {
173 const CHAR *endp;
9700b039 174 struct STRUCT end;
1fc82a56 175
9700b039 176 end.pattern = NULL;
955994e1
UD
177 endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'),
178 string_end - n);
179 if (endp == NULL)
180 endp = string_end;
1fc82a56 181
955994e1
UD
182 if (c == L('[')
183 || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
228293b5
UD
184 && (c == L('@') || c == L('+') || c == L('!'))
185 && *p == L('(')))
1fc82a56
UD
186 {
187 int flags2 = ((flags & FNM_FILE_NAME)
188 ? flags : (flags & ~FNM_PERIOD));
189
9700b039
UD
190 for (--p; n < endp; ++n, no_leading_period = 0)
191 if (FCT (p, n, string_end, no_leading_period, flags2,
f15ce4d8 192 &end, alloca_used) == 0)
9700b039 193 goto found;
1fc82a56
UD
194 }
195 else if (c == L('/') && (flags & FNM_FILE_NAME))
196 {
955994e1 197 while (n < string_end && *n != L('/'))
1fc82a56 198 ++n;
955994e1 199 if (n < string_end && *n == L('/')
9700b039 200 && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
f15ce4d8 201 NULL, alloca_used) == 0))
1fc82a56
UD
202 return 0;
203 }
204 else
205 {
206 int flags2 = ((flags & FNM_FILE_NAME)
207 ? flags : (flags & ~FNM_PERIOD));
208
209 if (c == L('\\') && !(flags & FNM_NOESCAPE))
210 c = *p;
211 c = FOLD (c);
9700b039 212 for (--p; n < endp; ++n, no_leading_period = 0)
1fc82a56 213 if (FOLD ((UCHAR) *n) == c
9700b039 214 && (FCT (p, n, string_end, no_leading_period, flags2,
f15ce4d8 215 &end, alloca_used) == 0))
9700b039
UD
216 {
217 found:
218 if (end.pattern == NULL)
219 return 0;
220 break;
221 }
222 if (end.pattern != NULL)
223 {
224 p = end.pattern;
225 n = end.string;
226 no_leading_period = end.no_leading_period;
227 continue;
228 }
1fc82a56
UD
229 }
230 }
231
232 /* If we come here no match is possible with the wildcard. */
233 return FNM_NOMATCH;
234
235 case L('['):
236 {
83b1b6d8 237 /* Nonzero if the sense of the character class is inverted. */
1fc82a56
UD
238 register int not;
239 CHAR cold;
955994e1 240 UCHAR fn;
1fc82a56
UD
241
242 if (posixly_correct == 0)
243 posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
244
955994e1 245 if (n == string_end)
1fc82a56
UD
246 return FNM_NOMATCH;
247
955994e1 248 if (*n == L('.') && no_leading_period)
1fc82a56
UD
249 return FNM_NOMATCH;
250
251 if (*n == L('/') && (flags & FNM_FILE_NAME))
252 /* `/' cannot be matched. */
253 return FNM_NOMATCH;
254
255 not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
256 if (not)
257 ++p;
258
955994e1
UD
259 fn = FOLD ((UCHAR) *n);
260
1fc82a56
UD
261 c = *p++;
262 for (;;)
263 {
1fc82a56
UD
264 if (!(flags & FNM_NOESCAPE) && c == L('\\'))
265 {
266 if (*p == L('\0'))
267 return FNM_NOMATCH;
268 c = FOLD ((UCHAR) *p);
269 ++p;
270
aae95a1b 271 goto normal_bracket;
1fc82a56
UD
272 }
273 else if (c == L('[') && *p == L(':'))
274 {
275 /* Leave room for the null. */
276 CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
277 size_t c1 = 0;
acb5ee2e 278#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
1fc82a56 279 wctype_t wt;
acb5ee2e 280#endif
1fc82a56
UD
281 const CHAR *startp = p;
282
283 for (;;)
284 {
285 if (c1 == CHAR_CLASS_MAX_LENGTH)
286 /* The name is too long and therefore the pattern
287 is ill-formed. */
288 return FNM_NOMATCH;
289
290 c = *++p;
291 if (c == L(':') && p[1] == L(']'))
292 {
293 p += 2;
294 break;
295 }
296 if (c < L('a') || c >= L('z'))
297 {
298 /* This cannot possibly be a character class name.
299 Match it as a normal range. */
300 p = startp;
301 c = L('[');
302 goto normal_bracket;
303 }
304 str[c1++] = c;
305 }
306 str[c1] = L('\0');
307
acb5ee2e 308#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
1fc82a56
UD
309 wt = IS_CHAR_CLASS (str);
310 if (wt == 0)
311 /* Invalid character class name. */
312 return FNM_NOMATCH;
313
7239b3a4 314# if defined _LIBC && ! WIDE_CHAR_VERSION
8fb81470
UD
315 /* The following code is glibc specific but does
316 there a good job in speeding up the code since
317 we can avoid the btowc() call. */
4c7d276e
UD
318 if (_ISCTYPE ((UCHAR) *n, wt))
319 goto matched;
8fb81470
UD
320# else
321 if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
322 goto matched;
7239b3a4 323# endif
acb5ee2e 324#else
1fc82a56
UD
325 if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n))
326 || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n))
327 || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n))
328 || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n))
329 || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n))
330 || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n))
331 || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n))
332 || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n))
333 || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n))
334 || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n))
335 || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n))
336 || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
337 goto matched;
acb5ee2e 338#endif
83b1b6d8 339 c = *p++;
1fc82a56 340 }
ecce00a9
UD
341#ifdef _LIBC
342 else if (c == L('[') && *p == L('='))
343 {
344 UCHAR str[1];
345 uint32_t nrules =
346 _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
347 const CHAR *startp = p;
348
349 c = *++p;
350 if (c == L('\0'))
351 {
352 p = startp;
353 c = L('[');
354 goto normal_bracket;
355 }
356 str[0] = c;
357
358 c = *++p;
359 if (c != L('=') || p[1] != L(']'))
360 {
361 p = startp;
362 c = L('[');
363 goto normal_bracket;
364 }
365 p += 2;
366
367 if (nrules == 0)
368 {
369 if ((UCHAR) *n == str[0])
370 goto matched;
371 }
372 else
373 {
374 const int32_t *table;
375# if WIDE_CHAR_VERSION
376 const int32_t *weights;
377 const int32_t *extra;
378# else
379 const unsigned char *weights;
380 const unsigned char *extra;
381# endif
382 const int32_t *indirect;
383 int32_t idx;
384 const UCHAR *cp = (const UCHAR *) str;
385
386 /* This #include defines a local function! */
387# if WIDE_CHAR_VERSION
388# include <locale/weightwc.h>
389# else
390# include <locale/weight.h>
391# endif
392
393# if WIDE_CHAR_VERSION
394 table = (const int32_t *)
395 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
396 weights = (const int32_t *)
397 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
398 extra = (const int32_t *)
399 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
400 indirect = (const int32_t *)
401 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
402# else
403 table = (const int32_t *)
404 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
405 weights = (const unsigned char *)
406 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
407 extra = (const unsigned char *)
408 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
409 indirect = (const int32_t *)
410 _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
411# endif
412
413 idx = findidx (&cp);
414 if (idx != 0)
415 {
416 /* We found a table entry. Now see whether the
417 character we are currently at has the same
418 equivalance class value. */
b7d1c5fa 419 int len = weights[idx & 0xffffff];
ecce00a9
UD
420 int32_t idx2;
421 const UCHAR *np = (const UCHAR *) n;
422
423 idx2 = findidx (&np);
b7d1c5fa
UD
424 if (idx2 != 0
425 && (idx >> 24) == (idx2 >> 24)
426 && len == weights[idx2 & 0xffffff])
ecce00a9
UD
427 {
428 int cnt = 0;
429
b7d1c5fa
UD
430 idx &= 0xffffff;
431 idx2 &= 0xffffff;
432
ecce00a9
UD
433 while (cnt < len
434 && (weights[idx + 1 + cnt]
435 == weights[idx2 + 1 + cnt]))
436 ++cnt;
437
438 if (cnt == len)
439 goto matched;
440 }
ecce00a9
UD
441 }
442 }
443
444 c = *p++;
445 }
446#endif
1fc82a56
UD
447 else if (c == L('\0'))
448 /* [ (unterminated) loses. */
449 return FNM_NOMATCH;
450 else
451 {
f3e29a1a 452 int is_range = 0;
1fc82a56 453
f3e29a1a 454#ifdef _LIBC
c1ac11df
UD
455 int is_seqval = 0;
456
f3e29a1a
UD
457 if (c == L('[') && *p == L('.'))
458 {
459 uint32_t nrules =
460 _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
461 const CHAR *startp = p;
462 size_t c1 = 0;
463
464 while (1)
465 {
466 c = *++p;
467 if (c == L('.') && p[1] == L(']'))
468 {
469 p += 2;
470 break;
471 }
472 if (c == '\0')
473 return FNM_NOMATCH;
474 ++c1;
475 }
476
477 /* We have to handling the symbols differently in
478 ranges since then the collation sequence is
479 important. */
480 is_range = *p == L('-') && p[1] != L('\0');
481
482 if (nrules == 0)
483 {
484 /* There are no names defined in the collation
485 data. Therefore we only accept the trivial
486 names consisting of the character itself. */
487 if (c1 != 1)
488 return FNM_NOMATCH;
489
490 if (!is_range && *n == startp[1])
491 goto matched;
492
493 cold = startp[1];
494 c = *p++;
495 }
496 else
497 {
498 int32_t table_size;
499 const int32_t *symb_table;
500# ifdef WIDE_CHAR_VERSION
501 char str[c1];
2e47aff5 502 unsigned int strcnt;
f3e29a1a
UD
503# else
504# define str (startp + 1)
505# endif
506 const unsigned char *extra;
507 int32_t idx;
508 int32_t elem;
509 int32_t second;
510 int32_t hash;
511
512# ifdef WIDE_CHAR_VERSION
513 /* We have to convert the name to a single-byte
514 string. This is possible since the names
515 consist of ASCII characters and the internal
516 representation is UCS4. */
517 for (strcnt = 0; strcnt < c1; ++strcnt)
518 str[strcnt] = startp[1 + strcnt];
519#endif
520
521 table_size =
522 _NL_CURRENT_WORD (LC_COLLATE,
523 _NL_COLLATE_SYMB_HASH_SIZEMB);
524 symb_table = (const int32_t *)
525 _NL_CURRENT (LC_COLLATE,
526 _NL_COLLATE_SYMB_TABLEMB);
527 extra = (const unsigned char *)
528 _NL_CURRENT (LC_COLLATE,
529 _NL_COLLATE_SYMB_EXTRAMB);
530
531 /* Locate the character in the hashing table. */
532 hash = elem_hash (str, c1);
533
534 idx = 0;
535 elem = hash % table_size;
7d4722e3 536 if (symb_table[2 * elem] != 0)
f3e29a1a 537 {
7d4722e3
UD
538 second = hash % (table_size - 2) + 1;
539
540 do
f3e29a1a 541 {
7d4722e3
UD
542 /* First compare the hashing value. */
543 if (symb_table[2 * elem] == hash
544 && (c1
545 == extra[symb_table[2 * elem + 1]])
546 && memcmp (str,
547 &extra[symb_table[2 * elem
548 + 1]
549 + 1], c1) == 0)
550 {
551 /* Yep, this is the entry. */
552 idx = symb_table[2 * elem + 1];
553 idx += 1 + extra[idx];
554 break;
555 }
a334319f 556
7d4722e3
UD
557 /* Next entry. */
558 elem += second;
559 }
560 while (symb_table[2 * elem] != 0);
f3e29a1a
UD
561 }
562
563 if (symb_table[2 * elem] != 0)
564 {
565 /* Compare the byte sequence but only if
566 this is not part of a range. */
567# ifdef WIDE_CHAR_VERSION
568 int32_t *wextra;
569
570 idx += 1 + extra[idx];
571 /* Adjust for the alignment. */
2f76d88d 572 idx = (idx + 3) & ~3;
f3e29a1a
UD
573
574 wextra = (int32_t *) &extra[idx + 4];
575# endif
576
577 if (! is_range)
578 {
579# ifdef WIDE_CHAR_VERSION
eb64f8cb
RM
580 for (c1 = 0;
581 (int32_t) c1 < wextra[idx];
582 ++c1)
f3e29a1a
UD
583 if (n[c1] != wextra[1 + c1])
584 break;
585
eb64f8cb 586 if ((int32_t) c1 == wextra[idx])
f3e29a1a
UD
587 goto matched;
588# else
589 for (c1 = 0; c1 < extra[idx]; ++c1)
590 if (n[c1] != extra[1 + c1])
591 break;
592
593 if (c1 == extra[idx])
594 goto matched;
595# endif
596 }
597
598 /* Get the collation sequence value. */
599 is_seqval = 1;
600# ifdef WIDE_CHAR_VERSION
601 cold = wextra[1 + wextra[idx]];
602# else
603 /* Adjust for the alignment. */
604 idx += 1 + extra[idx];
605 idx = (idx + 3) & ~4;
606 cold = *((int32_t *) &extra[idx]);
607# endif
608
609 c = *p++;
610 }
70dc5068 611 else if (c1 == 1)
f3e29a1a
UD
612 {
613 /* No valid character. Match it as a
614 single byte. */
615 if (!is_range && *n == str[0])
616 goto matched;
617
618 cold = str[0];
619 c = *p++;
620 }
621 else
622 return FNM_NOMATCH;
623 }
624 }
625 else
626# undef str
627#endif
628 {
629 c = FOLD (c);
630 normal_bracket:
631
632 /* We have to handling the symbols differently in
633 ranges since then the collation sequence is
634 important. */
be29c482
UD
635 is_range = (*p == L('-') && p[1] != L('\0')
636 && p[1] != L(']'));
f3e29a1a
UD
637
638 if (!is_range && c == fn)
639 goto matched;
640
469dcb0d
RM
641 /* This is needed if we goto normal_bracket; from
642 outside of is_seqval's scope. */
643 is_seqval = 0;
f3e29a1a
UD
644 cold = c;
645 c = *p++;
646 }
1fc82a56
UD
647
648 if (c == L('-') && *p != L(']'))
649 {
acb5ee2e
UD
650#if _LIBC
651 /* We have to find the collation sequence
652 value for C. Collation sequence is nothing
653 we can regularly access. The sequence
654 value is defined by the order in which the
655 definitions of the collation values for the
656 various characters appear in the source
657 file. A strange concept, nowhere
658 documented. */
f3e29a1a
UD
659 uint32_t fcollseq;
660 uint32_t lcollseq;
1fc82a56 661 UCHAR cend = *p++;
acb5ee2e 662
acb5ee2e
UD
663# ifdef WIDE_CHAR_VERSION
664 /* Search in the `names' array for the characters. */
25337753 665 fcollseq = __collseq_table_lookup (collseq, fn);
4c7d276e
UD
666 if (fcollseq == ~((uint32_t) 0))
667 /* XXX We don't know anything about the character
668 we are supposed to match. This means we are
669 failing. */
670 goto range_not_matched;
f3e29a1a
UD
671
672 if (is_seqval)
673 lcollseq = cold;
674 else
25337753 675 lcollseq = __collseq_table_lookup (collseq, cold);
acb5ee2e 676# else
f3e29a1a
UD
677 fcollseq = collseq[fn];
678 lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
679# endif
680
681 is_seqval = 0;
682 if (cend == L('[') && *p == L('.'))
683 {
684 uint32_t nrules =
685 _NL_CURRENT_WORD (LC_COLLATE,
686 _NL_COLLATE_NRULES);
687 const CHAR *startp = p;
688 size_t c1 = 0;
689
690 while (1)
691 {
692 c = *++p;
693 if (c == L('.') && p[1] == L(']'))
694 {
695 p += 2;
696 break;
697 }
698 if (c == '\0')
699 return FNM_NOMATCH;
700 ++c1;
701 }
702
703 if (nrules == 0)
704 {
705 /* There are no names defined in the
706 collation data. Therefore we only
707 accept the trivial names consisting
708 of the character itself. */
709 if (c1 != 1)
710 return FNM_NOMATCH;
711
712 cend = startp[1];
713 }
714 else
715 {
716 int32_t table_size;
717 const int32_t *symb_table;
718# ifdef WIDE_CHAR_VERSION
719 char str[c1];
2e47aff5 720 unsigned int strcnt;
f3e29a1a
UD
721# else
722# define str (startp + 1)
acb5ee2e 723# endif
f3e29a1a
UD
724 const unsigned char *extra;
725 int32_t idx;
726 int32_t elem;
727 int32_t second;
728 int32_t hash;
729
730# ifdef WIDE_CHAR_VERSION
731 /* We have to convert the name to a single-byte
732 string. This is possible since the names
733 consist of ASCII characters and the internal
734 representation is UCS4. */
735 for (strcnt = 0; strcnt < c1; ++strcnt)
736 str[strcnt] = startp[1 + strcnt];
82eafaf7 737# endif
f3e29a1a
UD
738
739 table_size =
740 _NL_CURRENT_WORD (LC_COLLATE,
741 _NL_COLLATE_SYMB_HASH_SIZEMB);
742 symb_table = (const int32_t *)
743 _NL_CURRENT (LC_COLLATE,
744 _NL_COLLATE_SYMB_TABLEMB);
745 extra = (const unsigned char *)
746 _NL_CURRENT (LC_COLLATE,
747 _NL_COLLATE_SYMB_EXTRAMB);
748
749 /* Locate the character in the hashing
f15ce4d8 750 table. */
f3e29a1a
UD
751 hash = elem_hash (str, c1);
752
753 idx = 0;
754 elem = hash % table_size;
7d4722e3 755 if (symb_table[2 * elem] != 0)
f3e29a1a 756 {
7d4722e3
UD
757 second = hash % (table_size - 2) + 1;
758
759 do
f3e29a1a 760 {
7d4722e3
UD
761 /* First compare the hashing value. */
762 if (symb_table[2 * elem] == hash
763 && (c1
764 == extra[symb_table[2 * elem + 1]])
765 && memcmp (str,
766 &extra[symb_table[2 * elem + 1]
767 + 1], c1) == 0)
768 {
769 /* Yep, this is the entry. */
770 idx = symb_table[2 * elem + 1];
771 idx += 1 + extra[idx];
772 break;
773 }
774
775 /* Next entry. */
776 elem += second;
f3e29a1a 777 }
7d4722e3 778 while (symb_table[2 * elem] != 0);
f3e29a1a
UD
779 }
780
781 if (symb_table[2 * elem] != 0)
782 {
783 /* Compare the byte sequence but only if
784 this is not part of a range. */
785# ifdef WIDE_CHAR_VERSION
786 int32_t *wextra;
787
788 idx += 1 + extra[idx];
789 /* Adjust for the alignment. */
790 idx = (idx + 3) & ~4;
791
792 wextra = (int32_t *) &extra[idx + 4];
793# endif
794 /* Get the collation sequence value. */
795 is_seqval = 1;
796# ifdef WIDE_CHAR_VERSION
797 cend = wextra[1 + wextra[idx]];
798# else
799 /* Adjust for the alignment. */
800 idx += 1 + extra[idx];
801 idx = (idx + 3) & ~4;
802 cend = *((int32_t *) &extra[idx]);
803# endif
804 }
805 else if (symb_table[2 * elem] != 0 && c1 == 1)
806 {
807 cend = str[0];
808 c = *p++;
809 }
810 else
811 return FNM_NOMATCH;
812 }
813# undef str
814 }
815 else
816 {
817 if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
818 cend = *p++;
819 if (cend == L('\0'))
820 return FNM_NOMATCH;
821 cend = FOLD (cend);
822 }
acb5ee2e
UD
823
824 /* XXX It is not entirely clear to me how to handle
825 characters which are not mentioned in the
826 collation specification. */
827 if (
828# ifdef WIDE_CHAR_VERSION
f3e29a1a 829 lcollseq == 0xffffffff ||
acb5ee2e 830# endif
f3e29a1a 831 lcollseq <= fcollseq)
acb5ee2e
UD
832 {
833 /* We have to look at the upper bound. */
f3e29a1a 834 uint32_t hcollseq;
acb5ee2e 835
f3e29a1a
UD
836 if (is_seqval)
837 hcollseq = cend;
838 else
acb5ee2e 839 {
f3e29a1a 840# ifdef WIDE_CHAR_VERSION
4c7d276e 841 hcollseq =
25337753 842 __collseq_table_lookup (collseq, cend);
4c7d276e 843 if (hcollseq == ~((uint32_t) 0))
acb5ee2e 844 {
4c7d276e
UD
845 /* Hum, no information about the upper
846 bound. The matching succeeds if the
847 lower bound is matched exactly. */
848 if (lcollseq != fcollseq)
849 goto range_not_matched;
04ea3b0f 850
4c7d276e 851 goto matched;
acb5ee2e 852 }
acb5ee2e 853# else
f3e29a1a 854 hcollseq = collseq[cend];
acb5ee2e 855# endif
f3e29a1a 856 }
acb5ee2e 857
f3e29a1a 858 if (lcollseq <= hcollseq && fcollseq <= hcollseq)
9de4e203
UD
859 goto matched;
860 }
acb5ee2e
UD
861# ifdef WIDE_CHAR_VERSION
862 range_not_matched:
863# endif
864#else
865 /* We use a boring value comparison of the character
866 values. This is better than comparing using
867 `strcoll' since the latter would have surprising
868 and sometimes fatal consequences. */
869 UCHAR cend = *p++;
870
871 if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
872 cend = *p++;
873 if (cend == L('\0'))
874 return FNM_NOMATCH;
875
876 /* It is a range. */
bd8fbd57 877 if (cold <= fn && fn <= cend)
acb5ee2e
UD
878 goto matched;
879#endif
1fc82a56
UD
880
881 c = *p++;
882 }
883 }
884
885 if (c == L(']'))
886 break;
887 }
888
889 if (!not)
890 return FNM_NOMATCH;
891 break;
892
893 matched:
894 /* Skip the rest of the [...] that already matched. */
83b1b6d8 895 do
1fc82a56 896 {
f3e29a1a 897 ignore_next:
83b1b6d8
UD
898 c = *p++;
899
1fc82a56
UD
900 if (c == L('\0'))
901 /* [... (unterminated) loses. */
902 return FNM_NOMATCH;
903
1fc82a56
UD
904 if (!(flags & FNM_NOESCAPE) && c == L('\\'))
905 {
906 if (*p == L('\0'))
907 return FNM_NOMATCH;
908 /* XXX 1003.2d11 is unclear if this is right. */
909 ++p;
910 }
911 else if (c == L('[') && *p == L(':'))
912 {
f3e29a1a
UD
913 int c1 = 0;
914 const CHAR *startp = p;
915
916 while (1)
917 {
918 c = *++p;
919 if (++c1 == CHAR_CLASS_MAX_LENGTH)
920 return FNM_NOMATCH;
921
922 if (*p == L(':') && p[1] == L(']'))
923 break;
924
925 if (c < L('a') || c >= L('z'))
926 {
927 p = startp;
928 goto ignore_next;
929 }
930 }
1fc82a56 931 p += 2;
f3e29a1a
UD
932 c = *p++;
933 }
934 else if (c == L('[') && *p == L('='))
935 {
936 c = *++p;
937 if (c == L('\0'))
938 return FNM_NOMATCH;
939 c = *++p;
940 if (c != L('=') || p[1] != L(']'))
941 return FNM_NOMATCH;
942 p += 2;
943 c = *p++;
944 }
945 else if (c == L('[') && *p == L('.'))
946 {
947 ++p;
948 while (1)
949 {
950 c = *++p;
951 if (c == '\0')
952 return FNM_NOMATCH;
953
954 if (*p == L('.') && p[1] == L(']'))
955 break;
956 }
957 p += 2;
958 c = *p++;
1fc82a56
UD
959 }
960 }
83b1b6d8 961 while (c != L(']'));
1fc82a56
UD
962 if (not)
963 return FNM_NOMATCH;
964 }
965 break;
966
955994e1
UD
967 case L('+'):
968 case L('@'):
969 case L('!'):
970 if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
971 {
f15ce4d8
UD
972 int res = EXT (c, p, n, string_end, no_leading_period, flags,
973 alloca_used);
955994e1
UD
974 if (res != -1)
975 return res;
976 }
977 goto normal_match;
978
979 case L('/'):
980 if (NO_LEADING_PERIOD (flags))
981 {
eb64f8cb 982 if (n == string_end || c != (UCHAR) *n)
955994e1
UD
983 return FNM_NOMATCH;
984
985 new_no_leading_period = 1;
986 break;
987 }
988 /* FALLTHROUGH */
1fc82a56 989 default:
955994e1
UD
990 normal_match:
991 if (n == string_end || c != FOLD ((UCHAR) *n))
1fc82a56
UD
992 return FNM_NOMATCH;
993 }
994
955994e1 995 no_leading_period = new_no_leading_period;
1fc82a56
UD
996 ++n;
997 }
998
955994e1 999 if (n == string_end)
1fc82a56
UD
1000 return 0;
1001
955994e1 1002 if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/'))
1fc82a56
UD
1003 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
1004 return 0;
1005
1006 return FNM_NOMATCH;
ea6eb383 1007}
1fc82a56 1008
955994e1
UD
1009
1010static const CHAR *
1011internal_function
1012END (const CHAR *pattern)
1013{
1014 const CHAR *p = pattern;
1015
1016 while (1)
1017 if (*++p == L('\0'))
1018 /* This is an invalid pattern. */
1019 return pattern;
1020 else if (*p == L('['))
1021 {
1022 /* Handle brackets special. */
1023 if (posixly_correct == 0)
1024 posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
1025
1026 /* Skip the not sign. We have to recognize it because of a possibly
1027 following ']'. */
1028 if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
1029 ++p;
1030 /* A leading ']' is recognized as such. */
1031 if (*p == L(']'))
1032 ++p;
1033 /* Skip over all characters of the list. */
1034 while (*p != L(']'))
1035 if (*p++ == L('\0'))
1036 /* This is no valid pattern. */
1037 return pattern;
1038 }
1039 else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
1040 || *p == L('!')) && p[1] == L('('))
1041 p = END (p + 1);
1042 else if (*p == L(')'))
1043 break;
1044
1045 return p + 1;
1046}
1047
1048
1049static int
1050internal_function
1051EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
f15ce4d8 1052 int no_leading_period, int flags, size_t alloca_used)
955994e1
UD
1053{
1054 const CHAR *startp;
1055 int level;
1056 struct patternlist
1057 {
1058 struct patternlist *next;
f15ce4d8 1059 CHAR malloced;
955994e1
UD
1060 CHAR str[0];
1061 } *list = NULL;
1062 struct patternlist **lastp = &list;
821a6bb4 1063 size_t pattern_len = STRLEN (pattern);
f15ce4d8 1064 int any_malloced = 0;
955994e1
UD
1065 const CHAR *p;
1066 const CHAR *rs;
f15ce4d8 1067 int retval = 0;
955994e1
UD
1068
1069 /* Parse the pattern. Store the individual parts in the list. */
1070 level = 0;
1071 for (startp = p = pattern + 1; level >= 0; ++p)
1072 if (*p == L('\0'))
f15ce4d8
UD
1073 {
1074 /* This is an invalid pattern. */
1075 retval = -1;
1076 goto out;
1077 }
955994e1
UD
1078 else if (*p == L('['))
1079 {
1080 /* Handle brackets special. */
1081 if (posixly_correct == 0)
1082 posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
1083
1084 /* Skip the not sign. We have to recognize it because of a possibly
1085 following ']'. */
1086 if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
1087 ++p;
1088 /* A leading ']' is recognized as such. */
1089 if (*p == L(']'))
1090 ++p;
1091 /* Skip over all characters of the list. */
1092 while (*p != L(']'))
1093 if (*p++ == L('\0'))
f15ce4d8
UD
1094 {
1095 /* This is no valid pattern. */
1096 retval = -1;
1097 goto out;
1098 }
955994e1
UD
1099 }
1100 else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
1101 || *p == L('!')) && p[1] == L('('))
1102 /* Remember the nesting level. */
1103 ++level;
1104 else if (*p == L(')'))
1105 {
1106 if (level-- == 0)
1107 {
1108 /* This means we found the end of the pattern. */
1109#define NEW_PATTERN \
821a6bb4 1110 struct patternlist *newp; \
f15ce4d8
UD
1111 size_t slen = (opt == L('?') || opt == L('@') \
1112 ? pattern_len : (p - startp + 1)); \
1113 slen = sizeof (struct patternlist) + (slen * sizeof (CHAR)); \
1114 int malloced = ! __libc_use_alloca (alloca_used + slen); \
1115 if (__builtin_expect (malloced, 0)) \
1116 { \
1117 newp = alloca_account (slen, alloca_used); \
1118 any_malloced = 1; \
1119 } \
821a6bb4 1120 else \
f15ce4d8
UD
1121 { \
1122 newp = malloc (slen); \
1123 if (newp == NULL) \
1124 { \
1125 retval = -2; \
1126 goto out; \
1127 } \
1128 } \
955994e1 1129 newp->next = NULL; \
f15ce4d8
UD
1130 newp->malloced = malloced; \
1131 *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
955994e1
UD
1132 *lastp = newp; \
1133 lastp = &newp->next
1134 NEW_PATTERN;
1135 }
1136 }
1137 else if (*p == L('|'))
1138 {
1139 if (level == 0)
1140 {
1141 NEW_PATTERN;
1142 startp = p + 1;
1143 }
1144 }
1145 assert (list != NULL);
1146 assert (p[-1] == L(')'));
817a51e2 1147#undef NEW_PATTERN
955994e1
UD
1148
1149 switch (opt)
1150 {
1151 case L('*'):
f15ce4d8
UD
1152 if (FCT (p, string, string_end, no_leading_period, flags, NULL,
1153 alloca_used) == 0)
1154 goto success;
955994e1
UD
1155 /* FALLTHROUGH */
1156
1157 case L('+'):
1158 do
1159 {
1160 for (rs = string; rs <= string_end; ++rs)
1161 /* First match the prefix with the current pattern with the
1162 current pattern. */
1163 if (FCT (list->str, string, rs, no_leading_period,
9700b039 1164 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
f15ce4d8 1165 NULL, alloca_used) == 0
955994e1
UD
1166 /* This was successful. Now match the rest with the rest
1167 of the pattern. */
1168 && (FCT (p, rs, string_end,
1169 rs == string
1170 ? no_leading_period
1171 : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
1172 flags & FNM_FILE_NAME
f15ce4d8 1173 ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
955994e1
UD
1174 /* This didn't work. Try the whole pattern. */
1175 || (rs != string
1176 && FCT (pattern - 1, rs, string_end,
1177 rs == string
1178 ? no_leading_period
1179 : (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
1180 ? 1 : 0),
1181 flags & FNM_FILE_NAME
f15ce4d8
UD
1182 ? flags : flags & ~FNM_PERIOD, NULL,
1183 alloca_used) == 0)))
955994e1 1184 /* It worked. Signal success. */
f15ce4d8 1185 goto success;
955994e1
UD
1186 }
1187 while ((list = list->next) != NULL);
1188
1189 /* None of the patterns lead to a match. */
f15ce4d8
UD
1190 retval = FNM_NOMATCH;
1191 break;
955994e1
UD
1192
1193 case L('?'):
f15ce4d8
UD
1194 if (FCT (p, string, string_end, no_leading_period, flags, NULL,
1195 alloca_used) == 0)
1196 goto success;
955994e1
UD
1197 /* FALLTHROUGH */
1198
1199 case L('@'):
1200 do
821a6bb4
UD
1201 /* I cannot believe it but `strcat' is actually acceptable
1202 here. Match the entire string with the prefix from the
1203 pattern list and the rest of the pattern following the
1204 pattern list. */
1205 if (FCT (STRCAT (list->str, p), string, string_end,
1206 no_leading_period,
9700b039 1207 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
f15ce4d8 1208 NULL, alloca_used) == 0)
821a6bb4 1209 /* It worked. Signal success. */
f15ce4d8 1210 goto success;
955994e1
UD
1211 while ((list = list->next) != NULL);
1212
1213 /* None of the patterns lead to a match. */
f15ce4d8
UD
1214 retval = FNM_NOMATCH;
1215 break;
955994e1
UD
1216
1217 case L('!'):
1218 for (rs = string; rs <= string_end; ++rs)
1219 {
1220 struct patternlist *runp;
1221
1222 for (runp = list; runp != NULL; runp = runp->next)
1223 if (FCT (runp->str, string, rs, no_leading_period,
9700b039 1224 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
f15ce4d8 1225 NULL, alloca_used) == 0)
955994e1
UD
1226 break;
1227
1228 /* If none of the patterns matched see whether the rest does. */
1229 if (runp == NULL
1230 && (FCT (p, rs, string_end,
1231 rs == string
1232 ? no_leading_period
1233 : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
9700b039 1234 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
f15ce4d8 1235 NULL, alloca_used) == 0))
955994e1 1236 /* This is successful. */
f15ce4d8 1237 goto success;
955994e1
UD
1238 }
1239
1240 /* None of the patterns together with the rest of the pattern
1241 lead to a match. */
f15ce4d8
UD
1242 retval = FNM_NOMATCH;
1243 break;
955994e1
UD
1244
1245 default:
1246 assert (! "Invalid extended matching operator");
f15ce4d8 1247 retval = -1;
955994e1
UD
1248 break;
1249 }
1250
f15ce4d8
UD
1251 success:
1252 out:
1253 if (any_malloced)
1254 while (list != NULL)
1255 {
1256 struct patternlist *old = list;
1257 list = list->next;
1258 if (old->malloced)
1259 free (old);
1260 }
1261
1262 return retval;
955994e1
UD
1263}
1264
1265
1fc82a56
UD
1266#undef FOLD
1267#undef CHAR
1268#undef UCHAR
955994e1 1269#undef INT
1fc82a56 1270#undef FCT
955994e1
UD
1271#undef EXT
1272#undef END
9700b039 1273#undef STRUCT
955994e1
UD
1274#undef MEMPCPY
1275#undef MEMCHR
1827fc4c 1276#undef STRCOLL
a986484f
UD
1277#undef STRLEN
1278#undef STRCAT
1fc82a56 1279#undef L
ea6eb383 1280#undef BTOWC