changeset 4096:66d7394f5822

[project @ 2002-10-09 18:47:16 by jwe]
author jwe
date Wed, 09 Oct 2002 18:47:16 +0000
parents 60abc5f86565
children 596f88296519
files glob/ChangeLog glob/ChangeLog.glob glob/fnmatch.c glob/fnmatch.h glob/glob.c glob/glob.h
diffstat 6 files changed, 1534 insertions(+), 501 deletions(-) [+]
line wrap: on
line diff
--- a/glob/ChangeLog	Wed Oct 09 14:44:44 2002 +0000
+++ b/glob/ChangeLog	Wed Oct 09 18:47:16 2002 +0000
@@ -1,3 +1,7 @@
+2002-10-09  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* fnmatch.h, glob.h, fnmatch.c, glob.c: Update to latest GNU sources.
+
 2002-05-01  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* configure.in: Add AC_CONFIG_HEADERS.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glob/ChangeLog.glob	Wed Oct 09 18:47:16 2002 +0000
@@ -0,0 +1,136 @@
+2002-04-22  Paul D. Smith  <psmith@gnu.org>
+
+	* Makefile.am: Use automake 1.6.
+	Use new automake condition USE_LOCAL_GLOB to decide whether or not
+	to build the local GNU glob library or use the system one.
+
+1999-09-12  Paul D. Smith  <psmith@gnu.org>
+
+	* fnmatch.c: Last GLIBC version wouldn't compile outside of GLIBC
+	(undefined reference to internal_function).  Update to the latest
+	version
+
+1999-09-11  Paul Eggert  <eggert@twinsun.com>
+
+	* glob.h (glob): If #defining to glob64, do this before
+	declaring it, so that all declarations and uses match, and
+	do not declare glob64, to avoid a declaration clash.
+	(globfree): Likewise with globfree64.
+
+1999-09-08  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* glob.c (prefix_array) [__MSDOS__,WINDOWS32]: Keep the trailing
+	slash unless DIRNAME is just "x:/".
+
+1999-09-06  Paul D. Smith  <psmith@gnu.org>
+
+	* fnmatch.c: Update to latest version from GLIBC.
+
+1999-07-21  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c, glob.h, fnmatch.c, fnmatch.h: Update to latest version
+	from GLIBC.
+
+	* fnmatch.c (internal_fnmatch): Use K&R definition syntax, not ANSI.
+	(__strchrnul): This won't exist outside GLIBC, so create one.
+
+	* glob.c: Move getlogin{,_r} prototypes below glob.h to get __P()
+	macro.
+
+1998-08-05  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Remove; configuration for glob is handled by the
+	make configure.in.
+
+1998-07-29  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c, fnmatch.c: New versions from the GLIBC folks (Ulrich
+	Drepper).  Fixes a bug reported by Eli Zaretski.  Integrates
+	DOS/Windows32 support.
+
+1998-07-27  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+	* glob.c (glob): Cast away const on assignment of pattern to dirname.
+	Cast the return type of __alloca() for traditional C compilers.
+
+1998-07-23  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c, fnmatch.c: New versions of these files from the GLIBC
+	folks (Ulrich Drepper).  Had to re-integrate some DOS/Windows
+	code.
+
+1998-07-10  Paul D. Smith  <psmith@gnu.org>
+
+	* glob.c (glob_in_dir): If no meta chars exist in PATTERN and
+	GLOB_NOCHECK is present, don't look for the file--whether it's
+	found or not, we'll always return it, so why bother searching?
+
+	Also, if we are searching and there are no meta chars, don't
+	bother trying fnmatch() if the strcmp() fails.
+
+1998-05-30  Eli Zaretskii  <eliz@is.elta.co.il>
+
+	* glob.c (glob) [__MSDOS__, WINDOWS32]: Compute the directory and
+	filename parts of the pattern correctly when it includes a drive
+	spec.  Disallow wildcards in the drive spec.  Prevent recursion
+	when dirname is of the form "d:/" or "d:".
+	(prefix_array) [__MSDOS__, WINDOWS32]: Don't append a slash to
+	"d:/" and "d:".
+
+1998-05-13  Paul D. Smith  <psmith@gnu.org>
+
+	* SMakefile, Makefile.ami, glob.c, glob.h, fnmatch.c: Updated from
+	the latest glibc version.
+
+1998-04-17  Paul D. Smith  <psmith@gnu.org>
+
+	* configure.in: Create a config.h file instead of setting things
+	on the compile line.  This is because when build.sh runs it merely
+	passes -DHAVE_CONFIG_H to the glob files, just as it does to the
+	make files.
+	* config.h.in: Created by autoheader.
+
+Tue Aug 12 10:52:34 1997  Paul D. Smith  <psmith@baynetworks.com>
+
+	* configure.in: Require autoconf 2.12.
+
+	* glob: Updates from latest GNU libc glob code.
+
+	* glob.c,glob.h,fnmatch.h: Change all WIN32 references to WINDOWS32.
+
+	* glob.h: OSF4 defines macros in such a way that GLOB_ALTDIRFUNC
+	is not defined.  Added a test to the #if which defines it if
+	_GNU_SOURCE is defined; that's set by both glob.c and GNU make.
+
+	* glob.c: SunOS4 w/ cc needs #include <stdio.h>, since assert.h
+	requires stderr but doesn't include stdio.h :-/.
+	(next_brace_sub): De-protoize function definition.
+	(glob): Cast __alloca(); on SunOS4 it uses the default return type
+	of int.
+	(glob): Irix defines getlogin_r() to return a char*; move the
+	extern for that into the _LIBC area since it isn't used except in
+	LIBC anyway.  Likewise, move extern getlogin() into the "else".
+
+Sat Jul 20 21:55:31 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	Win32 hacks from <Rob_Tulloh@tivoli.com>.
+	* posix/glob.c [WIN32]: Don't include <pwd.h>; don't use d_ino;
+	use void * for my_realloc; include <malloc.h> for alloca.
+	(glob) [WIN32]: Use "c:/users/default" for ~ if no HOME variable.
+	* posix/fnmatch.h [WIN32]: Use prototypes even if [!__STDC__].
+	* posix/glob.h: Likewise.
+
+Fri Jul 19 16:56:41 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* posix/glob.h [!_AMIGA && !VMS]: Check this instead of just [!_AMIGA]
+	for `struct stat;' forward decl.
+
+Sat Jun 22 10:44:09 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* posix/glob.c: Include <alloca.h> only [HAVE_ALLOCA_H], not [sparc].
+
+Fri Jun 21 00:27:51 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* posix/fnmatch.c (fnmatch): Fix \*[*?]+ case to increment name ptr
+ 	only for ?s, not for *s.  Fix from Chet Ramey.
+
--- a/glob/fnmatch.c	Wed Oct 09 14:44:44 2002 +0000
+++ b/glob/fnmatch.c	Wed Oct 09 18:47:16 2002 +0000
@@ -1,33 +1,51 @@
-/* Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 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.
+   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.
 
-This 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.
+   This 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.
 
-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 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.  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#if HAVE_CONFIG_H
+# include <config.h>
 #endif
 
 /* Enable GNU extensions in fnmatch.h.  */
 #ifndef _GNU_SOURCE
-#define	_GNU_SOURCE	1
+# define _GNU_SOURCE	1
 #endif
 
 #include <errno.h>
 #include <fnmatch.h>
 #include <ctype.h>
 
+#if HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+#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
 
 /* 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
@@ -37,26 +55,121 @@
    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.  */
 
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+#if defined _LIBC || !defined __GNU_LIBRARY__
 
 
-#ifndef errno
+# if defined STDC_HEADERS || !defined isascii
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# ifdef isblank
+#  define ISBLANK(c) (ISASCII (c) && isblank (c))
+# 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))
+# 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
+/* 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
+# 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
+
+/* 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
+# endif
+
+/* This function doesn't exist on most systems.  */
+
+# if !defined HAVE___STRCHRNUL && !defined _LIBC
+static char *
+__strchrnul (s, c)
+     const char *s;
+     int c;
+{
+  char *result = strchr (s, c);
+  if (result == NULL)
+    result = strchr (s, '\0');
+  return result;
+}
+# endif
+
+# ifndef internal_function
+/* Inside GNU libc we mark some function in a special way.  In other
+   environments simply ignore the marking.  */
+#  define internal_function
+# endif
 
 /* Match STRING against the filename pattern PATTERN, returning zero if
    it matches, nonzero if not.  */
-int
-fnmatch (pattern, string, flags)
+static int internal_fnmatch __P ((const char *pattern, const char *string,
+				  int no_leading_period, int flags))
+     internal_function;
+static int
+internal_function
+internal_fnmatch (pattern, string, no_leading_period, flags)
      const char *pattern;
      const char *string;
+     int no_leading_period;
      int flags;
 {
   register const char *p = pattern, *n = string;
-  register char c;
+  register unsigned char c;
 
-/* Note that this evalutes C many times.  */
-#define FOLD(c)	((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
+/* 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
 
   while ((c = *p++) != '\0')
     {
@@ -67,10 +180,11 @@
 	case '?':
 	  if (*n == '\0')
 	    return FNM_NOMATCH;
-	  else if ((flags & FNM_FILE_NAME) && *n == '/')
+	  else if (*n == '/' && (flags & FNM_FILE_NAME))
 	    return FNM_NOMATCH;
-	  else if ((flags & FNM_PERIOD) && *n == '.' &&
-		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+	  else if (*n == '.' && no_leading_period
+		   && (n == string
+		       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
 	    return FNM_NOMATCH;
 	  break;
 
@@ -83,18 +197,19 @@
 		return FNM_NOMATCH;
 	      c = FOLD (c);
 	    }
-	  if (FOLD (*n) != c)
+	  if (FOLD ((unsigned char) *n) != c)
 	    return FNM_NOMATCH;
 	  break;
 
 	case '*':
-	  if ((flags & FNM_PERIOD) && *n == '.' &&
-	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+	  if (*n == '.' && no_leading_period
+	      && (n == string
+		  || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
 	    return FNM_NOMATCH;
 
 	  for (c = *p++; c == '?' || c == '*'; c = *p++)
 	    {
-	      if ((flags & FNM_FILE_NAME) && *n == '/')
+	      if (*n == '/' && (flags & FNM_FILE_NAME))
 		/* A slash does not match a wildcard under FNM_FILE_NAME.  */
 		return FNM_NOMATCH;
 	      else if (c == '?')
@@ -112,82 +227,204 @@
 	    }
 
 	  if (c == '\0')
-	    return 0;
+	    /* The wildcard(s) is/are the last element of the pattern.
+	       If the name is a file name and contains another slash
+	       this does mean it cannot match.  */
+	    return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
+		    ? FNM_NOMATCH : 0);
+	  else
+	    {
+	      const char *endp;
+
+	      endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
+
+	      if (c == '[')
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
 
-	  {
-	    char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
-	    c1 = FOLD (c1);
-	    for (--p; *n != '\0'; ++n)
-	      if ((c == '[' || FOLD (*n) == c1) &&
-		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
-		return 0;
-	    return FNM_NOMATCH;
-	  }
+		  for (--p; n < endp; ++n)
+		    if (internal_fnmatch (p, n,
+					  (no_leading_period
+					   && (n == string
+					       || (n[-1] == '/'
+						   && (flags
+						       & FNM_FILE_NAME)))),
+					  flags2)
+			== 0)
+		      return 0;
+		}
+	      else if (c == '/' && (flags & FNM_FILE_NAME))
+		{
+		  while (*n != '\0' && *n != '/')
+		    ++n;
+		  if (*n == '/'
+		      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
+					    flags) == 0))
+		    return 0;
+		}
+	      else
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
+
+		  if (c == '\\' && !(flags & FNM_NOESCAPE))
+		    c = *p;
+		  c = FOLD (c);
+		  for (--p; n < endp; ++n)
+		    if (FOLD ((unsigned char) *n) == c
+			&& (internal_fnmatch (p, n,
+					      (no_leading_period
+					       && (n == string
+						   || (n[-1] == '/'
+						       && (flags
+							   & FNM_FILE_NAME)))),
+					      flags2) == 0))
+		      return 0;
+		}
+	    }
+
+	  /* If we come here no match is possible with the wildcard.  */
+	  return FNM_NOMATCH;
 
 	case '[':
 	  {
 	    /* Nonzero if the sense of the character class is inverted.  */
+	    static int posixly_correct;
 	    register int not;
+	    char cold;
+
+	    if (posixly_correct == 0)
+	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
 
 	    if (*n == '\0')
 	      return FNM_NOMATCH;
 
-	    if ((flags & FNM_PERIOD) && *n == '.' &&
-		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+	    if (*n == '.' && no_leading_period && (n == string
+						   || (n[-1] == '/'
+						       && (flags
+							   & FNM_FILE_NAME))))
 	      return FNM_NOMATCH;
 
-	    not = (*p == '!' || *p == '^');
+	    if (*n == '/' && (flags & FNM_FILE_NAME))
+	      /* `/' cannot be matched.  */
+	      return FNM_NOMATCH;
+
+	    not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
 	    if (not)
 	      ++p;
 
 	    c = *p++;
 	    for (;;)
 	      {
-		register char cstart = c, cend = c;
+		unsigned char fn = FOLD ((unsigned char) *n);
 
 		if (!(flags & FNM_NOESCAPE) && c == '\\')
 		  {
 		    if (*p == '\0')
 		      return FNM_NOMATCH;
-		    cstart = cend = *p++;
+		    c = FOLD ((unsigned char) *p);
+		    ++p;
+
+		    if (c == fn)
+		      goto matched;
 		  }
+		else if (c == '[' && *p == ':')
+		  {
+		    /* 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;
 
-		cstart = cend = FOLD (cstart);
+			c = *++p;
+			if (c == ':' && p[1] == ']')
+			  {
+			    p += 2;
+			    break;
+			  }
+			if (c < 'a' || c >= 'z')
+			  {
+			    /* This cannot possibly be a character class name.
+			       Match it as a normal range.  */
+			    p = startp;
+			    c = '[';
+			    goto normal_bracket;
+			  }
+			str[c1++] = c;
+		      }
+		    str[c1] = '\0';
 
-		if (c == '\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 (__iswctype (__btowc ((unsigned char) *n), wt))
+		      goto matched;
+# else
+		    if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
+			|| (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
+			|| (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
+			|| (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
+			|| (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
+			|| (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
+			|| (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
+			|| (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
+			|| (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
+			|| (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
+			|| (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
+			|| (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
+		      goto matched;
+# endif
+		  }
+		else if (c == '\0')
 		  /* [ (unterminated) loses.  */
 		  return FNM_NOMATCH;
-
-		c = *p++;
-		c = FOLD (c);
-
-		if ((flags & FNM_FILE_NAME) && c == '/')
-		  /* [/] can never match.  */
-		  return FNM_NOMATCH;
-
-		if (c == '-' && *p != ']')
+		else
 		  {
-		    cend = *p++;
-		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
-		      cend = *p++;
-		    if (cend == '\0')
-		      return FNM_NOMATCH;
-		    cend = FOLD (cend);
+		  normal_bracket:
+		    if (FOLD (c) == fn)
+		      goto matched;
+
+		    cold = c;
+		    c = *p++;
 
-		    c = *p++;
-		  }
+		    if (c == '-' && *p != ']')
+		      {
+			/* It is a range.  */
+			unsigned char cend = *p++;
+			if (!(flags & FNM_NOESCAPE) && cend == '\\')
+			  cend = *p++;
+			if (cend == '\0')
+			  return FNM_NOMATCH;
 
-		if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
-		  goto matched;
+			if (cold <= fn && fn <= FOLD (cend))
+			  goto matched;
+
+			c = *p++;
+		      }
+		  }
 
 		if (c == ']')
 		  break;
 	      }
+
 	    if (!not)
 	      return FNM_NOMATCH;
 	    break;
 
-	  matched:;
+	  matched:
 	    /* Skip the rest of the [...] that already matched.  */
 	    while (c != ']')
 	      {
@@ -203,6 +440,15 @@
 		    /* XXX 1003.2d11 is unclear if this is right.  */
 		    ++p;
 		  }
+		else if (c == '[' && *p == ':')
+		  {
+		    do
+		      if (*++p == '\0')
+			return FNM_NOMATCH;
+		    while (*p != ':' || p[1] == ']');
+		    p += 2;
+		    c = *p;
+		  }
 	      }
 	    if (not)
 	      return FNM_NOMATCH;
@@ -210,7 +456,7 @@
 	  break;
 
 	default:
-	  if (c != FOLD (*n))
+	  if (c != FOLD ((unsigned char) *n))
 	    return FNM_NOMATCH;
 	}
 
@@ -225,6 +471,18 @@
     return 0;
 
   return FNM_NOMATCH;
+
+# undef FOLD
+}
+
+
+int
+fnmatch (pattern, string, flags)
+     const char *pattern;
+     const char *string;
+     int flags;
+{
+  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
 }
 
 #endif	/* _LIBC or not __GNU_LIBRARY__.  */
--- a/glob/fnmatch.h	Wed Oct 09 14:44:44 2002 +0000
+++ b/glob/fnmatch.h	Wed Oct 09 18:47:16 2002 +0000
@@ -1,40 +1,48 @@
-/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-This 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.
+   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.
 
-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 Library General Public
+   License along with the GNU C 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.  */
 
 #ifndef	_FNMATCH_H
-
 #define	_FNMATCH_H	1
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
-#if (defined (__cplusplus) || (defined (__STDC__) && __STDC__) \
-     || defined (WIN32))
-#undef	__P
-#define	__P(protos)	protos
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# if !defined __GLIBC__ || !defined __P
+#  undef	__P
+#  define __P(protos)	protos
+# endif
 #else /* Not C++ or ANSI C.  */
-#undef	__P
-#define	__P(protos)	()
+# undef	__P
+# define __P(protos)	()
 /* We can get away without defining `const' here only because in this file
    it is used only inside the prototype for `fnmatch', which is elided in
    non-ANSI C where `const' is problematical.  */
 #endif /* C++ or ANSI C.  */
 
+#ifndef const
+# if (defined __STDC__ && __STDC__) || defined __cplusplus
+#  define __const	const
+# else
+#  define __const
+# endif
+#endif
 
 /* We #undef these before defining them because some losing systems
    (HP-UX A.08.07 for example) define these in <unistd.h>.  */
@@ -47,18 +55,26 @@
 #define	FNM_NOESCAPE	(1 << 1) /* Backslashes don't quote special chars.  */
 #define	FNM_PERIOD	(1 << 2) /* Leading `.' is matched only explicitly.  */
 
-#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
-#define	FNM_FILE_NAME	FNM_PATHNAME /* Preferred GNU name.  */
-#define	FNM_LEADING_DIR	(1 << 3) /* Ignore `/...' after a match.  */
-#define	FNM_CASEFOLD	(1 << 4) /* Compare without regard to case.  */
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
+# define FNM_FILE_NAME	 FNM_PATHNAME	/* Preferred GNU name.  */
+# define FNM_LEADING_DIR (1 << 3)	/* Ignore `/...' after a match.  */
+# define FNM_CASEFOLD	 (1 << 4)	/* Compare without regard to case.  */
 #endif
 
 /* Value returned by `fnmatch' if STRING does not match PATTERN.  */
 #define	FNM_NOMATCH	1
 
-/* Match STRING against the filename pattern PATTERN,
+/* This value is returned if the implementation does not support
+   `fnmatch'.  Since this is not the case here it will never be
+   returned but the conformance test suites still require the symbol
+   to be defined.  */
+#ifdef _XOPEN_SOURCE
+# define FNM_NOSYS	(-1)
+#endif
+
+/* Match NAME against the filename pattern PATTERN,
    returning zero if it matches, FNM_NOMATCH if not.  */
-extern int fnmatch __P ((const char *__pattern, const char *__string,
+extern int fnmatch __P ((__const char *__pattern, __const char *__name,
 			 int __flags));
 
 #ifdef	__cplusplus
--- a/glob/glob.c	Wed Oct 09 14:44:44 2002 +0000
+++ b/glob/glob.c	Wed Oct 09 18:47:16 2002 +0000
@@ -1,38 +1,44 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
 
-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.
+   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.
 
-This 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.
+   This 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.
 
-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 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.  */
 
 /* AIX requires this to be the first thing in the file.  */
-#if defined (_AIX) && !defined (__GNUC__)
+#if defined _AIX && !defined __GNUC__
  #pragma alloca
 #endif
 
 #ifdef	HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
 
 /* Enable GNU extensions in glob.h.  */
 #ifndef _GNU_SOURCE
-#define	_GNU_SOURCE	1
+# define _GNU_SOURCE	1
 #endif
 
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
+/* Outcomment the following line for production quality code.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+#include <stdio.h>		/* Needed on stupid SunOS for assert.  */
+
 
 /* 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
@@ -43,42 +49,45 @@
    it is simpler to just do this in the source for each such file.  */
 
 #define GLOB_INTERFACE_VERSION 1
-#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
-#include <gnu-versions.h>
-#if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
 #endif
 
 #ifndef ELIDE_CODE
 
-#ifdef	STDC_HEADERS
-#include <stddef.h>
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stddef.h>
 #endif
 
-#ifdef	HAVE_UNISTD_H
-#include <unistd.h>
-#ifndef POSIX
-#ifdef	_POSIX_VERSION
-#define	POSIX
-#endif
-#endif
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+# ifndef POSIX
+#  ifdef _POSIX_VERSION
+#   define POSIX
+#  endif
+# endif
 #endif
 
-#if !defined (_AMIGA) && !defined (VMS) && !defined(WIN32)
-#include <pwd.h>
+#if !defined _AMIGA && !defined VMS && !defined WINDOWS32
+# include <pwd.h>
 #endif
 
-#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
 extern int errno;
 #endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
 
 #ifndef	NULL
-#define	NULL	0
+# define NULL	0
 #endif
 
 
-#if defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
+#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
 # include <dirent.h>
 # define NAMLEN(dirent) strlen((dirent)->d_name)
 #else
@@ -101,36 +110,42 @@
 
 /* In GNU systems, <dirent.h> defines this macro for us.  */
 #ifdef _D_NAMLEN
-#undef NAMLEN
-#define NAMLEN(d) _D_NAMLEN(d)
+# undef NAMLEN
+# define NAMLEN(d) _D_NAMLEN(d)
+#endif
+
+/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
+   if the `d_type' member for `struct dirent' is available.  */
+#ifdef _DIRENT_HAVE_D_TYPE
+# define HAVE_D_TYPE	1
 #endif
 
 
-#if (defined (POSIX) || defined (WIN32)) && !defined (__GNU_LIBRARY__)
+#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
 /* Posix does not require that the d_ino field be present, and some
    systems do not provide it. */
-#define REAL_DIR_ENTRY(dp) 1
+# define REAL_DIR_ENTRY(dp) 1
 #else
-#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
 #endif /* POSIX */
 
-#if	(defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
-#include <stdlib.h>
-#include <string.h>
-#define	ANSI_STRING
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <stdlib.h>
+# include <string.h>
+# define	ANSI_STRING
 #else	/* No standard headers.  */
 
 extern char *getenv ();
 
-#ifdef HAVE_STRING_H
-#include <string.h>
-#define	ANSI_STRING
-#else
-#include <strings.h>
-#endif
-#ifdef	HAVE_MEMORY_H
-#include <memory.h>
-#endif
+# ifdef HAVE_STRING_H
+#  include <string.h>
+#  define ANSI_STRING
+# else
+#  include <strings.h>
+# endif
+# ifdef	HAVE_MEMORY_H
+#  include <memory.h>
+# endif
 
 extern char *malloc (), *realloc ();
 extern void free ();
@@ -142,35 +157,40 @@
 
 #ifndef	ANSI_STRING
 
-#ifndef	bzero
+# ifndef bzero
 extern void bzero ();
-#endif
-#ifndef	bcopy
+# endif
+# ifndef bcopy
 extern void bcopy ();
-#endif
+# endif
 
-#define	memcpy(d, s, n)	bcopy ((s), (d), (n))
-#define	strrchr	rindex
+# define memcpy(d, s, n)	bcopy ((s), (d), (n))
+# define strrchr	rindex
 /* memset is only used for zero here, but let's be paranoid.  */
-#define	memset(s, better_be_zero, n) \
+# define memset(s, better_be_zero, n) \
   ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
 #endif	/* Not ANSI_STRING.  */
 
-#ifndef	HAVE_STRCOLL
-#define	strcoll	strcmp
+#if !defined HAVE_STRCOLL && !defined _LIBC
+# define strcoll	strcmp
 #endif
 
+#if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1
+# define HAVE_MEMPCPY	1
+# undef  mempcpy
+# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
+#endif
 
 #ifndef	__GNU_LIBRARY__
-#ifdef	__GNUC__
+# ifdef	__GNUC__
 __inline
-#endif
-#ifndef __SASC
-#ifdef WIN32
+# endif
+# ifndef __SASC
+#  ifdef WINDOWS32
 static void *
-#else
+#  else
 static char *
-#endif
+# endif
 my_realloc (p, n)
      char *p;
      unsigned int n;
@@ -181,82 +201,162 @@
     return (char *) malloc (n);
   return (char *) realloc (p, n);
 }
-#define	realloc	my_realloc
-#endif /* __SASC */
+# define	realloc	my_realloc
+# endif /* __SASC */
 #endif /* __GNU_LIBRARY__ */
 
 
-#if	!defined(__alloca) && !defined(__GNU_LIBRARY__)
+#if !defined __alloca && !defined __GNU_LIBRARY__
 
-#ifdef	__GNUC__
-#undef	alloca
-#define	alloca(n)	__builtin_alloca (n)
-#else	/* Not GCC.  */
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#else	/* Not HAVE_ALLOCA_H.  */
-#ifndef	_AIX
-#ifdef WIN32
-#include <malloc.h>
-#else
+# ifdef	__GNUC__
+#  undef alloca
+#  define alloca(n)	__builtin_alloca (n)
+# else	/* Not GCC.  */
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else	/* Not HAVE_ALLOCA_H.  */
+#   ifndef _AIX
+#    ifdef WINDOWS32
+#     include <malloc.h>
+#    else
 extern char *alloca ();
-#endif /* WIN32 */
-#endif	/* Not _AIX.  */
-#endif	/* sparc or HAVE_ALLOCA_H.  */
-#endif	/* GCC.  */
+#    endif /* WINDOWS32 */
+#   endif /* Not _AIX.  */
+#  endif /* sparc or HAVE_ALLOCA_H.  */
+# endif	/* GCC.  */
 
-#define	__alloca	alloca
+# define __alloca	alloca
 
 #endif
 
 #ifndef __GNU_LIBRARY__
-#define __stat stat
-#ifdef STAT_MACROS_BROKEN
-#undef S_ISDIR
-#endif
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
-#endif
+# define __stat stat
+# ifdef STAT_MACROS_BROKEN
+#  undef S_ISDIR
+# endif
+# ifndef S_ISDIR
+#  define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+# endif
 #endif
 
-#ifndef	STDC_HEADERS
-#undef	size_t
-#define	size_t	unsigned int
+#ifdef _LIBC
+# undef strdup
+# define strdup(str) __strdup (str)
+# define sysconf(id) __sysconf (id)
+# define closedir(dir) __closedir (dir)
+# define opendir(name) __opendir (name)
+# define readdir(str) __readdir (str)
+# define getpwnam_r(name, bufp, buf, len, res) \
+   __getpwnam_r (name, bufp, buf, len, res)
+# ifndef __stat
+#  define __stat(fname, buf) __xstat (_STAT_VER, fname, buf)
+# endif
+#endif
+
+#if !(defined STDC_HEADERS || defined __GNU_LIBRARY__)
+# undef	size_t
+# define size_t	unsigned int
 #endif
 
 /* Some system header files erroneously define these.
    We want our own definitions from <fnmatch.h> to take precedence.  */
-#undef	FNM_PATHNAME
-#undef	FNM_NOESCAPE
-#undef	FNM_PERIOD
+#ifndef __GNU_LIBRARY__
+# undef	FNM_PATHNAME
+# undef	FNM_NOESCAPE
+# undef	FNM_PERIOD
+#endif
 #include <fnmatch.h>
 
 /* Some system header files erroneously define these.
    We want our own definitions from <glob.h> to take precedence.  */
-#undef	GLOB_ERR
-#undef	GLOB_MARK
-#undef	GLOB_NOSORT
-#undef	GLOB_DOOFFS
-#undef	GLOB_NOCHECK
-#undef	GLOB_APPEND
-#undef	GLOB_NOESCAPE
-#undef	GLOB_PERIOD
+#ifndef __GNU_LIBRARY__
+# undef	GLOB_ERR
+# undef	GLOB_MARK
+# undef	GLOB_NOSORT
+# undef	GLOB_DOOFFS
+# undef	GLOB_NOCHECK
+# undef	GLOB_APPEND
+# undef	GLOB_NOESCAPE
+# undef	GLOB_PERIOD
+#endif
 #include <glob.h>
+
+#ifdef HAVE_GETLOGIN_R
+extern int getlogin_r __P ((char *, size_t));
+#else
+extern char *getlogin __P ((void));
+#endif
 
-static int glob_pattern_p __P ((const char *pattern, int quote));
+static
+#if __GNUC__ - 0 >= 2
+inline
+#endif
+const char *next_brace_sub __P ((const char *begin));
 static int glob_in_dir __P ((const char *pattern, const char *directory,
 			     int flags,
-			     int (*errfunc) __P ((const char *, int)),
+			     int (*errfunc) (const char *, int),
 			     glob_t *pglob));
 static int prefix_array __P ((const char *prefix, char **array, size_t n));
 static int collated_compare __P ((const __ptr_t, const __ptr_t));
 
+#ifdef VMS
+/* these compilers like prototypes */
+#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
+int __glob_pattern_p (const char *pattern, int quote);
+#endif
+#endif
+
+/* Find the end of the sub-pattern in a brace expression.  We define
+   this as an inline function if the compiler permits.  */
+static
+#if __GNUC__ - 0 >= 2
+inline
+#endif
+const char *
+next_brace_sub (begin)
+     const char *begin;
+{
+  unsigned int depth = 0;
+  const char *cp = begin;
+
+  while (1)
+    {
+      if (depth == 0)
+	{
+	  if (*cp != ',' && *cp != '}' && *cp != '\0')
+	    {
+	      if (*cp == '{')
+		++depth;
+	      ++cp;
+	      continue;
+	    }
+	}
+      else
+	{
+	  while (*cp != '\0' && (*cp != '}' || depth > 0))
+	    {
+	      if (*cp == '}')
+		--depth;
+	      ++cp;
+	    }
+	  if (*cp == '\0')
+	    /* An incorrectly terminated brace expression.  */
+	    return NULL;
+
+	  continue;
+	}
+      break;
+    }
+
+  return cp;
+}
+
 /* Do glob searching for PATTERN, placing results in PGLOB.
    The bits defined above may be set in FLAGS.
    If a directory cannot be opened or read and ERRFUNC is not nil,
    it is called with the pathname that caused the error, and the
    `errno' value from the failing call; if it returns non-zero
-   `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
+   `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
    Otherwise, `glob' returns zero.  */
 int
@@ -267,14 +367,14 @@
      glob_t *pglob;
 {
   const char *filename;
-  char *dirname;
+  const char *dirname;
   size_t dirlen;
   int status;
   int oldcount;
 
   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       return -1;
     }
 
@@ -283,38 +383,63 @@
       const char *begin = strchr (pattern, '{');
       if (begin != NULL)
 	{
+	  /* Allocate working buffer large enough for our work.  Note that
+	    we have at least an opening and closing brace.  */
 	  int firstc;
-	  size_t restlen;
-	  const char *p, *end, *next;
-	  unsigned int depth = 0;
+	  char *alt_start;
+	  const char *p;
+	  const char *next;
+	  const char *rest;
+	  size_t rest_len;
+#ifdef __GNUC__
+	  char onealt[strlen (pattern) - 1];
+#else
+	  char *onealt = (char *) malloc (strlen (pattern) - 1);
+	  if (onealt == NULL)
+	    {
+	      if (!(flags & GLOB_APPEND))
+		globfree (pglob);
+	      return GLOB_NOSPACE;
+	    }
+#endif
 
-	  /* Find the end of the brace expression, by counting braces.
-	     While we're at it, notice the first comma at top brace level.  */
-	  end = begin + 1;
-	  next = NULL;
-	  while (1)
+	  /* We know the prefix for all sub-patterns.  */
+#ifdef HAVE_MEMPCPY
+	  alt_start = mempcpy (onealt, pattern, begin - pattern);
+#else
+	  memcpy (onealt, pattern, begin - pattern);
+	  alt_start = &onealt[begin - pattern];
+#endif
+
+	  /* Find the first sub-pattern and at the same time find the
+	     rest after the closing brace.  */
+	  next = next_brace_sub (begin + 1);
+	  if (next == NULL)
 	    {
-	      switch (*end++)
+	      /* It is an illegal expression.  */
+#ifndef __GNUC__
+	      free (onealt);
+#endif
+	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+	    }
+
+	  /* Now find the end of the whole brace expression.  */
+	  rest = next;
+	  while (*rest != '}')
+	    {
+	      rest = next_brace_sub (rest + 1);
+	      if (rest == NULL)
 		{
-		case ',':
-		  if (depth == 0 && next == NULL)
-		    next = end;
-		  continue;
-		case '{':
-		  ++depth;
-		  continue;
-		case '}':
-		  if (depth-- == 0)
-		    break;
-		  continue;
-		case '\0':
-		  return glob (pattern, flags &~ GLOB_BRACE, errfunc, pglob);
+		  /* It is an illegal expression.  */
+#ifndef __GNUC__
+		  free (onealt);
+#endif
+		  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
 		}
-	      break;
 	    }
-	  restlen = strlen (end) + 1;
-	  if (next == NULL)
-	    next = end;
+	  /* Please note that we now can be sure the brace expression
+	     is well-formed.  */
+	  rest_len = strlen (++rest) + 1;
 
 	  /* We have a brace expression.  BEGIN points to the opening {,
 	     NEXT points past the terminator of the first element, and END
@@ -331,111 +456,149 @@
 	    }
 	  firstc = pglob->gl_pathc;
 
-	  /* In this loop P points to the beginning of the current element
-	     and NEXT points past its terminator.  */
 	  p = begin + 1;
 	  while (1)
 	    {
-	      /* Construct a whole name that is one of the brace
-		 alternatives in a temporary buffer.  */
 	      int result;
-	      size_t bufsz = (begin - pattern) + (next - 1 - p) + restlen;
-#ifdef __GNUC__
-	      char onealt[bufsz];
+
+	      /* Construct the new glob expression.  */
+#ifdef HAVE_MEMPCPY
+	      mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
 #else
-	      char *onealt = malloc (bufsz);
-	      if (onealt == NULL)
-		{
-		  if (!(flags & GLOB_APPEND))
-		    globfree (pglob);
-		  return GLOB_NOSPACE;
-		}
+	      memcpy (alt_start, p, next - p);
+	      memcpy (&alt_start[next - p], rest, rest_len);
 #endif
-	      memcpy (onealt, pattern, begin - pattern);
-	      memcpy (&onealt[begin - pattern], p, next - 1 - p);
-	      memcpy (&onealt[(begin - pattern) + (next - 1 - p)],
-		      end, restlen);
+
 	      result = glob (onealt,
-			     ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) |
-			      GLOB_APPEND), errfunc, pglob);
-#ifndef __GNUC__
-	      free (onealt);
-#endif
+			     ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
+			      | GLOB_APPEND), errfunc, pglob);
 
 	      /* If we got an error, return it.  */
 	      if (result && result != GLOB_NOMATCH)
 		{
+#ifndef __GNUC__
+		  free (onealt);
+#endif
 		  if (!(flags & GLOB_APPEND))
 		    globfree (pglob);
 		  return result;
 		}
 
-	      /* Advance past this alternative and process the next.  */
-	      p = next;
-	      depth = 0;
-	    scan:
-	      switch (*p++)
-		{
-		case ',':
-		  if (depth == 0)
-		    {
-		      /* Found the next alternative.  Loop to glob it.  */
-		      next = p;
-		      continue;
-		    }
-		  goto scan;
-		case '{':
-		  ++depth;
-		  goto scan;
-		case '}':
-		  if (depth-- == 0)
-		    /* End of the brace expression.  Break out of the loop.  */
-		    break;
-		  goto scan;
-		}
+	      if (*next == '}')
+		/* We saw the last entry.  */
+		break;
+
+	      p = next + 1;
+	      next = next_brace_sub (p);
+	      assert (next != NULL);
 	    }
 
-	  if (pglob->gl_pathc == firstc &&
-	      !(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+#ifndef __GNUC__
+	  free (onealt);
+#endif
+
+	  if (pglob->gl_pathc != firstc)
+	    /* We found some entries.  */
+	    return 0;
+	  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
 	    return GLOB_NOMATCH;
 	}
     }
 
   /* Find the filename.  */
   filename = strrchr (pattern, '/');
+#if defined __MSDOS__ || defined WINDOWS32
+  /* The case of "d:pattern".  Since `:' is not allowed in
+     file names, we can safely assume that wherever it
+     happens in pattern, it signals the filename part.  This
+     is so we could some day support patterns like "[a-z]:foo".  */
+  if (filename == NULL)
+    filename = strchr (pattern, ':');
+#endif /* __MSDOS__ || WINDOWS32 */
   if (filename == NULL)
     {
-      filename = pattern;
+      /* This can mean two things: a simple name or "~name".  The later
+	 case is nothing but a notation for a directory.  */
+      if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
+	{
+	  dirname = pattern;
+	  dirlen = strlen (pattern);
+
+	  /* Set FILENAME to NULL as a special flag.  This is ugly but
+	     other solutions would require much more code.  We test for
+	     this special case below.  */
+	  filename = NULL;
+	}
+      else
+	{
+	  filename = pattern;
 #ifdef _AMIGA
-      dirname = (char *) "";
+	  dirname = "";
 #else
-      dirname = (char *) ".";
+	  dirname = ".";
 #endif
-      dirlen = 0;
+	  dirlen = 0;
+	}
     }
   else if (filename == pattern)
     {
       /* "/pattern".  */
-      dirname = (char *) "/";
+      dirname = "/";
       dirlen = 1;
       ++filename;
     }
   else
     {
+      char *newp;
       dirlen = filename - pattern;
-      dirname = (char *) __alloca (dirlen + 1);
-      memcpy (dirname, pattern, dirlen);
-      dirname[dirlen] = '\0';
-      ++filename;
-    }
+#if defined __MSDOS__ || defined WINDOWS32
+      if (*filename == ':'
+	  || (filename > pattern + 1 && filename[-1] == ':'))
+	{
+	  char *drive_spec;
 
-  if (filename[0] == '\0' && dirlen > 1)
-    /* "pattern/".  Expand "pattern", appending slashes.  */
-    {
-      int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
-      if (val == 0)
-	pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
-      return val;
+	  ++dirlen;
+	  drive_spec = (char *) __alloca (dirlen + 1);
+#ifdef HAVE_MEMPCPY
+	  *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+#else
+	  memcpy (drive_spec, pattern, dirlen);
+	  drive_spec[dirlen] = '\0';
+#endif
+	  /* For now, disallow wildcards in the drive spec, to
+	     prevent infinite recursion in glob.  */
+	  if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+	    return GLOB_NOMATCH;
+	  /* If this is "d:pattern", we need to copy `:' to DIRNAME
+	     as well.  If it's "d:/pattern", don't remove the slash
+	     from "d:/", since "d:" and "d:/" are not the same.*/
+	}
+#endif
+      newp = (char *) __alloca (dirlen + 1);
+#ifdef HAVE_MEMPCPY
+      *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
+#else
+      memcpy (newp, pattern, dirlen);
+      newp[dirlen] = '\0';
+#endif
+      dirname = newp;
+      ++filename;
+
+      if (filename[0] == '\0'
+#if defined __MSDOS__ || defined WINDOWS32
+          && dirname[dirlen - 1] != ':'
+	  && (dirlen < 3 || dirname[dirlen - 2] != ':'
+	      || dirname[dirlen - 1] != '/')
+#endif
+	  && dirlen > 1)
+	/* "pattern/".  Expand "pattern", appending slashes.  */
+	{
+	  int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+	  if (val == 0)
+	    pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
+			       | (flags & GLOB_MARK));
+	  return val;
+	}
     }
 
   if (!(flags & GLOB_APPEND))
@@ -447,57 +610,247 @@
   oldcount = pglob->gl_pathc;
 
 #ifndef VMS
-  if ((flags & GLOB_TILDE) && dirname[0] == '~')
+  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
     {
-      if (dirname[1] == '\0')
+      if (dirname[1] == '\0' || dirname[1] == '/')
 	{
 	  /* Look up home directory.  */
-	  dirname = getenv ("HOME");
-#ifdef _AMIGA
-	  if (dirname == NULL || dirname[0] == '\0')
-	    dirname = "SYS:";
-#else
-#ifdef WIN32
-	  if (dirname == NULL || dirname[0] == '\0')
-            dirname = "c:/users/default"; /* poor default */
+#ifdef VMS
+/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
+          const char *home_dir = getenv ("SYS$LOGIN");
 #else
-	  if (dirname == NULL || dirname[0] == '\0')
+          const char *home_dir = getenv ("HOME");
+#endif
+# ifdef _AMIGA
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    home_dir = "SYS:";
+# else
+#  ifdef WINDOWS32
+	  if (home_dir == NULL || home_dir[0] == '\0')
+            home_dir = "c:/users/default"; /* poor default */
+#  else
+#   ifdef VMS
+/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    home_dir = "SYS$DISK:[]";
+#   else
+	  if (home_dir == NULL || home_dir[0] == '\0')
 	    {
-	      extern char *getlogin __P ((void));
-	      char *name = getlogin ();
-	      if (name != NULL)
+	      int success;
+	      char *name;
+#   if defined HAVE_GETLOGIN_R || defined _LIBC
+	      size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
+
+	      if (buflen == 0)
+		/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
+		   a moderate value.  */
+		buflen = 20;
+	      name = (char *) __alloca (buflen);
+
+	      success = getlogin_r (name, buflen) >= 0;
+#   else
+	      success = (name = getlogin ()) != NULL;
+#   endif
+	      if (success)
 		{
-		  struct passwd *p = getpwnam (name);
+		  struct passwd *p;
+#   if defined HAVE_GETPWNAM_R || defined _LIBC
+		  size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+		  char *pwtmpbuf;
+		  struct passwd pwbuf;
+		  int save = errno;
+
+		  if (pwbuflen == -1)
+		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
+		       Try a moderate value.  */
+		    pwbuflen = 1024;
+		  pwtmpbuf = (char *) __alloca (pwbuflen);
+
+		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+			 != 0)
+		    {
+		      if (errno != ERANGE)
+			{
+			  p = NULL;
+			  break;
+			}
+		      pwbuflen *= 2;
+		      pwtmpbuf = (char *) __alloca (pwbuflen);
+		      __set_errno (save);
+		    }
+#   else
+		  p = getpwnam (name);
+#   endif
 		  if (p != NULL)
-		    dirname = p->pw_dir;
+		    home_dir = p->pw_dir;
 		}
 	    }
-	  if (dirname == NULL || dirname[0] == '\0')
-	    dirname = (char *) "~"; /* No luck.  */
-#endif /* WIN32 */
-#endif
+	  if (home_dir == NULL || home_dir[0] == '\0')
+	    {
+	      if (flags & GLOB_TILDE_CHECK)
+		return GLOB_NOMATCH;
+	      else
+		home_dir = "~"; /* No luck.  */
+	    }
+#   endif /* VMS */
+#  endif /* WINDOWS32 */
+# endif
+	  /* Now construct the full directory.  */
+	  if (dirname[1] == '\0')
+	    dirname = home_dir;
+	  else
+	    {
+	      char *newp;
+	      size_t home_len = strlen (home_dir);
+	      newp = (char *) __alloca (home_len + dirlen);
+# ifdef HAVE_MEMPCPY
+	      mempcpy (mempcpy (newp, home_dir, home_len),
+		       &dirname[1], dirlen);
+# else
+	      memcpy (newp, home_dir, home_len);
+	      memcpy (&newp[home_len], &dirname[1], dirlen);
+# endif
+	      dirname = newp;
+	    }
 	}
+# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
       else
 	{
-#ifdef _AMIGA
-	  if (dirname == NULL || dirname[0] == '\0')
-	    dirname = "SYS:";
-#else
-#ifdef WIN32
-	  if (dirname == NULL || dirname[0] == '\0')
-            dirname = "c:/users/default"; /* poor default */
-#else
+	  char *end_name = strchr (dirname, '/');
+	  const char *user_name;
+	  const char *home_dir;
+
+	  if (end_name == NULL)
+	    user_name = dirname + 1;
+	  else
+	    {
+	      char *newp;
+	      newp = (char *) __alloca (end_name - dirname);
+# ifdef HAVE_MEMPCPY
+	      *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
+		= '\0';
+# else
+	      memcpy (newp, dirname + 1, end_name - dirname);
+	      newp[end_name - dirname - 1] = '\0';
+# endif
+	      user_name = newp;
+	    }
+
 	  /* Look up specific user's home directory.  */
-	  struct passwd *p = getpwnam (dirname + 1);
-	  if (p != NULL)
-	    dirname = p->pw_dir;
-#endif /* WIN32 */
-#endif
+	  {
+	    struct passwd *p;
+#  if defined HAVE_GETPWNAM_R || defined _LIBC
+	    size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+	    char *pwtmpbuf;
+	    struct passwd pwbuf;
+	    int save = errno;
+
+	    if (buflen == -1)
+	      /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
+		 moderate value.  */
+	      buflen = 1024;
+	    pwtmpbuf = (char *) __alloca (buflen);
+
+	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+	      {
+		if (errno != ERANGE)
+		  {
+		    p = NULL;
+		    break;
+		  }
+		buflen *= 2;
+		pwtmpbuf = __alloca (buflen);
+		__set_errno (save);
+	      }
+#  else
+	    p = getpwnam (user_name);
+#  endif
+	    if (p != NULL)
+	      home_dir = p->pw_dir;
+	    else
+	      home_dir = NULL;
+	  }
+	  /* If we found a home directory use this.  */
+	  if (home_dir != NULL)
+	    {
+	      char *newp;
+	      size_t home_len = strlen (home_dir);
+	      size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+	      newp = (char *) __alloca (home_len + rest_len + 1);
+#  ifdef HAVE_MEMPCPY
+	      *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
+				  end_name, rest_len)) = '\0';
+#  else
+	      memcpy (newp, home_dir, home_len);
+	      memcpy (&newp[home_len], end_name, rest_len);
+	      newp[home_len + rest_len] = '\0';
+#  endif
+	      dirname = newp;
+	    }
+	  else
+	    if (flags & GLOB_TILDE_CHECK)
+	      /* We have to regard it as an error if we cannot find the
+		 home directory.  */
+	      return GLOB_NOMATCH;
 	}
+# endif	/* Not Amiga && not WINDOWS32 && not VMS.  */
     }
 #endif	/* Not VMS.  */
 
-  if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
+  /* Now test whether we looked for "~" or "~NAME".  In this case we
+     can give the answer now.  */
+  if (filename == NULL)
+    {
+      struct stat st;
+
+      /* Return the directory if we don't check for error or if it exists.  */
+      if ((flags & GLOB_NOCHECK)
+	  || (((flags & GLOB_ALTDIRFUNC)
+	       ? (*pglob->gl_stat) (dirname, &st)
+	       : __stat (dirname, &st)) == 0
+	      && S_ISDIR (st.st_mode)))
+	{
+	  pglob->gl_pathv
+	    = (char **) realloc (pglob->gl_pathv,
+				 (pglob->gl_pathc +
+				  ((flags & GLOB_DOOFFS) ?
+				   pglob->gl_offs : 0) +
+				  1 + 1) *
+				 sizeof (char *));
+	  if (pglob->gl_pathv == NULL)
+	    return GLOB_NOSPACE;
+
+	  if (flags & GLOB_DOOFFS)
+	    while (pglob->gl_pathc < pglob->gl_offs)
+	      pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+#if defined HAVE_STRDUP || defined _LIBC
+	  pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);
+#else
+	  {
+	    size_t len = strlen (dirname) + 1;
+	    char *dircopy = malloc (len);
+	    if (dircopy != NULL)
+	      pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,
+							 len);
+	  }
+#endif
+	  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
+	    {
+	      free (pglob->gl_pathv);
+	      return GLOB_NOSPACE;
+	    }
+	  pglob->gl_pathv[++pglob->gl_pathc] = NULL;
+	  pglob->gl_flags = flags;
+
+	  return 0;
+	}
+
+      /* Not found.  */
+      return GLOB_NOMATCH;
+    }
+
+  if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
     {
       /* The directory name contains metacharacters, so we
 	 have to glob for the directory, and then glob for
@@ -506,8 +859,8 @@
       register int i;
 
       status = glob (dirname,
-		     ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
-		      GLOB_NOSORT),
+		     ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))
+		      | GLOB_NOSORT | GLOB_ONLYDIR),
 		     errfunc, &dirs);
       if (status != 0)
 	return status;
@@ -517,7 +870,7 @@
 	 appending the results to PGLOB.  */
       for (i = 0; i < dirs.gl_pathc; ++i)
 	{
-	  int oldcount;
+	  int old_pathc;
 
 #ifdef	SHELL
 	  {
@@ -528,14 +881,15 @@
 	      {
 		globfree (&dirs);
 		globfree (&files);
-		return GLOB_ABEND;
+		return GLOB_ABORTED;
 	      }
 	  }
 #endif /* SHELL.  */
 
-	  oldcount = pglob->gl_pathc;
+	  old_pathc = pglob->gl_pathc;
 	  status = glob_in_dir (filename, dirs.gl_pathv[i],
-				(flags | GLOB_APPEND) & ~GLOB_NOCHECK,
+				((flags | GLOB_APPEND)
+				 & ~(GLOB_NOCHECK | GLOB_ERR)),
 				errfunc, pglob);
 	  if (status == GLOB_NOMATCH)
 	    /* No matches in this directory.  Try the next.  */
@@ -550,8 +904,8 @@
 
 	  /* Stick the directory on the front of each name.  */
 	  if (prefix_array (dirs.gl_pathv[i],
-			    &pglob->gl_pathv[oldcount],
-			    pglob->gl_pathc - oldcount))
+			    &pglob->gl_pathv[old_pathc],
+			    pglob->gl_pathc - old_pathc))
 	    {
 	      globfree (&dirs);
 	      globfree (pglob);
@@ -561,39 +915,87 @@
 
       flags |= GLOB_MAGCHAR;
 
+      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
+	 But if we have not found any matching entry and thie GLOB_NOCHECK
+	 flag was set we must return the list consisting of the disrectory
+	 names followed by the filename.  */
       if (pglob->gl_pathc == oldcount)
-	/* No matches.  */
-	if (flags & GLOB_NOCHECK)
-	  {
-	    size_t len = strlen (pattern) + 1;
-	    char *patcopy = (char *) malloc (len);
-	    if (patcopy == NULL)
-	      return GLOB_NOSPACE;
-	    memcpy (patcopy, pattern, len);
+	{
+	  /* No matches.  */
+	  if (flags & GLOB_NOCHECK)
+	    {
+	      size_t filename_len = strlen (filename) + 1;
+	      char **new_pathv;
+	      struct stat st;
+
+	      /* This is an pessimistic guess about the size.  */
+	      pglob->gl_pathv
+		= (char **) realloc (pglob->gl_pathv,
+				     (pglob->gl_pathc +
+				      ((flags & GLOB_DOOFFS) ?
+				       pglob->gl_offs : 0) +
+				      dirs.gl_pathc + 1) *
+				     sizeof (char *));
+	      if (pglob->gl_pathv == NULL)
+		{
+		  globfree (&dirs);
+		  return GLOB_NOSPACE;
+		}
+
+	      if (flags & GLOB_DOOFFS)
+		while (pglob->gl_pathc < pglob->gl_offs)
+		  pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+	      for (i = 0; i < dirs.gl_pathc; ++i)
+		{
+		  const char *dir = dirs.gl_pathv[i];
+		  size_t dir_len = strlen (dir);
 
-	    pglob->gl_pathv
-	      = (char **) realloc (pglob->gl_pathv,
-				   (pglob->gl_pathc +
-				    ((flags & GLOB_DOOFFS) ?
-				     pglob->gl_offs : 0) +
-				    1 + 1) *
-				   sizeof (char *));
-	    if (pglob->gl_pathv == NULL)
-	      {
-		free (patcopy);
-		return GLOB_NOSPACE;
-	      }
+		  /* First check whether this really is a directory.  */
+		  if (((flags & GLOB_ALTDIRFUNC)
+		       ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0
+		      || !S_ISDIR (st.st_mode))
+		    /* No directory, ignore this entry.  */
+		    continue;
+
+		  pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1
+							     + filename_len);
+		  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)
+		    {
+		      globfree (&dirs);
+		      globfree (pglob);
+		      return GLOB_NOSPACE;
+		    }
 
-	    if (flags & GLOB_DOOFFS)
-	      while (pglob->gl_pathc < pglob->gl_offs)
-		pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+#ifdef HAVE_MEMPCPY
+		  mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],
+					     dir, dir_len),
+				    "/", 1),
+			   filename, filename_len);
+#else
+		  memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);
+		  pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';
+		  memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],
+			  filename, filename_len);
+#endif
+		  ++pglob->gl_pathc;
+		}
 
-	    pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
-	    pglob->gl_pathv[pglob->gl_pathc] = NULL;
-	    pglob->gl_flags = flags;
-	  }
-	else
-	  return GLOB_NOMATCH;
+	      pglob->gl_pathv[pglob->gl_pathc] = NULL;
+	      pglob->gl_flags = flags;
+
+	      /* Now we know how large the gl_pathv vector must be.  */
+	      new_pathv = (char **) realloc (pglob->gl_pathv,
+					     ((pglob->gl_pathc + 1)
+					      * sizeof (char *)));
+	      if (new_pathv != NULL)
+		pglob->gl_pathv = new_pathv;
+	    }
+	  else
+	    return GLOB_NOMATCH;
+	}
+
+      globfree (&dirs);
     }
   else
     {
@@ -604,9 +1006,14 @@
       if (dirlen > 0)
 	{
 	  /* Stick the directory on the front of each name.  */
+	  int ignore = oldcount;
+
+	  if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)
+	    ignore = pglob->gl_offs;
+
 	  if (prefix_array (dirname,
-			    &pglob->gl_pathv[oldcount],
-			    pglob->gl_pathc - oldcount))
+			    &pglob->gl_pathv[ignore],
+			    pglob->gl_pathc - ignore))
 	    {
 	      globfree (pglob);
 	      return GLOB_NOSPACE;
@@ -620,10 +1027,10 @@
       int i;
       struct stat st;
       for (i = oldcount; i < pglob->gl_pathc; ++i)
-	if (((flags & GLOB_ALTDIRFUNC) ?
-	     (*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
-	     __stat (pglob->gl_pathv[i], &st)) == 0 &&
-	    S_ISDIR (st.st_mode))
+	if (((flags & GLOB_ALTDIRFUNC)
+	     ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)
+	     : __stat (pglob->gl_pathv[i], &st)) == 0
+	    && S_ISDIR (st.st_mode))
 	  {
  	    size_t len = strlen (pglob->gl_pathv[i]) + 2;
 	    char *new = realloc (pglob->gl_pathv[i], len);
@@ -638,10 +1045,17 @@
     }
 
   if (!(flags & GLOB_NOSORT))
-    /* Sort the vector.  */
-    qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
-	   pglob->gl_pathc - oldcount,
-	   sizeof (char *), collated_compare);
+    {
+      /* Sort the vector.  */
+      int non_sort = oldcount;
+
+      if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)
+	non_sort = pglob->gl_offs;
+
+      qsort ((__ptr_t) &pglob->gl_pathv[non_sort],
+	     pglob->gl_pathc - non_sort,
+	     sizeof (char *), collated_compare);
+    }
 
   return 0;
 }
@@ -694,11 +1108,31 @@
 {
   register size_t i;
   size_t dirlen = strlen (dirname);
+#if defined __MSDOS__ || defined WINDOWS32
+  int sep_char = '/';
+# define DIRSEP_CHAR sep_char
+#else
+# define DIRSEP_CHAR '/'
+#endif
 
   if (dirlen == 1 && dirname[0] == '/')
     /* DIRNAME is just "/", so normal prepending would get us "//foo".
        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
     dirlen = 0;
+#if defined __MSDOS__ || defined WINDOWS32
+  else if (dirlen > 1)
+    {
+      if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
+	/* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
+	--dirlen;
+      else if (dirname[dirlen - 1] == ':')
+	{
+	  /* DIRNAME is "d:".  Use `:' instead of `/'.  */
+	  --dirlen;
+	  sep_char = ':';
+	}
+    }
+#endif
 
   for (i = 0; i < n; ++i)
     {
@@ -711,9 +1145,17 @@
 	  return 1;
 	}
 
+#ifdef HAVE_MEMPCPY
+      {
+	char *endp = (char *) mempcpy (new, dirname, dirlen);
+	*endp++ = DIRSEP_CHAR;
+	mempcpy (endp, array[i], eltlen);
+      }
+#else
       memcpy (new, dirname, dirlen);
-      new[dirlen] = '/';
+      new[dirlen] = DIRSEP_CHAR;
       memcpy (&new[dirlen + 1], array[i], eltlen);
+#endif
       free ((__ptr_t) array[i]);
       array[i] = new;
     }
@@ -722,10 +1164,12 @@
 }
 
 
+/* We must not compile this function twice.  */
+#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
 /* Return nonzero if PATTERN contains any metacharacters.
    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
-static int
-glob_pattern_p (pattern, quote)
+int
+__glob_pattern_p (pattern, quote)
      const char *pattern;
      int quote;
 {
@@ -756,6 +1200,10 @@
 
   return 0;
 }
+# ifdef _LIBC
+weak_alias (__glob_pattern_p, glob_pattern_p)
+# endif
+#endif
 
 
 /* Like `glob', but PATTERN is a final pathname component,
@@ -770,7 +1218,7 @@
      int (*errfunc) __P ((const char *, int));
      glob_t *pglob;
 {
-  __ptr_t stream;
+  __ptr_t stream = NULL;
 
   struct globlink
     {
@@ -778,69 +1226,136 @@
       char *name;
     };
   struct globlink *names = NULL;
-  size_t nfound = 0;
+  size_t nfound;
+  int meta;
+  int save;
 
-  if (!glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
+#ifdef VMS
+  if (*directory == 0)
+    directory = "[]";
+#endif
+  meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
+  if (meta == 0)
     {
-      stream = NULL;
-      flags |= GLOB_NOCHECK;
+      if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))
+	/* We need not do any tests.  The PATTERN contains no meta
+	   characters and we must not return an error therefore the
+	   result will always contain exactly one name.  */
+	flags |= GLOB_NOCHECK;
+      else
+	{
+	  /* Since we use the normal file functions we can also use stat()
+	     to verify the file is there.  */
+	  struct stat st;
+	  size_t patlen = strlen (pattern);
+	  size_t dirlen = strlen (directory);
+	  char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
+
+# ifdef HAVE_MEMPCPY
+	  mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
+			    "/", 1),
+		   pattern, patlen + 1);
+# else
+	  memcpy (fullname, directory, dirlen);
+	  fullname[dirlen] = '/';
+	  memcpy (&fullname[dirlen + 1], pattern, patlen + 1);
+# endif
+	  if (((flags & GLOB_ALTDIRFUNC)
+	       ? (*pglob->gl_stat) (fullname, &st)
+	       : __stat (fullname, &st)) == 0)
+	    /* We found this file to be existing.  Now tell the rest
+	       of the function to copy this name into the result.  */
+	    flags |= GLOB_NOCHECK;
+	}
+
+      nfound = 0;
     }
   else
     {
-      flags |= GLOB_MAGCHAR;
-
-      stream = ((flags & GLOB_ALTDIRFUNC) ?
-		(*pglob->gl_opendir) (directory) :
-		(__ptr_t) opendir (directory));
-      if (stream == NULL)
+      if (pattern[0] == '\0')
 	{
-	  if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
-	      (flags & GLOB_ERR))
-	    return GLOB_ABEND;
+	  /* This is a special case for matching directories like in
+	     "*a/".  */
+	  names = (struct globlink *) __alloca (sizeof (struct globlink));
+	  names->name = (char *) malloc (1);
+	  if (names->name == NULL)
+	    goto memory_error;
+	  names->name[0] = '\0';
+	  names->next = NULL;
+	  nfound = 1;
+	  meta = 0;
 	}
       else
-	while (1)
-	  {
-	    const char *name;
-	    size_t len;
-	    struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
-				(*pglob->gl_readdir) (stream) :
-				readdir ((DIR *) stream));
-	    if (d == NULL)
-	      break;
-	    if (! REAL_DIR_ENTRY (d))
-	      continue;
-
-	    name = d->d_name;
-
-	    if (fnmatch (pattern, name,
-			 (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
-			 ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
-#ifdef _AMIGA
-			 | FNM_CASEFOLD
+	{
+	  stream = ((flags & GLOB_ALTDIRFUNC)
+		    ? (*pglob->gl_opendir) (directory)
+		    : (__ptr_t) opendir (directory));
+	  if (stream == NULL)
+	    {
+	      if (errno != ENOTDIR
+		  && ((errfunc != NULL && (*errfunc) (directory, errno))
+		      || (flags & GLOB_ERR)))
+		return GLOB_ABORTED;
+	      nfound = 0;
+	      meta = 0;
+	    }
+	  else
+	    {
+	      int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+			       | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+#if defined _AMIGA || defined VMS
+				   | FNM_CASEFOLD
 #endif
-			 ) == 0)
-	      {
-		struct globlink *new
-		  = (struct globlink *) __alloca (sizeof (struct globlink));
-		len = NAMLEN (d);
-		new->name
-		  = (char *) malloc (len + 1);
-		if (new->name == NULL)
-		  goto memory_error;
-		memcpy ((__ptr_t) new->name, name, len);
-		new->name[len] = '\0';
-		new->next = names;
-		names = new;
-		++nfound;
-	      }
-	  }
+				   );
+	      nfound = 0;
+	      flags |= GLOB_MAGCHAR;
+
+	      while (1)
+		{
+		  const char *name;
+		  size_t len;
+		  struct dirent *d = ((flags & GLOB_ALTDIRFUNC)
+				      ? (*pglob->gl_readdir) (stream)
+				      : readdir ((DIR *) stream));
+		  if (d == NULL)
+		    break;
+		  if (! REAL_DIR_ENTRY (d))
+		    continue;
+
+#ifdef HAVE_D_TYPE
+		  /* If we shall match only directories use the information
+		     provided by the dirent call if possible.  */
+		  if ((flags & GLOB_ONLYDIR)
+		      && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
+		    continue;
+#endif
+
+		  name = d->d_name;
+
+		  if (fnmatch (pattern, name, fnm_flags) == 0)
+		    {
+		      struct globlink *new = (struct globlink *)
+			__alloca (sizeof (struct globlink));
+		      len = NAMLEN (d);
+		      new->name = (char *) malloc (len + 1);
+		      if (new->name == NULL)
+			goto memory_error;
+#ifdef HAVE_MEMPCPY
+		      *((char *) mempcpy ((__ptr_t) new->name, name, len))
+			= '\0';
+#else
+		      memcpy ((__ptr_t) new->name, name, len);
+		      new->name[len] = '\0';
+#endif
+		      new->next = names;
+		      names = new;
+		      ++nfound;
+		    }
+		}
+	    }
+	}
     }
 
-  if (nfound == 0 && (flags & GLOB_NOMAGIC) &&
-      ! glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
-    flags |= GLOB_NOCHECK;
-
   if (nfound == 0 && (flags & GLOB_NOCHECK))
     {
       size_t len = strlen (pattern);
@@ -850,38 +1365,46 @@
       names->name = (char *) malloc (len + 1);
       if (names->name == NULL)
 	goto memory_error;
+#ifdef HAVE_MEMPCPY
+      *((char *) mempcpy (names->name, pattern, len)) = '\0';
+#else
       memcpy (names->name, pattern, len);
       names->name[len] = '\0';
+#endif
     }
 
-  pglob->gl_pathv
-    = (char **) realloc (pglob->gl_pathv,
-			 (pglob->gl_pathc +
-			  ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
-			  nfound + 1) *
-			 sizeof (char *));
-  if (pglob->gl_pathv == NULL)
-    goto memory_error;
+  if (nfound != 0)
+    {
+      pglob->gl_pathv
+	= (char **) realloc (pglob->gl_pathv,
+			     (pglob->gl_pathc +
+			      ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
+			      nfound + 1) *
+			     sizeof (char *));
+      if (pglob->gl_pathv == NULL)
+	goto memory_error;
 
-  if (flags & GLOB_DOOFFS)
-    while (pglob->gl_pathc < pglob->gl_offs)
-      pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+      if (flags & GLOB_DOOFFS)
+	while (pglob->gl_pathc < pglob->gl_offs)
+	  pglob->gl_pathv[pglob->gl_pathc++] = NULL;
 
-  for (; names != NULL; names = names->next)
-    pglob->gl_pathv[pglob->gl_pathc++] = names->name;
-  pglob->gl_pathv[pglob->gl_pathc] = NULL;
+      for (; names != NULL; names = names->next)
+	pglob->gl_pathv[pglob->gl_pathc++] = names->name;
+      pglob->gl_pathv[pglob->gl_pathc] = NULL;
 
-  pglob->gl_flags = flags;
+      pglob->gl_flags = flags;
+    }
 
+  save = errno;
   if (stream != NULL)
     {
-      int save = errno;
       if (flags & GLOB_ALTDIRFUNC)
 	(*pglob->gl_closedir) (stream);
       else
 	closedir ((DIR *) stream);
-      errno = save;
     }
+  __set_errno (save);
+
   return nfound == 0 ? GLOB_NOMATCH : 0;
 
  memory_error:
@@ -891,7 +1414,7 @@
       (*pglob->gl_closedir) (stream);
     else
       closedir ((DIR *) stream);
-    errno = save;
+    __set_errno (save);
   }
   while (names != NULL)
     {
@@ -903,4 +1426,3 @@
 }
 
 #endif	/* Not ELIDE_CODE.  */
-
--- a/glob/glob.h	Wed Oct 09 14:44:44 2002 +0000
+++ b/glob/glob.h	Wed Oct 09 18:47:16 2002 +0000
@@ -1,43 +1,73 @@
-/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc.
 
-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 Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-This 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.
+   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.
 
-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 Library General Public
+   License along with the GNU C 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.  */
 
 #ifndef	_GLOB_H
-
 #define	_GLOB_H	1
 
 #ifdef	__cplusplus
-extern "C"
-{
+extern "C" {
 #endif
 
 #undef	__ptr_t
-#if (defined (__cplusplus) || (defined (__STDC__) && __STDC__) \
-     || defined (WIN32))
-#undef	__P
-#define	__P(protos)	protos
-#define	__ptr_t	void *
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# if !defined __GLIBC__ || !defined __P
+#  undef __P
+#  undef __PMT
+#  define __P(protos)	protos
+#  define __PMT(protos)	protos
+#  if !defined __GNUC__ || __GNUC__ < 2
+#   undef __const
+#   define __const const
+#  endif
+# endif
+# define __ptr_t	void *
 #else /* Not C++ or ANSI C.  */
-#undef	__P
-#define	__P(protos)	()
-#undef	const
-#define	const
-#define	__ptr_t	char *
+# undef	__P
+# undef __PMT
+# define __P(protos)	()
+# define __PMT(protos)	()
+# undef	__const
+# define __const
+# define __ptr_t	char *
 #endif /* C++ or ANSI C.  */
 
+/* We need `size_t' for the following definitions.  */
+#ifndef __size_t
+# if defined __GNUC__ && __GNUC__ >= 2
+typedef __SIZE_TYPE__ __size_t;
+# else
+/* This is a guess.  */
+/*hb
+ *	Conflicts with DECCs aready defined type __size_t.
+ *	Defining an own type with a name beginning with '__' is no good.
+ *	Anyway if DECC is used and __SIZE_T is defined then __size_t is
+ *	already defined (and I hope it's exactly the one we need here).
+ */
+#if !(defined __DECC && defined __SIZE_T)
+typedef unsigned long int __size_t;
+#endif
+# endif
+#else
+/* The GNU CC stddef.h version defines __size_t as empty.  We need a real
+   definition.  */
+# undef __size_t
+# define __size_t size_t
+#endif
+
 /* Bits set in the FLAGS argument to `glob'.  */
 #define	GLOB_ERR	(1 << 0)/* Return on read errors.  */
 #define	GLOB_MARK	(1 << 1)/* Append a slash to each name.  */
@@ -47,44 +77,94 @@
 #define	GLOB_APPEND	(1 << 5)/* Append to results of a previous call.  */
 #define	GLOB_NOESCAPE	(1 << 6)/* Backslashes don't quote metacharacters.  */
 #define	GLOB_PERIOD	(1 << 7)/* Leading `.' can be matched by metachars.  */
-#define	__GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+
+#if (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _BSD_SOURCE \
+     || defined _GNU_SOURCE)
+# define GLOB_MAGCHAR	 (1 << 8)/* Set in gl_flags if any metachars seen.  */
+# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions.  */
+# define GLOB_BRACE	 (1 << 10)/* Expand "{a,b}" to "a" "b".  */
+# define GLOB_NOMAGIC	 (1 << 11)/* If no magic chars, return the pattern.  */
+# define GLOB_TILDE	 (1 << 12)/* Expand ~user and ~ to home directories. */
+# define GLOB_ONLYDIR	 (1 << 13)/* Match only directories.  */
+# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error
+				      if the user name is not available.  */
+# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
 			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
 			 GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \
-			 GLOB_NOMAGIC|GLOB_TILDE)
-
-#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
-#define	GLOB_MAGCHAR	(1 << 8)/* Set in gl_flags if any metachars seen.  */
-#define GLOB_ALTDIRFUNC	(1 << 9)/* Use gl_opendir et al functions.  */
-#define GLOB_BRACE	(1 << 10)/* Expand "{a,b}" to "a" "b".  */
-#define GLOB_NOMAGIC	(1 << 11)/* If no magic chars, return the pattern.  */
-#define GLOB_TILDE	(1 <<12)/* Expand ~user and ~ to home directories.  */
+			 GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
+#else
+# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
+			 GLOB_PERIOD)
 #endif
 
 /* Error returns from `glob'.  */
 #define	GLOB_NOSPACE	1	/* Ran out of memory.  */
-#define	GLOB_ABEND	2	/* Read error.  */
+#define	GLOB_ABORTED	2	/* Read error.  */
 #define	GLOB_NOMATCH	3	/* No matches found.  */
+#define GLOB_NOSYS	4	/* Not implemented.  */
+#ifdef _GNU_SOURCE
+/* Previous versions of this file defined GLOB_ABEND instead of
+   GLOB_ABORTED.  Provide a compatibility definition here.  */
+# define GLOB_ABEND GLOB_ABORTED
+#endif
 
 /* Structure describing a globbing run.  */
-#if !defined (_AMIGA) && !defined (VMS) /* Buggy compiler.   */
+#if !defined _AMIGA && !defined VMS /* Buggy compiler.   */
 struct stat;
 #endif
 typedef struct
   {
-    int gl_pathc;		/* Count of paths matched by the pattern.  */
+    __size_t gl_pathc;		/* Count of paths matched by the pattern.  */
     char **gl_pathv;		/* List of matched pathnames.  */
-    int gl_offs;		/* Slots to reserve in `gl_pathv'.  */
+    __size_t gl_offs;		/* Slots to reserve in `gl_pathv'.  */
     int gl_flags;		/* Set to FLAGS, maybe | GLOB_MAGCHAR.  */
 
     /* If the GLOB_ALTDIRFUNC flag is set, the following functions
        are used instead of the normal file access functions.  */
-    void (*gl_closedir) __P ((void *));
-    struct dirent *(*gl_readdir) __P ((void *));
-    __ptr_t (*gl_opendir) __P ((const char *));
-    int (*gl_lstat) __P ((const char *, struct stat *));
-    int (*gl_stat) __P ((const char *, struct stat *));
+    void (*gl_closedir) __PMT ((void *));
+    struct dirent *(*gl_readdir) __PMT ((void *));
+    __ptr_t (*gl_opendir) __PMT ((__const char *));
+    int (*gl_lstat) __PMT ((__const char *, struct stat *));
+#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
+    int (*gl_stat) __PMT ((__const char *, struct stat *, ...));
+#else
+    int (*gl_stat) __PMT ((__const char *, struct stat *));
+#endif
   } glob_t;
 
+#ifdef _LARGEFILE64_SOURCE
+struct stat64;
+typedef struct
+  {
+    __size_t gl_pathc;
+    char **gl_pathv;
+    __size_t gl_offs;
+    int gl_flags;
+
+    /* If the GLOB_ALTDIRFUNC flag is set, the following functions
+       are used instead of the normal file access functions.  */
+    void (*gl_closedir) __PMT ((void *));
+    struct dirent64 *(*gl_readdir) __PMT ((void *));
+    __ptr_t (*gl_opendir) __PMT ((__const char *));
+    int (*gl_lstat) __PMT ((__const char *, struct stat64 *));
+    int (*gl_stat) __PMT ((__const char *, struct stat64 *));
+  } glob64_t;
+#endif
+
+#if _FILE_OFFSET_BITS == 64 && __GNUC__ < 2
+# define glob glob64
+# define globfree globfree64
+#else
+# ifdef _LARGEFILE64_SOURCE
+extern int glob64 __P ((__const char *__pattern, int __flags,
+			int (*__errfunc) (__const char *, int),
+			glob64_t *__pglob));
+
+extern void globfree64 __P ((glob64_t *__pglob));
+# endif
+#endif
+
 /* Do glob searching for PATTERN, placing results in PGLOB.
    The bits defined above may be set in FLAGS.
    If a directory cannot be opened or read and ERRFUNC is not nil,
@@ -93,13 +173,30 @@
    `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
    Otherwise, `glob' returns zero.  */
-extern int glob __P ((const char *__pattern, int __flags,
-		      int (*__errfunc) __P ((const char *, int)),
+#if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2
+extern int glob __P ((__const char *__pattern, int __flags,
+		      int (*__errfunc) (__const char *, int),
 		      glob_t *__pglob));
 
 /* Free storage allocated in PGLOB by a previous `glob' call.  */
 extern void globfree __P ((glob_t *__pglob));
+#else
+extern int glob __P ((__const char *__pattern, int __flags,
+		      int (*__errfunc) (__const char *, int),
+		      glob_t *__pglob)) __asm__ ("glob64");
 
+extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64");
+#endif
+
+
+#ifdef _GNU_SOURCE
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.
+
+   This function is not part of the interface specified by POSIX.2
+   but several programs want to use it.  */
+extern int glob_pattern_p __P ((__const char *__pattern, int __quote));
+#endif
 
 #ifdef	__cplusplus
 }