have bootstrap initialize git-merge-changelog if found
[gnulib.git] / lib / fnmatch_loop.c
index e3450b6..d1008c2 100644 (file)
@@ -1,5 +1,6 @@
-/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-/* Match STRING against the filename pattern PATTERN, returning zero if
+/* Match STRING against the file name pattern PATTERN, returning zero if
    it matches, nonzero if not.  */
-static int FCT (const CHAR *pattern, const CHAR *string,
-               const CHAR *string_end, int no_leading_period, int flags)
-     internal_function;
 static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
-               const CHAR *string_end, int no_leading_period, int flags)
+               const CHAR *string_end, bool no_leading_period, int flags)
      internal_function;
 static const CHAR *END (const CHAR *patternp) internal_function;
 
 static int
 internal_function
-FCT (pattern, string, string_end, no_leading_period, flags)
-     const CHAR *pattern;
-     const CHAR *string;
-     const CHAR *string_end;
-     int no_leading_period;
-     int flags;
+FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+     bool no_leading_period, int flags)
 {
   register const CHAR *p = pattern, *n = string;
   register UCHAR c;
@@ -46,14 +40,14 @@ FCT (pattern, string, string_end, no_leading_period, flags)
 # endif
 #endif
 
-  while ((c = *p++) != L('\0'))
+  while ((c = *p++) != L_('\0'))
     {
-      int new_no_leading_period = 0;
+      bool new_no_leading_period = false;
       c = FOLD (c);
 
       switch (c)
        {
-       case L('?'):
+       case L_('?'):
          if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
            {
              int res;
@@ -66,17 +60,17 @@ FCT (pattern, string, string_end, no_leading_period, flags)
 
          if (n == string_end)
            return FNM_NOMATCH;
-         else if (*n == L('/') && (flags & FNM_FILE_NAME))
+         else if (*n == L_('/') && (flags & FNM_FILE_NAME))
            return FNM_NOMATCH;
-         else if (*n == L('.') && no_leading_period)
+         else if (*n == L_('.') && no_leading_period)
            return FNM_NOMATCH;
          break;
 
-       case L('\\'):
+       case L_('\\'):
          if (!(flags & FNM_NOESCAPE))
            {
              c = *p++;
-             if (c == L('\0'))
+             if (c == L_('\0'))
                /* Trailing \ loses.  */
                return FNM_NOMATCH;
              c = FOLD (c);
@@ -85,7 +79,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
            return FNM_NOMATCH;
          break;
 
-       case L('*'):
+       case L_('*'):
          if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
            {
              int res;
@@ -96,12 +90,12 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                return res;
            }
 
-         if (n != string_end && *n == L('.') && no_leading_period)
+         if (n != string_end && *n == L_('.') && no_leading_period)
            return FNM_NOMATCH;
 
-         for (c = *p++; c == L('?') || c == L('*'); c = *p++)
+         for (c = *p++; c == L_('?') || c == L_('*'); c = *p++)
            {
-             if (*p == L('(') && (flags & FNM_EXTMATCH) != 0)
+             if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0)
                {
                  const CHAR *endp = END (p);
                  if (endp != p)
@@ -112,13 +106,13 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                    }
                }
 
-             if (c == L('?'))
+             if (c == L_('?'))
                {
                  /* A ? needs to match one character.  */
                  if (n == string_end)
                    /* There isn't another character; no match.  */
                    return FNM_NOMATCH;
-                 else if (*n == L('/')
+                 else if (*n == L_('/')
                           && __builtin_expect (flags & FNM_FILE_NAME, 0))
                    /* A slash does not match a wildcard under
                       FNM_FILE_NAME.  */
@@ -131,7 +125,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                }
            }
 
-         if (c == L('\0'))
+         if (c == L_('\0'))
            /* The wildcard(s) is/are the last element of the pattern.
               If the name is a file name and contains another slash
               this means it cannot match, unless the FNM_LEADING_DIR
@@ -145,7 +139,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                    result = 0;
                  else
                    {
-                     if (MEMCHR (n, L('/'), string_end - n) == NULL)
+                     if (MEMCHR (n, L_('/'), string_end - n) == NULL)
                        result = 0;
                    }
                }
@@ -156,30 +150,30 @@ FCT (pattern, string, string_end, no_leading_period, flags)
            {
              const CHAR *endp;
 
-             endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'),
+             endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'),
                             string_end - n);
              if (endp == NULL)
                endp = string_end;
 
-             if (c == L('[')
+             if (c == L_('[')
                  || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
-                     && (c == L('@') || c == L('+') || c == L('!'))
-                     && *p == L('(')))
+                     && (c == L_('@') || c == L_('+') || c == L_('!'))
+                     && *p == L_('(')))
                {
                  int flags2 = ((flags & FNM_FILE_NAME)
                                ? flags : (flags & ~FNM_PERIOD));
-                 int no_leading_period2 = no_leading_period;
+                 bool no_leading_period2 = no_leading_period;
 
-                 for (--p; n < endp; ++n, no_leading_period2 = 0)
+                 for (--p; n < endp; ++n, no_leading_period2 = false)
                    if (FCT (p, n, string_end, no_leading_period2, flags2)
                        == 0)
                      return 0;
                }
-             else if (c == L('/') && (flags & FNM_FILE_NAME))
+             else if (c == L_('/') && (flags & FNM_FILE_NAME))
                {
-                 while (n < string_end && *n != L('/'))
+                 while (n < string_end && *n != L_('/'))
                    ++n;
-                 if (n < string_end && *n == L('/')
+                 if (n < string_end && *n == L_('/')
                      && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags)
                          == 0))
                    return 0;
@@ -190,10 +184,10 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                                ? flags : (flags & ~FNM_PERIOD));
                  int no_leading_period2 = no_leading_period;
 
-                 if (c == L('\\') && !(flags & FNM_NOESCAPE))
+                 if (c == L_('\\') && !(flags & FNM_NOESCAPE))
                    c = *p;
                  c = FOLD (c);
-                 for (--p; n < endp; ++n, no_leading_period2 = 0)
+                 for (--p; n < endp; ++n, no_leading_period2 = false)
                    if (FOLD ((UCHAR) *n) == c
                        && (FCT (p, n, string_end, no_leading_period2, flags2)
                            == 0))
@@ -204,10 +198,10 @@ FCT (pattern, string, string_end, no_leading_period, flags)
          /* If we come here no match is possible with the wildcard.  */
          return FNM_NOMATCH;
 
-       case L('['):
+       case L_('['):
          {
            /* Nonzero if the sense of the character class is inverted.  */
-           register int not;
+           register bool not;
            CHAR cold;
            UCHAR fn;
 
@@ -217,14 +211,14 @@ FCT (pattern, string, string_end, no_leading_period, flags)
            if (n == string_end)
              return FNM_NOMATCH;
 
-           if (*n == L('.') && no_leading_period)
+           if (*n == L_('.') && no_leading_period)
              return FNM_NOMATCH;
 
-           if (*n == L('/') && (flags & FNM_FILE_NAME))
+           if (*n == L_('/') && (flags & FNM_FILE_NAME))
              /* `/' cannot be matched.  */
              return FNM_NOMATCH;
 
-           not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
+           not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^')));
            if (not)
              ++p;
 
@@ -233,17 +227,16 @@ FCT (pattern, string, string_end, no_leading_period, flags)
            c = *p++;
            for (;;)
              {
-               if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+               if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
                  {
-                   if (*p == L('\0'))
+                   if (*p == L_('\0'))
                      return FNM_NOMATCH;
                    c = FOLD ((UCHAR) *p);
                    ++p;
 
-                   if (c == fn)
-                     goto matched;
+                   goto normal_bracket;
                  }
-               else if (c == L('[') && *p == L(':'))
+               else if (c == L_('[') && *p == L_(':'))
                  {
                    /* Leave room for the null.  */
                    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
@@ -261,22 +254,22 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                          return FNM_NOMATCH;
 
                        c = *++p;
-                       if (c == L(':') && p[1] == L(']'))
+                       if (c == L_(':') && p[1] == L_(']'))
                          {
                            p += 2;
                            break;
                          }
-                       if (c < L('a') || c >= L('z'))
+                       if (c < L_('a') || c >= L_('z'))
                          {
                            /* This cannot possibly be a character class name.
                               Match it as a normal range.  */
                            p = startp;
-                           c = L('[');
+                           c = L_('[');
                            goto normal_bracket;
                          }
                        str[c1++] = c;
                      }
-                   str[c1] = L('\0');
+                   str[c1] = L_('\0');
 
 #if defined _LIBC || WIDE_CHAR_SUPPORT
                    wt = IS_CHAR_CLASS (str);
@@ -295,24 +288,24 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                      goto matched;
 # endif
 #else
-                   if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n))
-                       || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n))
-                       || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n))
-                       || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n))
-                       || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n))
-                       || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n))
-                       || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n))
-                       || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n))
-                       || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n))
-                       || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n))
-                       || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n))
-                       || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
+                   if ((STREQ (str, L_("alnum")) && isalnum ((UCHAR) *n))
+                       || (STREQ (str, L_("alpha")) && isalpha ((UCHAR) *n))
+                       || (STREQ (str, L_("blank")) && isblank ((UCHAR) *n))
+                       || (STREQ (str, L_("cntrl")) && iscntrl ((UCHAR) *n))
+                       || (STREQ (str, L_("digit")) && isdigit ((UCHAR) *n))
+                       || (STREQ (str, L_("graph")) && isgraph ((UCHAR) *n))
+                       || (STREQ (str, L_("lower")) && islower ((UCHAR) *n))
+                       || (STREQ (str, L_("print")) && isprint ((UCHAR) *n))
+                       || (STREQ (str, L_("punct")) && ispunct ((UCHAR) *n))
+                       || (STREQ (str, L_("space")) && isspace ((UCHAR) *n))
+                       || (STREQ (str, L_("upper")) && isupper ((UCHAR) *n))
+                       || (STREQ (str, L_("xdigit")) && isxdigit ((UCHAR) *n)))
                      goto matched;
 #endif
                    c = *p++;
                  }
 #ifdef _LIBC
-               else if (c == L('[') && *p == L('='))
+               else if (c == L_('[') && *p == L_('='))
                  {
                    UCHAR str[1];
                    uint32_t nrules =
@@ -320,19 +313,19 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                    const CHAR *startp = p;
 
                    c = *++p;
-                   if (c == L('\0'))
+                   if (c == L_('\0'))
                      {
                        p = startp;
-                       c = L('[');
+                       c = L_('[');
                        goto normal_bracket;
                      }
                    str[0] = c;
 
                    c = *++p;
-                   if (c != L('=') || p[1] != L(']'))
+                   if (c != L_('=') || p[1] != L_(']'))
                      {
                        p = startp;
-                       c = L('[');
+                       c = L_('[');
                        goto normal_bracket;
                      }
                    p += 2;
@@ -412,17 +405,17 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                    c = *p++;
                  }
 #endif
-               else if (c == L('\0'))
+               else if (c == L_('\0'))
                  /* [ (unterminated) loses.  */
                  return FNM_NOMATCH;
                else
                  {
-                   int is_range = 0;
+                   bool is_range = false;
 
 #ifdef _LIBC
-                   int is_seqval = 0;
+                   bool is_seqval = false;
 
-                   if (c == L('[') && *p == L('.'))
+                   if (c == L_('[') && *p == L_('.'))
                      {
                        uint32_t nrules =
                          _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
@@ -432,7 +425,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                        while (1)
                          {
                            c = *++p;
-                           if (c == L('.') && p[1] == L(']'))
+                           if (c == L_('.') && p[1] == L_(']'))
                              {
                                p += 2;
                                break;
@@ -445,7 +438,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                        /* We have to handling the symbols differently in
                           ranges since then the collation sequence is
                           important.  */
-                       is_range = *p == L('-') && p[1] != L('\0');
+                       is_range = *p == L_('-') && p[1] != L_('\0');
 
                        if (nrules == 0)
                          {
@@ -467,7 +460,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                            const int32_t *symb_table;
 # ifdef WIDE_CHAR_VERSION
                            char str[c1];
-                           unsigned int strcnt;
+                           size_t strcnt;
 # else
 #  define str (startp + 1)
 # endif
@@ -501,24 +494,31 @@ FCT (pattern, string, string_end, no_leading_period, flags)
 
                            idx = 0;
                            elem = hash % table_size;
-                           second = hash % (table_size - 2);
-                           while (symb_table[2 * elem] != 0)
+                           if (symb_table[2 * elem] != 0)
                              {
-                               /* First compare the hashing value.  */
-                               if (symb_table[2 * elem] == hash
-                                   && c1 == extra[symb_table[2 * elem + 1]]
-                                   && memcmp (str,
-                                              &extra[symb_table[2 * elem + 1]
-                                                    + 1], c1) == 0)
+                               second = hash % (table_size - 2) + 1;
+
+                               do
                                  {
-                                   /* Yep, this is the entry.  */
-                                   idx = symb_table[2 * elem + 1];
-                                   idx += 1 + extra[idx];
-                                   break;
-                                 }
+                                   /* First compare the hashing value.  */
+                                   if (symb_table[2 * elem] == hash
+                                       && (c1
+                                           == extra[symb_table[2 * elem + 1]])
+                                       && memcmp (str,
+                                                  &extra[symb_table[2 * elem
+                                                                    + 1]
+                                                         + 1], c1) == 0)
+                                     {
+                                       /* Yep, this is the entry.  */
+                                       idx = symb_table[2 * elem + 1];
+                                       idx += 1 + extra[idx];
+                                       break;
+                                     }
 
-                               /* Next entry.  */
-                               elem += second;
+                                   /* Next entry.  */
+                                   elem += second;
+                                 }
+                               while (symb_table[2 * elem] != 0);
                              }
 
                            if (symb_table[2 * elem] != 0)
@@ -538,11 +538,13 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                                if (! is_range)
                                  {
 # ifdef WIDE_CHAR_VERSION
-                                   for (c1 = 0; c1 < wextra[idx]; ++c1)
+                                   for (c1 = 0;
+                                        (int32_t) c1 < wextra[idx];
+                                        ++c1)
                                      if (n[c1] != wextra[1 + c1])
                                        break;
 
-                                   if (c1 == wextra[idx])
+                                   if ((int32_t) c1 == wextra[idx])
                                      goto matched;
 # else
                                    for (c1 = 0; c1 < extra[idx]; ++c1)
@@ -555,7 +557,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                                  }
 
                                /* Get the collation sequence value.  */
-                               is_seqval = 1;
+                               is_seqval = true;
 # ifdef WIDE_CHAR_VERSION
                                cold = wextra[1 + wextra[idx]];
 # else
@@ -591,17 +593,23 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                        /* We have to handling the symbols differently in
                           ranges since then the collation sequence is
                           important.  */
-                       is_range = (*p == L('-') && p[1] != L('\0')
-                                   && p[1] != L(']'));
+                       is_range = (*p == L_('-') && p[1] != L_('\0')
+                                   && p[1] != L_(']'));
 
                        if (!is_range && c == fn)
                          goto matched;
 
+#if _LIBC
+                       /* This is needed if we goto normal_bracket; from
+                          outside of is_seqval's scope.  */
+                       is_seqval = false;
+#endif
+
                        cold = c;
                        c = *p++;
                      }
 
-                   if (c == L('-') && *p != L(']'))
+                   if (c == L_('-') && *p != L_(']'))
                      {
 #if _LIBC
                        /* We have to find the collation sequence
@@ -618,7 +626,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
 
 # ifdef WIDE_CHAR_VERSION
                        /* Search in the `names' array for the characters.  */
-                       fcollseq = collseq_table_lookup (collseq, fn);
+                       fcollseq = __collseq_table_lookup (collseq, fn);
                        if (fcollseq == ~((uint32_t) 0))
                          /* XXX We don't know anything about the character
                             we are supposed to match.  This means we are
@@ -628,14 +636,14 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                        if (is_seqval)
                          lcollseq = cold;
                        else
-                         lcollseq = collseq_table_lookup (collseq, cold);
+                         lcollseq = __collseq_table_lookup (collseq, cold);
 # else
                        fcollseq = collseq[fn];
                        lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
 # endif
 
-                       is_seqval = 0;
-                       if (cend == L('[') && *p == L('.'))
+                       is_seqval = false;
+                       if (cend == L_('[') && *p == L_('.'))
                          {
                            uint32_t nrules =
                              _NL_CURRENT_WORD (LC_COLLATE,
@@ -646,7 +654,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                            while (1)
                              {
                                c = *++p;
-                               if (c == L('.') && p[1] == L(']'))
+                               if (c == L_('.') && p[1] == L_(']'))
                                  {
                                    p += 2;
                                    break;
@@ -673,7 +681,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                                const int32_t *symb_table;
 # ifdef WIDE_CHAR_VERSION
                                char str[c1];
-                               unsigned int strcnt;
+                               size_t strcnt;
 # else
 #  define str (startp + 1)
 # endif
@@ -708,25 +716,30 @@ FCT (pattern, string, string_end, no_leading_period, flags)
 
                                idx = 0;
                                elem = hash % table_size;
-                               second = hash % (table_size - 2);
-                               while (symb_table[2 * elem] != 0)
+                               if (symb_table[2 * elem] != 0)
                                  {
-                               /* First compare the hashing value.  */
-                                   if (symb_table[2 * elem] == hash
-                                       && (c1
-                                           == extra[symb_table[2 * elem + 1]])
-                                       && memcmp (str,
-                                                  &extra[symb_table[2 * elem + 1]
-                                                        + 1], c1) == 0)
+                                   second = hash % (table_size - 2) + 1;
+
+                                   do
                                      {
-                                       /* Yep, this is the entry.  */
-                                       idx = symb_table[2 * elem + 1];
-                                       idx += 1 + extra[idx];
-                                       break;
+                                       /* First compare the hashing value.  */
+                                       if (symb_table[2 * elem] == hash
+                                           && (c1
+                                               == extra[symb_table[2 * elem + 1]])
+                                           && memcmp (str,
+                                                      &extra[symb_table[2 * elem + 1]
+                                                             + 1], c1) == 0)
+                                         {
+                                           /* Yep, this is the entry.  */
+                                           idx = symb_table[2 * elem + 1];
+                                           idx += 1 + extra[idx];
+                                           break;
+                                         }
+
+                                       /* Next entry.  */
+                                       elem += second;
                                      }
-
-                                   /* Next entry.  */
-                                   elem += second;
+                                   while (symb_table[2 * elem] != 0);
                                  }
 
                                if (symb_table[2 * elem] != 0)
@@ -743,7 +756,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                                    wextra = (int32_t *) &extra[idx + 4];
 # endif
                                    /* Get the collation sequence value.  */
-                                   is_seqval = 1;
+                                   is_seqval = true;
 # ifdef WIDE_CHAR_VERSION
                                    cend = wextra[1 + wextra[idx]];
 # else
@@ -765,9 +778,9 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                          }
                        else
                          {
-                           if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
+                           if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
                              cend = *p++;
-                           if (cend == L('\0'))
+                           if (cend == L_('\0'))
                              return FNM_NOMATCH;
                            cend = FOLD (cend);
                          }
@@ -790,7 +803,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                              {
 # ifdef WIDE_CHAR_VERSION
                                hcollseq =
-                                 collseq_table_lookup (collseq, cend);
+                                 __collseq_table_lookup (collseq, cend);
                                if (hcollseq == ~((uint32_t) 0))
                                  {
                                    /* Hum, no information about the upper
@@ -819,9 +832,9 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                           and sometimes fatal consequences.  */
                        UCHAR cend = *p++;
 
-                       if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
+                       if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
                          cend = *p++;
-                       if (cend == L('\0'))
+                       if (cend == L_('\0'))
                          return FNM_NOMATCH;
 
                        /* It is a range.  */
@@ -833,7 +846,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                      }
                  }
 
-               if (c == L(']'))
+               if (c == L_(']'))
                  break;
              }
 
@@ -848,18 +861,18 @@ FCT (pattern, string, string_end, no_leading_period, flags)
              ignore_next:
                c = *p++;
 
-               if (c == L('\0'))
+               if (c == L_('\0'))
                  /* [... (unterminated) loses.  */
                  return FNM_NOMATCH;
 
-               if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+               if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
                  {
-                   if (*p == L('\0'))
+                   if (*p == L_('\0'))
                      return FNM_NOMATCH;
                    /* XXX 1003.2d11 is unclear if this is right.  */
                    ++p;
                  }
-               else if (c == L('[') && *p == L(':'))
+               else if (c == L_('[') && *p == L_(':'))
                  {
                    int c1 = 0;
                    const CHAR *startp = p;
@@ -870,10 +883,10 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                        if (++c1 == CHAR_CLASS_MAX_LENGTH)
                          return FNM_NOMATCH;
 
-                       if (*p == L(':') && p[1] == L(']'))
+                       if (*p == L_(':') && p[1] == L_(']'))
                          break;
 
-                       if (c < L('a') || c >= L('z'))
+                       if (c < L_('a') || c >= L_('z'))
                          {
                            p = startp;
                            goto ignore_next;
@@ -882,18 +895,18 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                    p += 2;
                    c = *p++;
                  }
-               else if (c == L('[') && *p == L('='))
+               else if (c == L_('[') && *p == L_('='))
                  {
                    c = *++p;
-                   if (c == L('\0'))
+                   if (c == L_('\0'))
                      return FNM_NOMATCH;
                    c = *++p;
-                   if (c != L('=') || p[1] != L(']'))
+                   if (c != L_('=') || p[1] != L_(']'))
                      return FNM_NOMATCH;
                    p += 2;
                    c = *p++;
                  }
-               else if (c == L('[') && *p == L('.'))
+               else if (c == L_('[') && *p == L_('.'))
                  {
                    ++p;
                    while (1)
@@ -902,22 +915,22 @@ FCT (pattern, string, string_end, no_leading_period, flags)
                        if (c == '\0')
                          return FNM_NOMATCH;
 
-                       if (*p == L('.') && p[1] == L(']'))
+                       if (*p == L_('.') && p[1] == L_(']'))
                          break;
                      }
                    p += 2;
                    c = *p++;
                  }
              }
-           while (c != L(']'));
+           while (c != L_(']'));
            if (not)
              return FNM_NOMATCH;
          }
          break;
 
-       case L('+'):
-       case L('@'):
-       case L('!'):
+       case L_('+'):
+       case L_('@'):
+       case L_('!'):
          if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
            {
              int res;
@@ -928,13 +941,13 @@ FCT (pattern, string, string_end, no_leading_period, flags)
            }
          goto normal_match;
 
-       case L('/'):
+       case L_('/'):
          if (NO_LEADING_PERIOD (flags))
            {
-             if (n == string_end || c != *n)
+             if (n == string_end || c != (UCHAR) *n)
                return FNM_NOMATCH;
 
-             new_no_leading_period = 1;
+             new_no_leading_period = true;
              break;
            }
          /* FALLTHROUGH */
@@ -951,7 +964,7 @@ FCT (pattern, string, string_end, no_leading_period, flags)
   if (n == string_end)
     return 0;
 
-  if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/'))
+  if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/'))
     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
     return 0;
 
@@ -966,10 +979,10 @@ END (const CHAR *pattern)
   const CHAR *p = pattern;
 
   while (1)
-    if (*++p == L('\0'))
+    if (*++p == L_('\0'))
       /* This is an invalid pattern.  */
       return pattern;
-    else if (*p == L('['))
+    else if (*p == L_('['))
       {
        /* Handle brackets special.  */
        if (posixly_correct == 0)
@@ -977,21 +990,21 @@ END (const CHAR *pattern)
 
        /* Skip the not sign.  We have to recognize it because of a possibly
           following ']'.  */
-       if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
+       if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
          ++p;
        /* A leading ']' is recognized as such.  */
-       if (*p == L(']'))
+       if (*p == L_(']'))
          ++p;
        /* Skip over all characters of the list.  */
-       while (*p != L(']'))
-         if (*p++ == L('\0'))
+       while (*p != L_(']'))
+         if (*p++ == L_('\0'))
            /* This is no valid pattern.  */
            return pattern;
       }
-    else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
-             || *p == L('!')) && p[1] == L('('))
+    else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
+             || *p == L_('!')) && p[1] == L_('('))
       p = END (p + 1);
-    else if (*p == L(')'))
+    else if (*p == L_(')'))
       break;
 
   return p + 1;
@@ -1001,10 +1014,10 @@ END (const CHAR *pattern)
 static int
 internal_function
 EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
-     int no_leading_period, int flags)
+     bool no_leading_period, int flags)
 {
   const CHAR *startp;
-  int level;
+  size_t level;
   struct patternlist
   {
     struct patternlist *next;
@@ -1014,14 +1027,15 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
   size_t pattern_len = STRLEN (pattern);
   const CHAR *p;
   const CHAR *rs;
+  enum { ALLOCA_LIMIT = 8000 };
 
   /* Parse the pattern.  Store the individual parts in the list.  */
   level = 0;
-  for (startp = p = pattern + 1; level >= 0; ++p)
-    if (*p == L('\0'))
+  for (startp = p = pattern + 1; ; ++p)
+    if (*p == L_('\0'))
       /* This is an invalid pattern.  */
       return -1;
-    else if (*p == L('['))
+    else if (*p == L_('['))
       {
        /* Handle brackets special.  */
        if (posixly_correct == 0)
@@ -1029,43 +1043,51 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
 
        /* Skip the not sign.  We have to recognize it because of a possibly
           following ']'.  */
-       if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
+       if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
          ++p;
        /* A leading ']' is recognized as such.  */
-       if (*p == L(']'))
+       if (*p == L_(']'))
          ++p;
        /* Skip over all characters of the list.  */
-       while (*p != L(']'))
-         if (*p++ == L('\0'))
+       while (*p != L_(']'))
+         if (*p++ == L_('\0'))
            /* This is no valid pattern.  */
            return -1;
       }
-    else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
-             || *p == L('!')) && p[1] == L('('))
+    else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
+             || *p == L_('!')) && p[1] == L_('('))
       /* Remember the nesting level.  */
       ++level;
-    else if (*p == L(')'))
+    else if (*p == L_(')'))
       {
        if (level-- == 0)
          {
            /* This means we found the end of the pattern.  */
 #define NEW_PATTERN \
            struct patternlist *newp;                                         \
+           size_t plen;                                                      \
+           size_t plensize;                                                  \
+           size_t newpsize;                                                  \
                                                                              \
-           if (opt == L('?') || opt == L('@'))                               \
-             newp = alloca (offsetof (struct patternlist, str)               \
-                            + (pattern_len * sizeof (CHAR)));                \
-           else                                                              \
-             newp = alloca (offsetof (struct patternlist, str)               \
-                            + ((p - startp + 1) * sizeof (CHAR)));           \
-           *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0');    \
+           plen = (opt == L_('?') || opt == L_('@')                          \
+                   ? pattern_len                                             \
+                   : p - startp + 1);                                        \
+           plensize = plen * sizeof (CHAR);                                  \
+           newpsize = offsetof (struct patternlist, str) + plensize;         \
+           if ((size_t) -1 / sizeof (CHAR) < plen                            \
+               || newpsize < offsetof (struct patternlist, str)              \
+               || ALLOCA_LIMIT <= newpsize)                                  \
+             return -1;                                                      \
+           newp = (struct patternlist *) alloca (newpsize);                  \
+           *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0');    \
            newp->next = NULL;                                                \
            *lastp = newp;                                                    \
            lastp = &newp->next
            NEW_PATTERN;
+           break;
          }
       }
-    else if (*p == L('|'))
+    else if (*p == L_('|'))
       {
        if (level == 0)
          {
@@ -1074,17 +1096,17 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
          }
       }
   assert (list != NULL);
-  assert (p[-1] == L(')'));
+  assert (p[-1] == L_(')'));
 #undef NEW_PATTERN
 
   switch (opt)
     {
-    case L('*'):
+    case L_('*'):
       if (FCT (p, string, string_end, no_leading_period, flags) == 0)
        return 0;
       /* FALLTHROUGH */
 
-    case L('+'):
+    case L_('+'):
       do
        {
          for (rs = string; rs <= string_end; ++rs)
@@ -1097,7 +1119,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
                && (FCT (p, rs, string_end,
                         rs == string
                         ? no_leading_period
-                        : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+                        : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
                         flags & FNM_FILE_NAME
                         ? flags : flags & ~FNM_PERIOD) == 0
                    /* This didn't work.  Try the whole pattern.  */
@@ -1105,8 +1127,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
                        && FCT (pattern - 1, rs, string_end,
                                rs == string
                                ? no_leading_period
-                               : (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
-                                  ? 1 : 0),
+                               : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
                                flags & FNM_FILE_NAME
                                ? flags : flags & ~FNM_PERIOD) == 0)))
              /* It worked.  Signal success.  */
@@ -1117,12 +1138,12 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
       /* None of the patterns lead to a match.  */
       return FNM_NOMATCH;
 
-    case L('?'):
+    case L_('?'):
       if (FCT (p, string, string_end, no_leading_period, flags) == 0)
        return 0;
       /* FALLTHROUGH */
 
-    case L('@'):
+    case L_('@'):
       do
        /* I cannot believe it but `strcat' is actually acceptable
           here.  Match the entire string with the prefix from the
@@ -1138,7 +1159,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
       /* None of the patterns lead to a match.  */
       return FNM_NOMATCH;
 
-    case L('!'):
+    case L_('!'):
       for (rs = string; rs <= string_end; ++rs)
        {
          struct patternlist *runp;
@@ -1153,7 +1174,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
              && (FCT (p, rs, string_end,
                       rs == string
                       ? no_leading_period
-                      : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+                      : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
                       flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
                  == 0))
            /* This is successful.  */
@@ -1185,5 +1206,5 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
 #undef STRCOLL
 #undef STRLEN
 #undef STRCAT
-#undef L
+#undef L_
 #undef BTOWC