Blame lib/fnmatch_loop.c

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