-/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004
+ Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#if HAVE_CONFIG_H
# include <config.h>
# define _GNU_SOURCE 1
#endif
-#ifdef __GNUC__
-# define alloca __builtin_alloca
-# define HAVE_ALLOCA 1
-#else
-# if defined HAVE_ALLOCA_H || defined _LIBC
-# include <alloca.h>
-# else
-# ifdef _AIX
- # pragma alloca
-# else
-# ifndef alloca
-char *alloca ();
-# endif
-# endif
-# endif
-#endif
-
#if ! defined __builtin_expect && __GNUC__ < 3
# define __builtin_expect(expr, expected) (expr)
#endif
-#include <assert.h>
-#include <errno.h>
#include <fnmatch.h>
-#include <ctype.h>
-#if HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# if HAVE_STRINGS_H
-# include <strings.h>
-# endif
-#endif
+#include <alloca.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
-#if defined STDC_HEADERS || defined _LIBC
-# include <stddef.h>
-# include <stdlib.h>
-#endif
+#define WIDE_CHAR_SUPPORT \
+ (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC \
+ && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY))
/* 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)
+#if defined _LIBC || WIDE_CHAR_SUPPORT
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
# include <wchar.h>
# include <wctype.h>
# include <shlib-compat.h>
# define CONCAT(a,b) __CONCAT(a,b)
-# define mbsinit __mbsinit
# define mbsrtowcs __mbsrtowcs
# define fnmatch __fnmatch
extern int fnmatch (const char *pattern, const char *string, int flags);
#endif
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#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, are not
+/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself, and have not detected a bug
in the library. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+# if defined _LIBC || WIDE_CHAR_SUPPORT
/* The GNU C library provides support for user-defined character classes
and the functions from ISO C amendement 1. */
# ifdef CHARCLASS_NAME_MAX
/* Avoid depending on library functions or files
whose names are inconsistent. */
-# if !defined _LIBC && !defined getenv && !HAVE_DECL_GETENV
-extern char *getenv ();
-# endif
-
-# ifndef errno
-extern int errno;
-# endif
-
/* Global variable. */
static int posixly_correct;
int
-fnmatch (pattern, string, flags)
- const char *pattern;
- const char *string;
- int flags;
+fnmatch (const char *pattern, const char *string, int flags)
{
# if HANDLE_MULTIBYTE
+# define ALLOCA_LIMIT 2000
if (__builtin_expect (MB_CUR_MAX, 1) != 1)
{
mbstate_t ps;
- size_t n;
+ size_t patsize;
+ size_t strsize;
+ size_t totsize;
wchar_t *wpattern;
wchar_t *wstring;
+ int res;
- /* Convert the strings into wide characters. */
+ /* Calculate the size needed to convert the strings to
+ wide characters. */
memset (&ps, '\0', sizeof (ps));
- n = mbsrtowcs (NULL, &pattern, 0, &ps);
- if (__builtin_expect (n, 0) == (size_t) -1)
+ patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
+ if (__builtin_expect (patsize == 0, 0))
/* Something wrong.
XXX Do we have to set `errno' to something which mbsrtows hasn't
already done? */
return -1;
- wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
- assert (mbsinit (&ps));
- (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
-
assert (mbsinit (&ps));
- n = mbsrtowcs (NULL, &string, 0, &ps);
- if (__builtin_expect (n, 0) == (size_t) -1)
+ strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
+ if (__builtin_expect (strsize == 0, 0))
/* Something wrong.
XXX Do we have to set `errno' to something which mbsrtows hasn't
already done? */
return -1;
- wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
assert (mbsinit (&ps));
- (void) mbsrtowcs (wstring, &string, n + 1, &ps);
+ totsize = patsize + strsize;
+ if (__builtin_expect (! (patsize <= totsize
+ && totsize <= SIZE_MAX / sizeof (wchar_t)),
+ 0))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Allocate room for the wide characters. */
+ if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
+ wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
+ else
+ {
+ wpattern = malloc (totsize * sizeof (wchar_t));
+ if (__builtin_expect (! wpattern, 0))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ wstring = wpattern + patsize;
+
+ /* Convert the strings into wide characters. */
+ mbsrtowcs (wpattern, &pattern, patsize, &ps);
+ assert (mbsinit (&ps));
+ mbsrtowcs (wstring, &string, strsize, &ps);
+
+ res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
+ flags & FNM_PERIOD, flags);
- return internal_fnwmatch (wpattern, wstring, wstring + n,
- flags & FNM_PERIOD, flags);
+ if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
+ free (wpattern);
+ return res;
}
-# endif /* mbstate_t and mbsrtowcs or _LIBC. */
+# endif /* HANDLE_MULTIBYTE */
return internal_fnmatch (pattern, string, string + strlen (string),
flags & FNM_PERIOD, flags);
strong_alias (__fnmatch, __fnmatch_old)
compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
# endif
+libc_hidden_ver (__fnmatch, fnmatch)
# endif
#endif /* _LIBC or not __GNU_LIBRARY__. */