~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to gnulib/fnmatch_loop.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

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