Blame lib/fnmatch_loop.c

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