(root)/
make-4.4/
lib/
fnmatch.c
       1  /* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software
       2  Foundation, Inc.
       3  This file is part of the GNU C Library.
       4  
       5  This library is free software; you can redistribute it and/or
       6  modify it under the terms of the GNU Library General Public License as
       7  published by the Free Software Foundation; either version 2 of the
       8  License, or (at your option) any later version.
       9  
      10  This library is distributed in the hope that it will be useful,
      11  but WITHOUT ANY WARRANTY; without even the implied warranty of
      12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13  Library General Public License for more details.
      14  
      15  You should have received a copy of the GNU Library General Public License
      16  along with this library; see the file COPYING.LIB.  If not, write to the Free
      17  Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
      18  USA.  */
      19  
      20  #if HAVE_CONFIG_H
      21  # include <config.h>
      22  #endif
      23  
      24  /* Enable GNU extensions in fnmatch.h.  */
      25  #ifndef _GNU_SOURCE
      26  # define _GNU_SOURCE	1
      27  #endif
      28  
      29  #include <errno.h>
      30  #include <fnmatch.h>
      31  #include <ctype.h>
      32  
      33  #if HAVE_STRING_H || defined _LIBC
      34  # include <string.h>
      35  #else
      36  # include <strings.h>
      37  #endif
      38  
      39  #if defined STDC_HEADERS || defined _LIBC
      40  # include <stdlib.h>
      41  #endif
      42  
      43  /* For platform which support the ISO C amendement 1 functionality we
      44     support user defined character classes.  */
      45  #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
      46  /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
      47  # include <wchar.h>
      48  # include <wctype.h>
      49  #endif
      50  
      51  /* Comment out all this code if we are using the GNU C Library, and are not
      52     actually compiling the library itself.  This code is part of the GNU C
      53     Library, but also included in many other GNU distributions.  Compiling
      54     and linking in this code is a waste when using the GNU C library
      55     (especially if it is a shared library).  Rather than having every GNU
      56     program understand `configure --with-gnu-libc' and omit the object files,
      57     it is simpler to just do this in the source for each such file.  */
      58  
      59  #if defined _LIBC || !defined __GNU_LIBRARY__
      60  
      61  
      62  # if defined STDC_HEADERS || !defined isascii
      63  #  define ISASCII(c) 1
      64  # else
      65  #  define ISASCII(c) isascii(c)
      66  # endif
      67  
      68  # ifdef isblank
      69  #  define ISBLANK(c) (ISASCII (c) && isblank (c))
      70  # else
      71  #  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
      72  # endif
      73  # ifdef isgraph
      74  #  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
      75  # else
      76  #  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
      77  # endif
      78  
      79  # define ISPRINT(c) (ISASCII (c) && isprint (c))
      80  # define ISDIGIT(c) (ISASCII (c) && isdigit (c))
      81  # define ISALNUM(c) (ISASCII (c) && isalnum (c))
      82  # define ISALPHA(c) (ISASCII (c) && isalpha (c))
      83  # define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
      84  # define ISLOWER(c) (ISASCII (c) && islower (c))
      85  # define ISPUNCT(c) (ISASCII (c) && ispunct (c))
      86  # define ISSPACE(c) (ISASCII (c) && isspace (c))
      87  # define ISUPPER(c) (ISASCII (c) && isupper (c))
      88  # define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
      89  
      90  # define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
      91  
      92  # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
      93  /* The GNU C library provides support for user-defined character classes
      94     and the functions from ISO C amendement 1.  */
      95  #  ifdef CHARCLASS_NAME_MAX
      96  #   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
      97  #  else
      98  /* This shouldn't happen but some implementation might still have this
      99     problem.  Use a reasonable default value.  */
     100  #   define CHAR_CLASS_MAX_LENGTH 256
     101  #  endif
     102  
     103  #  ifdef _LIBC
     104  #   define IS_CHAR_CLASS(string) __wctype (string)
     105  #  else
     106  #   define IS_CHAR_CLASS(string) wctype (string)
     107  #  endif
     108  # else
     109  #  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
     110  
     111  #  define IS_CHAR_CLASS(string)						      \
     112     (STREQ (string, "alpha") || STREQ (string, "upper")			      \
     113      || STREQ (string, "lower") || STREQ (string, "digit")		      \
     114      || STREQ (string, "alnum") || STREQ (string, "xdigit")		      \
     115      || STREQ (string, "space") || STREQ (string, "print")		      \
     116      || STREQ (string, "punct") || STREQ (string, "graph")		      \
     117      || STREQ (string, "cntrl") || STREQ (string, "blank"))
     118  # endif
     119  
     120  /* Avoid depending on library functions or files
     121     whose names are inconsistent.  */
     122  
     123  # if !defined _LIBC && !defined getenv
     124  extern char *getenv ();
     125  # endif
     126  
     127  # ifndef errno
     128  extern int errno;
     129  # endif
     130  
     131  /* This function doesn't exist on most systems.  */
     132  
     133  # if !defined HAVE___STRCHRNUL && !defined _LIBC
     134  static char *
     135  __strchrnul (s, c)
     136       const char *s;
     137       int c;
     138  {
     139    char *result = strchr (s, c);
     140    if (result == NULL)
     141      result = strchr (s, '\0');
     142    return result;
     143  }
     144  # endif
     145  
     146  # ifndef internal_function
     147  /* Inside GNU libc we mark some function in a special way.  In other
     148     environments simply ignore the marking.  */
     149  #  define internal_function
     150  # endif
     151  
     152  /* Match STRING against the filename pattern PATTERN, returning zero if
     153     it matches, nonzero if not.  */
     154  static int internal_fnmatch __P ((const char *pattern, const char *string,
     155  				  int no_leading_period, int flags))
     156       internal_function;
     157  static int
     158  internal_function
     159  internal_fnmatch (pattern, string, no_leading_period, flags)
     160       const char *pattern;
     161       const char *string;
     162       int no_leading_period;
     163       int flags;
     164  {
     165    register const char *p = pattern, *n = string;
     166    register unsigned char c;
     167  
     168  /* Note that this evaluates C many times.  */
     169  # ifdef _LIBC
     170  #  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
     171  # else
     172  #  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
     173  # endif
     174  
     175    while ((c = *p++) != '\0')
     176      {
     177        c = FOLD (c);
     178  
     179        switch (c)
     180  	{
     181  	case '?':
     182  	  if (*n == '\0')
     183  	    return FNM_NOMATCH;
     184  	  else if (*n == '/' && (flags & FNM_FILE_NAME))
     185  	    return FNM_NOMATCH;
     186  	  else if (*n == '.' && no_leading_period
     187  		   && (n == string
     188  		       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
     189  	    return FNM_NOMATCH;
     190  	  break;
     191  
     192  	case '\\':
     193  	  if (!(flags & FNM_NOESCAPE))
     194  	    {
     195  	      c = *p++;
     196  	      if (c == '\0')
     197  		/* Trailing \ loses.  */
     198  		return FNM_NOMATCH;
     199  	      c = FOLD (c);
     200  	    }
     201  	  if (FOLD ((unsigned char) *n) != c)
     202  	    return FNM_NOMATCH;
     203  	  break;
     204  
     205  	case '*':
     206  	  if (*n == '.' && no_leading_period
     207  	      && (n == string
     208  		  || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
     209  	    return FNM_NOMATCH;
     210  
     211  	  for (c = *p++; c == '?' || c == '*'; c = *p++)
     212  	    {
     213  	      if (*n == '/' && (flags & FNM_FILE_NAME))
     214  		/* A slash does not match a wildcard under FNM_FILE_NAME.  */
     215  		return FNM_NOMATCH;
     216  	      else if (c == '?')
     217  		{
     218  		  /* A ? needs to match one character.  */
     219  		  if (*n == '\0')
     220  		    /* There isn't another character; no match.  */
     221  		    return FNM_NOMATCH;
     222  		  else
     223  		    /* One character of the string is consumed in matching
     224  		       this ? wildcard, so *??? won't match if there are
     225  		       less than three characters.  */
     226  		    ++n;
     227  		}
     228  	    }
     229  
     230  	  if (c == '\0')
     231  	    /* The wildcard(s) is/are the last element of the pattern.
     232  	       If the name is a file name and contains another slash
     233  	       this does mean it cannot match.  */
     234  	    return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
     235  		    ? FNM_NOMATCH : 0);
     236  	  else
     237  	    {
     238  	      const char *endp;
     239  
     240  	      endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
     241  
     242  	      if (c == '[')
     243  		{
     244  		  int flags2 = ((flags & FNM_FILE_NAME)
     245  				? flags : (flags & ~FNM_PERIOD));
     246  
     247  		  for (--p; n < endp; ++n)
     248  		    if (internal_fnmatch (p, n,
     249  					  (no_leading_period
     250  					   && (n == string
     251  					       || (n[-1] == '/'
     252  						   && (flags
     253  						       & FNM_FILE_NAME)))),
     254  					  flags2)
     255  			== 0)
     256  		      return 0;
     257  		}
     258  	      else if (c == '/' && (flags & FNM_FILE_NAME))
     259  		{
     260  		  while (*n != '\0' && *n != '/')
     261  		    ++n;
     262  		  if (*n == '/'
     263  		      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
     264  					    flags) == 0))
     265  		    return 0;
     266  		}
     267  	      else
     268  		{
     269  		  int flags2 = ((flags & FNM_FILE_NAME)
     270  				? flags : (flags & ~FNM_PERIOD));
     271  
     272  		  if (c == '\\' && !(flags & FNM_NOESCAPE))
     273  		    c = *p;
     274  		  c = FOLD (c);
     275  		  for (--p; n < endp; ++n)
     276  		    if (FOLD ((unsigned char) *n) == c
     277  			&& (internal_fnmatch (p, n,
     278  					      (no_leading_period
     279  					       && (n == string
     280  						   || (n[-1] == '/'
     281  						       && (flags
     282  							   & FNM_FILE_NAME)))),
     283  					      flags2) == 0))
     284  		      return 0;
     285  		}
     286  	    }
     287  
     288  	  /* If we come here no match is possible with the wildcard.  */
     289  	  return FNM_NOMATCH;
     290  
     291  	case '[':
     292  	  {
     293  	    /* Nonzero if the sense of the character class is inverted.  */
     294  	    static int posixly_correct;
     295  	    register int not;
     296  	    char cold;
     297  
     298  	    if (posixly_correct == 0)
     299  	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
     300  
     301  	    if (*n == '\0')
     302  	      return FNM_NOMATCH;
     303  
     304  	    if (*n == '.' && no_leading_period && (n == string
     305  						   || (n[-1] == '/'
     306  						       && (flags
     307  							   & FNM_FILE_NAME))))
     308  	      return FNM_NOMATCH;
     309  
     310  	    if (*n == '/' && (flags & FNM_FILE_NAME))
     311  	      /* `/' cannot be matched.  */
     312  	      return FNM_NOMATCH;
     313  
     314  	    not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
     315  	    if (not)
     316  	      ++p;
     317  
     318  	    c = *p++;
     319  	    for (;;)
     320  	      {
     321  		unsigned char fn = FOLD ((unsigned char) *n);
     322  
     323  		if (!(flags & FNM_NOESCAPE) && c == '\\')
     324  		  {
     325  		    if (*p == '\0')
     326  		      return FNM_NOMATCH;
     327  		    c = FOLD ((unsigned char) *p);
     328  		    ++p;
     329  
     330  		    if (c == fn)
     331  		      goto matched;
     332  		  }
     333  		else if (c == '[' && *p == ':')
     334  		  {
     335  		    /* Leave room for the null.  */
     336  		    char str[CHAR_CLASS_MAX_LENGTH + 1];
     337  		    size_t c1 = 0;
     338  # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
     339  		    wctype_t wt;
     340  # endif
     341  		    const char *startp = p;
     342  
     343  		    for (;;)
     344  		      {
     345  			if (c1 == CHAR_CLASS_MAX_LENGTH)
     346  			  /* The name is too long and therefore the pattern
     347  			     is ill-formed.  */
     348  			  return FNM_NOMATCH;
     349  
     350  			c = *++p;
     351  			if (c == ':' && p[1] == ']')
     352  			  {
     353  			    p += 2;
     354  			    break;
     355  			  }
     356  			if (c < 'a' || c >= 'z')
     357  			  {
     358  			    /* This cannot possibly be a character class name.
     359  			       Match it as a normal range.  */
     360  			    p = startp;
     361  			    c = '[';
     362  			    goto normal_bracket;
     363  			  }
     364  			str[c1++] = c;
     365  		      }
     366  		    str[c1] = '\0';
     367  
     368  # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
     369  		    wt = IS_CHAR_CLASS (str);
     370  		    if (wt == 0)
     371  		      /* Invalid character class name.  */
     372  		      return FNM_NOMATCH;
     373  
     374  		    if (__iswctype (__btowc ((unsigned char) *n), wt))
     375  		      goto matched;
     376  # else
     377  		    if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
     378  			|| (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
     379  			|| (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
     380  			|| (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
     381  			|| (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
     382  			|| (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
     383  			|| (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
     384  			|| (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
     385  			|| (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
     386  			|| (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
     387  			|| (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
     388  			|| (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
     389  		      goto matched;
     390  # endif
     391  		  }
     392  		else if (c == '\0')
     393  		  /* [ (unterminated) loses.  */
     394  		  return FNM_NOMATCH;
     395  		else
     396  		  {
     397  		  normal_bracket:
     398  		    if (FOLD (c) == fn)
     399  		      goto matched;
     400  
     401  		    cold = c;
     402  		    c = *p++;
     403  
     404  		    if (c == '-' && *p != ']')
     405  		      {
     406  			/* It is a range.  */
     407  			unsigned char cend = *p++;
     408  			if (!(flags & FNM_NOESCAPE) && cend == '\\')
     409  			  cend = *p++;
     410  			if (cend == '\0')
     411  			  return FNM_NOMATCH;
     412  
     413  			if (cold <= fn && fn <= FOLD (cend))
     414  			  goto matched;
     415  
     416  			c = *p++;
     417  		      }
     418  		  }
     419  
     420  		if (c == ']')
     421  		  break;
     422  	      }
     423  
     424  	    if (!not)
     425  	      return FNM_NOMATCH;
     426  	    break;
     427  
     428  	  matched:
     429  	    /* Skip the rest of the [...] that already matched.  */
     430  	    while (c != ']')
     431  	      {
     432  		if (c == '\0')
     433  		  /* [... (unterminated) loses.  */
     434  		  return FNM_NOMATCH;
     435  
     436  		c = *p++;
     437  		if (!(flags & FNM_NOESCAPE) && c == '\\')
     438  		  {
     439  		    if (*p == '\0')
     440  		      return FNM_NOMATCH;
     441  		    /* XXX 1003.2d11 is unclear if this is right.  */
     442  		    ++p;
     443  		  }
     444  		else if (c == '[' && *p == ':')
     445  		  {
     446  		    do
     447  		      if (*++p == '\0')
     448  			return FNM_NOMATCH;
     449  		    while (*p != ':' || p[1] == ']');
     450  		    p += 2;
     451  		    c = *p;
     452  		  }
     453  	      }
     454  	    if (not)
     455  	      return FNM_NOMATCH;
     456  	  }
     457  	  break;
     458  
     459  	default:
     460  	  if (c != FOLD ((unsigned char) *n))
     461  	    return FNM_NOMATCH;
     462  	}
     463  
     464        ++n;
     465      }
     466  
     467    if (*n == '\0')
     468      return 0;
     469  
     470    if ((flags & FNM_LEADING_DIR) && *n == '/')
     471      /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
     472      return 0;
     473  
     474    return FNM_NOMATCH;
     475  
     476  # undef FOLD
     477  }
     478  
     479  
     480  int
     481  fnmatch (pattern, string, flags)
     482       const char *pattern;
     483       const char *string;
     484       int flags;
     485  {
     486    return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
     487  }
     488  
     489  #endif	/* _LIBC or not __GNU_LIBRARY__.  */