xref: /netbsd-src/external/gpl3/gcc.old/dist/libiberty/fnmatch.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1*8feb0f0bSmrg /* Copyright (C) 1991-2020 Free Software Foundation, Inc.
21debfc3dSmrg 
31debfc3dSmrg NOTE: This source is derived from an old version taken from the GNU C
41debfc3dSmrg Library (glibc).
51debfc3dSmrg 
61debfc3dSmrg This program is free software; you can redistribute it and/or modify it
71debfc3dSmrg under the terms of the GNU General Public License as published by the
81debfc3dSmrg Free Software Foundation; either version 2, or (at your option) any
91debfc3dSmrg later version.
101debfc3dSmrg 
111debfc3dSmrg This program is distributed in the hope that it will be useful,
121debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141debfc3dSmrg GNU General Public License for more details.
151debfc3dSmrg 
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with this program; if not, write to the Free Software
181debfc3dSmrg Foundation, 51 Franklin Street - Fifth Floor,
191debfc3dSmrg Boston, MA 02110-1301, USA.  */
201debfc3dSmrg 
211debfc3dSmrg #ifdef HAVE_CONFIG_H
221debfc3dSmrg #if defined (CONFIG_BROKETS)
231debfc3dSmrg /* We use <config.h> instead of "config.h" so that a compilation
241debfc3dSmrg    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
251debfc3dSmrg    (which it would do because it found this file in $srcdir).  */
261debfc3dSmrg #include <config.h>
271debfc3dSmrg #else
281debfc3dSmrg #include "config.h"
291debfc3dSmrg #endif
301debfc3dSmrg #endif
311debfc3dSmrg 
321debfc3dSmrg 
331debfc3dSmrg #ifndef _GNU_SOURCE
341debfc3dSmrg #define _GNU_SOURCE
351debfc3dSmrg #endif
361debfc3dSmrg 
371debfc3dSmrg /* This code to undef const added in libiberty.  */
381debfc3dSmrg #ifndef __STDC__
391debfc3dSmrg /* This is a separate conditional since some stdc systems
401debfc3dSmrg    reject `defined (const)'.  */
411debfc3dSmrg #ifndef const
421debfc3dSmrg #define const
431debfc3dSmrg #endif
441debfc3dSmrg #endif
451debfc3dSmrg 
461debfc3dSmrg #include <errno.h>
471debfc3dSmrg #include <fnmatch.h>
481debfc3dSmrg #include <safe-ctype.h>
491debfc3dSmrg 
501debfc3dSmrg /* Comment out all this code if we are using the GNU C Library, and are not
511debfc3dSmrg    actually compiling the library itself.  This code is part of the GNU C
521debfc3dSmrg    Library, but also included in many other GNU distributions.  Compiling
531debfc3dSmrg    and linking in this code is a waste when using the GNU C library
541debfc3dSmrg    (especially if it is a shared library).  Rather than having every GNU
551debfc3dSmrg    program understand `configure --with-gnu-libc' and omit the object files,
561debfc3dSmrg    it is simpler to just do this in the source for each such file.  */
571debfc3dSmrg 
581debfc3dSmrg #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
591debfc3dSmrg 
601debfc3dSmrg 
611debfc3dSmrg #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
621debfc3dSmrg extern int errno;
631debfc3dSmrg #endif
641debfc3dSmrg 
651debfc3dSmrg /* Match STRING against the filename pattern PATTERN, returning zero if
661debfc3dSmrg    it matches, nonzero if not.  */
671debfc3dSmrg int
fnmatch(const char * pattern,const char * string,int flags)681debfc3dSmrg fnmatch (const char *pattern, const char *string, int flags)
691debfc3dSmrg {
701debfc3dSmrg   register const char *p = pattern, *n = string;
711debfc3dSmrg   register unsigned char c;
721debfc3dSmrg 
731debfc3dSmrg #define FOLD(c)	((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
741debfc3dSmrg 
751debfc3dSmrg   while ((c = *p++) != '\0')
761debfc3dSmrg     {
771debfc3dSmrg       c = FOLD (c);
781debfc3dSmrg 
791debfc3dSmrg       switch (c)
801debfc3dSmrg 	{
811debfc3dSmrg 	case '?':
821debfc3dSmrg 	  if (*n == '\0')
831debfc3dSmrg 	    return FNM_NOMATCH;
841debfc3dSmrg 	  else if ((flags & FNM_FILE_NAME) && *n == '/')
851debfc3dSmrg 	    return FNM_NOMATCH;
861debfc3dSmrg 	  else if ((flags & FNM_PERIOD) && *n == '.' &&
871debfc3dSmrg 		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
881debfc3dSmrg 	    return FNM_NOMATCH;
891debfc3dSmrg 	  break;
901debfc3dSmrg 
911debfc3dSmrg 	case '\\':
921debfc3dSmrg 	  if (!(flags & FNM_NOESCAPE))
931debfc3dSmrg 	    {
941debfc3dSmrg 	      c = *p++;
951debfc3dSmrg 	      c = FOLD (c);
961debfc3dSmrg 	    }
971debfc3dSmrg 	  if (FOLD ((unsigned char)*n) != c)
981debfc3dSmrg 	    return FNM_NOMATCH;
991debfc3dSmrg 	  break;
1001debfc3dSmrg 
1011debfc3dSmrg 	case '*':
1021debfc3dSmrg 	  if ((flags & FNM_PERIOD) && *n == '.' &&
1031debfc3dSmrg 	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1041debfc3dSmrg 	    return FNM_NOMATCH;
1051debfc3dSmrg 
1061debfc3dSmrg 	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
1071debfc3dSmrg 	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
1081debfc3dSmrg 		(c == '?' && *n == '\0'))
1091debfc3dSmrg 	      return FNM_NOMATCH;
1101debfc3dSmrg 
1111debfc3dSmrg 	  if (c == '\0')
1121debfc3dSmrg 	    return 0;
1131debfc3dSmrg 
1141debfc3dSmrg 	  {
1151debfc3dSmrg 	    unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
1161debfc3dSmrg 	    c1 = FOLD (c1);
1171debfc3dSmrg 	    for (--p; *n != '\0'; ++n)
1181debfc3dSmrg 	      if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
1191debfc3dSmrg 		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
1201debfc3dSmrg 		return 0;
1211debfc3dSmrg 	    return FNM_NOMATCH;
1221debfc3dSmrg 	  }
1231debfc3dSmrg 
1241debfc3dSmrg 	case '[':
1251debfc3dSmrg 	  {
1261debfc3dSmrg 	    /* Nonzero if the sense of the character class is inverted.  */
1271debfc3dSmrg 	    register int negate;
1281debfc3dSmrg 
1291debfc3dSmrg 	    if (*n == '\0')
1301debfc3dSmrg 	      return FNM_NOMATCH;
1311debfc3dSmrg 
1321debfc3dSmrg 	    if ((flags & FNM_PERIOD) && *n == '.' &&
1331debfc3dSmrg 		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1341debfc3dSmrg 	      return FNM_NOMATCH;
1351debfc3dSmrg 
1361debfc3dSmrg 	    negate = (*p == '!' || *p == '^');
1371debfc3dSmrg 	    if (negate)
1381debfc3dSmrg 	      ++p;
1391debfc3dSmrg 
1401debfc3dSmrg 	    c = *p++;
1411debfc3dSmrg 	    for (;;)
1421debfc3dSmrg 	      {
1431debfc3dSmrg 		register unsigned char cstart = c, cend = c;
1441debfc3dSmrg 
1451debfc3dSmrg 		if (!(flags & FNM_NOESCAPE) && c == '\\')
1461debfc3dSmrg 		  cstart = cend = *p++;
1471debfc3dSmrg 
1481debfc3dSmrg 		cstart = cend = FOLD (cstart);
1491debfc3dSmrg 
1501debfc3dSmrg 		if (c == '\0')
1511debfc3dSmrg 		  /* [ (unterminated) loses.  */
1521debfc3dSmrg 		  return FNM_NOMATCH;
1531debfc3dSmrg 
1541debfc3dSmrg 		c = *p++;
1551debfc3dSmrg 		c = FOLD (c);
1561debfc3dSmrg 
1571debfc3dSmrg 		if ((flags & FNM_FILE_NAME) && c == '/')
1581debfc3dSmrg 		  /* [/] can never match.  */
1591debfc3dSmrg 		  return FNM_NOMATCH;
1601debfc3dSmrg 
1611debfc3dSmrg 		if (c == '-' && *p != ']')
1621debfc3dSmrg 		  {
1631debfc3dSmrg 		    cend = *p++;
1641debfc3dSmrg 		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
1651debfc3dSmrg 		      cend = *p++;
1661debfc3dSmrg 		    if (cend == '\0')
1671debfc3dSmrg 		      return FNM_NOMATCH;
1681debfc3dSmrg 		    cend = FOLD (cend);
1691debfc3dSmrg 
1701debfc3dSmrg 		    c = *p++;
1711debfc3dSmrg 		  }
1721debfc3dSmrg 
1731debfc3dSmrg 		if (FOLD ((unsigned char)*n) >= cstart
1741debfc3dSmrg 		    && FOLD ((unsigned char)*n) <= cend)
1751debfc3dSmrg 		  goto matched;
1761debfc3dSmrg 
1771debfc3dSmrg 		if (c == ']')
1781debfc3dSmrg 		  break;
1791debfc3dSmrg 	      }
1801debfc3dSmrg 	    if (!negate)
1811debfc3dSmrg 	      return FNM_NOMATCH;
1821debfc3dSmrg 	    break;
1831debfc3dSmrg 
1841debfc3dSmrg 	  matched:;
1851debfc3dSmrg 	    /* Skip the rest of the [...] that already matched.  */
1861debfc3dSmrg 	    while (c != ']')
1871debfc3dSmrg 	      {
1881debfc3dSmrg 		if (c == '\0')
1891debfc3dSmrg 		  /* [... (unterminated) loses.  */
1901debfc3dSmrg 		  return FNM_NOMATCH;
1911debfc3dSmrg 
1921debfc3dSmrg 		c = *p++;
1931debfc3dSmrg 		if (!(flags & FNM_NOESCAPE) && c == '\\')
1941debfc3dSmrg 		  /* XXX 1003.2d11 is unclear if this is right.  */
1951debfc3dSmrg 		  ++p;
1961debfc3dSmrg 	      }
1971debfc3dSmrg 	    if (negate)
1981debfc3dSmrg 	      return FNM_NOMATCH;
1991debfc3dSmrg 	  }
2001debfc3dSmrg 	  break;
2011debfc3dSmrg 
2021debfc3dSmrg 	default:
2031debfc3dSmrg 	  if (c != FOLD ((unsigned char)*n))
2041debfc3dSmrg 	    return FNM_NOMATCH;
2051debfc3dSmrg 	}
2061debfc3dSmrg 
2071debfc3dSmrg       ++n;
2081debfc3dSmrg     }
2091debfc3dSmrg 
2101debfc3dSmrg   if (*n == '\0')
2111debfc3dSmrg     return 0;
2121debfc3dSmrg 
2131debfc3dSmrg   if ((flags & FNM_LEADING_DIR) && *n == '/')
2141debfc3dSmrg     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
2151debfc3dSmrg     return 0;
2161debfc3dSmrg 
2171debfc3dSmrg   return FNM_NOMATCH;
2181debfc3dSmrg }
2191debfc3dSmrg 
2201debfc3dSmrg #endif	/* _LIBC or not __GNU_LIBRARY__.  */
221