Blame gnulib/lib/fnmatch_loop.c

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