diff mbox series

[5/5] posix: Sync fnmatch with gnulib

Message ID 20201230201507.2755086-5-adhemerval.zanella@linaro.org
State Committed
Headers show
Series [1/5] posix: Sync regex code with gnulib | expand

Commit Message

Adhemerval Zanella Dec. 30, 2020, 8:15 p.m. UTC
It sync with gnulib commit 43ee1a6bf with following changes:

Comments

Paul Eggert Dec. 31, 2020, 9:54 p.m. UTC | #1
On 12/30/20 12:15 PM, Adhemerval Zanella wrote:

> -  ssize_t level;
> +  size_t level;

'level' should be ptrdiff_t not ssize_t, for portability to 
(now-ancient, but still allowed by POSIX) hosts where ssize_t is 32 bits 
and size_t is 64 bits.

> -    CHAR str[];
> +    CHAR str[FLEXIBLE_ARRAY_MEMBER];

This assumes C99 flex array members which is fine for glibc but dubious 
for Gnulib; it should be safer to use __flexarr.

> Because otherwise it triggers some glibc regressions:

Thanks for spotting that. I installed the attached patch into Gnulib, 
which should fix the glibc regressions and the other abovementioned 
glitches, so that you should now be able to sync fnmatch from Gnulib 
unchanged.
diff mbox series

Patch

--- posix/fnmatch_loop.c
+++ ../../gnulib/gnulib-lib/lib/fnmatch_loop.c
@@ -978,12 +978,12 @@ 
      bool no_leading_period, int flags, size_t alloca_used)
 {
   const CHAR *startp;
-  ssize_t level;
+  size_t level;
   struct patternlist
   {
     struct patternlist *next;
     CHAR malloced;
-    CHAR str[];
+    CHAR str[FLEXIBLE_ARRAY_MEMBER];
   } *list = NULL;
   struct patternlist **lastp = &list;
   size_t pattern_len = STRLEN (pattern);
@@ -994,7 +994,7 @@ 

   /* Parse the pattern.  Store the individual parts in the list.  */
   level = 0;
-  for (startp = p = pattern + 1; level >= 0; ++p)
+  for (startp = p = pattern + 1; ; ++p)
     if (*p == L_('\0'))
       {
         /* This is an invalid pattern.  */
@@ -1065,6 +1065,7 @@ 
             *lastp = newp;                                                    \
             lastp = &newp->next
             NEW_PATTERN;
+            break;
           }
       }
     else if (*p == L_('|'))

Because otherwise it triggers some glibc regressions:

FAIL: posix/tst-fnmatch
FAIL: posix/tst-fnmatch-mem
FAIL: posix/tst-fnmatch3

$ cat posix/tst-fnmatch.out
[...]
537: fnmatch ("x?y", "x/y/z", FNM_PATHNAME|FNM_LEADING_DIR) = FNM_NOMATCH
Didn't expect signal from child: got `Aborted'

$ cat posix/tst-fnmatch3.out
Didn't expect signal from child: got `Aborted'

It is due the loops returns early and hits the assert below.

Checked on x86_64-linux-gnu.
---
 posix/fnmatch.c      |  548 +++++-------
 posix/fnmatch_loop.c | 1977 +++++++++++++++++++++---------------------
 2 files changed, 1208 insertions(+), 1317 deletions(-)

diff --git a/posix/fnmatch.c b/posix/fnmatch.c
index 315584f900..c80809e783 100644
--- a/posix/fnmatch.c
+++ b/posix/fnmatch.c
@@ -15,38 +15,29 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#if HAVE_CONFIG_H
-# include <config.h>
+#ifndef _LIBC
+# include <libc-config.h>
 #endif
 
 /* Enable GNU extensions in fnmatch.h.  */
 #ifndef _GNU_SOURCE
-# define _GNU_SOURCE	1
+# define _GNU_SOURCE    1
 #endif
 
+#include <fnmatch.h>
+
 #include <assert.h>
 #include <errno.h>
-#include <fnmatch.h>
 #include <ctype.h>
 #include <string.h>
-
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#endif
-
-#ifdef _LIBC
+#include <stdlib.h>
+#if defined _LIBC || HAVE_ALLOCA
 # include <alloca.h>
-#else
-# define alloca_account(size., var) alloca (size)
-#endif
-
-/* For platform which support the ISO C amendement 1 functionality we
-   support user defined character classes.  */
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
-# include <wchar.h>
-# include <wctype.h>
 #endif
+#include <wchar.h>
+#include <wctype.h>
+#include <stddef.h>
+#include <stdbool.h>
 
 /* We need some of the locale data (the collation sequence information)
    but there is no interface to get this information in general.  Therefore
@@ -57,199 +48,125 @@ 
 # include <shlib-compat.h>
 
 # define CONCAT(a,b) __CONCAT(a,b)
+# define btowc __btowc
+# define iswctype __iswctype
 # define mbsrtowcs __mbsrtowcs
+# define mempcpy __mempcpy
+# define strnlen __strnlen
+# define towlower __towlower
+# define wcscat __wcscat
+# define wcslen __wcslen
+# define wctype __wctype
+# define wmemchr __wmemchr
+# define wmempcpy __wmempcpy
 # define fnmatch __fnmatch
 extern int fnmatch (const char *pattern, const char *string, int flags);
 #endif
 
-/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
-#define NO_LEADING_PERIOD(flags) \
-  ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
+#ifdef _LIBC
+# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
+#  define FALLTHROUGH __attribute__ ((__fallthrough__))
+# else
+#  define FALLTHROUGH ((void) 0)
+# endif
+#else
+# include "attribute.h"
+#endif
 
-#if defined _LIBC || !defined __GNU_LIBRARY__
+#include <intprops.h>
+#include <flexmember.h>
 
+#ifdef _LIBC
+typedef ptrdiff_t idx_t;
+#else
+# include "idx.h"
+#endif
 
-# if defined STDC_HEADERS || !defined isascii
-#  define ISASCII(c) 1
-# else
-#  define ISASCII(c) isascii(c)
-# endif
+/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
+#define NO_LEADING_PERIOD(flags) \
+  ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
 
-# ifdef isblank
-#  define ISBLANK(c) (ISASCII (c) && isblank (c))
+#ifndef _LIBC
+# if HAVE_ALLOCA
+/* The OS usually guarantees only one guard page at the bottom of the stack,
+   and a page size can be as small as 4096 bytes.  So we cannot safely
+   allocate anything larger than 4096 bytes.  Also care for the possibility
+   of a few compiler-allocated temporary stack slots.  */
+#  define __libc_use_alloca(n) ((n) < 4032)
 # else
-#  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-# endif
-# ifdef isgraph
-#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
-# else
-#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+/* Just use malloc.  */
+#  define __libc_use_alloca(n) false
+#  undef alloca
+#  define alloca(n) malloc (n)
 # endif
+# define alloca_account(size, avar) ((avar) += (size), alloca (size))
+#endif
 
-# define ISPRINT(c) (ISASCII (c) && isprint (c))
-# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
-# define ISALNUM(c) (ISASCII (c) && isalnum (c))
-# define ISALPHA(c) (ISASCII (c) && isalpha (c))
-# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
-# define ISLOWER(c) (ISASCII (c) && islower (c))
-# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
-# define ISSPACE(c) (ISASCII (c) && isspace (c))
-# define ISUPPER(c) (ISASCII (c) && isupper (c))
-# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
-
-# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-
-# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-/* The GNU C library provides support for user-defined character classes
-   and the functions from ISO C amendement 1.  */
-#  ifdef CHARCLASS_NAME_MAX
-#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
-#  else
+/* Provide support for user-defined character classes, based on the functions
+   from ISO C 90 amendment 1.  */
+#ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#else
 /* This shouldn't happen but some implementation might still have this
    problem.  Use a reasonable default value.  */
-#   define CHAR_CLASS_MAX_LENGTH 256
-#  endif
-
-#  ifdef _LIBC
-#   define IS_CHAR_CLASS(string) __wctype (string)
-#  else
-#   define IS_CHAR_CLASS(string) wctype (string)
-#  endif
-
-#  ifdef _LIBC
-#   define ISWCTYPE(WC, WT)	__iswctype (WC, WT)
-#  else
-#   define ISWCTYPE(WC, WT)	iswctype (WC, WT)
-#  endif
-
-#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
-/* In this case we are implementing the multibyte character handling.  */
-#   define HANDLE_MULTIBYTE	1
-#  endif
+# define CHAR_CLASS_MAX_LENGTH 256
+#endif
 
-# else
-#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
-
-#  define IS_CHAR_CLASS(string)						      \
-   (STREQ (string, "alpha") || STREQ (string, "upper")			      \
-    || STREQ (string, "lower") || STREQ (string, "digit")		      \
-    || STREQ (string, "alnum") || STREQ (string, "xdigit")		      \
-    || STREQ (string, "space") || STREQ (string, "print")		      \
-    || STREQ (string, "punct") || STREQ (string, "graph")		      \
-    || STREQ (string, "cntrl") || STREQ (string, "blank"))
-# endif
+#define IS_CHAR_CLASS(string) wctype (string)
 
 /* Avoid depending on library functions or files
    whose names are inconsistent.  */
 
-# if !defined _LIBC && !defined getenv
-extern char *getenv ();
-# endif
-
-# ifndef errno
-extern int errno;
-# endif
-
 /* Global variable.  */
 static int posixly_correct;
 
-/* This function doesn't exist on most systems.  */
-
-# if !defined HAVE___STRCHRNUL && !defined _LIBC
-static char *
-__strchrnul (const char *s, int c)
-{
-  char *result = strchr (s, c);
-  if (result == NULL)
-    result = strchr (s, '\0');
-  return result;
-}
-# endif
-
-# if HANDLE_MULTIBYTE && !defined HAVE___STRCHRNUL && !defined _LIBC
-static wchar_t *
-__wcschrnul (const wchar_t *s, wint_t c)
-{
-  wchar_t *result = wcschr (s, c);
-  if (result == NULL)
-    result = wcschr (s, '\0');
-  return result;
-}
-# endif
-
 /* Note that this evaluates C many times.  */
-# ifdef _LIBC
-#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
-# else
-#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
-# endif
-# define CHAR	char
-# define UCHAR	unsigned char
-# define INT	int
-# define FCT	internal_fnmatch
-# define EXT	ext_match
-# define END	end_pattern
-# define STRUCT	fnmatch_struct
-# define L(CS)	CS
-# ifdef _LIBC
-#  define BTOWC(C)	__btowc (C)
-# else
-#  define BTOWC(C)	btowc (C)
-# endif
-# define STRLEN(S) strlen (S)
-# define STRCAT(D, S) strcat (D, S)
-# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
-# define MEMCHR(S, C, N) memchr (S, C, N)
-# define STRCOLL(S1, S2) strcoll (S1, S2)
-# define WIDE_CHAR_VERSION 0
+#define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+#define CHAR    char
+#define UCHAR   unsigned char
+#define INT     int
+#define FCT     internal_fnmatch
+#define EXT     ext_match
+#define END     end_pattern
+#define STRUCT  fnmatch_struct
+#define L_(CS)  CS
+#define BTOWC(C) btowc (C)
+#define STRLEN(S) strlen (S)
+#define STRCAT(D, S) strcat (D, S)
+#define MEMPCPY(D, S, N) mempcpy (D, S, N)
+#define MEMCHR(S, C, N) memchr (S, C, N)
+#define WIDE_CHAR_VERSION 0
+#ifdef _LIBC
 # include <locale/weight.h>
 # define FINDIDX findidx
-# include "fnmatch_loop.c"
-
-
-# if HANDLE_MULTIBYTE
-/* Note that this evaluates C many times.  */
-#  ifdef _LIBC
-#   define FOLD(c) ((flags & FNM_CASEFOLD) ? __towlower (c) : (c))
-#  else
-#   define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? towlower (c) : (c))
-#  endif
-#  define CHAR	wchar_t
-#  define UCHAR	wint_t
-#  define INT	wint_t
-#  define FCT	internal_fnwmatch
-#  define EXT	ext_wmatch
-#  define END	end_wpattern
-#  define STRUCT fnwmatch_struct
-#  define L(CS)	L##CS
-#  define BTOWC(C)	(C)
-#  define STRLEN(S) __wcslen (S)
-#  define STRCAT(D, S) __wcscat (D, S)
-#  define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
-#  define MEMCHR(S, C, N) __wmemchr (S, C, N)
-#  define STRCOLL(S1, S2) wcscoll (S1, S2)
-#  ifdef _LIBC
-#   define WMEMCMP(S1, S2, N) __wmemcmp (S1, S2, N)
-#  else
-#   define WMEMCMP(S1, S2, N) wmemcmp (S1, S2, N)
-#  endif
-#  define WIDE_CHAR_VERSION 1
+#endif
+#include "fnmatch_loop.c"
+
+
+#define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
+#define CHAR    wchar_t
+#define UCHAR   wint_t
+#define INT     wint_t
+#define FCT     internal_fnwmatch
+#define EXT     ext_wmatch
+#define END     end_wpattern
+#define L_(CS)  L##CS
+#define BTOWC(C) (C)
+#define STRLEN(S) wcslen (S)
+#define STRCAT(D, S) wcscat (D, S)
+#define MEMPCPY(D, S, N) wmempcpy (D, S, N)
+#define MEMCHR(S, C, N) wmemchr (S, C, N)
+#define WIDE_CHAR_VERSION 1
+#ifdef _LIBC
 /* Change the name the header defines so it doesn't conflict with
    the <locale/weight.h> version included above.  */
-#  define findidx findidxwc
-#  include <locale/weightwc.h>
-#  undef findidx
-#  define FINDIDX findidxwc
+# define findidx findidxwc
+# include <locale/weightwc.h>
+# undef findidx
+# define FINDIDX findidxwc
+#endif
 
-#  undef IS_CHAR_CLASS
+#undef IS_CHAR_CLASS
 /* We have to convert the wide character string in a multibyte string.  But
    we know that the character class names consist of alphanumeric characters
    from the portable character set, and since the wide character encoding
@@ -265,42 +182,42 @@  is_char_class (const wchar_t *wcs)
   do
     {
       /* Test for a printable character from the portable character set.  */
-#  ifdef _LIBC
+#ifdef _LIBC
       if (*wcs < 0x20 || *wcs > 0x7e
-	  || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
-	return (wctype_t) 0;
-#  else
+          || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
+        return (wctype_t) 0;
+#else
       switch (*wcs)
-	{
-	case L' ': case L'!': case L'"': case L'#': case L'%':
-	case L'&': case L'\'': case L'(': case L')': case L'*':
-	case L'+': case L',': case L'-': case L'.': case L'/':
-	case L'0': case L'1': case L'2': case L'3': case L'4':
-	case L'5': case L'6': case L'7': case L'8': case L'9':
-	case L':': case L';': case L'<': case L'=': case L'>':
-	case L'?':
-	case L'A': case L'B': case L'C': case L'D': case L'E':
-	case L'F': case L'G': case L'H': case L'I': case L'J':
-	case L'K': case L'L': case L'M': case L'N': case L'O':
-	case L'P': case L'Q': case L'R': case L'S': case L'T':
-	case L'U': case L'V': case L'W': case L'X': case L'Y':
-	case L'Z':
-	case L'[': case L'\\': case L']': case L'^': case L'_':
-	case L'a': case L'b': case L'c': case L'd': case L'e':
-	case L'f': case L'g': case L'h': case L'i': case L'j':
-	case L'k': case L'l': case L'm': case L'n': case L'o':
-	case L'p': case L'q': case L'r': case L's': case L't':
-	case L'u': case L'v': case L'w': case L'x': case L'y':
-	case L'z': case L'{': case L'|': case L'}': case L'~':
-	  break;
-	default:
-	  return (wctype_t) 0;
-	}
-#  endif
+        {
+        case L' ': case L'!': case L'"': case L'#': case L'%':
+        case L'&': case L'\'': case L'(': case L')': case L'*':
+        case L'+': case L',': case L'-': case L'.': case L'/':
+        case L'0': case L'1': case L'2': case L'3': case L'4':
+        case L'5': case L'6': case L'7': case L'8': case L'9':
+        case L':': case L';': case L'<': case L'=': case L'>':
+        case L'?':
+        case L'A': case L'B': case L'C': case L'D': case L'E':
+        case L'F': case L'G': case L'H': case L'I': case L'J':
+        case L'K': case L'L': case L'M': case L'N': case L'O':
+        case L'P': case L'Q': case L'R': case L'S': case L'T':
+        case L'U': case L'V': case L'W': case L'X': case L'Y':
+        case L'Z':
+        case L'[': case L'\\': case L']': case L'^': case L'_':
+        case L'a': case L'b': case L'c': case L'd': case L'e':
+        case L'f': case L'g': case L'h': case L'i': case L'j':
+        case L'k': case L'l': case L'm': case L'n': case L'o':
+        case L'p': case L'q': case L'r': case L's': case L't':
+        case L'u': case L'v': case L'w': case L'x': case L'y':
+        case L'z': case L'{': case L'|': case L'}': case L'~':
+          break;
+        default:
+          return (wctype_t) 0;
+        }
+#endif
 
       /* Avoid overrunning the buffer.  */
       if (cp == s + CHAR_CLASS_MAX_LENGTH)
-	return (wctype_t) 0;
+        return (wctype_t) 0;
 
       *cp++ = (char) *wcs++;
     }
@@ -308,23 +225,17 @@  is_char_class (const wchar_t *wcs)
 
   *cp = '\0';
 
-#  ifdef _LIBC
-  return __wctype (s);
-#  else
   return wctype (s);
-#  endif
 }
-#  define IS_CHAR_CLASS(string) is_char_class (string)
+#define IS_CHAR_CLASS(string) is_char_class (string)
 
-#  include "fnmatch_loop.c"
-# endif
+#include "fnmatch_loop.c"
 
 
 int
 fnmatch (const char *pattern, const char *string, int flags)
 {
-# if HANDLE_MULTIBYTE
-  if (__builtin_expect (MB_CUR_MAX, 1) != 1)
+  if (__glibc_unlikely (MB_CUR_MAX != 1))
     {
       mbstate_t ps;
       size_t n;
@@ -338,126 +249,113 @@  fnmatch (const char *pattern, const char *string, int flags)
       /* Convert the strings into wide characters.  */
       memset (&ps, '\0', sizeof (ps));
       p = pattern;
-#ifdef _LIBC
-      n = __strnlen (pattern, 1024);
-#else
-      n = strlen (pattern);
-#endif
+      n = strnlen (pattern, 1024);
       if (__glibc_likely (n < 1024))
-	{
-	  wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
-						 alloca_used);
-	  n = mbsrtowcs (wpattern, &p, n + 1, &ps);
-	  if (__glibc_unlikely (n == (size_t) -1))
-	    /* Something wrong.
-	       XXX Do we have to set `errno' to something which mbsrtows hasn't
-	       already done?  */
-	    return -1;
-	  if (p)
-	    {
-	      memset (&ps, '\0', sizeof (ps));
-	      goto prepare_wpattern;
-	    }
-	}
+        {
+          wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
+                                                 alloca_used);
+          n = mbsrtowcs (wpattern, &p, n + 1, &ps);
+          if (__glibc_unlikely (n == (size_t) -1))
+            /* Something wrong.
+               XXX Do we have to set 'errno' to something which mbsrtows hasn't
+               already done?  */
+            return -1;
+          if (p)
+            {
+              memset (&ps, '\0', sizeof (ps));
+              goto prepare_wpattern;
+            }
+        }
       else
-	{
-	prepare_wpattern:
-	  n = mbsrtowcs (NULL, &pattern, 0, &ps);
-	  if (__glibc_unlikely (n == (size_t) -1))
-	    /* Something wrong.
-	       XXX Do we have to set `errno' to something which mbsrtows hasn't
-	       already done?  */
-	    return -1;
-	  if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
-	    {
-	      __set_errno (ENOMEM);
-	      return -2;
-	    }
-	  wpattern_malloc = wpattern
-	    = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
-	  assert (mbsinit (&ps));
-	  if (wpattern == NULL)
-	    return -2;
-	  (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
-	}
+        {
+        prepare_wpattern:
+          n = mbsrtowcs (NULL, &pattern, 0, &ps);
+          if (__glibc_unlikely (n == (size_t) -1))
+            /* Something wrong.
+               XXX Do we have to set 'errno' to something which mbsrtows hasn't
+               already done?  */
+            return -1;
+          if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
+            {
+              __set_errno (ENOMEM);
+              return -2;
+            }
+          wpattern_malloc = wpattern
+            = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
+          assert (mbsinit (&ps));
+          if (wpattern == NULL)
+            return -2;
+          (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
+        }
 
       assert (mbsinit (&ps));
-#ifdef _LIBC
-      n = __strnlen (string, 1024);
-#else
-      n = strlen (string);
-#endif
+      n = strnlen (string, 1024);
       p = string;
       if (__glibc_likely (n < 1024))
-	{
-	  wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
-						alloca_used);
-	  n = mbsrtowcs (wstring, &p, n + 1, &ps);
-	  if (__glibc_unlikely (n == (size_t) -1))
-	    {
-	      /* Something wrong.
-		 XXX Do we have to set `errno' to something which
-		 mbsrtows hasn't already done?  */
-	    free_return:
-	      free (wpattern_malloc);
-	      return -1;
-	    }
-	  if (p)
-	    {
-	      memset (&ps, '\0', sizeof (ps));
-	      goto prepare_wstring;
-	    }
-	}
+        {
+          wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
+                                                alloca_used);
+          n = mbsrtowcs (wstring, &p, n + 1, &ps);
+          if (__glibc_unlikely (n == (size_t) -1))
+            {
+              /* Something wrong.
+                 XXX Do we have to set 'errno' to something which
+                 mbsrtows hasn't already done?  */
+            free_return:
+              free (wpattern_malloc);
+              return -1;
+            }
+          if (p)
+            {
+              memset (&ps, '\0', sizeof (ps));
+              goto prepare_wstring;
+            }
+        }
       else
-	{
-	prepare_wstring:
-	  n = mbsrtowcs (NULL, &string, 0, &ps);
-	  if (__glibc_unlikely (n == (size_t) -1))
-	    /* Something wrong.
-	       XXX Do we have to set `errno' to something which mbsrtows hasn't
-	       already done?  */
-	    goto free_return;
-	  if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
-	    {
-	      free (wpattern_malloc);
-	      __set_errno (ENOMEM);
-	      return -2;
-	    }
-
-	  wstring_malloc = wstring
-	    = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
-	  if (wstring == NULL)
-	    {
-	      free (wpattern_malloc);
-	      return -2;
-	    }
-	  assert (mbsinit (&ps));
-	  (void) mbsrtowcs (wstring, &string, n + 1, &ps);
-	}
+        {
+        prepare_wstring:
+          n = mbsrtowcs (NULL, &string, 0, &ps);
+          if (__glibc_unlikely (n == (size_t) -1))
+            /* Something wrong.
+               XXX Do we have to set 'errno' to something which mbsrtows hasn't
+               already done?  */
+            goto free_return;
+          if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
+            {
+              free (wpattern_malloc);
+              __set_errno (ENOMEM);
+              return -2;
+            }
+
+          wstring_malloc = wstring
+            = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
+          if (wstring == NULL)
+            {
+              free (wpattern_malloc);
+              return -2;
+            }
+          assert (mbsinit (&ps));
+          (void) mbsrtowcs (wstring, &string, n + 1, &ps);
+        }
 
       int res = internal_fnwmatch (wpattern, wstring, wstring + n,
-				   flags & FNM_PERIOD, flags, NULL,
-				   alloca_used);
+                                   flags & FNM_PERIOD, flags, NULL,
+                                   alloca_used);
 
       free (wstring_malloc);
       free (wpattern_malloc);
 
       return res;
     }
-# endif  /* mbstate_t and mbsrtowcs or _LIBC.  */
 
   return internal_fnmatch (pattern, string, string + strlen (string),
-			   flags & FNM_PERIOD, flags, NULL, 0);
+                           flags & FNM_PERIOD, flags, NULL, 0);
 }
 
-# ifdef _LIBC
-#  undef fnmatch
+#undef fnmatch
 versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
-#  if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
 strong_alias (__fnmatch, __fnmatch_old)
 compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
-#  endif
+#endif
 libc_hidden_ver (__fnmatch, fnmatch)
-# endif
-
-#endif	/* _LIBC or not __GNU_LIBRARY__.  */
diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
index 0f890d4782..2804eae6b1 100644
--- a/posix/fnmatch_loop.c
+++ b/posix/fnmatch_loop.c
@@ -15,28 +15,30 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <stdint.h>
+#ifdef _LIBC
+# include <stdint.h>
+#endif
 
 struct STRUCT
 {
   const CHAR *pattern;
   const CHAR *string;
-  int no_leading_period;
+  bool no_leading_period;
 };
 
-/* 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,
-		struct STRUCT *ends, size_t alloca_used);
+                const CHAR *string_end, bool no_leading_period, int flags,
+                struct STRUCT *ends, size_t alloca_used);
 static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
-		const CHAR *string_end, int no_leading_period, int flags,
-		size_t alloca_used);
+                const CHAR *string_end, bool no_leading_period, int flags,
+                size_t alloca_used);
 static const CHAR *END (const CHAR *patternp);
 
 static int
 FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
-     int no_leading_period, int flags, struct STRUCT *ends, size_t alloca_used)
+     bool no_leading_period, int flags, struct STRUCT *ends, size_t alloca_used)
 {
   const CHAR *p = pattern, *n = string;
   UCHAR c;
@@ -50,882 +52,868 @@  FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
 # 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('?'):
-	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
-	    {
-	      int res = EXT (c, p, n, string_end, no_leading_period,
-			     flags, alloca_used);
-	      if (res != -1)
-		return res;
-	    }
-
-	  if (n == string_end)
-	    return FNM_NOMATCH;
-	  else if (*n == L('/') && (flags & FNM_FILE_NAME))
-	    return FNM_NOMATCH;
-	  else if (*n == L('.') && no_leading_period)
-	    return FNM_NOMATCH;
-	  break;
-
-	case L('\\'):
-	  if (!(flags & FNM_NOESCAPE))
-	    {
-	      c = *p++;
-	      if (c == L('\0'))
-		/* Trailing \ loses.  */
-		return FNM_NOMATCH;
-	      c = FOLD (c);
-	    }
-	  if (n == string_end || FOLD ((UCHAR) *n) != c)
-	    return FNM_NOMATCH;
-	  break;
-
-	case L('*'):
-	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
-	    {
-	      int res = EXT (c, p, n, string_end, no_leading_period,
-			     flags, alloca_used);
-	      if (res != -1)
-		return res;
-	    }
-	  else if (ends != NULL)
-	    {
-	      ends->pattern = p - 1;
-	      ends->string = n;
-	      ends->no_leading_period = no_leading_period;
-	      return 0;
-	    }
-
-	  if (n != string_end && *n == L('.') && no_leading_period)
-	    return FNM_NOMATCH;
-
-	  for (c = *p++; c == L('?') || c == L('*'); c = *p++)
-	    {
-	      if (*p == L('(') && (flags & FNM_EXTMATCH) != 0)
-		{
-		  const CHAR *endp = END (p);
-		  if (endp != p)
-		    {
-		      /* This is a pattern.  Skip over it.  */
-		      p = endp;
-		      continue;
-		    }
-		}
-
-	      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('/')
-			   && __builtin_expect (flags & FNM_FILE_NAME, 0))
-		    /* A slash does not match a wildcard under
-		       FNM_FILE_NAME.  */
-		    return FNM_NOMATCH;
-		  else
-		    /* One character of the string is consumed in matching
-		       this ? wildcard, so *??? won't match if there are
-		       less than three characters.  */
-		    ++n;
-		}
-	    }
-
-	  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
-	       flag is set.  */
-	    {
-	      int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
-
-	      if (flags & FNM_FILE_NAME)
-		{
-		  if (flags & FNM_LEADING_DIR)
-		    result = 0;
-		  else
-		    {
-		      if (MEMCHR (n, L('/'), string_end - n) == NULL)
-			result = 0;
-		    }
-		}
-
-	      return result;
-	    }
-	  else
-	    {
-	      const CHAR *endp;
-	      struct STRUCT end;
-
-	      end.pattern = NULL;
-	      endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'),
-			     string_end - n);
-	      if (endp == NULL)
-		endp = string_end;
-
-	      if (c == L('[')
-		  || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
-		      && (c == L('@') || c == L('+') || c == L('!'))
-		      && *p == L('(')))
-		{
-		  int flags2 = ((flags & FNM_FILE_NAME)
-				? flags : (flags & ~FNM_PERIOD));
-
-		  for (--p; n < endp; ++n, no_leading_period = 0)
-		    if (FCT (p, n, string_end, no_leading_period, flags2,
-			     &end, alloca_used) == 0)
-		      goto found;
-		}
-	      else if (c == L('/') && (flags & FNM_FILE_NAME))
-		{
-		  while (n < string_end && *n != L('/'))
-		    ++n;
-		  if (n < string_end && *n == L('/')
-		      && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
-			       NULL, alloca_used) == 0))
-		    return 0;
-		}
-	      else
-		{
-		  int flags2 = ((flags & FNM_FILE_NAME)
-				? flags : (flags & ~FNM_PERIOD));
-
-		  if (c == L('\\') && !(flags & FNM_NOESCAPE))
-		    c = *p;
-		  c = FOLD (c);
-		  for (--p; n < endp; ++n, no_leading_period = 0)
-		    if (FOLD ((UCHAR) *n) == c
-			&& (FCT (p, n, string_end, no_leading_period, flags2,
-				 &end, alloca_used) == 0))
-		      {
-		      found:
-			if (end.pattern == NULL)
-			  return 0;
-			break;
-		      }
-		  if (end.pattern != NULL)
-		    {
-		      p = end.pattern;
-		      n = end.string;
-		      no_leading_period = end.no_leading_period;
-		      continue;
-		    }
-		}
-	    }
-
-	  /* If we come here no match is possible with the wildcard.  */
-	  return FNM_NOMATCH;
-
-	case L('['):
-	  {
-	    /* Nonzero if the sense of the character class is inverted.  */
-	    const CHAR *p_init = p;
-	    const CHAR *n_init = n;
-	    int not;
-	    CHAR cold;
-	    UCHAR fn;
-
-	    if (posixly_correct == 0)
-	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
-
-	    if (n == string_end)
-	      return FNM_NOMATCH;
-
-	    if (*n == L('.') && no_leading_period)
-	      return FNM_NOMATCH;
-
-	    if (*n == L('/') && (flags & FNM_FILE_NAME))
-	      /* `/' cannot be matched.  */
-	      return FNM_NOMATCH;
-
-	    not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
-	    if (not)
-	      ++p;
-
-	    fn = FOLD ((UCHAR) *n);
-
-	    c = *p++;
-	    for (;;)
-	      {
-		if (!(flags & FNM_NOESCAPE) && c == L('\\'))
-		  {
-		    if (*p == L('\0'))
-		      return FNM_NOMATCH;
-		    c = FOLD ((UCHAR) *p);
-		    ++p;
-
-		    goto normal_bracket;
-		  }
-		else if (c == L('[') && *p == L(':'))
-		  {
-		    /* Leave room for the null.  */
-		    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
-		    size_t c1 = 0;
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-		    wctype_t wt;
-#endif
-		    const CHAR *startp = p;
-
-		    for (;;)
-		      {
-			if (c1 == CHAR_CLASS_MAX_LENGTH)
-			  /* The name is too long and therefore the pattern
-			     is ill-formed.  */
-			  return FNM_NOMATCH;
-
-			c = *++p;
-			if (c == L(':') && p[1] == L(']'))
-			  {
-			    p += 2;
-			    break;
-			  }
-			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('[');
-			    goto normal_bracket;
-			  }
-			str[c1++] = c;
-		      }
-		    str[c1] = L('\0');
-
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-		    wt = IS_CHAR_CLASS (str);
-		    if (wt == 0)
-		      /* Invalid character class name.  */
-		      return FNM_NOMATCH;
-
-# if defined _LIBC && ! WIDE_CHAR_VERSION
-		    /* The following code is glibc specific but does
-		       there a good job in speeding up the code since
-		       we can avoid the btowc() call.  */
-		    if (_ISCTYPE ((UCHAR) *n, wt))
-		      goto matched;
-# else
-		    if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
-		      goto matched;
-# endif
+        {
+        case L_('?'):
+          if (__glibc_unlikely (flags & FNM_EXTMATCH) && *p == '(')
+            {
+              int res = EXT (c, p, n, string_end, no_leading_period,
+                             flags, alloca_used);
+              if (res != -1)
+                return res;
+            }
+
+          if (n == string_end)
+            return FNM_NOMATCH;
+          else if (*n == L_('/') && (flags & FNM_FILE_NAME))
+            return FNM_NOMATCH;
+          else if (*n == L_('.') && no_leading_period)
+            return FNM_NOMATCH;
+          break;
+
+        case L_('\\'):
+          if (!(flags & FNM_NOESCAPE))
+            {
+              c = *p++;
+              if (c == L_('\0'))
+                /* Trailing \ loses.  */
+                return FNM_NOMATCH;
+              c = FOLD (c);
+            }
+          if (n == string_end || FOLD ((UCHAR) *n) != c)
+            return FNM_NOMATCH;
+          break;
+
+        case L_('*'):
+          if (__glibc_unlikely (flags & FNM_EXTMATCH) && *p == '(')
+            {
+              int res = EXT (c, p, n, string_end, no_leading_period,
+                             flags, alloca_used);
+              if (res != -1)
+                return res;
+            }
+          else if (ends != NULL)
+            {
+              ends->pattern = p - 1;
+              ends->string = n;
+              ends->no_leading_period = no_leading_period;
+              return 0;
+            }
+
+          if (n != string_end && *n == L_('.') && no_leading_period)
+            return FNM_NOMATCH;
+
+          for (c = *p++; c == L_('?') || c == L_('*'); c = *p++)
+            {
+              if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0)
+                {
+                  const CHAR *endp = END (p);
+                  if (endp != p)
+                    {
+                      /* This is a pattern.  Skip over it.  */
+                      p = endp;
+                      continue;
+                    }
+                }
+
+              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_('/')
+                           && __glibc_unlikely (flags & FNM_FILE_NAME))
+                    /* A slash does not match a wildcard under
+                       FNM_FILE_NAME.  */
+                    return FNM_NOMATCH;
+                  else
+                    /* One character of the string is consumed in matching
+                       this ? wildcard, so *??? won't match if there are
+                       less than three characters.  */
+                    ++n;
+                }
+            }
+
+          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
+               flag is set.  */
+            {
+              int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
+
+              if (flags & FNM_FILE_NAME)
+                {
+                  if (flags & FNM_LEADING_DIR)
+                    result = 0;
+                  else
+                    {
+                      if (MEMCHR (n, L_('/'), string_end - n) == NULL)
+                        result = 0;
+                    }
+                }
+
+              return result;
+            }
+          else
+            {
+              const CHAR *endp;
+              struct STRUCT end;
+
+              end.pattern = NULL;
+              endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'),
+                             string_end - n);
+              if (endp == NULL)
+                endp = string_end;
+
+              if (c == L_('[')
+                  || (__glibc_unlikely (flags & FNM_EXTMATCH)
+                      && (c == L_('@') || c == L_('+') || c == L_('!'))
+                      && *p == L_('(')))
+                {
+                  int flags2 = ((flags & FNM_FILE_NAME)
+                                ? flags : (flags & ~FNM_PERIOD));
+
+                  for (--p; n < endp; ++n, no_leading_period = false)
+                    if (FCT (p, n, string_end, no_leading_period, flags2,
+                             &end, alloca_used) == 0)
+                      goto found;
+                }
+              else if (c == L_('/') && (flags & FNM_FILE_NAME))
+                {
+                  while (n < string_end && *n != L_('/'))
+                    ++n;
+                  if (n < string_end && *n == L_('/')
+                      && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
+                               NULL, alloca_used) == 0))
+                    return 0;
+                }
+              else
+                {
+                  int flags2 = ((flags & FNM_FILE_NAME)
+                                ? flags : (flags & ~FNM_PERIOD));
+
+                  if (c == L_('\\') && !(flags & FNM_NOESCAPE))
+                    c = *p;
+                  c = FOLD (c);
+                  for (--p; n < endp; ++n, no_leading_period = false)
+                    if (FOLD ((UCHAR) *n) == c
+                        && (FCT (p, n, string_end, no_leading_period, flags2,
+                                 &end, alloca_used) == 0))
+                      {
+                      found:
+                        if (end.pattern == NULL)
+                          return 0;
+                        break;
+                      }
+                  if (end.pattern != NULL)
+                    {
+                      p = end.pattern;
+                      n = end.string;
+                      no_leading_period = end.no_leading_period;
+                      continue;
+                    }
+                }
+            }
+
+          /* If we come here no match is possible with the wildcard.  */
+          return FNM_NOMATCH;
+
+        case L_('['):
+          {
+            /* Nonzero if the sense of the character class is inverted.  */
+            const CHAR *p_init = p;
+            const CHAR *n_init = n;
+            bool not;
+            CHAR cold;
+            UCHAR fn;
+
+            if (posixly_correct == 0)
+              posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+            if (n == string_end)
+              return FNM_NOMATCH;
+
+            if (*n == L_('.') && no_leading_period)
+              return FNM_NOMATCH;
+
+            if (*n == L_('/') && (flags & FNM_FILE_NAME))
+              /* '/' cannot be matched.  */
+              return FNM_NOMATCH;
+
+            not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^')));
+            if (not)
+              ++p;
+
+            fn = FOLD ((UCHAR) *n);
+
+            c = *p++;
+            for (;;)
+              {
+                if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
+                  {
+                    if (*p == L_('\0'))
+                      return FNM_NOMATCH;
+                    c = FOLD ((UCHAR) *p);
+                    ++p;
+
+                    goto normal_bracket;
+                  }
+                else if (c == L_('[') && *p == L_(':'))
+                  {
+                    /* Leave room for the null.  */
+                    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
+                    size_t c1 = 0;
+                    wctype_t wt;
+                    const CHAR *startp = p;
+
+                    for (;;)
+                      {
+                        if (c1 == CHAR_CLASS_MAX_LENGTH)
+                          /* The name is too long and therefore the pattern
+                             is ill-formed.  */
+                          return FNM_NOMATCH;
+
+                        c = *++p;
+                        if (c == L_(':') && p[1] == L_(']'))
+                          {
+                            p += 2;
+                            break;
+                          }
+                        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_('[');
+                            goto normal_bracket;
+                          }
+                        str[c1++] = c;
+                      }
+                    str[c1] = L_('\0');
+
+                    wt = IS_CHAR_CLASS (str);
+                    if (wt == 0)
+                      /* Invalid character class name.  */
+                      return FNM_NOMATCH;
+
+#if defined _LIBC && ! WIDE_CHAR_VERSION
+                    /* The following code is glibc specific but does
+                       there a good job in speeding up the code since
+                       we can avoid the btowc() call.  */
+                    if (_ISCTYPE ((UCHAR) *n, wt))
+                      goto matched;
 #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)))
-		      goto matched;
+                    if (iswctype (BTOWC ((UCHAR) *n), wt))
+                      goto matched;
 #endif
-		    c = *p++;
-		  }
+                    c = *p++;
+                  }
 #ifdef _LIBC
-		else if (c == L('[') && *p == L('='))
-		  {
-		    /* It's important that STR be a scalar variable rather
-		       than a one-element array, because GCC (at least 4.9.2
-		       -O2 on x86-64) can be confused by the array and
-		       diagnose a "used initialized" in a dead branch in the
-		       findidx function.  */
-		    UCHAR str;
-		    uint32_t nrules =
-		      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-		    const CHAR *startp = p;
-
-		    c = *++p;
-		    if (c == L('\0'))
-		      {
-			p = startp;
-			c = L('[');
-			goto normal_bracket;
-		      }
-		    str = c;
-
-		    c = *++p;
-		    if (c != L('=') || p[1] != L(']'))
-		      {
-			p = startp;
-			c = L('[');
-			goto normal_bracket;
-		      }
-		    p += 2;
-
-		    if (nrules == 0)
-		      {
-			if ((UCHAR) *n == str)
-			  goto matched;
-		      }
-		    else
-		      {
-			const int32_t *table;
+                else if (c == L_('[') && *p == L_('='))
+                  {
+                    /* It's important that STR be a scalar variable rather
+                       than a one-element array, because GCC (at least 4.9.2
+                       -O2 on x86-64) can be confused by the array and
+                       diagnose a "used initialized" in a dead branch in the
+                       findidx function.  */
+                    UCHAR str;
+                    uint32_t nrules =
+                      _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+                    const CHAR *startp = p;
+
+                    c = *++p;
+                    if (c == L_('\0'))
+                      {
+                        p = startp;
+                        c = L_('[');
+                        goto normal_bracket;
+                      }
+                    str = c;
+
+                    c = *++p;
+                    if (c != L_('=') || p[1] != L_(']'))
+                      {
+                        p = startp;
+                        c = L_('[');
+                        goto normal_bracket;
+                      }
+                    p += 2;
+
+                    if (nrules == 0)
+                      {
+                        if ((UCHAR) *n == str)
+                          goto matched;
+                      }
+                    else
+                      {
+                        const int32_t *table;
 # if WIDE_CHAR_VERSION
-			const int32_t *weights;
-			const wint_t *extra;
+                        const int32_t *weights;
+                        const wint_t *extra;
 # else
-			const unsigned char *weights;
-			const unsigned char *extra;
+                        const unsigned char *weights;
+                        const unsigned char *extra;
 # endif
-			const int32_t *indirect;
-			int32_t idx;
-			const UCHAR *cp = (const UCHAR *) &str;
+                        const int32_t *indirect;
+                        int32_t idx;
+                        const UCHAR *cp = (const UCHAR *) &str;
 
 # if WIDE_CHAR_VERSION
-			table = (const int32_t *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
-			weights = (const int32_t *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
-			extra = (const wint_t *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
-			indirect = (const int32_t *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+                        table = (const int32_t *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+                        weights = (const int32_t *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+                        extra = (const wint_t *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+                        indirect = (const int32_t *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
 # else
-			table = (const int32_t *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
-			weights = (const unsigned char *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
-			extra = (const unsigned char *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
-			indirect = (const int32_t *)
-			  _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+                        table = (const int32_t *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+                        weights = (const unsigned char *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+                        extra = (const unsigned char *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+                        indirect = (const int32_t *)
+                          _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
 # endif
 
-			idx = FINDIDX (table, indirect, extra, &cp, 1);
-			if (idx != 0)
-			  {
-			    /* We found a table entry.  Now see whether the
-			       character we are currently at has the same
-			       equivalance class value.  */
-			    int len = weights[idx & 0xffffff];
-			    int32_t idx2;
-			    const UCHAR *np = (const UCHAR *) n;
-
-			    idx2 = FINDIDX (table, indirect, extra,
-					    &np, string_end - n);
-			    if (idx2 != 0
-				&& (idx >> 24) == (idx2 >> 24)
-				&& len == weights[idx2 & 0xffffff])
-			      {
-				int cnt = 0;
-
-				idx &= 0xffffff;
-				idx2 &= 0xffffff;
-
-				while (cnt < len
-				       && (weights[idx + 1 + cnt]
-					   == weights[idx2 + 1 + cnt]))
-				  ++cnt;
-
-				if (cnt == len)
-				  goto matched;
-			      }
-			  }
-		      }
-
-		    c = *p++;
-		  }
+                        idx = FINDIDX (table, indirect, extra, &cp, 1);
+                        if (idx != 0)
+                          {
+                            /* We found a table entry.  Now see whether the
+                               character we are currently at has the same
+                               equivalence class value.  */
+                            int len = weights[idx & 0xffffff];
+                            int32_t idx2;
+                            const UCHAR *np = (const UCHAR *) n;
+
+                            idx2 = FINDIDX (table, indirect, extra,
+                                            &np, string_end - n);
+                            if (idx2 != 0
+                                && (idx >> 24) == (idx2 >> 24)
+                                && len == weights[idx2 & 0xffffff])
+                              {
+                                int cnt = 0;
+
+                                idx &= 0xffffff;
+                                idx2 &= 0xffffff;
+
+                                while (cnt < len
+                                       && (weights[idx + 1 + cnt]
+                                           == weights[idx2 + 1 + cnt]))
+                                  ++cnt;
+
+                                if (cnt == len)
+                                  goto matched;
+                              }
+                          }
+                      }
+
+                    c = *p++;
+                  }
 #endif
-		else if (c == L('\0'))
-		  {
-		    /* [ unterminated, treat as normal character.  */
-		    p = p_init;
-		    n = n_init;
-		    c = L('[');
-		    goto normal_match;
-		  }
-		else
-		  {
-		    int is_range = 0;
+                else if (c == L_('\0'))
+                  {
+                    /* [ unterminated, treat as normal character.  */
+                    p = p_init;
+                    n = n_init;
+                    c = L_('[');
+                    goto normal_match;
+                  }
+                else
+                  {
+                    bool is_range = false;
 
 #ifdef _LIBC
-		    int is_seqval = 0;
-
-		    if (c == L('[') && *p == L('.'))
-		      {
-			uint32_t nrules =
-			  _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-			const CHAR *startp = p;
-			size_t c1 = 0;
-
-			while (1)
-			  {
-			    c = *++p;
-			    if (c == L('.') && p[1] == L(']'))
-			      {
-				p += 2;
-				break;
-			      }
-			    if (c == '\0')
-			      return FNM_NOMATCH;
-			    ++c1;
-			  }
-
-			/* We have to handling the symbols differently in
-			   ranges since then the collation sequence is
-			   important.  */
-			is_range = *p == L('-') && p[1] != L('\0');
-
-			if (nrules == 0)
-			  {
-			    /* There are no names defined in the collation
-			       data.  Therefore we only accept the trivial
-			       names consisting of the character itself.  */
-			    if (c1 != 1)
-			      return FNM_NOMATCH;
-
-			    if (!is_range && *n == startp[1])
-			      goto matched;
-
-			    cold = startp[1];
-			    c = *p++;
-			  }
-			else
-			  {
-			    int32_t table_size;
-			    const int32_t *symb_table;
-			    const unsigned char *extra;
-			    int32_t idx;
-			    int32_t elem;
+                    bool is_seqval = false;
+
+                    if (c == L_('[') && *p == L_('.'))
+                      {
+                        uint32_t nrules =
+                          _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+                        const CHAR *startp = p;
+                        size_t c1 = 0;
+
+                        while (1)
+                          {
+                            c = *++p;
+                            if (c == L_('.') && p[1] == L_(']'))
+                              {
+                                p += 2;
+                                break;
+                              }
+                            if (c == '\0')
+                              return FNM_NOMATCH;
+                            ++c1;
+                          }
+
+                        /* We have to handling the symbols differently in
+                           ranges since then the collation sequence is
+                           important.  */
+                        is_range = *p == L_('-') && p[1] != L_('\0');
+
+                        if (nrules == 0)
+                          {
+                            /* There are no names defined in the collation
+                               data.  Therefore we only accept the trivial
+                               names consisting of the character itself.  */
+                            if (c1 != 1)
+                              return FNM_NOMATCH;
+
+                            if (!is_range && *n == startp[1])
+                              goto matched;
+
+                            cold = startp[1];
+                            c = *p++;
+                          }
+                        else
+                          {
+                            int32_t table_size;
+                            const int32_t *symb_table;
+                            const unsigned char *extra;
+                            int32_t idx;
+                            int32_t elem;
 # if WIDE_CHAR_VERSION
-			    CHAR *wextra;
+                            CHAR *wextra;
 # endif
 
-			    table_size =
-			      _NL_CURRENT_WORD (LC_COLLATE,
-						_NL_COLLATE_SYMB_HASH_SIZEMB);
-			    symb_table = (const int32_t *)
-			      _NL_CURRENT (LC_COLLATE,
-					   _NL_COLLATE_SYMB_TABLEMB);
-			    extra = (const unsigned char *)
-			      _NL_CURRENT (LC_COLLATE,
-					   _NL_COLLATE_SYMB_EXTRAMB);
-
-			    for (elem = 0; elem < table_size; elem++)
-			      if (symb_table[2 * elem] != 0)
-				{
-				  idx = symb_table[2 * elem + 1];
-				  /* Skip the name of collating element.  */
-				  idx += 1 + extra[idx];
+                            table_size =
+                              _NL_CURRENT_WORD (LC_COLLATE,
+                                                _NL_COLLATE_SYMB_HASH_SIZEMB);
+                            symb_table = (const int32_t *)
+                              _NL_CURRENT (LC_COLLATE,
+                                           _NL_COLLATE_SYMB_TABLEMB);
+                            extra = (const unsigned char *)
+                              _NL_CURRENT (LC_COLLATE,
+                                           _NL_COLLATE_SYMB_EXTRAMB);
+
+                            for (elem = 0; elem < table_size; elem++)
+                              if (symb_table[2 * elem] != 0)
+                                {
+                                  idx = symb_table[2 * elem + 1];
+                                  /* Skip the name of collating element.  */
+                                  idx += 1 + extra[idx];
 # if WIDE_CHAR_VERSION
-				  /* Skip the byte sequence of the
-				     collating element.  */
-				  idx += 1 + extra[idx];
-				  /* Adjust for the alignment.  */
-				  idx = (idx + 3) & ~3;
-
-				  wextra = (CHAR *) &extra[idx + 4];
-
-				  if (/* Compare the length of the sequence.  */
-				      c1 == wextra[0]
-				      /* Compare the wide char sequence.  */
-				      && WMEMCMP (startp + 1, &wextra[1],
-						  c1) == 0)
-				    /* Yep, this is the entry.  */
-				    break;
+                                  /* Skip the byte sequence of the
+                                     collating element.  */
+                                  idx += 1 + extra[idx];
+                                  /* Adjust for the alignment.  */
+                                  idx = (idx + 3) & ~3;
+
+                                  wextra = (CHAR *) &extra[idx + 4];
+
+                                  if (/* Compare the length of the sequence.  */
+                                      c1 == wextra[0]
+                                      /* Compare the wide char sequence.  */
+                                      && (__wmemcmp (startp + 1, &wextra[1],
+                                                     c1)
+                                          == 0))
+                                    /* Yep, this is the entry.  */
+                                    break;
 # else
-				  if (/* Compare the length of the sequence.  */
-				      c1 == extra[idx]
-				      /* Compare the byte sequence.  */
-				      && memcmp (startp + 1,
-						 &extra[idx + 1], c1) == 0)
-				    /* Yep, this is the entry.  */
-				    break;
+                                  if (/* Compare the length of the sequence.  */
+                                      c1 == extra[idx]
+                                      /* Compare the byte sequence.  */
+                                      && memcmp (startp + 1,
+                                                 &extra[idx + 1], c1) == 0)
+                                    /* Yep, this is the entry.  */
+                                    break;
 # endif
-				}
+                                }
 
-			    if (elem < table_size)
-			      {
-				/* Compare the byte sequence but only if
-				   this is not part of a range.  */
-				if (! is_range
+                            if (elem < table_size)
+                              {
+                                /* Compare the byte sequence but only if
+                                   this is not part of a range.  */
+                                if (! is_range
 
 # if WIDE_CHAR_VERSION
-				    && WMEMCMP (n, &wextra[1], c1) == 0
+                                    && __wmemcmp (n, &wextra[1], c1) == 0
 # else
-				    && memcmp (n, &extra[idx + 1], c1) == 0
+                                    && memcmp (n, &extra[idx + 1], c1) == 0
 # endif
-				    )
-				  {
-				    n += c1 - 1;
-				    goto matched;
-				  }
-
-				/* Get the collation sequence value.  */
-				is_seqval = 1;
+                                    )
+                                  {
+                                    n += c1 - 1;
+                                    goto matched;
+                                  }
+
+                                /* Get the collation sequence value.  */
+                                is_seqval = true;
 # if WIDE_CHAR_VERSION
-				cold = wextra[1 + wextra[0]];
+                                cold = wextra[1 + wextra[0]];
 # else
-				idx += 1 + extra[idx];
-				/* Adjust for the alignment.  */
-				idx = (idx + 3) & ~3;
-				cold = *((int32_t *) &extra[idx]);
+                                idx += 1 + extra[idx];
+                                /* Adjust for the alignment.  */
+                                idx = (idx + 3) & ~3;
+                                cold = *((int32_t *) &extra[idx]);
 # endif
 
-				c = *p++;
-			      }
-			    else if (c1 == 1)
-			      {
-				/* No valid character.  Match it as a
-				   single byte.  */
-				if (!is_range && *n == startp[1])
-				  goto matched;
-
-				cold = startp[1];
-				c = *p++;
-			      }
-			    else
-			      return FNM_NOMATCH;
-			  }
-		      }
-		    else
+                                c = *p++;
+                              }
+                            else if (c1 == 1)
+                              {
+                                /* No valid character.  Match it as a
+                                   single byte.  */
+                                if (!is_range && *n == startp[1])
+                                  goto matched;
+
+                                cold = startp[1];
+                                c = *p++;
+                              }
+                            else
+                              return FNM_NOMATCH;
+                          }
+                      }
+                    else
 #endif
-		      {
-			c = FOLD (c);
-		      normal_bracket:
-
-			/* 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(']'));
-
-			if (!is_range && c == fn)
-			  goto matched;
-
-			/* This is needed if we goto normal_bracket; from
-			   outside of is_seqval's scope.  */
-			is_seqval = 0;
-			cold = c;
-			c = *p++;
-		      }
-
-		    if (c == L('-') && *p != L(']'))
-		      {
+                      {
+                        c = FOLD (c);
+                      normal_bracket:
+
+                        /* 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_(']'));
+
+                        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 _LIBC
-			/* We have to find the collation sequence
-			   value for C.  Collation sequence is nothing
-			   we can regularly access.  The sequence
-			   value is defined by the order in which the
-			   definitions of the collation values for the
-			   various characters appear in the source
-			   file.  A strange concept, nowhere
-			   documented.  */
-			uint32_t fcollseq;
-			uint32_t lcollseq;
-			UCHAR cend = *p++;
+                        /* We have to find the collation sequence
+                           value for C.  Collation sequence is nothing
+                           we can regularly access.  The sequence
+                           value is defined by the order in which the
+                           definitions of the collation values for the
+                           various characters appear in the source
+                           file.  A strange concept, nowhere
+                           documented.  */
+                        uint32_t fcollseq;
+                        uint32_t lcollseq;
+                        UCHAR cend = *p++;
 
 # if WIDE_CHAR_VERSION
-			/* Search in the `names' array for the characters.  */
-			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
-			     failing.  */
-			  goto range_not_matched;
-
-			if (is_seqval)
-			  lcollseq = cold;
-			else
-			  lcollseq = __collseq_table_lookup (collseq, cold);
+                        /* Search in the 'names' array for the characters.  */
+                        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
+                             failing.  */
+                          goto range_not_matched;
+
+                        if (is_seqval)
+                          lcollseq = cold;
+                        else
+                          lcollseq = __collseq_table_lookup (collseq, cold);
 # else
-			fcollseq = collseq[fn];
-			lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
+                        fcollseq = collseq[fn];
+                        lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
 # endif
 
-			is_seqval = 0;
-			if (cend == L('[') && *p == L('.'))
-			  {
-			    uint32_t nrules =
-			      _NL_CURRENT_WORD (LC_COLLATE,
-						_NL_COLLATE_NRULES);
-			    const CHAR *startp = p;
-			    size_t c1 = 0;
-
-			    while (1)
-			      {
-				c = *++p;
-				if (c == L('.') && p[1] == L(']'))
-				  {
-				    p += 2;
-				    break;
-				  }
-				if (c == '\0')
-				  return FNM_NOMATCH;
-				++c1;
-			      }
-
-			    if (nrules == 0)
-			      {
-				/* There are no names defined in the
-				   collation data.  Therefore we only
-				   accept the trivial names consisting
-				   of the character itself.  */
-				if (c1 != 1)
-				  return FNM_NOMATCH;
-
-				cend = startp[1];
-			      }
-			    else
-			      {
-				int32_t table_size;
-				const int32_t *symb_table;
-				const unsigned char *extra;
-				int32_t idx;
-				int32_t elem;
+                        is_seqval = false;
+                        if (cend == L_('[') && *p == L_('.'))
+                          {
+                            uint32_t nrules =
+                              _NL_CURRENT_WORD (LC_COLLATE,
+                                                _NL_COLLATE_NRULES);
+                            const CHAR *startp = p;
+                            size_t c1 = 0;
+
+                            while (1)
+                              {
+                                c = *++p;
+                                if (c == L_('.') && p[1] == L_(']'))
+                                  {
+                                    p += 2;
+                                    break;
+                                  }
+                                if (c == '\0')
+                                  return FNM_NOMATCH;
+                                ++c1;
+                              }
+
+                            if (nrules == 0)
+                              {
+                                /* There are no names defined in the
+                                   collation data.  Therefore we only
+                                   accept the trivial names consisting
+                                   of the character itself.  */
+                                if (c1 != 1)
+                                  return FNM_NOMATCH;
+
+                                cend = startp[1];
+                              }
+                            else
+                              {
+                                int32_t table_size;
+                                const int32_t *symb_table;
+                                const unsigned char *extra;
+                                int32_t idx;
+                                int32_t elem;
 # if WIDE_CHAR_VERSION
-				CHAR *wextra;
+                                CHAR *wextra;
 # endif
 
-				table_size =
-				  _NL_CURRENT_WORD (LC_COLLATE,
-						    _NL_COLLATE_SYMB_HASH_SIZEMB);
-				symb_table = (const int32_t *)
-				  _NL_CURRENT (LC_COLLATE,
-					       _NL_COLLATE_SYMB_TABLEMB);
-				extra = (const unsigned char *)
-				  _NL_CURRENT (LC_COLLATE,
-					       _NL_COLLATE_SYMB_EXTRAMB);
-
-				for (elem = 0; elem < table_size; elem++)
-				  if (symb_table[2 * elem] != 0)
-				    {
-				      idx = symb_table[2 * elem + 1];
-				      /* Skip the name of collating
-					 element.  */
-				      idx += 1 + extra[idx];
+                                table_size =
+                                  _NL_CURRENT_WORD (LC_COLLATE,
+                                                    _NL_COLLATE_SYMB_HASH_SIZEMB);
+                                symb_table = (const int32_t *)
+                                  _NL_CURRENT (LC_COLLATE,
+                                               _NL_COLLATE_SYMB_TABLEMB);
+                                extra = (const unsigned char *)
+                                  _NL_CURRENT (LC_COLLATE,
+                                               _NL_COLLATE_SYMB_EXTRAMB);
+
+                                for (elem = 0; elem < table_size; elem++)
+                                  if (symb_table[2 * elem] != 0)
+                                    {
+                                      idx = symb_table[2 * elem + 1];
+                                      /* Skip the name of collating
+                                         element.  */
+                                      idx += 1 + extra[idx];
 # if WIDE_CHAR_VERSION
-				      /* Skip the byte sequence of the
-					 collating element.  */
-				      idx += 1 + extra[idx];
-				      /* Adjust for the alignment.  */
-				      idx = (idx + 3) & ~3;
-
-				      wextra = (CHAR *) &extra[idx + 4];
-
-				      if (/* Compare the length of the
-					     sequence.  */
-					  c1 == wextra[0]
-					  /* Compare the wide char sequence.  */
-					  && WMEMCMP (startp + 1, &wextra[1],
-						      c1) == 0)
-					/* Yep, this is the entry.  */
-					break;
+                                      /* Skip the byte sequence of the
+                                         collating element.  */
+                                      idx += 1 + extra[idx];
+                                      /* Adjust for the alignment.  */
+                                      idx = (idx + 3) & ~3;
+
+                                      wextra = (CHAR *) &extra[idx + 4];
+
+                                      if (/* Compare the length of the
+                                             sequence.  */
+                                          c1 == wextra[0]
+                                          /* Compare the wide char sequence.  */
+                                          && (__wmemcmp (startp + 1,
+                                                         &wextra[1], c1)
+                                              == 0))
+                                        /* Yep, this is the entry.  */
+                                        break;
 # else
-				      if (/* Compare the length of the
-					     sequence.  */
-					  c1 == extra[idx]
-					  /* Compare the byte sequence.  */
-					  && memcmp (startp + 1,
-						     &extra[idx + 1], c1) == 0)
-					/* Yep, this is the entry.  */
-					break;
+                                      if (/* Compare the length of the
+                                             sequence.  */
+                                          c1 == extra[idx]
+                                          /* Compare the byte sequence.  */
+                                          && memcmp (startp + 1,
+                                                     &extra[idx + 1], c1) == 0)
+                                        /* Yep, this is the entry.  */
+                                        break;
 # endif
-				    }
+                                    }
 
-				if (elem < table_size)
-				  {
-				    /* Get the collation sequence value.  */
-				    is_seqval = 1;
+                                if (elem < table_size)
+                                  {
+                                    /* Get the collation sequence value.  */
+                                    is_seqval = true;
 # if WIDE_CHAR_VERSION
-				    cend = wextra[1 + wextra[0]];
+                                    cend = wextra[1 + wextra[0]];
 # else
-				    idx += 1 + extra[idx];
-				    /* Adjust for the alignment.  */
-				    idx = (idx + 3) & ~3;
-				    cend = *((int32_t *) &extra[idx]);
+                                    idx += 1 + extra[idx];
+                                    /* Adjust for the alignment.  */
+                                    idx = (idx + 3) & ~3;
+                                    cend = *((int32_t *) &extra[idx]);
 # endif
-				  }
-				else if (c1 == 1)
-				  {
-				    cend = startp[1];
-				    c = *p++;
-				  }
-				else
-				  return FNM_NOMATCH;
-			      }
-			  }
-			else
-			  {
-			    if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
-			      cend = *p++;
-			    if (cend == L('\0'))
-			      return FNM_NOMATCH;
-			    cend = FOLD (cend);
-			  }
-
-			/* XXX It is not entirely clear to me how to handle
-			   characters which are not mentioned in the
-			   collation specification.  */
-			if (
+                                  }
+                                else if (c1 == 1)
+                                  {
+                                    cend = startp[1];
+                                    c = *p++;
+                                  }
+                                else
+                                  return FNM_NOMATCH;
+                              }
+                          }
+                        else
+                          {
+                            if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
+                              cend = *p++;
+                            if (cend == L_('\0'))
+                              return FNM_NOMATCH;
+                            cend = FOLD (cend);
+                          }
+
+                        /* XXX It is not entirely clear to me how to handle
+                           characters which are not mentioned in the
+                           collation specification.  */
+                        if (
 # if WIDE_CHAR_VERSION
-			    lcollseq == 0xffffffff ||
+                            lcollseq == 0xffffffff ||
 # endif
-			    lcollseq <= fcollseq)
-			  {
-			    /* We have to look at the upper bound.  */
-			    uint32_t hcollseq;
-
-			    if (is_seqval)
-			      hcollseq = cend;
-			    else
-			      {
+                            lcollseq <= fcollseq)
+                          {
+                            /* We have to look at the upper bound.  */
+                            uint32_t hcollseq;
+
+                            if (is_seqval)
+                              hcollseq = cend;
+                            else
+                              {
 # if WIDE_CHAR_VERSION
-				hcollseq =
-				  __collseq_table_lookup (collseq, cend);
-				if (hcollseq == ~((uint32_t) 0))
-				  {
-				    /* Hum, no information about the upper
-				       bound.  The matching succeeds if the
-				       lower bound is matched exactly.  */
-				    if (lcollseq != fcollseq)
-				      goto range_not_matched;
-
-				    goto matched;
-				  }
+                                hcollseq =
+                                  __collseq_table_lookup (collseq, cend);
+                                if (hcollseq == ~((uint32_t) 0))
+                                  {
+                                    /* Hum, no information about the upper
+                                       bound.  The matching succeeds if the
+                                       lower bound is matched exactly.  */
+                                    if (lcollseq != fcollseq)
+                                      goto range_not_matched;
+
+                                    goto matched;
+                                  }
 # else
-				hcollseq = collseq[cend];
+                                hcollseq = collseq[cend];
 # endif
-			      }
+                              }
 
-			    if (lcollseq <= hcollseq && fcollseq <= hcollseq)
-			      goto matched;
-			  }
+                            if (lcollseq <= hcollseq && fcollseq <= hcollseq)
+                              goto matched;
+                          }
 # if WIDE_CHAR_VERSION
-		      range_not_matched:
+                      range_not_matched:
 # endif
 #else
-			/* We use a boring value comparison of the character
-			   values.  This is better than comparing using
-			   `strcoll' since the latter would have surprising
-			   and sometimes fatal consequences.  */
-			UCHAR cend = *p++;
-
-			if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
-			  cend = *p++;
-			if (cend == L('\0'))
-			  return FNM_NOMATCH;
-
-			/* It is a range.  */
-			if (cold <= fn && fn <= cend)
-			  goto matched;
+                        /* We use a boring value comparison of the character
+                           values.  This is better than comparing using
+                           'strcoll' since the latter would have surprising
+                           and sometimes fatal consequences.  */
+                        UCHAR cend = *p++;
+
+                        if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
+                          cend = *p++;
+                        if (cend == L_('\0'))
+                          return FNM_NOMATCH;
+
+                        /* It is a range.  */
+                        if ((UCHAR) cold <= fn && fn <= cend)
+                          goto matched;
 #endif
 
-			c = *p++;
-		      }
-		  }
-
-		if (c == L(']'))
-		  break;
-	      }
-
-	    if (!not)
-	      return FNM_NOMATCH;
-	    break;
-
-	  matched:
-	    /* Skip the rest of the [...] that already matched.  */
-	    while ((c = *p++) != L (']'))
-	      {
-		if (c == L('\0'))
-		  /* [... (unterminated) loses.  */
-		  return FNM_NOMATCH;
-
-		if (!(flags & FNM_NOESCAPE) && c == L('\\'))
-		  {
-		    if (*p == L('\0'))
-		      return FNM_NOMATCH;
-		    /* XXX 1003.2d11 is unclear if this is right.  */
-		    ++p;
-		  }
-		else if (c == L('[') && *p == L(':'))
-		  {
-		    int c1 = 0;
-		    const CHAR *startp = p;
-
-		    while (1)
-		      {
-			c = *++p;
-			if (++c1 == CHAR_CLASS_MAX_LENGTH)
-			  return FNM_NOMATCH;
-
-			if (*p == L(':') && p[1] == L(']'))
-			  break;
-
-			if (c < L('a') || c >= L('z'))
-			  {
-			    p = startp - 2;
-			    break;
-			  }
-		      }
-		    p += 2;
-		  }
-		else if (c == L('[') && *p == L('='))
-		  {
-		    c = *++p;
-		    if (c == L('\0'))
-		      return FNM_NOMATCH;
-		    c = *++p;
-		    if (c != L('=') || p[1] != L(']'))
-		      return FNM_NOMATCH;
-		    p += 2;
-		  }
-		else if (c == L('[') && *p == L('.'))
-		  {
-		    while (1)
-		      {
-			c = *++p;
-			if (c == L('\0'))
-			  return FNM_NOMATCH;
-
-			if (c == L('.') && p[1] == L(']'))
-			  break;
-		      }
-		    p += 2;
-		  }
-	      }
-	    if (not)
-	      return FNM_NOMATCH;
-	  }
-	  break;
-
-	case L('+'):
-	case L('@'):
-	case L('!'):
-	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
-	    {
-	      int res = EXT (c, p, n, string_end, no_leading_period, flags,
-			     alloca_used);
-	      if (res != -1)
-		return res;
-	    }
-	  goto normal_match;
-
-	case L('/'):
-	  if (NO_LEADING_PERIOD (flags))
-	    {
-	      if (n == string_end || c != (UCHAR) *n)
-		return FNM_NOMATCH;
-
-	      new_no_leading_period = 1;
-	      break;
-	    }
-	  /* FALLTHROUGH */
-	default:
-	normal_match:
-	  if (n == string_end || c != FOLD ((UCHAR) *n))
-	    return FNM_NOMATCH;
-	}
+                        c = *p++;
+                      }
+                  }
+
+                if (c == L_(']'))
+                  break;
+              }
+
+            if (!not)
+              return FNM_NOMATCH;
+            break;
+
+          matched:
+            /* Skip the rest of the [...] that already matched.  */
+            while ((c = *p++) != L_(']'))
+              {
+                if (c == L_('\0'))
+                  /* [... (unterminated) loses.  */
+                  return FNM_NOMATCH;
+
+                if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
+                  {
+                    if (*p == L_('\0'))
+                      return FNM_NOMATCH;
+                    /* XXX 1003.2d11 is unclear if this is right.  */
+                    ++p;
+                  }
+                else if (c == L_('[') && *p == L_(':'))
+                  {
+                    int c1 = 0;
+                    const CHAR *startp = p;
+
+                    while (1)
+                      {
+                        c = *++p;
+                        if (++c1 == CHAR_CLASS_MAX_LENGTH)
+                          return FNM_NOMATCH;
+
+                        if (*p == L_(':') && p[1] == L_(']'))
+                          break;
+
+                        if (c < L_('a') || c >= L_('z'))
+                          {
+                            p = startp - 2;
+                            break;
+                          }
+                      }
+                    p += 2;
+                  }
+                else if (c == L_('[') && *p == L_('='))
+                  {
+                    c = *++p;
+                    if (c == L_('\0'))
+                      return FNM_NOMATCH;
+                    c = *++p;
+                    if (c != L_('=') || p[1] != L_(']'))
+                      return FNM_NOMATCH;
+                    p += 2;
+                  }
+                else if (c == L_('[') && *p == L_('.'))
+                  {
+                    while (1)
+                      {
+                        c = *++p;
+                        if (c == L_('\0'))
+                          return FNM_NOMATCH;
+
+                        if (c == L_('.') && p[1] == L_(']'))
+                          break;
+                      }
+                    p += 2;
+                  }
+              }
+            if (not)
+              return FNM_NOMATCH;
+          }
+          break;
+
+        case L_('+'):
+        case L_('@'):
+        case L_('!'):
+          if (__glibc_unlikely (flags & FNM_EXTMATCH) && *p == '(')
+            {
+              int res = EXT (c, p, n, string_end, no_leading_period, flags,
+                             alloca_used);
+              if (res != -1)
+                return res;
+            }
+          goto normal_match;
+
+        case L_('/'):
+          if (NO_LEADING_PERIOD (flags))
+            {
+              if (n == string_end || c != (UCHAR) *n)
+                return FNM_NOMATCH;
+
+              new_no_leading_period = true;
+              break;
+            }
+          FALLTHROUGH;
+        default:
+        normal_match:
+          if (n == string_end || c != FOLD ((UCHAR) *n))
+            return FNM_NOMATCH;
+        }
 
       no_leading_period = new_no_leading_period;
       ++n;
@@ -934,7 +922,7 @@  FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
   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;
 
@@ -948,37 +936,37 @@  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)
-	  posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
-
-	/* Skip the not sign.  We have to recognize it because of a possibly
-	   following ']'.  */
-	if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
-	  ++p;
-	/* A leading ']' is recognized as such.  */
-	if (*p == L(']'))
-	  ++p;
-	/* Skip over all characters of the list.  */
-	while (*p != L(']'))
-	  if (*p++ == L('\0'))
-	    /* This is no valid pattern.  */
-	    return pattern;
+        /* Handle brackets special.  */
+        if (posixly_correct == 0)
+          posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+        /* Skip the not sign.  We have to recognize it because of a possibly
+           following ']'.  */
+        if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
+          ++p;
+        /* A leading ']' is recognized as such.  */
+        if (*p == L_(']'))
+          ++p;
+        /* Skip over all characters of the list.  */
+        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);
-	if (*p == L('\0'))
-	  /* This is an invalid pattern.  */
-	  return pattern;
+        p = END (p + 1);
+        if (*p == L_('\0'))
+          /* This is an invalid pattern.  */
+          return pattern;
       }
-    else if (*p == L(')'))
+    else if (*p == L_(')'))
       break;
 
   return p + 1;
@@ -987,19 +975,19 @@  END (const CHAR *pattern)
 
 static int
 EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
-     int no_leading_period, int flags, size_t alloca_used)
+     bool no_leading_period, int flags, size_t alloca_used)
 {
   const CHAR *startp;
-  int level;
+  ssize_t level;
   struct patternlist
   {
     struct patternlist *next;
     CHAR malloced;
-    CHAR str[0];
+    CHAR str[];
   } *list = NULL;
   struct patternlist **lastp = &list;
   size_t pattern_len = STRLEN (pattern);
-  int any_malloced = 0;
+  bool any_malloced = false;
   const CHAR *p;
   const CHAR *rs;
   int retval = 0;
@@ -1007,174 +995,180 @@  EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
   /* Parse the pattern.  Store the individual parts in the list.  */
   level = 0;
   for (startp = p = pattern + 1; level >= 0; ++p)
-    if (*p == L('\0'))
+    if (*p == L_('\0'))
       {
-	/* This is an invalid pattern.  */
-	retval = -1;
-	goto out;
+        /* This is an invalid pattern.  */
+        retval = -1;
+        goto out;
       }
-    else if (*p == L('['))
+    else if (*p == L_('['))
       {
-	/* Handle brackets special.  */
-	if (posixly_correct == 0)
-	  posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
-
-	/* Skip the not sign.  We have to recognize it because of a possibly
-	   following ']'.  */
-	if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
-	  ++p;
-	/* A leading ']' is recognized as such.  */
-	if (*p == L(']'))
-	  ++p;
-	/* Skip over all characters of the list.  */
-	while (*p != L(']'))
-	  if (*p++ == L('\0'))
-	    {
-	      /* This is no valid pattern.  */
-	      retval = -1;
-	      goto out;
-	    }
+        /* Handle brackets special.  */
+        if (posixly_correct == 0)
+          posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+        /* Skip the not sign.  We have to recognize it because of a possibly
+           following ']'.  */
+        if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
+          ++p;
+        /* A leading ']' is recognized as such.  */
+        if (*p == L_(']'))
+          ++p;
+        /* Skip over all characters of the list.  */
+        while (*p != L_(']'))
+          if (*p++ == L_('\0'))
+            {
+              /* This is no valid pattern.  */
+              retval = -1;
+              goto out;
+            }
       }
-    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.  */
+        if (level-- == 0)
+          {
+            /* This means we found the end of the pattern.  */
 #define NEW_PATTERN \
-	    struct patternlist *newp;					      \
-	    size_t slen = (opt == L('?') || opt == L('@')		      \
-			   ? pattern_len : (p - startp + 1));		      \
-	    slen = sizeof (struct patternlist) + (slen * sizeof (CHAR));      \
-	    int malloced = ! __libc_use_alloca (alloca_used + slen);	      \
-	    if (__builtin_expect (malloced, 0))				      \
-	      {								      \
-		newp = malloc (slen);					      \
-		if (newp == NULL)					      \
-		  {							      \
-		    retval = -2;					      \
-		    goto out;						      \
-		  }							      \
-		any_malloced = 1;					      \
-	      }								      \
-	    else							      \
-	      newp = alloca_account (slen, alloca_used);		      \
-	    newp->next = NULL;						      \
-	    newp->malloced = malloced;					      \
-	    *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0');    \
-	    *lastp = newp;						      \
-	    lastp = &newp->next
-	    NEW_PATTERN;
-	  }
+            struct patternlist *newp;                                         \
+            size_t plen = (opt == L_('?') || opt == L_('@')                   \
+                           ? pattern_len : (p - startp + 1UL));               \
+            idx_t slen = FLEXSIZEOF (struct patternlist, str, 0);             \
+            idx_t new_used = alloca_used + slen;                              \
+            idx_t plensize;                                                   \
+            if (INT_MULTIPLY_WRAPV (plen, sizeof (CHAR), &plensize)           \
+                || INT_ADD_WRAPV (new_used, plensize, &new_used))             \
+              {                                                               \
+                retval = -2;                                                  \
+                goto out;                                                     \
+              }                                                               \
+            slen += plensize;                                                 \
+            bool malloced = ! __libc_use_alloca (new_used);                   \
+            if (__glibc_unlikely (malloced))                                  \
+              {                                                               \
+                newp = malloc (slen);                                         \
+                if (newp == NULL)                                             \
+                  {                                                           \
+                    retval = -2;                                              \
+                    goto out;                                                 \
+                  }                                                           \
+                any_malloced = true;                                          \
+              }                                                               \
+            else                                                              \
+              newp = alloca_account (slen, alloca_used);                      \
+            newp->next = NULL;                                                \
+            newp->malloced = malloced;                                        \
+            *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0');   \
+            *lastp = newp;                                                    \
+            lastp = &newp->next
+            NEW_PATTERN;
+          }
       }
-    else if (*p == L('|'))
+    else if (*p == L_('|'))
       {
-	if (level == 0)
-	  {
-	    NEW_PATTERN;
-	    startp = p + 1;
-	  }
+        if (level == 0)
+          {
+            NEW_PATTERN;
+            startp = p + 1;
+          }
       }
   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, NULL,
-	       alloca_used) == 0)
-	goto success;
-      /* FALLTHROUGH */
-
-    case L('+'):
+               alloca_used) == 0)
+        goto success;
+      FALLTHROUGH;
+    case L_('+'):
       do
-	{
-	  for (rs = string; rs <= string_end; ++rs)
-	    /* First match the prefix with the current pattern with the
-	       current pattern.  */
-	    if (FCT (list->str, string, rs, no_leading_period,
-		     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
-		     NULL, alloca_used) == 0
-		/* This was successful.  Now match the rest with the rest
-		   of the pattern.  */
-		&& (FCT (p, rs, string_end,
-			 rs == string
-			 ? no_leading_period
-			 : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
-			 flags & FNM_FILE_NAME
-			 ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
-		    /* This didn't work.  Try the whole pattern.  */
-		    || (rs != string
-			&& FCT (pattern - 1, rs, string_end,
-				rs == string
-				? no_leading_period
-				: (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
-				   ? 1 : 0),
-				flags & FNM_FILE_NAME
-				? flags : flags & ~FNM_PERIOD, NULL,
-				alloca_used) == 0)))
-	      /* It worked.  Signal success.  */
-	      goto success;
-	}
+        {
+          for (rs = string; rs <= string_end; ++rs)
+            /* First match the prefix with the current pattern with the
+               current pattern.  */
+            if (FCT (list->str, string, rs, no_leading_period,
+                     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+                     NULL, alloca_used) == 0
+                /* This was successful.  Now match the rest with the rest
+                   of the pattern.  */
+                && (FCT (p, rs, string_end,
+                         rs == string
+                         ? no_leading_period
+                         : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+                         flags & FNM_FILE_NAME
+                         ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
+                    /* This didn't work.  Try the whole pattern.  */
+                    || (rs != string
+                        && FCT (pattern - 1, rs, string_end,
+                                rs == string
+                                ? no_leading_period
+                                : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+                                flags & FNM_FILE_NAME
+                                ? flags : flags & ~FNM_PERIOD, NULL,
+                                alloca_used) == 0)))
+              /* It worked.  Signal success.  */
+              goto success;
+        }
       while ((list = list->next) != NULL);
 
       /* None of the patterns lead to a match.  */
       retval = FNM_NOMATCH;
       break;
 
-    case L('?'):
+    case L_('?'):
       if (FCT (p, string, string_end, no_leading_period, flags, NULL,
-	       alloca_used) == 0)
-	goto success;
-      /* FALLTHROUGH */
-
-    case L('@'):
+               alloca_used) == 0)
+        goto success;
+      FALLTHROUGH;
+    case L_('@'):
       do
-	/* I cannot believe it but `strcat' is actually acceptable
-	   here.  Match the entire string with the prefix from the
-	   pattern list and the rest of the pattern following the
-	   pattern list.  */
-	if (FCT (STRCAT (list->str, p), string, string_end,
-		 no_leading_period,
-		 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
-		 NULL, alloca_used) == 0)
-	  /* It worked.  Signal success.  */
-	  goto success;
+        /* I cannot believe it but 'strcat' is actually acceptable
+           here.  Match the entire string with the prefix from the
+           pattern list and the rest of the pattern following the
+           pattern list.  */
+        if (FCT (STRCAT (list->str, p), string, string_end,
+                 no_leading_period,
+                 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+                 NULL, alloca_used) == 0)
+          /* It worked.  Signal success.  */
+          goto success;
       while ((list = list->next) != NULL);
 
       /* None of the patterns lead to a match.  */
       retval = FNM_NOMATCH;
       break;
 
-    case L('!'):
+    case L_('!'):
       for (rs = string; rs <= string_end; ++rs)
-	{
-	  struct patternlist *runp;
-
-	  for (runp = list; runp != NULL; runp = runp->next)
-	    if (FCT (runp->str, string, rs,  no_leading_period,
-		     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
-		     NULL, alloca_used) == 0)
-	      break;
-
-	  /* If none of the patterns matched see whether the rest does.  */
-	  if (runp == NULL
-	      && (FCT (p, rs, string_end,
-		       rs == string
-		       ? no_leading_period
-		       : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
-		       flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
-		       NULL, alloca_used) == 0))
-	    /* This is successful.  */
-	    goto success;
-	}
+        {
+          struct patternlist *runp;
+
+          for (runp = list; runp != NULL; runp = runp->next)
+            if (FCT (runp->str, string, rs,  no_leading_period,
+                     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+                     NULL, alloca_used) == 0)
+              break;
+
+          /* If none of the patterns matched see whether the rest does.  */
+          if (runp == NULL
+              && (FCT (p, rs, string_end,
+                       rs == string
+                       ? no_leading_period
+                       : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+                       flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+                       NULL, alloca_used) == 0))
+            /* This is successful.  */
+            goto success;
+        }
 
       /* None of the patterns together with the rest of the pattern
-	 lead to a match.  */
+         lead to a match.  */
       retval = FNM_NOMATCH;
       break;
 
@@ -1189,10 +1183,10 @@  EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
   if (any_malloced)
     while (list != NULL)
       {
-	struct patternlist *old = list;
-	list = list->next;
-	if (old->malloced)
-	  free (old);
+        struct patternlist *old = list;
+        list = list->next;
+        if (old->malloced)
+          free (old);
       }
 
   return retval;
@@ -1209,10 +1203,9 @@  EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
 #undef STRUCT
 #undef MEMPCPY
 #undef MEMCHR
-#undef STRCOLL
 #undef STRLEN
 #undef STRCAT
-#undef L
+#undef L_
 #undef BTOWC
 #undef WIDE_CHAR_VERSION
 #undef FINDIDX