Add .cantunwind to _dl_start_user
[platform/upstream/glibc.git] / posix / fnmatch.c
index 98c5ffc..a707847 100644 (file)
@@ -1,20 +1,19 @@
-/* Copyright (C) 1991-1993,1996-1999,2000,2001 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
-   This library is distributed in the hope that it will be useful,
+   The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
-   License along with this library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #if HAVE_CONFIG_H
 # include <config.h>
 #include <errno.h>
 #include <fnmatch.h>
 #include <ctype.h>
-
-#if HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-#endif
+#include <string.h>
 
 #if defined STDC_HEADERS || defined _LIBC
 # include <stdlib.h>
 #endif
 
+#ifdef _LIBC
+# 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)
 # include "../locale/localeinfo.h"
 # include "../locale/elem-hash.h"
 # include "../locale/coll-lookup.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
 
 /* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
@@ -206,15 +208,21 @@ __wcschrnul (s, c)
 # 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
+# include <locale/weight.h>
+# define FINDIDX findidx
 # include "fnmatch_loop.c"
 
 
@@ -230,13 +238,22 @@ __wcschrnul (s, c)
 #  define INT  wint_t
 #  define FCT  internal_fnwmatch
 #  define EXT  ext_wmatch
-# define END   end_wpattern
+#  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)
 #  define WIDE_CHAR_VERSION 1
+/* 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
 
 #  undef IS_CHAR_CLASS
 /* We have to convert the wide character string in a multibyte string.  But
@@ -320,39 +337,136 @@ fnmatch (pattern, string, flags)
     {
       mbstate_t ps;
       size_t n;
+      const char *p;
+      wchar_t *wpattern_malloc = NULL;
       wchar_t *wpattern;
+      wchar_t *wstring_malloc = NULL;
       wchar_t *wstring;
+      size_t alloca_used = 0;
 
       /* Convert the strings into wide characters.  */
       memset (&ps, '\0', sizeof (ps));
-      n = mbsrtowcs (NULL, &pattern, 0, &ps);
-      if (__builtin_expect (n, 0) == (size_t) -1)
-       /* 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);
+      p = pattern;
+#ifdef _LIBC
+      n = strnlen (pattern, 1024);
+#else
+      n = strlen (pattern);
+#endif
+      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;
+           }
+       }
+      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);
+       }
 
       assert (mbsinit (&ps));
-      n = mbsrtowcs (NULL, &string, 0, &ps);
-      if (__builtin_expect (n, 0) == (size_t) -1)
-       /* 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);
+#ifdef _LIBC
+      n = strnlen (string, 1024);
+#else
+      n = strlen (string);
+#endif
+      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;
+           }
+       }
+      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);
+       }
+
+      int res = internal_fnwmatch (wpattern, wstring, wstring + n,
+                                  flags & FNM_PERIOD, flags, NULL,
+                                  alloca_used);
 
-      return internal_fnwmatch (wpattern, wstring, wstring + n,
-                               flags & FNM_PERIOD, flags);
+      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);
+                          flags & FNM_PERIOD, flags, NULL, 0);
 }
 
+# ifdef _LIBC
+#  undef fnmatch
+versioned_symbol (libc, __fnmatch, fnmatch, 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
+libc_hidden_ver (__fnmatch, fnmatch)
+# endif
+
 #endif /* _LIBC or not __GNU_LIBRARY__.  */