Blame lib/fnmatch_loop.c

Packit Service fdd496
/* Copyright (C) 1991-1993, 1996-2006, 2009-2017 Free Software Foundation, Inc.
Packit Service fdd496
   This file is part of the GNU C Library.
Packit Service fdd496
Packit Service fdd496
   This program is free software; you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3, or (at your option)
Packit Service fdd496
   any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
/* Match STRING against the file name pattern PATTERN, returning zero if
Packit Service fdd496
   it matches, nonzero if not.  */
Packit Service fdd496
static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
Packit Service fdd496
                const CHAR *string_end, bool no_leading_period, int flags)
Packit Service fdd496
     internal_function;
Packit Service fdd496
static const CHAR *END (const CHAR *patternp) internal_function;
Packit Service fdd496
Packit Service fdd496
static int
Packit Service fdd496
internal_function
Packit Service fdd496
FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
Packit Service fdd496
     bool no_leading_period, int flags)
Packit Service fdd496
{
Packit Service fdd496
  register const CHAR *p = pattern, *n = string;
Packit Service fdd496
  register UCHAR c;
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
# if WIDE_CHAR_VERSION
Packit Service fdd496
  const char *collseq = (const char *)
Packit Service fdd496
    _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
Packit Service fdd496
# else
Packit Service fdd496
  const UCHAR *collseq = (const UCHAR *)
Packit Service fdd496
    _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
Packit Service fdd496
# endif
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
  while ((c = *p++) != L_('\0'))
Packit Service fdd496
    {
Packit Service fdd496
      bool new_no_leading_period = false;
Packit Service fdd496
      c = FOLD (c);
Packit Service fdd496
Packit Service fdd496
      switch (c)
Packit Service fdd496
        {
Packit Service fdd496
        case L_('?'):
Packit Service fdd496
          if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
Packit Service fdd496
            {
Packit Service fdd496
              int res;
Packit Service fdd496
Packit Service fdd496
              res = EXT (c, p, n, string_end, no_leading_period,
Packit Service fdd496
                         flags);
Packit Service fdd496
              if (res != -1)
Packit Service fdd496
                return res;
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          if (n == string_end)
Packit Service fdd496
            return FNM_NOMATCH;
Packit Service fdd496
          else if (*n == L_('/') && (flags & FNM_FILE_NAME))
Packit Service fdd496
            return FNM_NOMATCH;
Packit Service fdd496
          else if (*n == L_('.') && no_leading_period)
Packit Service fdd496
            return FNM_NOMATCH;
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('\\'):
Packit Service fdd496
          if (!(flags & FNM_NOESCAPE))
Packit Service fdd496
            {
Packit Service fdd496
              c = *p++;
Packit Service fdd496
              if (c == L_('\0'))
Packit Service fdd496
                /* Trailing \ loses.  */
Packit Service fdd496
                return FNM_NOMATCH;
Packit Service fdd496
              c = FOLD (c);
Packit Service fdd496
            }
Packit Service fdd496
          if (n == string_end || FOLD ((UCHAR) *n) != c)
Packit Service fdd496
            return FNM_NOMATCH;
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('*'):
Packit Service fdd496
          if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
Packit Service fdd496
            {
Packit Service fdd496
              int res;
Packit Service fdd496
Packit Service fdd496
              res = EXT (c, p, n, string_end, no_leading_period,
Packit Service fdd496
                         flags);
Packit Service fdd496
              if (res != -1)
Packit Service fdd496
                return res;
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          if (n != string_end && *n == L_('.') && no_leading_period)
Packit Service fdd496
            return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
          for (c = *p++; c == L_('?') || c == L_('*'); c = *p++)
Packit Service fdd496
            {
Packit Service fdd496
              if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0)
Packit Service fdd496
                {
Packit Service fdd496
                  const CHAR *endp = END (p);
Packit Service fdd496
                  if (endp != p)
Packit Service fdd496
                    {
Packit Service fdd496
                      /* This is a pattern.  Skip over it.  */
Packit Service fdd496
                      p = endp;
Packit Service fdd496
                      continue;
Packit Service fdd496
                    }
Packit Service fdd496
                }
Packit Service fdd496
Packit Service fdd496
              if (c == L_('?'))
Packit Service fdd496
                {
Packit Service fdd496
                  /* A ? needs to match one character.  */
Packit Service fdd496
                  if (n == string_end)
Packit Service fdd496
                    /* There isn't another character; no match.  */
Packit Service fdd496
                    return FNM_NOMATCH;
Packit Service fdd496
                  else if (*n == L_('/')
Packit Service fdd496
                           && __builtin_expect (flags & FNM_FILE_NAME, 0))
Packit Service fdd496
                    /* A slash does not match a wildcard under
Packit Service fdd496
                       FNM_FILE_NAME.  */
Packit Service fdd496
                    return FNM_NOMATCH;
Packit Service fdd496
                  else
Packit Service fdd496
                    /* One character of the string is consumed in matching
Packit Service fdd496
                       this ? wildcard, so *??? won't match if there are
Packit Service fdd496
                       less than three characters.  */
Packit Service fdd496
                    ++n;
Packit Service fdd496
                }
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          if (c == L_('\0'))
Packit Service fdd496
            /* The wildcard(s) is/are the last element of the pattern.
Packit Service fdd496
               If the name is a file name and contains another slash
Packit Service fdd496
               this means it cannot match, unless the FNM_LEADING_DIR
Packit Service fdd496
               flag is set.  */
Packit Service fdd496
            {
Packit Service fdd496
              int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
              if (flags & FNM_FILE_NAME)
Packit Service fdd496
                {
Packit Service fdd496
                  if (flags & FNM_LEADING_DIR)
Packit Service fdd496
                    result = 0;
Packit Service fdd496
                  else
Packit Service fdd496
                    {
Packit Service fdd496
                      if (MEMCHR (n, L_('/'), string_end - n) == NULL)
Packit Service fdd496
                        result = 0;
Packit Service fdd496
                    }
Packit Service fdd496
                }
Packit Service fdd496
Packit Service fdd496
              return result;
Packit Service fdd496
            }
Packit Service fdd496
          else
Packit Service fdd496
            {
Packit Service fdd496
              const CHAR *endp;
Packit Service fdd496
Packit Service fdd496
              endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'),
Packit Service fdd496
                             string_end - n);
Packit Service fdd496
              if (endp == NULL)
Packit Service fdd496
                endp = string_end;
Packit Service fdd496
Packit Service fdd496
              if (c == L_('[')
Packit Service fdd496
                  || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
Packit Service fdd496
                      && (c == L_('@') || c == L_('+') || c == L_('!'))
Packit Service fdd496
                      && *p == L_('(')))
Packit Service fdd496
                {
Packit Service fdd496
                  int flags2 = ((flags & FNM_FILE_NAME)
Packit Service fdd496
                                ? flags : (flags & ~FNM_PERIOD));
Packit Service fdd496
                  bool no_leading_period2 = no_leading_period;
Packit Service fdd496
Packit Service fdd496
                  for (--p; n < endp; ++n, no_leading_period2 = false)
Packit Service fdd496
                    if (FCT (p, n, string_end, no_leading_period2, flags2)
Packit Service fdd496
                        == 0)
Packit Service fdd496
                      return 0;
Packit Service fdd496
                }
Packit Service fdd496
              else if (c == L_('/') && (flags & FNM_FILE_NAME))
Packit Service fdd496
                {
Packit Service fdd496
                  while (n < string_end && *n != L_('/'))
Packit Service fdd496
                    ++n;
Packit Service fdd496
                  if (n < string_end && *n == L_('/')
Packit Service fdd496
                      && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags)
Packit Service fdd496
                          == 0))
Packit Service fdd496
                    return 0;
Packit Service fdd496
                }
Packit Service fdd496
              else
Packit Service fdd496
                {
Packit Service fdd496
                  int flags2 = ((flags & FNM_FILE_NAME)
Packit Service fdd496
                                ? flags : (flags & ~FNM_PERIOD));
Packit Service fdd496
                  int no_leading_period2 = no_leading_period;
Packit Service fdd496
Packit Service fdd496
                  if (c == L_('\\') && !(flags & FNM_NOESCAPE))
Packit Service fdd496
                    c = *p;
Packit Service fdd496
                  c = FOLD (c);
Packit Service fdd496
                  for (--p; n < endp; ++n, no_leading_period2 = false)
Packit Service fdd496
                    if (FOLD ((UCHAR) *n) == c
Packit Service fdd496
                        && (FCT (p, n, string_end, no_leading_period2, flags2)
Packit Service fdd496
                            == 0))
Packit Service fdd496
                      return 0;
Packit Service fdd496
                }
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          /* If we come here no match is possible with the wildcard.  */
Packit Service fdd496
          return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
        case L_('['):
Packit Service fdd496
          {
Packit Service fdd496
            /* Nonzero if the sense of the character class is inverted.  */
Packit Service fdd496
            const CHAR *p_init = p;
Packit Service fdd496
            const CHAR *n_init = n;
Packit Service fdd496
            register bool not;
Packit Service fdd496
            CHAR cold;
Packit Service fdd496
            UCHAR fn;
Packit Service fdd496
Packit Service fdd496
            if (posixly_correct == 0)
Packit Service fdd496
              posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
Packit Service fdd496
Packit Service fdd496
            if (n == string_end)
Packit Service fdd496
              return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
            if (*n == L_('.') && no_leading_period)
Packit Service fdd496
              return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
            if (*n == L_('/') && (flags & FNM_FILE_NAME))
Packit Service fdd496
              /* '/' cannot be matched.  */
Packit Service fdd496
              return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
            not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^')));
Packit Service fdd496
            if (not)
Packit Service fdd496
              ++p;
Packit Service fdd496
Packit Service fdd496
            fn = FOLD ((UCHAR) *n);
Packit Service fdd496
Packit Service fdd496
            c = *p++;
Packit Service fdd496
            for (;;)
Packit Service fdd496
              {
Packit Service fdd496
		bool is_range = false;
Packit Service fdd496
Packit Service fdd496
                if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
Packit Service fdd496
                  {
Packit Service fdd496
                    if (*p == L_('\0'))
Packit Service fdd496
                      return FNM_NOMATCH;
Packit Service fdd496
                    c = FOLD ((UCHAR) *p);
Packit Service fdd496
                    ++p;
Packit Service fdd496
Packit Service fdd496
                    goto normal_bracket;
Packit Service fdd496
                  }
Packit Service fdd496
                else if (c == L_('[') && *p == L_(':'))
Packit Service fdd496
                  {
Packit Service fdd496
                    /* Leave room for the null.  */
Packit Service fdd496
                    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
Packit Service fdd496
                    size_t c1 = 0;
Packit Service fdd496
#if defined _LIBC || WIDE_CHAR_SUPPORT
Packit Service fdd496
                    wctype_t wt;
Packit Service fdd496
#endif
Packit Service fdd496
                    const CHAR *startp = p;
Packit Service fdd496
Packit Service fdd496
                    for (;;)
Packit Service fdd496
                      {
Packit Service fdd496
                        if (c1 == CHAR_CLASS_MAX_LENGTH)
Packit Service fdd496
                          /* The name is too long and therefore the pattern
Packit Service fdd496
                             is ill-formed.  */
Packit Service fdd496
                          return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
                        c = *++p;
Packit Service fdd496
                        if (c == L_(':') && p[1] == L_(']'))
Packit Service fdd496
                          {
Packit Service fdd496
                            p += 2;
Packit Service fdd496
                            break;
Packit Service fdd496
                          }
Packit Service fdd496
                        if (c < L_('a') || c >= L_('z'))
Packit Service fdd496
                          {
Packit Service fdd496
                            /* This cannot possibly be a character class name.
Packit Service fdd496
                               Match it as a normal range.  */
Packit Service fdd496
                            p = startp;
Packit Service fdd496
                            c = L_('[');
Packit Service fdd496
                            goto normal_bracket;
Packit Service fdd496
                          }
Packit Service fdd496
                        str[c1++] = c;
Packit Service fdd496
                      }
Packit Service fdd496
                    str[c1] = L_('\0');
Packit Service fdd496
Packit Service fdd496
#if defined _LIBC || WIDE_CHAR_SUPPORT
Packit Service fdd496
                    wt = IS_CHAR_CLASS (str);
Packit Service fdd496
                    if (wt == 0)
Packit Service fdd496
                      /* Invalid character class name.  */
Packit Service fdd496
                      return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
# if defined _LIBC && ! WIDE_CHAR_VERSION
Packit Service fdd496
                    /* The following code is glibc specific but does
Packit Service fdd496
                       there a good job in speeding up the code since
Packit Service fdd496
                       we can avoid the btowc() call.  */
Packit Service fdd496
                    if (_ISCTYPE ((UCHAR) *n, wt))
Packit Service fdd496
                      goto matched;
Packit Service fdd496
# else
Packit Service fdd496
                    if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
Packit Service fdd496
                      goto matched;
Packit Service fdd496
# endif
Packit Service fdd496
#else
Packit Service fdd496
                    if ((STREQ (str, L_("alnum")) && isalnum ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("alpha")) && isalpha ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("blank")) && isblank ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("cntrl")) && iscntrl ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("digit")) && isdigit ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("graph")) && isgraph ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("lower")) && islower ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("print")) && isprint ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("punct")) && ispunct ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("space")) && isspace ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("upper")) && isupper ((UCHAR) *n))
Packit Service fdd496
                        || (STREQ (str, L_("xdigit")) && isxdigit ((UCHAR) *n)))
Packit Service fdd496
                      goto matched;
Packit Service fdd496
#endif
Packit Service fdd496
                    c = *p++;
Packit Service fdd496
                  }
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
                else if (c == L_('[') && *p == L_('='))
Packit Service fdd496
                  {
Packit Service fdd496
                    UCHAR str[1];
Packit Service fdd496
                    uint32_t nrules =
Packit Service fdd496
                      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
Packit Service fdd496
                    const CHAR *startp = p;
Packit Service fdd496
Packit Service fdd496
                    c = *++p;
Packit Service fdd496
                    if (c == L_('\0'))
Packit Service fdd496
                      {
Packit Service fdd496
                        p = startp;
Packit Service fdd496
                        c = L_('[');
Packit Service fdd496
                        goto normal_bracket;
Packit Service fdd496
                      }
Packit Service fdd496
                    str[0] = c;
Packit Service fdd496
Packit Service fdd496
                    c = *++p;
Packit Service fdd496
                    if (c != L_('=') || p[1] != L_(']'))
Packit Service fdd496
                      {
Packit Service fdd496
                        p = startp;
Packit Service fdd496
                        c = L_('[');
Packit Service fdd496
                        goto normal_bracket;
Packit Service fdd496
                      }
Packit Service fdd496
                    p += 2;
Packit Service fdd496
Packit Service fdd496
                    if (nrules == 0)
Packit Service fdd496
                      {
Packit Service fdd496
                        if ((UCHAR) *n == str[0])
Packit Service fdd496
                          goto matched;
Packit Service fdd496
                      }
Packit Service fdd496
                    else
Packit Service fdd496
                      {
Packit Service fdd496
                        const int32_t *table;
Packit Service fdd496
# if WIDE_CHAR_VERSION
Packit Service fdd496
                        const int32_t *weights;
Packit Service fdd496
                        const int32_t *extra;
Packit Service fdd496
# else
Packit Service fdd496
                        const unsigned char *weights;
Packit Service fdd496
                        const unsigned char *extra;
Packit Service fdd496
# endif
Packit Service fdd496
                        const int32_t *indirect;
Packit Service fdd496
                        int32_t idx;
Packit Service fdd496
                        const UCHAR *cp = (const UCHAR *) str;
Packit Service fdd496
Packit Service fdd496
                        /* This #include defines a local function!  */
Packit Service fdd496
# if WIDE_CHAR_VERSION
Packit Service fdd496
#  include <locale/weightwc.h>
Packit Service fdd496
# else
Packit Service fdd496
#  include <locale/weight.h>
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
# if WIDE_CHAR_VERSION
Packit Service fdd496
                        table = (const int32_t *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
Packit Service fdd496
                        weights = (const int32_t *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
Packit Service fdd496
                        extra = (const int32_t *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
Packit Service fdd496
                        indirect = (const int32_t *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
Packit Service fdd496
# else
Packit Service fdd496
                        table = (const int32_t *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
Packit Service fdd496
                        weights = (const unsigned char *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
Packit Service fdd496
                        extra = (const unsigned char *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
Packit Service fdd496
                        indirect = (const int32_t *)
Packit Service fdd496
                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
                        idx = findidx (&cp;;
Packit Service fdd496
                        if (idx != 0)
Packit Service fdd496
                          {
Packit Service fdd496
                            /* We found a table entry.  Now see whether the
Packit Service fdd496
                               character we are currently at has the same
Packit Service fdd496
                               equivalence class value.  */
Packit Service fdd496
                            int len = weights[idx & 0xffffff];
Packit Service fdd496
                            int32_t idx2;
Packit Service fdd496
                            const UCHAR *np = (const UCHAR *) n;
Packit Service fdd496
Packit Service fdd496
                            idx2 = findidx (&np);
Packit Service fdd496
                            if (idx2 != 0
Packit Service fdd496
                                && (idx >> 24) == (idx2 >> 24)
Packit Service fdd496
                                && len == weights[idx2 & 0xffffff])
Packit Service fdd496
                              {
Packit Service fdd496
                                int cnt = 0;
Packit Service fdd496
Packit Service fdd496
                                idx &= 0xffffff;
Packit Service fdd496
                                idx2 &= 0xffffff;
Packit Service fdd496
Packit Service fdd496
                                while (cnt < len
Packit Service fdd496
                                       && (weights[idx + 1 + cnt]
Packit Service fdd496
                                           == weights[idx2 + 1 + cnt]))
Packit Service fdd496
                                  ++cnt;
Packit Service fdd496
Packit Service fdd496
                                if (cnt == len)
Packit Service fdd496
                                  goto matched;
Packit Service fdd496
                              }
Packit Service fdd496
                          }
Packit Service fdd496
                      }
Packit Service fdd496
Packit Service fdd496
                    c = *p++;
Packit Service fdd496
                  }
Packit Service fdd496
#endif
Packit Service fdd496
                else if (c == L_('\0'))
Packit Service fdd496
                  {
Packit Service fdd496
                    /* [ unterminated, treat as normal character.  */
Packit Service fdd496
                    p = p_init;
Packit Service fdd496
                    n = n_init;
Packit Service fdd496
                    c = L_('[');
Packit Service fdd496
                    goto normal_match;
Packit Service fdd496
                  }
Packit Service fdd496
                else
Packit Service fdd496
                  {
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
                    bool is_seqval = false;
Packit Service fdd496
Packit Service fdd496
                    if (c == L_('[') && *p == L_('.'))
Packit Service fdd496
                      {
Packit Service fdd496
                        uint32_t nrules =
Packit Service fdd496
                          _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
Packit Service fdd496
                        const CHAR *startp = p;
Packit Service fdd496
                        size_t c1 = 0;
Packit Service fdd496
Packit Service fdd496
                        while (1)
Packit Service fdd496
                          {
Packit Service fdd496
                            c = *++p;
Packit Service fdd496
                            if (c == L_('.') && p[1] == L_(']'))
Packit Service fdd496
                              {
Packit Service fdd496
                                p += 2;
Packit Service fdd496
                                break;
Packit Service fdd496
                              }
Packit Service fdd496
                            if (c == '\0')
Packit Service fdd496
                              return FNM_NOMATCH;
Packit Service fdd496
                            ++c1;
Packit Service fdd496
                          }
Packit Service fdd496
Packit Service fdd496
                        /* We have to handling the symbols differently in
Packit Service fdd496
                           ranges since then the collation sequence is
Packit Service fdd496
                           important.  */
Packit Service fdd496
                        is_range = *p == L_('-') && p[1] != L_('\0');
Packit Service fdd496
Packit Service fdd496
                        if (nrules == 0)
Packit Service fdd496
                          {
Packit Service fdd496
                            /* There are no names defined in the collation
Packit Service fdd496
                               data.  Therefore we only accept the trivial
Packit Service fdd496
                               names consisting of the character itself.  */
Packit Service fdd496
                            if (c1 != 1)
Packit Service fdd496
                              return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
                            if (!is_range && *n == startp[1])
Packit Service fdd496
                              goto matched;
Packit Service fdd496
Packit Service fdd496
                            cold = startp[1];
Packit Service fdd496
                            c = *p++;
Packit Service fdd496
                          }
Packit Service fdd496
                        else
Packit Service fdd496
                          {
Packit Service fdd496
                            int32_t table_size;
Packit Service fdd496
                            const int32_t *symb_table;
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                            char str[c1];
Packit Service fdd496
                            size_t strcnt;
Packit Service fdd496
# else
Packit Service fdd496
#  define str (startp + 1)
Packit Service fdd496
# endif
Packit Service fdd496
                            const unsigned char *extra;
Packit Service fdd496
                            int32_t idx;
Packit Service fdd496
                            int32_t elem;
Packit Service fdd496
                            int32_t second;
Packit Service fdd496
                            int32_t hash;
Packit Service fdd496
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                            /* We have to convert the name to a single-byte
Packit Service fdd496
                               string.  This is possible since the names
Packit Service fdd496
                               consist of ASCII characters and the internal
Packit Service fdd496
                               representation is UCS4.  */
Packit Service fdd496
                            for (strcnt = 0; strcnt < c1; ++strcnt)
Packit Service fdd496
                              str[strcnt] = startp[1 + strcnt];
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
                            table_size =
Packit Service fdd496
                              _NL_CURRENT_WORD (LC_COLLATE,
Packit Service fdd496
                                                _NL_COLLATE_SYMB_HASH_SIZEMB);
Packit Service fdd496
                            symb_table = (const int32_t *)
Packit Service fdd496
                              _NL_CURRENT (LC_COLLATE,
Packit Service fdd496
                                           _NL_COLLATE_SYMB_TABLEMB);
Packit Service fdd496
                            extra = (const unsigned char *)
Packit Service fdd496
                              _NL_CURRENT (LC_COLLATE,
Packit Service fdd496
                                           _NL_COLLATE_SYMB_EXTRAMB);
Packit Service fdd496
Packit Service fdd496
                            /* Locate the character in the hashing table.  */
Packit Service fdd496
                            hash = elem_hash (str, c1);
Packit Service fdd496
Packit Service fdd496
                            idx = 0;
Packit Service fdd496
                            elem = hash % table_size;
Packit Service fdd496
                            if (symb_table[2 * elem] != 0)
Packit Service fdd496
                              {
Packit Service fdd496
                                second = hash % (table_size - 2) + 1;
Packit Service fdd496
Packit Service fdd496
                                do
Packit Service fdd496
                                  {
Packit Service fdd496
                                    /* First compare the hashing value.  */
Packit Service fdd496
                                    if (symb_table[2 * elem] == hash
Packit Service fdd496
                                        && (c1
Packit Service fdd496
                                            == extra[symb_table[2 * elem + 1]])
Packit Service fdd496
                                        && memcmp (str,
Packit Service fdd496
                                                   &extra[symb_table[2 * elem
Packit Service fdd496
                                                                     + 1]
Packit Service fdd496
                                                          + 1], c1) == 0)
Packit Service fdd496
                                      {
Packit Service fdd496
                                        /* Yep, this is the entry.  */
Packit Service fdd496
                                        idx = symb_table[2 * elem + 1];
Packit Service fdd496
                                        idx += 1 + extra[idx];
Packit Service fdd496
                                        break;
Packit Service fdd496
                                      }
Packit Service fdd496
Packit Service fdd496
                                    /* Next entry.  */
Packit Service fdd496
                                    elem += second;
Packit Service fdd496
                                  }
Packit Service fdd496
                                while (symb_table[2 * elem] != 0);
Packit Service fdd496
                              }
Packit Service fdd496
Packit Service fdd496
                            if (symb_table[2 * elem] != 0)
Packit Service fdd496
                              {
Packit Service fdd496
                                /* Compare the byte sequence but only if
Packit Service fdd496
                                   this is not part of a range.  */
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                int32_t *wextra;
Packit Service fdd496
Packit Service fdd496
                                idx += 1 + extra[idx];
Packit Service fdd496
                                /* Adjust for the alignment.  */
Packit Service fdd496
                                idx = (idx + 3) & ~3;
Packit Service fdd496
Packit Service fdd496
                                wextra = (int32_t *) &extra[idx + 4];
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
                                if (! is_range)
Packit Service fdd496
                                  {
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                    for (c1 = 0;
Packit Service fdd496
                                         (int32_t) c1 < wextra[idx];
Packit Service fdd496
                                         ++c1)
Packit Service fdd496
                                      if (n[c1] != wextra[1 + c1])
Packit Service fdd496
                                        break;
Packit Service fdd496
Packit Service fdd496
                                    if ((int32_t) c1 == wextra[idx])
Packit Service fdd496
                                      goto matched;
Packit Service fdd496
# else
Packit Service fdd496
                                    for (c1 = 0; c1 < extra[idx]; ++c1)
Packit Service fdd496
                                      if (n[c1] != extra[1 + c1])
Packit Service fdd496
                                        break;
Packit Service fdd496
Packit Service fdd496
                                    if (c1 == extra[idx])
Packit Service fdd496
                                      goto matched;
Packit Service fdd496
# endif
Packit Service fdd496
                                  }
Packit Service fdd496
Packit Service fdd496
                                /* Get the collation sequence value.  */
Packit Service fdd496
                                is_seqval = true;
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                cold = wextra[1 + wextra[idx]];
Packit Service fdd496
# else
Packit Service fdd496
                                /* Adjust for the alignment.  */
Packit Service fdd496
                                idx += 1 + extra[idx];
Packit Service fdd496
                                idx = (idx + 3) & ~4;
Packit Service fdd496
                                cold = *((int32_t *) &extra[idx]);
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
                                c = *p++;
Packit Service fdd496
                              }
Packit Service fdd496
                            else if (c1 == 1)
Packit Service fdd496
                              {
Packit Service fdd496
                                /* No valid character.  Match it as a
Packit Service fdd496
                                   single byte.  */
Packit Service fdd496
                                if (!is_range && *n == str[0])
Packit Service fdd496
                                  goto matched;
Packit Service fdd496
Packit Service fdd496
                                cold = str[0];
Packit Service fdd496
                                c = *p++;
Packit Service fdd496
                              }
Packit Service fdd496
                            else
Packit Service fdd496
                              return FNM_NOMATCH;
Packit Service fdd496
                          }
Packit Service fdd496
                      }
Packit Service fdd496
                    else
Packit Service fdd496
# undef str
Packit Service fdd496
#endif
Packit Service fdd496
                      {
Packit Service fdd496
                        c = FOLD (c);
Packit Service fdd496
                      normal_bracket:
Packit Service fdd496
Packit Service fdd496
                        /* We have to handling the symbols differently in
Packit Service fdd496
                           ranges since then the collation sequence is
Packit Service fdd496
                           important.  */
Packit Service fdd496
                        is_range = (*p == L_('-') && p[1] != L_('\0')
Packit Service fdd496
                                    && p[1] != L_(']'));
Packit Service fdd496
Packit Service fdd496
                        if (!is_range && c == fn)
Packit Service fdd496
                          goto matched;
Packit Service fdd496
Packit Service fdd496
#if _LIBC
Packit Service fdd496
                        /* This is needed if we goto normal_bracket; from
Packit Service fdd496
                           outside of is_seqval's scope.  */
Packit Service fdd496
                        is_seqval = false;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
                        cold = c;
Packit Service fdd496
                        c = *p++;
Packit Service fdd496
                      }
Packit Service fdd496
Packit Service fdd496
                    if (c == L_('-') && *p != L_(']'))
Packit Service fdd496
                      {
Packit Service fdd496
#if _LIBC
Packit Service fdd496
                        /* We have to find the collation sequence
Packit Service fdd496
                           value for C.  Collation sequence is nothing
Packit Service fdd496
                           we can regularly access.  The sequence
Packit Service fdd496
                           value is defined by the order in which the
Packit Service fdd496
                           definitions of the collation values for the
Packit Service fdd496
                           various characters appear in the source
Packit Service fdd496
                           file.  A strange concept, nowhere
Packit Service fdd496
                           documented.  */
Packit Service fdd496
                        uint32_t fcollseq;
Packit Service fdd496
                        uint32_t lcollseq;
Packit Service fdd496
                        UCHAR cend = *p++;
Packit Service fdd496
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                        /* Search in the 'names' array for the characters.  */
Packit Service fdd496
                        fcollseq = __collseq_table_lookup (collseq, fn);
Packit Service fdd496
                        if (fcollseq == ~((uint32_t) 0))
Packit Service fdd496
                          /* XXX We don't know anything about the character
Packit Service fdd496
                             we are supposed to match.  This means we are
Packit Service fdd496
                             failing.  */
Packit Service fdd496
                          goto range_not_matched;
Packit Service fdd496
Packit Service fdd496
                        if (is_seqval)
Packit Service fdd496
                          lcollseq = cold;
Packit Service fdd496
                        else
Packit Service fdd496
                          lcollseq = __collseq_table_lookup (collseq, cold);
Packit Service fdd496
# else
Packit Service fdd496
                        fcollseq = collseq[fn];
Packit Service fdd496
                        lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
                        is_seqval = false;
Packit Service fdd496
                        if (cend == L_('[') && *p == L_('.'))
Packit Service fdd496
                          {
Packit Service fdd496
                            uint32_t nrules =
Packit Service fdd496
                              _NL_CURRENT_WORD (LC_COLLATE,
Packit Service fdd496
                                                _NL_COLLATE_NRULES);
Packit Service fdd496
                            const CHAR *startp = p;
Packit Service fdd496
                            size_t c1 = 0;
Packit Service fdd496
Packit Service fdd496
                            while (1)
Packit Service fdd496
                              {
Packit Service fdd496
                                c = *++p;
Packit Service fdd496
                                if (c == L_('.') && p[1] == L_(']'))
Packit Service fdd496
                                  {
Packit Service fdd496
                                    p += 2;
Packit Service fdd496
                                    break;
Packit Service fdd496
                                  }
Packit Service fdd496
                                if (c == '\0')
Packit Service fdd496
                                  return FNM_NOMATCH;
Packit Service fdd496
                                ++c1;
Packit Service fdd496
                              }
Packit Service fdd496
Packit Service fdd496
                            if (nrules == 0)
Packit Service fdd496
                              {
Packit Service fdd496
                                /* There are no names defined in the
Packit Service fdd496
                                   collation data.  Therefore we only
Packit Service fdd496
                                   accept the trivial names consisting
Packit Service fdd496
                                   of the character itself.  */
Packit Service fdd496
                                if (c1 != 1)
Packit Service fdd496
                                  return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
                                cend = startp[1];
Packit Service fdd496
                              }
Packit Service fdd496
                            else
Packit Service fdd496
                              {
Packit Service fdd496
                                int32_t table_size;
Packit Service fdd496
                                const int32_t *symb_table;
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                char str[c1];
Packit Service fdd496
                                size_t strcnt;
Packit Service fdd496
# else
Packit Service fdd496
#  define str (startp + 1)
Packit Service fdd496
# endif
Packit Service fdd496
                                const unsigned char *extra;
Packit Service fdd496
                                int32_t idx;
Packit Service fdd496
                                int32_t elem;
Packit Service fdd496
                                int32_t second;
Packit Service fdd496
                                int32_t hash;
Packit Service fdd496
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                /* We have to convert the name to a single-byte
Packit Service fdd496
                                   string.  This is possible since the names
Packit Service fdd496
                                   consist of ASCII characters and the internal
Packit Service fdd496
                                   representation is UCS4.  */
Packit Service fdd496
                                for (strcnt = 0; strcnt < c1; ++strcnt)
Packit Service fdd496
                                  str[strcnt] = startp[1 + strcnt];
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
                                table_size =
Packit Service fdd496
                                  _NL_CURRENT_WORD (LC_COLLATE,
Packit Service fdd496
                                                    _NL_COLLATE_SYMB_HASH_SIZEMB);
Packit Service fdd496
                                symb_table = (const int32_t *)
Packit Service fdd496
                                  _NL_CURRENT (LC_COLLATE,
Packit Service fdd496
                                               _NL_COLLATE_SYMB_TABLEMB);
Packit Service fdd496
                                extra = (const unsigned char *)
Packit Service fdd496
                                  _NL_CURRENT (LC_COLLATE,
Packit Service fdd496
                                               _NL_COLLATE_SYMB_EXTRAMB);
Packit Service fdd496
Packit Service fdd496
                                /* Locate the character in the hashing
Packit Service fdd496
                                   table.  */
Packit Service fdd496
                                hash = elem_hash (str, c1);
Packit Service fdd496
Packit Service fdd496
                                idx = 0;
Packit Service fdd496
                                elem = hash % table_size;
Packit Service fdd496
                                if (symb_table[2 * elem] != 0)
Packit Service fdd496
                                  {
Packit Service fdd496
                                    second = hash % (table_size - 2) + 1;
Packit Service fdd496
Packit Service fdd496
                                    do
Packit Service fdd496
                                      {
Packit Service fdd496
                                        /* First compare the hashing value.  */
Packit Service fdd496
                                        if (symb_table[2 * elem] == hash
Packit Service fdd496
                                            && (c1
Packit Service fdd496
                                                == extra[symb_table[2 * elem + 1]])
Packit Service fdd496
                                            && memcmp (str,
Packit Service fdd496
                                                       &extra[symb_table[2 * elem + 1]
Packit Service fdd496
                                                              + 1], c1) == 0)
Packit Service fdd496
                                          {
Packit Service fdd496
                                            /* Yep, this is the entry.  */
Packit Service fdd496
                                            idx = symb_table[2 * elem + 1];
Packit Service fdd496
                                            idx += 1 + extra[idx];
Packit Service fdd496
                                            break;
Packit Service fdd496
                                          }
Packit Service fdd496
Packit Service fdd496
                                        /* Next entry.  */
Packit Service fdd496
                                        elem += second;
Packit Service fdd496
                                      }
Packit Service fdd496
                                    while (symb_table[2 * elem] != 0);
Packit Service fdd496
                                  }
Packit Service fdd496
Packit Service fdd496
                                if (symb_table[2 * elem] != 0)
Packit Service fdd496
                                  {
Packit Service fdd496
                                    /* Compare the byte sequence but only if
Packit Service fdd496
                                       this is not part of a range.  */
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                    int32_t *wextra;
Packit Service fdd496
Packit Service fdd496
                                    idx += 1 + extra[idx];
Packit Service fdd496
                                    /* Adjust for the alignment.  */
Packit Service fdd496
                                    idx = (idx + 3) & ~4;
Packit Service fdd496
Packit Service fdd496
                                    wextra = (int32_t *) &extra[idx + 4];
Packit Service fdd496
# endif
Packit Service fdd496
                                    /* Get the collation sequence value.  */
Packit Service fdd496
                                    is_seqval = true;
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                    cend = wextra[1 + wextra[idx]];
Packit Service fdd496
# else
Packit Service fdd496
                                    /* Adjust for the alignment.  */
Packit Service fdd496
                                    idx += 1 + extra[idx];
Packit Service fdd496
                                    idx = (idx + 3) & ~4;
Packit Service fdd496
                                    cend = *((int32_t *) &extra[idx]);
Packit Service fdd496
# endif
Packit Service fdd496
                                  }
Packit Service fdd496
                                else if (symb_table[2 * elem] != 0 && c1 == 1)
Packit Service fdd496
                                  {
Packit Service fdd496
                                    cend = str[0];
Packit Service fdd496
                                    c = *p++;
Packit Service fdd496
                                  }
Packit Service fdd496
                                else
Packit Service fdd496
                                  return FNM_NOMATCH;
Packit Service fdd496
                              }
Packit Service fdd496
# undef str
Packit Service fdd496
                          }
Packit Service fdd496
                        else
Packit Service fdd496
                          {
Packit Service fdd496
                            if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
Packit Service fdd496
                              cend = *p++;
Packit Service fdd496
                            if (cend == L_('\0'))
Packit Service fdd496
                              return FNM_NOMATCH;
Packit Service fdd496
                            cend = FOLD (cend);
Packit Service fdd496
                          }
Packit Service fdd496
Packit Service fdd496
                        /* XXX It is not entirely clear to me how to handle
Packit Service fdd496
                           characters which are not mentioned in the
Packit Service fdd496
                           collation specification.  */
Packit Service fdd496
                        if (
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                            lcollseq == 0xffffffff ||
Packit Service fdd496
# endif
Packit Service fdd496
                            lcollseq <= fcollseq)
Packit Service fdd496
                          {
Packit Service fdd496
                            /* We have to look at the upper bound.  */
Packit Service fdd496
                            uint32_t hcollseq;
Packit Service fdd496
Packit Service fdd496
                            if (is_seqval)
Packit Service fdd496
                              hcollseq = cend;
Packit Service fdd496
                            else
Packit Service fdd496
                              {
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                                hcollseq =
Packit Service fdd496
                                  __collseq_table_lookup (collseq, cend);
Packit Service fdd496
                                if (hcollseq == ~((uint32_t) 0))
Packit Service fdd496
                                  {
Packit Service fdd496
                                    /* Hum, no information about the upper
Packit Service fdd496
                                       bound.  The matching succeeds if the
Packit Service fdd496
                                       lower bound is matched exactly.  */
Packit Service fdd496
                                    if (lcollseq != fcollseq)
Packit Service fdd496
                                      goto range_not_matched;
Packit Service fdd496
Packit Service fdd496
                                    goto matched;
Packit Service fdd496
                                  }
Packit Service fdd496
# else
Packit Service fdd496
                                hcollseq = collseq[cend];
Packit Service fdd496
# endif
Packit Service fdd496
                              }
Packit Service fdd496
Packit Service fdd496
                            if (lcollseq <= hcollseq && fcollseq <= hcollseq)
Packit Service fdd496
                              goto matched;
Packit Service fdd496
                          }
Packit Service fdd496
# ifdef WIDE_CHAR_VERSION
Packit Service fdd496
                      range_not_matched:
Packit Service fdd496
# endif
Packit Service fdd496
#else
Packit Service fdd496
                        /* We use a boring value comparison of the character
Packit Service fdd496
                           values.  This is better than comparing using
Packit Service fdd496
                           'strcoll' since the latter would have surprising
Packit Service fdd496
                           and sometimes fatal consequences.  */
Packit Service fdd496
                        UCHAR cend = *p++;
Packit Service fdd496
Packit Service fdd496
                        if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
Packit Service fdd496
                          cend = *p++;
Packit Service fdd496
                        if (cend == L_('\0'))
Packit Service fdd496
                          return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
                        /* It is a range.  */
Packit Service fdd496
                        if (cold <= fn && fn <= cend)
Packit Service fdd496
                          goto matched;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
                        c = *p++;
Packit Service fdd496
                      }
Packit Service fdd496
                  }
Packit Service fdd496
Packit Service fdd496
                if (c == L_(']'))
Packit Service fdd496
                  break;
Packit Service fdd496
              }
Packit Service fdd496
Packit Service fdd496
            if (!not)
Packit Service fdd496
              return FNM_NOMATCH;
Packit Service fdd496
            break;
Packit Service fdd496
Packit Service fdd496
          matched:
Packit Service fdd496
            /* Skip the rest of the [...] that already matched.  */
Packit Service fdd496
            do
Packit Service fdd496
              {
Packit Service fdd496
              ignore_next:
Packit Service fdd496
                c = *p++;
Packit Service fdd496
Packit Service fdd496
                if (c == L_('\0'))
Packit Service fdd496
                  /* [... (unterminated) loses.  */
Packit Service fdd496
                  return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
                if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
Packit Service fdd496
                  {
Packit Service fdd496
                    if (*p == L_('\0'))
Packit Service fdd496
                      return FNM_NOMATCH;
Packit Service fdd496
                    /* XXX 1003.2d11 is unclear if this is right.  */
Packit Service fdd496
                    ++p;
Packit Service fdd496
                  }
Packit Service fdd496
                else if (c == L_('[') && *p == L_(':'))
Packit Service fdd496
                  {
Packit Service fdd496
                    int c1 = 0;
Packit Service fdd496
                    const CHAR *startp = p;
Packit Service fdd496
Packit Service fdd496
                    while (1)
Packit Service fdd496
                      {
Packit Service fdd496
                        c = *++p;
Packit Service fdd496
                        if (++c1 == CHAR_CLASS_MAX_LENGTH)
Packit Service fdd496
                          return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
                        if (*p == L_(':') && p[1] == L_(']'))
Packit Service fdd496
                          break;
Packit Service fdd496
Packit Service fdd496
                        if (c < L_('a') || c >= L_('z'))
Packit Service fdd496
                          {
Packit Service fdd496
                            p = startp;
Packit Service fdd496
                            goto ignore_next;
Packit Service fdd496
                          }
Packit Service fdd496
                      }
Packit Service fdd496
                    p += 2;
Packit Service fdd496
                    c = *p++;
Packit Service fdd496
                  }
Packit Service fdd496
                else if (c == L_('[') && *p == L_('='))
Packit Service fdd496
                  {
Packit Service fdd496
                    c = *++p;
Packit Service fdd496
                    if (c == L_('\0'))
Packit Service fdd496
                      return FNM_NOMATCH;
Packit Service fdd496
                    c = *++p;
Packit Service fdd496
                    if (c != L_('=') || p[1] != L_(']'))
Packit Service fdd496
                      return FNM_NOMATCH;
Packit Service fdd496
                    p += 2;
Packit Service fdd496
                    c = *p++;
Packit Service fdd496
                  }
Packit Service fdd496
                else if (c == L_('[') && *p == L_('.'))
Packit Service fdd496
                  {
Packit Service fdd496
                    ++p;
Packit Service fdd496
                    while (1)
Packit Service fdd496
                      {
Packit Service fdd496
                        c = *++p;
Packit Service fdd496
                        if (c == '\0')
Packit Service fdd496
                          return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
                        if (*p == L_('.') && p[1] == L_(']'))
Packit Service fdd496
                          break;
Packit Service fdd496
                      }
Packit Service fdd496
                    p += 2;
Packit Service fdd496
                    c = *p++;
Packit Service fdd496
                  }
Packit Service fdd496
              }
Packit Service fdd496
            while (c != L_(']'));
Packit Service fdd496
            if (not)
Packit Service fdd496
              return FNM_NOMATCH;
Packit Service fdd496
          }
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('+'):
Packit Service fdd496
        case L_('@'):
Packit Service fdd496
        case L_('!'):
Packit Service fdd496
          if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
Packit Service fdd496
            {
Packit Service fdd496
              int res;
Packit Service fdd496
Packit Service fdd496
              res = EXT (c, p, n, string_end, no_leading_period, flags);
Packit Service fdd496
              if (res != -1)
Packit Service fdd496
                return res;
Packit Service fdd496
            }
Packit Service fdd496
          goto normal_match;
Packit Service fdd496
Packit Service fdd496
        case L_('/'):
Packit Service fdd496
          if (NO_LEADING_PERIOD (flags))
Packit Service fdd496
            {
Packit Service fdd496
              if (n == string_end || c != (UCHAR) *n)
Packit Service fdd496
                return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
              new_no_leading_period = true;
Packit Service fdd496
              break;
Packit Service fdd496
            }
Packit Service fdd496
          FALLTHROUGH;
Packit Service fdd496
        default:
Packit Service fdd496
        normal_match:
Packit Service fdd496
          if (n == string_end || c != FOLD ((UCHAR) *n))
Packit Service fdd496
            return FNM_NOMATCH;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      no_leading_period = new_no_leading_period;
Packit Service fdd496
      ++n;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  if (n == string_end)
Packit Service fdd496
    return 0;
Packit Service fdd496
Packit Service fdd496
  if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/'))
Packit Service fdd496
    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
Packit Service fdd496
    return 0;
Packit Service fdd496
Packit Service fdd496
  return FNM_NOMATCH;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
static const CHAR *
Packit Service fdd496
internal_function
Packit Service fdd496
END (const CHAR *pattern)
Packit Service fdd496
{
Packit Service fdd496
  const CHAR *p = pattern;
Packit Service fdd496
Packit Service fdd496
  while (1)
Packit Service fdd496
    if (*++p == L_('\0'))
Packit Service fdd496
      /* This is an invalid pattern.  */
Packit Service fdd496
      return pattern;
Packit Service fdd496
    else if (*p == L_('['))
Packit Service fdd496
      {
Packit Service fdd496
        /* Handle brackets special.  */
Packit Service fdd496
        if (posixly_correct == 0)
Packit Service fdd496
          posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
Packit Service fdd496
Packit Service fdd496
        /* Skip the not sign.  We have to recognize it because of a possibly
Packit Service fdd496
           following ']'.  */
Packit Service fdd496
        if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
Packit Service fdd496
          ++p;
Packit Service fdd496
        /* A leading ']' is recognized as such.  */
Packit Service fdd496
        if (*p == L_(']'))
Packit Service fdd496
          ++p;
Packit Service fdd496
        /* Skip over all characters of the list.  */
Packit Service fdd496
        while (*p != L_(']'))
Packit Service fdd496
          if (*p++ == L_('\0'))
Packit Service fdd496
            /* This is no valid pattern.  */
Packit Service fdd496
            return pattern;
Packit Service fdd496
      }
Packit Service fdd496
    else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
Packit Service fdd496
              || *p == L_('!')) && p[1] == L_('('))
Packit Service fdd496
      p = END (p + 1);
Packit Service fdd496
    else if (*p == L_(')'))
Packit Service fdd496
      break;
Packit Service fdd496
Packit Service fdd496
  return p + 1;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
static int
Packit Service fdd496
internal_function
Packit Service fdd496
EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
Packit Service fdd496
     bool no_leading_period, int flags)
Packit Service fdd496
{
Packit Service fdd496
  const CHAR *startp;
Packit Service fdd496
  size_t level;
Packit Service fdd496
  struct patternlist
Packit Service fdd496
  {
Packit Service fdd496
    struct patternlist *next;
Packit Service fdd496
    CHAR str[FLEXIBLE_ARRAY_MEMBER];
Packit Service fdd496
  } *list = NULL;
Packit Service fdd496
  struct patternlist **lastp = &list;
Packit Service fdd496
  size_t pattern_len = STRLEN (pattern);
Packit Service fdd496
  const CHAR *p;
Packit Service fdd496
  const CHAR *rs;
Packit Service fdd496
  enum { ALLOCA_LIMIT = 8000 };
Packit Service fdd496
Packit Service fdd496
  /* Parse the pattern.  Store the individual parts in the list.  */
Packit Service fdd496
  level = 0;
Packit Service fdd496
  for (startp = p = pattern + 1; ; ++p)
Packit Service fdd496
    if (*p == L_('\0'))
Packit Service fdd496
      /* This is an invalid pattern.  */
Packit Service fdd496
      return -1;
Packit Service fdd496
    else if (*p == L_('['))
Packit Service fdd496
      {
Packit Service fdd496
        /* Handle brackets special.  */
Packit Service fdd496
        if (posixly_correct == 0)
Packit Service fdd496
          posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
Packit Service fdd496
Packit Service fdd496
        /* Skip the not sign.  We have to recognize it because of a possibly
Packit Service fdd496
           following ']'.  */
Packit Service fdd496
        if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
Packit Service fdd496
          ++p;
Packit Service fdd496
        /* A leading ']' is recognized as such.  */
Packit Service fdd496
        if (*p == L_(']'))
Packit Service fdd496
          ++p;
Packit Service fdd496
        /* Skip over all characters of the list.  */
Packit Service fdd496
        while (*p != L_(']'))
Packit Service fdd496
          if (*p++ == L_('\0'))
Packit Service fdd496
            /* This is no valid pattern.  */
Packit Service fdd496
            return -1;
Packit Service fdd496
      }
Packit Service fdd496
    else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
Packit Service fdd496
              || *p == L_('!')) && p[1] == L_('('))
Packit Service fdd496
      /* Remember the nesting level.  */
Packit Service fdd496
      ++level;
Packit Service fdd496
    else if (*p == L_(')'))
Packit Service fdd496
      {
Packit Service fdd496
        if (level-- == 0)
Packit Service fdd496
          {
Packit Service fdd496
            /* This means we found the end of the pattern.  */
Packit Service fdd496
#define NEW_PATTERN \
Packit Service fdd496
            struct patternlist *newp;                                         \
Packit Service fdd496
            size_t plen;                                                      \
Packit Service fdd496
            size_t plensize;                                                  \
Packit Service fdd496
            size_t newpsize;                                                  \
Packit Service fdd496
                                                                              \
Packit Service fdd496
            plen = (opt == L_('?') || opt == L_('@')                          \
Packit Service fdd496
                    ? pattern_len                                             \
Packit Service fdd496
                    : p - startp + 1UL);                                      \
Packit Service fdd496
            plensize = plen * sizeof (CHAR);                                  \
Packit Service fdd496
            newpsize = FLEXSIZEOF (struct patternlist, str, plensize);        \
Packit Service fdd496
            if ((size_t) -1 / sizeof (CHAR) < plen                            \
Packit Service fdd496
                || newpsize < offsetof (struct patternlist, str)              \
Packit Service fdd496
                || ALLOCA_LIMIT <= newpsize)                                  \
Packit Service fdd496
              return -1;                                                      \
Packit Service fdd496
            newp = (struct patternlist *) alloca (newpsize);                  \
Packit Service fdd496
            *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0');    \
Packit Service fdd496
            newp->next = NULL;                                                \
Packit Service fdd496
            *lastp = newp;                                                    \
Packit Service fdd496
            lastp = &newp->next
Packit Service fdd496
            NEW_PATTERN;
Packit Service fdd496
            break;
Packit Service fdd496
          }
Packit Service fdd496
      }
Packit Service fdd496
    else if (*p == L_('|'))
Packit Service fdd496
      {
Packit Service fdd496
        if (level == 0)
Packit Service fdd496
          {
Packit Service fdd496
            NEW_PATTERN;
Packit Service fdd496
            startp = p + 1;
Packit Service fdd496
          }
Packit Service fdd496
      }
Packit Service fdd496
  assert (list != NULL);
Packit Service fdd496
  assert (p[-1] == L_(')'));
Packit Service fdd496
#undef NEW_PATTERN
Packit Service fdd496
Packit Service fdd496
  switch (opt)
Packit Service fdd496
    {
Packit Service fdd496
    case L_('*'):
Packit Service fdd496
      if (FCT (p, string, string_end, no_leading_period, flags) == 0)
Packit Service fdd496
        return 0;
Packit Service fdd496
      FALLTHROUGH;
Packit Service fdd496
    case L_('+'):
Packit Service fdd496
      do
Packit Service fdd496
        {
Packit Service fdd496
          for (rs = string; rs <= string_end; ++rs)
Packit Service fdd496
            /* First match the prefix with the current pattern with the
Packit Service fdd496
               current pattern.  */
Packit Service fdd496
            if (FCT (list->str, string, rs, no_leading_period,
Packit Service fdd496
                     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0
Packit Service fdd496
                /* This was successful.  Now match the rest with the rest
Packit Service fdd496
                   of the pattern.  */
Packit Service fdd496
                && (FCT (p, rs, string_end,
Packit Service fdd496
                         rs == string
Packit Service fdd496
                         ? no_leading_period
Packit Service fdd496
                         : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
Packit Service fdd496
                         flags & FNM_FILE_NAME
Packit Service fdd496
                         ? flags : flags & ~FNM_PERIOD) == 0
Packit Service fdd496
                    /* This didn't work.  Try the whole pattern.  */
Packit Service fdd496
                    || (rs != string
Packit Service fdd496
                        && FCT (pattern - 1, rs, string_end,
Packit Service fdd496
                                rs == string
Packit Service fdd496
                                ? no_leading_period
Packit Service fdd496
                                : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
Packit Service fdd496
                                flags & FNM_FILE_NAME
Packit Service fdd496
                                ? flags : flags & ~FNM_PERIOD) == 0)))
Packit Service fdd496
              /* It worked.  Signal success.  */
Packit Service fdd496
              return 0;
Packit Service fdd496
        }
Packit Service fdd496
      while ((list = list->next) != NULL);
Packit Service fdd496
Packit Service fdd496
      /* None of the patterns lead to a match.  */
Packit Service fdd496
      return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
    case L_('?'):
Packit Service fdd496
      if (FCT (p, string, string_end, no_leading_period, flags) == 0)
Packit Service fdd496
        return 0;
Packit Service fdd496
      FALLTHROUGH;
Packit Service fdd496
    case L_('@'):
Packit Service fdd496
      do
Packit Service fdd496
        /* I cannot believe it but 'strcat' is actually acceptable
Packit Service fdd496
           here.  Match the entire string with the prefix from the
Packit Service fdd496
           pattern list and the rest of the pattern following the
Packit Service fdd496
           pattern list.  */
Packit Service fdd496
        if (FCT (STRCAT (list->str, p), string, string_end,
Packit Service fdd496
                 no_leading_period,
Packit Service fdd496
                 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
Packit Service fdd496
          /* It worked.  Signal success.  */
Packit Service fdd496
          return 0;
Packit Service fdd496
      while ((list = list->next) != NULL);
Packit Service fdd496
Packit Service fdd496
      /* None of the patterns lead to a match.  */
Packit Service fdd496
      return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
    case L_('!'):
Packit Service fdd496
      for (rs = string; rs <= string_end; ++rs)
Packit Service fdd496
        {
Packit Service fdd496
          struct patternlist *runp;
Packit Service fdd496
Packit Service fdd496
          for (runp = list; runp != NULL; runp = runp->next)
Packit Service fdd496
            if (FCT (runp->str, string, rs,  no_leading_period,
Packit Service fdd496
                     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
Packit Service fdd496
              break;
Packit Service fdd496
Packit Service fdd496
          /* If none of the patterns matched see whether the rest does.  */
Packit Service fdd496
          if (runp == NULL
Packit Service fdd496
              && (FCT (p, rs, string_end,
Packit Service fdd496
                       rs == string
Packit Service fdd496
                       ? no_leading_period
Packit Service fdd496
                       : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
Packit Service fdd496
                       flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
Packit Service fdd496
                  == 0))
Packit Service fdd496
            /* This is successful.  */
Packit Service fdd496
            return 0;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      /* None of the patterns together with the rest of the pattern
Packit Service fdd496
         lead to a match.  */
Packit Service fdd496
      return FNM_NOMATCH;
Packit Service fdd496
Packit Service fdd496
    default:
Packit Service fdd496
      assert (! "Invalid extended matching operator");
Packit Service fdd496
      break;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  return -1;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
#undef FOLD
Packit Service fdd496
#undef CHAR
Packit Service fdd496
#undef UCHAR
Packit Service fdd496
#undef INT
Packit Service fdd496
#undef FCT
Packit Service fdd496
#undef EXT
Packit Service fdd496
#undef END
Packit Service fdd496
#undef MEMPCPY
Packit Service fdd496
#undef MEMCHR
Packit Service fdd496
#undef STRLEN
Packit Service fdd496
#undef STRCAT
Packit Service fdd496
#undef L_
Packit Service fdd496
#undef BTOWC