csomh / source-git / rpm

Forked from source-git/rpm 4 years ago
Clone
2ff057
/* Copyright (C) 1991-1993, 1996-1999, 2000 Free Software Foundation, Inc.
2ff057
   This file is part of the GNU C Library.
2ff057
2ff057
   This library is free software; you can redistribute it and/or
2ff057
   modify it under the terms of the GNU Library General Public License as
2ff057
   published by the Free Software Foundation; either version 2 of the
2ff057
   License, or (at your option) any later version.
2ff057
2ff057
   This library is distributed in the hope that it will be useful,
2ff057
   but WITHOUT ANY WARRANTY; without even the implied warranty of
2ff057
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2ff057
   Library General Public License for more details.
2ff057
2ff057
   You should have received a copy of the GNU Library General Public
2ff057
   License along with this library; see the file COPYING.LIB.  If not,
2ff057
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
2ff057
   Boston, MA 02111-1307, USA.  */
2ff057
2ff057
# include "system.h"
2ff057
# include <ctype.h>
2ff057
# include <stdlib.h>
2ff057
# include <string.h>
2ff057
2ff057
/* Find the first occurrence of C in S or the final NUL byte.  */
2ff057
static inline char *
2ff057
__strchrnul (const char *s, int c)
2ff057
{
2ff057
  const unsigned char *char_ptr;
2ff057
  const unsigned long int *longword_ptr;
2ff057
  unsigned long int longword, magic_bits, charmask;
2ff057
2ff057
  c = (unsigned char) c;
2ff057
2ff057
  /* Handle the first few characters by reading one character at a time.
2ff057
     Do this until CHAR_PTR is aligned on a longword boundary.  */
2ff057
  for (char_ptr = (const unsigned char *)s; ((unsigned long int) char_ptr
2ff057
		      & (sizeof (longword) - 1)) != 0;
2ff057
       ++char_ptr)
2ff057
    if (*char_ptr == c || *char_ptr == '\0')
2ff057
      return (void *) char_ptr;
2ff057
2ff057
  /* All these elucidatory comments refer to 4-byte longwords,
2ff057
     but the theory applies equally well to 8-byte longwords.  */
2ff057
2ff057
  longword_ptr = (unsigned long int *) char_ptr;
2ff057
2ff057
  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
2ff057
     the "holes."  Note that there is a hole just to the left of
2ff057
     each byte, with an extra at the end:
2ff057
2ff057
     bits:  01111110 11111110 11111110 11111111
2ff057
     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
2ff057
2ff057
     The 1-bits make sure that carries propagate to the next 0-bit.
2ff057
     The 0-bits provide holes for carries to fall into.  */
2ff057
  switch (sizeof (longword))
2ff057
    {
2ff057
    case 4: magic_bits = 0x7efefeffL; break;
2ff057
    case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;
2ff057
    default:
2ff057
      abort ();
2ff057
    }
2ff057
2ff057
  /* Set up a longword, each of whose bytes is C.  */
2ff057
  charmask = c | (c << 8);
2ff057
  charmask |= charmask << 16;
2ff057
  if (sizeof (longword) > 4)
2ff057
    /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
2ff057
    charmask |= (charmask << 16) << 16;
2ff057
  if (sizeof (longword) > 8)
2ff057
    abort ();
2ff057
2ff057
  /* Instead of the traditional loop which tests each character,
2ff057
     we will test a longword at a time.  The tricky part is testing
2ff057
     if *any of the four* bytes in the longword in question are zero.  */
2ff057
  for (;;)
2ff057
    {
2ff057
      /* We tentatively exit the loop if adding MAGIC_BITS to
2ff057
	 LONGWORD fails to change any of the hole bits of LONGWORD.
2ff057
2ff057
	 1) Is this safe?  Will it catch all the zero bytes?
2ff057
	 Suppose there is a byte with all zeros.  Any carry bits
2ff057
	 propagating from its left will fall into the hole at its
2ff057
	 least significant bit and stop.  Since there will be no
2ff057
	 carry from its most significant bit, the LSB of the
2ff057
	 byte to the left will be unchanged, and the zero will be
2ff057
	 detected.
2ff057
2ff057
	 2) Is this worthwhile?  Will it ignore everything except
2ff057
	 zero bytes?  Suppose every byte of LONGWORD has a bit set
2ff057
	 somewhere.  There will be a carry into bit 8.  If bit 8
2ff057
	 is set, this will carry into bit 16.  If bit 8 is clear,
2ff057
	 one of bits 9-15 must be set, so there will be a carry
2ff057
	 into bit 16.  Similarly, there will be a carry into bit
2ff057
	 24.  If one of bits 24-30 is set, there will be a carry
2ff057
	 into bit 31, so all of the hole bits will be changed.
2ff057
2ff057
	 The one misfire occurs when bits 24-30 are clear and bit
2ff057
	 31 is set; in this case, the hole at bit 31 is not
2ff057
	 changed.  If we had access to the processor carry flag,
2ff057
	 we could close this loophole by putting the fourth hole
2ff057
	 at bit 32!
2ff057
2ff057
	 So it ignores everything except 128's, when they're aligned
2ff057
	 properly.
2ff057
2ff057
	 3) But wait!  Aren't we looking for C as well as zero?
2ff057
	 Good point.  So what we do is XOR LONGWORD with a longword,
2ff057
	 each of whose bytes is C.  This turns each byte that is C
2ff057
	 into a zero.  */
2ff057
2ff057
      longword = *longword_ptr++;
2ff057
2ff057
      /* Add MAGIC_BITS to LONGWORD.  */
2ff057
      if ((((longword + magic_bits)
2ff057
2ff057
	    /* Set those bits that were unchanged by the addition.  */
2ff057
	    ^ ~longword)
2ff057
2ff057
	   /* Look at only the hole bits.  If any of the hole bits
2ff057
	      are unchanged, most likely one of the bytes was a
2ff057
	      zero.  */
2ff057
	   & ~magic_bits) != 0 ||
2ff057
2ff057
	  /* That caught zeroes.  Now test for C.  */
2ff057
	  ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))
2ff057
	   & ~magic_bits) != 0)
2ff057
	{
2ff057
	  /* Which of the bytes was C or zero?
2ff057
	     If none of them were, it was a misfire; continue the search.  */
2ff057
2ff057
	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
2ff057
2ff057
	  if (*cp == c || *cp == '\0')
2ff057
	    return (char *) cp;
2ff057
	  if (*++cp == c || *cp == '\0')
2ff057
	    return (char *) cp;
2ff057
	  if (*++cp == c || *cp == '\0')
2ff057
	    return (char *) cp;
2ff057
	  if (*++cp == c || *cp == '\0')
2ff057
	    return (char *) cp;
2ff057
	  if (sizeof (longword) > 4)
2ff057
	    {
2ff057
	      if (*++cp == c || *cp == '\0')
2ff057
		return (char *) cp;
2ff057
	      if (*++cp == c || *cp == '\0')
2ff057
		return (char *) cp;
2ff057
	      if (*++cp == c || *cp == '\0')
2ff057
		return (char *) cp;
2ff057
	      if (*++cp == c || *cp == '\0')
2ff057
		return (char *) cp;
2ff057
	    }
2ff057
	}
2ff057
    }
2ff057
2ff057
  /* This should never happen.  */
2ff057
  return NULL;
2ff057
}
2ff057
2ff057
/* For platform which support the ISO C amendement 1 functionality we
2ff057
   support user defined character classes.  */
2ff057
#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
2ff057
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
2ff057
# include <wchar.h>
2ff057
# include <wctype.h>
2ff057
#endif
2ff057
2ff057
/* Comment out all this code if we are using the GNU C Library, and are not
2ff057
   actually compiling the library itself.  This code is part of the GNU C
2ff057
   Library, but also included in many other GNU distributions.  Compiling
2ff057
   and linking in this code is a waste when using the GNU C library
2ff057
   (especially if it is a shared library).  Rather than having every GNU
2ff057
   program understand `configure --with-gnu-libc' and omit the object files,
2ff057
   it is simpler to just do this in the source for each such file.  */
2ff057
2ff057
#if defined _LIBC || !defined __GNU_LIBRARY__
2ff057
2ff057
2ff057
# if defined STDC_HEADERS || !defined isascii
2ff057
#  define ISASCII(c) 1
2ff057
# else
2ff057
#  define ISASCII(c) isascii(c)
2ff057
# endif
2ff057
2ff057
#ifdef isblank
2ff057
# define ISBLANK(c) (ISASCII (c) && isblank (c))
2ff057
#else
2ff057
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
2ff057
#endif
2ff057
#ifdef isgraph
2ff057
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
2ff057
#else
2ff057
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
2ff057
#endif
2ff057
2ff057
#define ISPRINT(c) (ISASCII (c) && isprint (c))
2ff057
#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
2ff057
#define ISALNUM(c) (ISASCII (c) && isalnum (c))
2ff057
#define ISALPHA(c) (ISASCII (c) && isalpha (c))
2ff057
#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
2ff057
#define ISLOWER(c) (ISASCII (c) && islower (c))
2ff057
#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
2ff057
#define ISSPACE(c) (ISASCII (c) && isspace (c))
2ff057
#define ISUPPER(c) (ISASCII (c) && isupper (c))
2ff057
#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
2ff057
2ff057
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
2ff057
2ff057
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
2ff057
/* The GNU C library provides support for user-defined character classes
2ff057
   and the functions from ISO C amendement 1.  */
2ff057
#  ifdef CHARCLASS_NAME_MAX
2ff057
#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
2ff057
#  else
2ff057
/* This shouldn't happen but some implementation might still have this
2ff057
   problem.  Use a reasonable default value.  */
2ff057
#   define CHAR_CLASS_MAX_LENGTH 256
2ff057
#  endif
2ff057
2ff057
#  ifdef _LIBC
2ff057
#   define IS_CHAR_CLASS(string) __wctype (string)
2ff057
#  else
2ff057
#   define IS_CHAR_CLASS(string) wctype (string)
2ff057
#  endif
2ff057
# else
2ff057
#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
2ff057
2ff057
#  define IS_CHAR_CLASS(string)						      \
2ff057
   (STREQ (string, "alpha") || STREQ (string, "upper")			      \
2ff057
    || STREQ (string, "lower") || STREQ (string, "digit")		      \
2ff057
    || STREQ (string, "alnum") || STREQ (string, "xdigit")		      \
2ff057
    || STREQ (string, "space") || STREQ (string, "print")		      \
2ff057
    || STREQ (string, "punct") || STREQ (string, "graph")		      \
2ff057
    || STREQ (string, "cntrl") || STREQ (string, "blank"))
2ff057
# endif
2ff057
2ff057
/* Avoid depending on library functions or files
2ff057
   whose names are inconsistent.  */
2ff057
2ff057
# if !defined _LIBC && !defined getenv
2ff057
extern char *getenv ();
2ff057
# endif
2ff057
2ff057
# ifndef errno
2ff057
extern int errno;
2ff057
# endif
2ff057
2ff057
/* Match STRING against the filename pattern PATTERN, returning zero if
2ff057
   it matches, nonzero if not.  */
2ff057
static int
2ff057
#ifdef _LIBC
2ff057
internal_function
2ff057
#endif
2ff057
internal_fnmatch (const char *pattern, const char *string,
2ff057
		  int no_leading_period, int flags)
2ff057
{
2ff057
  register const char *p = pattern, *n = string;
2ff057
  register unsigned char c;
2ff057
2ff057
/* Note that this evaluates C many times.  */
2ff057
# ifdef _LIBC
2ff057
#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
2ff057
# else
2ff057
#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
2ff057
# endif
2ff057
2ff057
  while ((c = *p++) != '\0')
2ff057
    {
2ff057
      c = FOLD (c);
2ff057
2ff057
      switch (c)
2ff057
	{
2ff057
	case '?':
2ff057
	  if (*n == '\0')
2ff057
	    return FNM_NOMATCH;
2ff057
	  else if (*n == '/' && (flags & FNM_FILE_NAME))
2ff057
	    return FNM_NOMATCH;
2ff057
	  else if (*n == '.' && no_leading_period
2ff057
		   && (n == string
2ff057
		       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
2ff057
	    return FNM_NOMATCH;
2ff057
	  break;
2ff057
2ff057
	case '\\':
2ff057
	  if (!(flags & FNM_NOESCAPE))
2ff057
	    {
2ff057
	      c = *p++;
2ff057
	      if (c == '\0')
2ff057
		/* Trailing \ loses.  */
2ff057
		return FNM_NOMATCH;
2ff057
	      c = FOLD (c);
2ff057
	    }
2ff057
	  if (FOLD ((unsigned char) *n) != c)
2ff057
	    return FNM_NOMATCH;
2ff057
	  break;
2ff057
2ff057
	case '*':
2ff057
	  if (*n == '.' && no_leading_period
2ff057
	      && (n == string
2ff057
		  || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
2ff057
	    return FNM_NOMATCH;
2ff057
2ff057
	  for (c = *p++; c == '?' || c == '*'; c = *p++)
2ff057
	    {
2ff057
	      if (*n == '/' && (flags & FNM_FILE_NAME))
2ff057
		/* A slash does not match a wildcard under FNM_FILE_NAME.  */
2ff057
		return FNM_NOMATCH;
2ff057
	      else if (c == '?')
2ff057
		{
2ff057
		  /* A ? needs to match one character.  */
2ff057
		  if (*n == '\0')
2ff057
		    /* There isn't another character; no match.  */
2ff057
		    return FNM_NOMATCH;
2ff057
		  else
2ff057
		    /* One character of the string is consumed in matching
2ff057
		       this ? wildcard, so *??? won't match if there are
2ff057
		       less than three characters.  */
2ff057
		    ++n;
2ff057
		}
2ff057
	    }
2ff057
2ff057
	  if (c == '\0')
2ff057
	    /* The wildcard(s) is/are the last element of the pattern.
2ff057
	       If the name is a file name and contains another slash
2ff057
	       this does mean it cannot match.  If the FNM_LEADING_DIR
2ff057
	       flag is set and exactly one slash is following, we have
2ff057
	       a match.  */
2ff057
	    {
2ff057
	      int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
2ff057
2ff057
	      if (flags & FNM_FILE_NAME)
2ff057
		{
2ff057
		  const char *slashp = strchr (n, '/');
2ff057
2ff057
		  if (flags & FNM_LEADING_DIR)
2ff057
		    {
2ff057
		      if (slashp != NULL
2ff057
			  && strchr (slashp + 1, '/') == NULL)
2ff057
			result = 0;
2ff057
		    }
2ff057
		  else
2ff057
		    {
2ff057
		      if (slashp == NULL)
2ff057
			result = 0;
2ff057
		    }
2ff057
		}
2ff057
2ff057
	      return result;
2ff057
	    }
2ff057
	  else
2ff057
	    {
2ff057
	      const char *endp;
2ff057
2ff057
	      endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
2ff057
2ff057
	      if (c == '[')
2ff057
		{
2ff057
		  int flags2 = ((flags & FNM_FILE_NAME)
2ff057
				? flags : (flags & ~FNM_PERIOD));
2ff057
2ff057
		  for (--p; n < endp; ++n)
2ff057
		    if (internal_fnmatch (p, n,
2ff057
					  (no_leading_period
2ff057
					   && (n == string
2ff057
					       || (n[-1] == '/'
2ff057
						   && (flags
2ff057
						       & FNM_FILE_NAME)))),
2ff057
					  flags2)
2ff057
			== 0)
2ff057
		      return 0;
2ff057
		}
2ff057
	      else if (c == '/' && (flags & FNM_FILE_NAME))
2ff057
		{
2ff057
		  while (*n != '\0' && *n != '/')
2ff057
		    ++n;
2ff057
		  if (*n == '/'
2ff057
		      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
2ff057
					    flags) == 0))
2ff057
		    return 0;
2ff057
		}
2ff057
	      else
2ff057
		{
2ff057
		  int flags2 = ((flags & FNM_FILE_NAME)
2ff057
				? flags : (flags & ~FNM_PERIOD));
2ff057
2ff057
		  if (c == '\\' && !(flags & FNM_NOESCAPE))
2ff057
		    c = *p;
2ff057
		  c = FOLD (c);
2ff057
		  for (--p; n < endp; ++n)
2ff057
		    if (FOLD ((unsigned char) *n) == c
2ff057
			&& (internal_fnmatch (p, n,
2ff057
					      (no_leading_period
2ff057
					       && (n == string
2ff057
						   || (n[-1] == '/'
2ff057
						       && (flags
2ff057
							   & FNM_FILE_NAME)))),
2ff057
					      flags2) == 0))
2ff057
		      return 0;
2ff057
		}
2ff057
	    }
2ff057
2ff057
	  /* If we come here no match is possible with the wildcard.  */
2ff057
	  return FNM_NOMATCH;
2ff057
2ff057
	case '[':
2ff057
	  {
2ff057
	    /* Nonzero if the sense of the character class is inverted.  */
2ff057
	    static int posixly_correct;
2ff057
	    register int not;
2ff057
	    char cold;
2ff057
2ff057
	    if (posixly_correct == 0)
2ff057
	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
2ff057
2ff057
	    if (*n == '\0')
2ff057
	      return FNM_NOMATCH;
2ff057
2ff057
	    if (*n == '.' && no_leading_period && (n == string
2ff057
						   || (n[-1] == '/'
2ff057
						       && (flags
2ff057
							   & FNM_FILE_NAME))))
2ff057
	      return FNM_NOMATCH;
2ff057
2ff057
	    if (*n == '/' && (flags & FNM_FILE_NAME))
2ff057
	      /* `/' cannot be matched.  */
2ff057
	      return FNM_NOMATCH;
2ff057
2ff057
	    not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
2ff057
	    if (not)
2ff057
	      ++p;
2ff057
2ff057
	    c = *p++;
2ff057
	    for (;;)
2ff057
	      {
2ff057
		unsigned char fn = FOLD ((unsigned char) *n);
2ff057
2ff057
		if (!(flags & FNM_NOESCAPE) && c == '\\')
2ff057
		  {
2ff057
		    if (*p == '\0')
2ff057
		      return FNM_NOMATCH;
2ff057
		    c = FOLD ((unsigned char) *p);
2ff057
		    ++p;
2ff057
2ff057
		    if (c == fn)
2ff057
		      goto matched;
2ff057
		  }
2ff057
		else if (c == '[' && *p == ':')
2ff057
		  {
2ff057
		    /* Leave room for the null.  */
2ff057
		    char str[CHAR_CLASS_MAX_LENGTH + 1];
2ff057
		    size_t c1 = 0;
2ff057
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
2ff057
		    wctype_t wt;
2ff057
# endif
2ff057
		    const char *startp = p;
2ff057
2ff057
		    for (;;)
2ff057
		      {
2ff057
			if (c1 == CHAR_CLASS_MAX_LENGTH)
2ff057
			  /* The name is too long and therefore the pattern
2ff057
			     is ill-formed.  */
2ff057
			  return FNM_NOMATCH;
2ff057
2ff057
			c = *++p;
2ff057
			if (c == ':' && p[1] == ']')
2ff057
			  {
2ff057
			    p += 2;
2ff057
			    break;
2ff057
			  }
2ff057
			if (c < 'a' || c >= 'z')
2ff057
			  {
2ff057
			    /* This cannot possibly be a character class name.
2ff057
			       Match it as a normal range.  */
2ff057
			    p = startp;
2ff057
			    c = '[';
2ff057
			    goto normal_bracket;
2ff057
			  }
2ff057
			str[c1++] = c;
2ff057
		      }
2ff057
		    str[c1] = '\0';
2ff057
2ff057
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
2ff057
		    wt = IS_CHAR_CLASS (str);
2ff057
		    if (wt == 0)
2ff057
		      /* Invalid character class name.  */
2ff057
		      return FNM_NOMATCH;
2ff057
2ff057
		    if (__iswctype (__btowc ((unsigned char) *n), wt))
2ff057
		      goto matched;
2ff057
# else
2ff057
		    if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
2ff057
			|| (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
2ff057
			|| (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
2ff057
			|| (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
2ff057
			|| (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
2ff057
			|| (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
2ff057
			|| (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
2ff057
			|| (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
2ff057
			|| (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
2ff057
			|| (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
2ff057
			|| (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
2ff057
			|| (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
2ff057
		      goto matched;
2ff057
# endif
2ff057
		  }
2ff057
		else if (c == '\0')
2ff057
		  /* [ (unterminated) loses.  */
2ff057
		  return FNM_NOMATCH;
2ff057
		else
2ff057
		  {
2ff057
		    c = FOLD (c);
2ff057
		  normal_bracket:
2ff057
		    if (c == fn)
2ff057
		      goto matched;
2ff057
2ff057
		    cold = c;
2ff057
		    c = *p++;
2ff057
2ff057
		    if (c == '-' && *p != ']')
2ff057
		      {
2ff057
			/* It is a range.  */
2ff057
			char lo[2];
2ff057
			char fc[2];
2ff057
			unsigned char cend = *p++;
2ff057
			if (!(flags & FNM_NOESCAPE) && cend == '\\')
2ff057
			  cend = *p++;
2ff057
			if (cend == '\0')
2ff057
			  return FNM_NOMATCH;
2ff057
2ff057
			lo[0] = cold;
2ff057
			lo[1] = '\0';
2ff057
			fc[0] = fn;
2ff057
			fc[1] = '\0';
2ff057
			if (strcoll (lo, fc) <= 0)
2ff057
			  {
2ff057
			    char hi[2];
2ff057
			    hi[0] = FOLD (cend);
2ff057
			    hi[1] = '\0';
2ff057
			    if (strcoll (fc, hi) <= 0)
2ff057
			      goto matched;
2ff057
			  }
2ff057
2ff057
			c = *p++;
2ff057
		      }
2ff057
		  }
2ff057
2ff057
		if (c == ']')
2ff057
		  break;
2ff057
	      }
2ff057
2ff057
	    if (!not)
2ff057
	      return FNM_NOMATCH;
2ff057
	    break;
2ff057
2ff057
	  matched:
2ff057
	    /* Skip the rest of the [...] that already matched.  */
2ff057
	    while (c != ']')
2ff057
	      {
2ff057
		if (c == '\0')
2ff057
		  /* [... (unterminated) loses.  */
2ff057
		  return FNM_NOMATCH;
2ff057
2ff057
		c = *p++;
2ff057
		if (!(flags & FNM_NOESCAPE) && c == '\\')
2ff057
		  {
2ff057
		    if (*p == '\0')
2ff057
		      return FNM_NOMATCH;
2ff057
		    /* XXX 1003.2d11 is unclear if this is right.  */
2ff057
		    ++p;
2ff057
		  }
2ff057
		else if (c == '[' && *p == ':')
2ff057
		  {
2ff057
		    do
2ff057
		      if (*++p == '\0')
2ff057
			return FNM_NOMATCH;
2ff057
		    while (*p != ':' || p[1] == ']');
2ff057
		    p += 2;
2ff057
		    c = *p;
2ff057
		  }
2ff057
	      }
2ff057
	    if (not)
2ff057
	      return FNM_NOMATCH;
2ff057
	  }
2ff057
	  break;
2ff057
2ff057
	default:
2ff057
	  if (c != FOLD ((unsigned char) *n))
2ff057
	    return FNM_NOMATCH;
2ff057
	}
2ff057
2ff057
      ++n;
2ff057
    }
2ff057
2ff057
  if (*n == '\0')
2ff057
    return 0;
2ff057
2ff057
  if ((flags & FNM_LEADING_DIR) && *n == '/')
2ff057
    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
2ff057
    return 0;
2ff057
2ff057
  return FNM_NOMATCH;
2ff057
2ff057
# undef FOLD
2ff057
}
2ff057
2ff057
2ff057
int
2ff057
fnmatch (const char *pattern, const char *string, int flags)
2ff057
{
2ff057
  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
2ff057
}
2ff057
2ff057
#endif	/* _LIBC or not __GNU_LIBRARY__.  */