Blame lib/fnmatch_loop.c

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