~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to misc/fnmatch.c

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1991-1993, 1996-1999, 2000 Free Software Foundation, Inc.
 
2
   This file is part of the GNU C Library.
 
3
 
 
4
   This library is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU Library General Public License as
 
6
   published by the Free Software Foundation; either version 2 of the
 
7
   License, or (at your option) any later version.
 
8
 
 
9
   This library is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
   Library General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU Library General Public
 
15
   License along with this library; see the file COPYING.LIB.  If not,
 
16
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
   Boston, MA 02111-1307, USA.  */
 
18
 
 
19
# include "system.h"
 
20
 
 
21
/* Find the first occurrence of C in S or the final NUL byte.  */
 
22
static inline char *
 
23
__strchrnul (s, c)
 
24
     const char *s;
 
25
     int c;
 
26
{
 
27
  const unsigned char *char_ptr;
 
28
  const unsigned long int *longword_ptr;
 
29
  unsigned long int longword, magic_bits, charmask;
 
30
 
 
31
  c = (unsigned char) c;
 
32
 
 
33
  /* Handle the first few characters by reading one character at a time.
 
34
     Do this until CHAR_PTR is aligned on a longword boundary.  */
 
35
  for (char_ptr = s; ((unsigned long int) char_ptr
 
36
                      & (sizeof (longword) - 1)) != 0;
 
37
       ++char_ptr)
 
38
    if (*char_ptr == c || *char_ptr == '\0')
 
39
      return (void *) char_ptr;
 
40
 
 
41
  /* All these elucidatory comments refer to 4-byte longwords,
 
42
     but the theory applies equally well to 8-byte longwords.  */
 
43
 
 
44
  longword_ptr = (unsigned long int *) char_ptr;
 
45
 
 
46
  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
 
47
     the "holes."  Note that there is a hole just to the left of
 
48
     each byte, with an extra at the end:
 
49
 
 
50
     bits:  01111110 11111110 11111110 11111111
 
51
     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
 
52
 
 
53
     The 1-bits make sure that carries propagate to the next 0-bit.
 
54
     The 0-bits provide holes for carries to fall into.  */
 
55
  switch (sizeof (longword))
 
56
    {
 
57
    case 4: magic_bits = 0x7efefeffL; break;
 
58
    case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;
 
59
    default:
 
60
      abort ();
 
61
    }
 
62
 
 
63
  /* Set up a longword, each of whose bytes is C.  */
 
64
  charmask = c | (c << 8);
 
65
  charmask |= charmask << 16;
 
66
  if (sizeof (longword) > 4)
 
67
    /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
 
68
    charmask |= (charmask << 16) << 16;
 
69
  if (sizeof (longword) > 8)
 
70
    abort ();
 
71
 
 
72
  /* Instead of the traditional loop which tests each character,
 
73
     we will test a longword at a time.  The tricky part is testing
 
74
     if *any of the four* bytes in the longword in question are zero.  */
 
75
  for (;;)
 
76
    {
 
77
      /* We tentatively exit the loop if adding MAGIC_BITS to
 
78
         LONGWORD fails to change any of the hole bits of LONGWORD.
 
79
 
 
80
         1) Is this safe?  Will it catch all the zero bytes?
 
81
         Suppose there is a byte with all zeros.  Any carry bits
 
82
         propagating from its left will fall into the hole at its
 
83
         least significant bit and stop.  Since there will be no
 
84
         carry from its most significant bit, the LSB of the
 
85
         byte to the left will be unchanged, and the zero will be
 
86
         detected.
 
87
 
 
88
         2) Is this worthwhile?  Will it ignore everything except
 
89
         zero bytes?  Suppose every byte of LONGWORD has a bit set
 
90
         somewhere.  There will be a carry into bit 8.  If bit 8
 
91
         is set, this will carry into bit 16.  If bit 8 is clear,
 
92
         one of bits 9-15 must be set, so there will be a carry
 
93
         into bit 16.  Similarly, there will be a carry into bit
 
94
         24.  If one of bits 24-30 is set, there will be a carry
 
95
         into bit 31, so all of the hole bits will be changed.
 
96
 
 
97
         The one misfire occurs when bits 24-30 are clear and bit
 
98
         31 is set; in this case, the hole at bit 31 is not
 
99
         changed.  If we had access to the processor carry flag,
 
100
         we could close this loophole by putting the fourth hole
 
101
         at bit 32!
 
102
 
 
103
         So it ignores everything except 128's, when they're aligned
 
104
         properly.
 
105
 
 
106
         3) But wait!  Aren't we looking for C as well as zero?
 
107
         Good point.  So what we do is XOR LONGWORD with a longword,
 
108
         each of whose bytes is C.  This turns each byte that is C
 
109
         into a zero.  */
 
110
 
 
111
      longword = *longword_ptr++;
 
112
 
 
113
      /* Add MAGIC_BITS to LONGWORD.  */
 
114
      if ((((longword + magic_bits)
 
115
 
 
116
            /* Set those bits that were unchanged by the addition.  */
 
117
            ^ ~longword)
 
118
 
 
119
           /* Look at only the hole bits.  If any of the hole bits
 
120
              are unchanged, most likely one of the bytes was a
 
121
              zero.  */
 
122
           & ~magic_bits) != 0 ||
 
123
 
 
124
          /* That caught zeroes.  Now test for C.  */
 
125
          ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))
 
126
           & ~magic_bits) != 0)
 
127
        {
 
128
          /* Which of the bytes was C or zero?
 
129
             If none of them were, it was a misfire; continue the search.  */
 
130
 
 
131
          const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
 
132
 
 
133
          if (*cp == c || *cp == '\0')
 
134
            return (char *) cp;
 
135
          if (*++cp == c || *cp == '\0')
 
136
            return (char *) cp;
 
137
          if (*++cp == c || *cp == '\0')
 
138
            return (char *) cp;
 
139
          if (*++cp == c || *cp == '\0')
 
140
            return (char *) cp;
 
141
          if (sizeof (longword) > 4)
 
142
            {
 
143
              if (*++cp == c || *cp == '\0')
 
144
                return (char *) cp;
 
145
              if (*++cp == c || *cp == '\0')
 
146
                return (char *) cp;
 
147
              if (*++cp == c || *cp == '\0')
 
148
                return (char *) cp;
 
149
              if (*++cp == c || *cp == '\0')
 
150
                return (char *) cp;
 
151
            }
 
152
        }
 
153
    }
 
154
 
 
155
  /* This should never happen.  */
 
156
  return NULL;
 
157
}
 
158
 
 
159
/* For platform which support the ISO C amendement 1 functionality we
 
160
   support user defined character classes.  */
 
161
#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 
162
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
 
163
# include <wchar.h>
 
164
# include <wctype.h>
 
165
#endif
 
166
 
 
167
/* Comment out all this code if we are using the GNU C Library, and are not
 
168
   actually compiling the library itself.  This code is part of the GNU C
 
169
   Library, but also included in many other GNU distributions.  Compiling
 
170
   and linking in this code is a waste when using the GNU C library
 
171
   (especially if it is a shared library).  Rather than having every GNU
 
172
   program understand `configure --with-gnu-libc' and omit the object files,
 
173
   it is simpler to just do this in the source for each such file.  */
 
174
 
 
175
#if defined _LIBC || !defined __GNU_LIBRARY__
 
176
 
 
177
 
 
178
# if defined STDC_HEADERS || !defined isascii
 
179
#  define ISASCII(c) 1
 
180
# else
 
181
#  define ISASCII(c) isascii(c)
 
182
# endif
 
183
 
 
184
#ifdef isblank
 
185
# define ISBLANK(c) (ISASCII (c) && isblank (c))
 
186
#else
 
187
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
 
188
#endif
 
189
#ifdef isgraph
 
190
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
 
191
#else
 
192
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
 
193
#endif
 
194
 
 
195
#define ISPRINT(c) (ISASCII (c) && isprint (c))
 
196
#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
 
197
#define ISALNUM(c) (ISASCII (c) && isalnum (c))
 
198
#define ISALPHA(c) (ISASCII (c) && isalpha (c))
 
199
#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
 
200
#define ISLOWER(c) (ISASCII (c) && islower (c))
 
201
#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
 
202
#define ISSPACE(c) (ISASCII (c) && isspace (c))
 
203
#define ISUPPER(c) (ISASCII (c) && isupper (c))
 
204
#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
 
205
 
 
206
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
 
207
 
 
208
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 
209
/* The GNU C library provides support for user-defined character classes
 
210
   and the functions from ISO C amendement 1.  */
 
211
#  ifdef CHARCLASS_NAME_MAX
 
212
#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
 
213
#  else
 
214
/* This shouldn't happen but some implementation might still have this
 
215
   problem.  Use a reasonable default value.  */
 
216
#   define CHAR_CLASS_MAX_LENGTH 256
 
217
#  endif
 
218
 
 
219
#  ifdef _LIBC
 
220
#   define IS_CHAR_CLASS(string) __wctype (string)
 
221
#  else
 
222
#   define IS_CHAR_CLASS(string) wctype (string)
 
223
#  endif
 
224
# else
 
225
#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
 
226
 
 
227
#  define IS_CHAR_CLASS(string)                                               \
 
228
   (STREQ (string, "alpha") || STREQ (string, "upper")                        \
 
229
    || STREQ (string, "lower") || STREQ (string, "digit")                     \
 
230
    || STREQ (string, "alnum") || STREQ (string, "xdigit")                    \
 
231
    || STREQ (string, "space") || STREQ (string, "print")                     \
 
232
    || STREQ (string, "punct") || STREQ (string, "graph")                     \
 
233
    || STREQ (string, "cntrl") || STREQ (string, "blank"))
 
234
# endif
 
235
 
 
236
/* Avoid depending on library functions or files
 
237
   whose names are inconsistent.  */
 
238
 
 
239
# if !defined _LIBC && !defined getenv
 
240
extern char *getenv ();
 
241
# endif
 
242
 
 
243
# ifndef errno
 
244
extern int errno;
 
245
# endif
 
246
 
 
247
/* Match STRING against the filename pattern PATTERN, returning zero if
 
248
   it matches, nonzero if not.  */
 
249
static int
 
250
#ifdef _LIBC
 
251
internal_function
 
252
#endif
 
253
internal_fnmatch (const char *pattern, const char *string,
 
254
                  int no_leading_period, int flags)
 
255
{
 
256
  register const char *p = pattern, *n = string;
 
257
  register unsigned char c;
 
258
 
 
259
/* Note that this evaluates C many times.  */
 
260
# ifdef _LIBC
 
261
#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
 
262
# else
 
263
#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
 
264
# endif
 
265
 
 
266
  while ((c = *p++) != '\0')
 
267
    {
 
268
      c = FOLD (c);
 
269
 
 
270
      switch (c)
 
271
        {
 
272
        case '?':
 
273
          if (*n == '\0')
 
274
            return FNM_NOMATCH;
 
275
          else if (*n == '/' && (flags & FNM_FILE_NAME))
 
276
            return FNM_NOMATCH;
 
277
          else if (*n == '.' && no_leading_period
 
278
                   && (n == string
 
279
                       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
 
280
            return FNM_NOMATCH;
 
281
          break;
 
282
 
 
283
        case '\\':
 
284
          if (!(flags & FNM_NOESCAPE))
 
285
            {
 
286
              c = *p++;
 
287
              if (c == '\0')
 
288
                /* Trailing \ loses.  */
 
289
                return FNM_NOMATCH;
 
290
              c = FOLD (c);
 
291
            }
 
292
          if (FOLD ((unsigned char) *n) != c)
 
293
            return FNM_NOMATCH;
 
294
          break;
 
295
 
 
296
        case '*':
 
297
          if (*n == '.' && no_leading_period
 
298
              && (n == string
 
299
                  || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
 
300
            return FNM_NOMATCH;
 
301
 
 
302
          for (c = *p++; c == '?' || c == '*'; c = *p++)
 
303
            {
 
304
              if (*n == '/' && (flags & FNM_FILE_NAME))
 
305
                /* A slash does not match a wildcard under FNM_FILE_NAME.  */
 
306
                return FNM_NOMATCH;
 
307
              else if (c == '?')
 
308
                {
 
309
                  /* A ? needs to match one character.  */
 
310
                  if (*n == '\0')
 
311
                    /* There isn't another character; no match.  */
 
312
                    return FNM_NOMATCH;
 
313
                  else
 
314
                    /* One character of the string is consumed in matching
 
315
                       this ? wildcard, so *??? won't match if there are
 
316
                       less than three characters.  */
 
317
                    ++n;
 
318
                }
 
319
            }
 
320
 
 
321
          if (c == '\0')
 
322
            /* The wildcard(s) is/are the last element of the pattern.
 
323
               If the name is a file name and contains another slash
 
324
               this does mean it cannot match.  If the FNM_LEADING_DIR
 
325
               flag is set and exactly one slash is following, we have
 
326
               a match.  */
 
327
            {
 
328
              int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
 
329
 
 
330
              if (flags & FNM_FILE_NAME)
 
331
                {
 
332
                  const char *slashp = strchr (n, '/');
 
333
 
 
334
                  if (flags & FNM_LEADING_DIR)
 
335
                    {
 
336
                      if (slashp != NULL
 
337
                          && strchr (slashp + 1, '/') == NULL)
 
338
                        result = 0;
 
339
                    }
 
340
                  else
 
341
                    {
 
342
                      if (slashp == NULL)
 
343
                        result = 0;
 
344
                    }
 
345
                }
 
346
 
 
347
              return result;
 
348
            }
 
349
          else
 
350
            {
 
351
              const char *endp;
 
352
 
 
353
              endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
 
354
 
 
355
              if (c == '[')
 
356
                {
 
357
                  int flags2 = ((flags & FNM_FILE_NAME)
 
358
                                ? flags : (flags & ~FNM_PERIOD));
 
359
 
 
360
                  for (--p; n < endp; ++n)
 
361
                    if (internal_fnmatch (p, n,
 
362
                                          (no_leading_period
 
363
                                           && (n == string
 
364
                                               || (n[-1] == '/'
 
365
                                                   && (flags
 
366
                                                       & FNM_FILE_NAME)))),
 
367
                                          flags2)
 
368
                        == 0)
 
369
                      return 0;
 
370
                }
 
371
              else if (c == '/' && (flags & FNM_FILE_NAME))
 
372
                {
 
373
                  while (*n != '\0' && *n != '/')
 
374
                    ++n;
 
375
                  if (*n == '/'
 
376
                      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
 
377
                                            flags) == 0))
 
378
                    return 0;
 
379
                }
 
380
              else
 
381
                {
 
382
                  int flags2 = ((flags & FNM_FILE_NAME)
 
383
                                ? flags : (flags & ~FNM_PERIOD));
 
384
 
 
385
                  if (c == '\\' && !(flags & FNM_NOESCAPE))
 
386
                    c = *p;
 
387
                  c = FOLD (c);
 
388
                  for (--p; n < endp; ++n)
 
389
                    if (FOLD ((unsigned char) *n) == c
 
390
                        && (internal_fnmatch (p, n,
 
391
                                              (no_leading_period
 
392
                                               && (n == string
 
393
                                                   || (n[-1] == '/'
 
394
                                                       && (flags
 
395
                                                           & FNM_FILE_NAME)))),
 
396
                                              flags2) == 0))
 
397
                      return 0;
 
398
                }
 
399
            }
 
400
 
 
401
          /* If we come here no match is possible with the wildcard.  */
 
402
          return FNM_NOMATCH;
 
403
 
 
404
        case '[':
 
405
          {
 
406
            /* Nonzero if the sense of the character class is inverted.  */
 
407
            static int posixly_correct;
 
408
            register int not;
 
409
            char cold;
 
410
 
 
411
            if (posixly_correct == 0)
 
412
              posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
 
413
 
 
414
            if (*n == '\0')
 
415
              return FNM_NOMATCH;
 
416
 
 
417
            if (*n == '.' && no_leading_period && (n == string
 
418
                                                   || (n[-1] == '/'
 
419
                                                       && (flags
 
420
                                                           & FNM_FILE_NAME))))
 
421
              return FNM_NOMATCH;
 
422
 
 
423
            if (*n == '/' && (flags & FNM_FILE_NAME))
 
424
              /* `/' cannot be matched.  */
 
425
              return FNM_NOMATCH;
 
426
 
 
427
            not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
 
428
            if (not)
 
429
              ++p;
 
430
 
 
431
            c = *p++;
 
432
            for (;;)
 
433
              {
 
434
                unsigned char fn = FOLD ((unsigned char) *n);
 
435
 
 
436
                if (!(flags & FNM_NOESCAPE) && c == '\\')
 
437
                  {
 
438
                    if (*p == '\0')
 
439
                      return FNM_NOMATCH;
 
440
                    c = FOLD ((unsigned char) *p);
 
441
                    ++p;
 
442
 
 
443
                    if (c == fn)
 
444
                      goto matched;
 
445
                  }
 
446
                else if (c == '[' && *p == ':')
 
447
                  {
 
448
                    /* Leave room for the null.  */
 
449
                    char str[CHAR_CLASS_MAX_LENGTH + 1];
 
450
                    size_t c1 = 0;
 
451
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 
452
                    wctype_t wt;
 
453
# endif
 
454
                    const char *startp = p;
 
455
 
 
456
                    for (;;)
 
457
                      {
 
458
                        if (c1 == CHAR_CLASS_MAX_LENGTH)
 
459
                          /* The name is too long and therefore the pattern
 
460
                             is ill-formed.  */
 
461
                          return FNM_NOMATCH;
 
462
 
 
463
                        c = *++p;
 
464
                        if (c == ':' && p[1] == ']')
 
465
                          {
 
466
                            p += 2;
 
467
                            break;
 
468
                          }
 
469
                        if (c < 'a' || c >= 'z')
 
470
                          {
 
471
                            /* This cannot possibly be a character class name.
 
472
                               Match it as a normal range.  */
 
473
                            p = startp;
 
474
                            c = '[';
 
475
                            goto normal_bracket;
 
476
                          }
 
477
                        str[c1++] = c;
 
478
                      }
 
479
                    str[c1] = '\0';
 
480
 
 
481
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 
482
                    wt = IS_CHAR_CLASS (str);
 
483
                    if (wt == 0)
 
484
                      /* Invalid character class name.  */
 
485
                      return FNM_NOMATCH;
 
486
 
 
487
                    if (__iswctype (__btowc ((unsigned char) *n), wt))
 
488
                      goto matched;
 
489
# else
 
490
                    if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
 
491
                        || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
 
492
                        || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
 
493
                        || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
 
494
                        || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
 
495
                        || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
 
496
                        || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
 
497
                        || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
 
498
                        || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
 
499
                        || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
 
500
                        || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
 
501
                        || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
 
502
                      goto matched;
 
503
# endif
 
504
                  }
 
505
                else if (c == '\0')
 
506
                  /* [ (unterminated) loses.  */
 
507
                  return FNM_NOMATCH;
 
508
                else
 
509
                  {
 
510
                    c = FOLD (c);
 
511
                  normal_bracket:
 
512
                    if (c == fn)
 
513
                      goto matched;
 
514
 
 
515
                    cold = c;
 
516
                    c = *p++;
 
517
 
 
518
                    if (c == '-' && *p != ']')
 
519
                      {
 
520
                        /* It is a range.  */
 
521
                        char lo[2];
 
522
                        char fc[2];
 
523
                        unsigned char cend = *p++;
 
524
                        if (!(flags & FNM_NOESCAPE) && cend == '\\')
 
525
                          cend = *p++;
 
526
                        if (cend == '\0')
 
527
                          return FNM_NOMATCH;
 
528
 
 
529
                        lo[0] = cold;
 
530
                        lo[1] = '\0';
 
531
                        fc[0] = fn;
 
532
                        fc[1] = '\0';
 
533
                        if (strcoll (lo, fc) <= 0)
 
534
                          {
 
535
                            char hi[2];
 
536
                            hi[0] = FOLD (cend);
 
537
                            hi[1] = '\0';
 
538
                            if (strcoll (fc, hi) <= 0)
 
539
                              goto matched;
 
540
                          }
 
541
 
 
542
                        c = *p++;
 
543
                      }
 
544
                  }
 
545
 
 
546
                if (c == ']')
 
547
                  break;
 
548
              }
 
549
 
 
550
            if (!not)
 
551
              return FNM_NOMATCH;
 
552
            break;
 
553
 
 
554
          matched:
 
555
            /* Skip the rest of the [...] that already matched.  */
 
556
            while (c != ']')
 
557
              {
 
558
                if (c == '\0')
 
559
                  /* [... (unterminated) loses.  */
 
560
                  return FNM_NOMATCH;
 
561
 
 
562
                c = *p++;
 
563
                if (!(flags & FNM_NOESCAPE) && c == '\\')
 
564
                  {
 
565
                    if (*p == '\0')
 
566
                      return FNM_NOMATCH;
 
567
                    /* XXX 1003.2d11 is unclear if this is right.  */
 
568
                    ++p;
 
569
                  }
 
570
                else if (c == '[' && *p == ':')
 
571
                  {
 
572
                    do
 
573
                      if (*++p == '\0')
 
574
                        return FNM_NOMATCH;
 
575
                    while (*p != ':' || p[1] == ']');
 
576
                    p += 2;
 
577
                    c = *p;
 
578
                  }
 
579
              }
 
580
            if (not)
 
581
              return FNM_NOMATCH;
 
582
          }
 
583
          break;
 
584
 
 
585
        default:
 
586
          if (c != FOLD ((unsigned char) *n))
 
587
            return FNM_NOMATCH;
 
588
        }
 
589
 
 
590
      ++n;
 
591
    }
 
592
 
 
593
  if (*n == '\0')
 
594
    return 0;
 
595
 
 
596
  if ((flags & FNM_LEADING_DIR) && *n == '/')
 
597
    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
 
598
    return 0;
 
599
 
 
600
  return FNM_NOMATCH;
 
601
 
 
602
# undef FOLD
 
603
}
 
604
 
 
605
 
 
606
int
 
607
fnmatch (pattern, string, flags)
 
608
     const char *pattern;
 
609
     const char *string;
 
610
     int flags;
 
611
{
 
612
  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
 
613
}
 
614
 
 
615
#endif  /* _LIBC or not __GNU_LIBRARY__.  */