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