Remove unused vars and decls in obstack.
[gnulib.git] / lib / fnmatch.c
index 452edc0..b9b0598 100644 (file)
@@ -1,5 +1,5 @@
-/* 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
 # 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 <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)
 
 /* 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>
@@ -81,17 +58,20 @@ char *alloca ();
 # 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
@@ -103,7 +83,6 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
 #if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU
 
 
-# undef ISASCII  /* defined in Solaris5.6's /usr/include/sys/euc.h */
 # if defined STDC_HEADERS || !defined isascii
 #  define ISASCII(c) 1
 # else
@@ -121,7 +100,6 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
 #  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
 # endif
 
-# undef ISPRINT  /* defined in Solaris5.6's /usr/include/sys/euc.h */
 # define ISPRINT(c) (ISASCII (c) && isprint (c))
 # define ISDIGIT(c) (ISASCII (c) && isdigit (c))
 # define ISALNUM(c) (ISASCII (c) && isalnum (c))
@@ -135,7 +113,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
 
 # 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
@@ -178,10 +156,6 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
 /* 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
@@ -328,46 +302,73 @@ is_char_class (const wchar_t *wcs)
 
 
 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);
@@ -380,6 +381,7 @@ versioned_symbol (libc, __fnmatch, fnmatch, 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__.  */