xref: /netbsd-src/external/gpl3/gcc/dist/libiberty/fnmatch.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1*b1e83836Smrg /* Copyright (C) 1991-2022 Free Software Foundation, Inc.
24fee23f9Smrg 
34fee23f9Smrg NOTE: This source is derived from an old version taken from the GNU C
44fee23f9Smrg Library (glibc).
54fee23f9Smrg 
64fee23f9Smrg This program is free software; you can redistribute it and/or modify it
74fee23f9Smrg under the terms of the GNU General Public License as published by the
84fee23f9Smrg Free Software Foundation; either version 2, or (at your option) any
94fee23f9Smrg later version.
104fee23f9Smrg 
114fee23f9Smrg This program is distributed in the hope that it will be useful,
124fee23f9Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
134fee23f9Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144fee23f9Smrg GNU General Public License for more details.
154fee23f9Smrg 
164fee23f9Smrg You should have received a copy of the GNU General Public License
174fee23f9Smrg along with this program; if not, write to the Free Software
184fee23f9Smrg Foundation, 51 Franklin Street - Fifth Floor,
194fee23f9Smrg Boston, MA 02110-1301, USA.  */
204fee23f9Smrg 
214fee23f9Smrg #ifdef HAVE_CONFIG_H
224fee23f9Smrg #if defined (CONFIG_BROKETS)
234fee23f9Smrg /* We use <config.h> instead of "config.h" so that a compilation
244fee23f9Smrg    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
254fee23f9Smrg    (which it would do because it found this file in $srcdir).  */
264fee23f9Smrg #include <config.h>
274fee23f9Smrg #else
284fee23f9Smrg #include "config.h"
294fee23f9Smrg #endif
304fee23f9Smrg #endif
314fee23f9Smrg 
324fee23f9Smrg 
334fee23f9Smrg #ifndef _GNU_SOURCE
344fee23f9Smrg #define _GNU_SOURCE
354fee23f9Smrg #endif
364fee23f9Smrg 
374fee23f9Smrg /* This code to undef const added in libiberty.  */
384fee23f9Smrg #ifndef __STDC__
394fee23f9Smrg /* This is a separate conditional since some stdc systems
404fee23f9Smrg    reject `defined (const)'.  */
414fee23f9Smrg #ifndef const
424fee23f9Smrg #define const
434fee23f9Smrg #endif
444fee23f9Smrg #endif
454fee23f9Smrg 
464fee23f9Smrg #include <errno.h>
474fee23f9Smrg #include <fnmatch.h>
484fee23f9Smrg #include <safe-ctype.h>
494fee23f9Smrg 
504fee23f9Smrg /* Comment out all this code if we are using the GNU C Library, and are not
514fee23f9Smrg    actually compiling the library itself.  This code is part of the GNU C
524fee23f9Smrg    Library, but also included in many other GNU distributions.  Compiling
534fee23f9Smrg    and linking in this code is a waste when using the GNU C library
544fee23f9Smrg    (especially if it is a shared library).  Rather than having every GNU
554fee23f9Smrg    program understand `configure --with-gnu-libc' and omit the object files,
564fee23f9Smrg    it is simpler to just do this in the source for each such file.  */
574fee23f9Smrg 
584fee23f9Smrg #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
594fee23f9Smrg 
604fee23f9Smrg 
614fee23f9Smrg #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
624fee23f9Smrg extern int errno;
634fee23f9Smrg #endif
644fee23f9Smrg 
654fee23f9Smrg /* Match STRING against the filename pattern PATTERN, returning zero if
664fee23f9Smrg    it matches, nonzero if not.  */
674fee23f9Smrg int
fnmatch(const char * pattern,const char * string,int flags)684fee23f9Smrg fnmatch (const char *pattern, const char *string, int flags)
694fee23f9Smrg {
704fee23f9Smrg   register const char *p = pattern, *n = string;
714fee23f9Smrg   register unsigned char c;
724fee23f9Smrg 
734fee23f9Smrg #define FOLD(c)	((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
744fee23f9Smrg 
754fee23f9Smrg   while ((c = *p++) != '\0')
764fee23f9Smrg     {
774fee23f9Smrg       c = FOLD (c);
784fee23f9Smrg 
794fee23f9Smrg       switch (c)
804fee23f9Smrg 	{
814fee23f9Smrg 	case '?':
824fee23f9Smrg 	  if (*n == '\0')
834fee23f9Smrg 	    return FNM_NOMATCH;
844fee23f9Smrg 	  else if ((flags & FNM_FILE_NAME) && *n == '/')
854fee23f9Smrg 	    return FNM_NOMATCH;
864fee23f9Smrg 	  else if ((flags & FNM_PERIOD) && *n == '.' &&
874fee23f9Smrg 		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
884fee23f9Smrg 	    return FNM_NOMATCH;
894fee23f9Smrg 	  break;
904fee23f9Smrg 
914fee23f9Smrg 	case '\\':
924fee23f9Smrg 	  if (!(flags & FNM_NOESCAPE))
934fee23f9Smrg 	    {
944fee23f9Smrg 	      c = *p++;
954fee23f9Smrg 	      c = FOLD (c);
964fee23f9Smrg 	    }
974fee23f9Smrg 	  if (FOLD ((unsigned char)*n) != c)
984fee23f9Smrg 	    return FNM_NOMATCH;
994fee23f9Smrg 	  break;
1004fee23f9Smrg 
1014fee23f9Smrg 	case '*':
1024fee23f9Smrg 	  if ((flags & FNM_PERIOD) && *n == '.' &&
1034fee23f9Smrg 	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1044fee23f9Smrg 	    return FNM_NOMATCH;
1054fee23f9Smrg 
1064fee23f9Smrg 	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
1074fee23f9Smrg 	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
1084fee23f9Smrg 		(c == '?' && *n == '\0'))
1094fee23f9Smrg 	      return FNM_NOMATCH;
1104fee23f9Smrg 
1114fee23f9Smrg 	  if (c == '\0')
1124fee23f9Smrg 	    return 0;
1134fee23f9Smrg 
1144fee23f9Smrg 	  {
1154fee23f9Smrg 	    unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
1164fee23f9Smrg 	    c1 = FOLD (c1);
1174fee23f9Smrg 	    for (--p; *n != '\0'; ++n)
1184fee23f9Smrg 	      if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
1194fee23f9Smrg 		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
1204fee23f9Smrg 		return 0;
1214fee23f9Smrg 	    return FNM_NOMATCH;
1224fee23f9Smrg 	  }
1234fee23f9Smrg 
1244fee23f9Smrg 	case '[':
1254fee23f9Smrg 	  {
1264fee23f9Smrg 	    /* Nonzero if the sense of the character class is inverted.  */
1274fee23f9Smrg 	    register int negate;
1284fee23f9Smrg 
1294fee23f9Smrg 	    if (*n == '\0')
1304fee23f9Smrg 	      return FNM_NOMATCH;
1314fee23f9Smrg 
1324fee23f9Smrg 	    if ((flags & FNM_PERIOD) && *n == '.' &&
1334fee23f9Smrg 		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1344fee23f9Smrg 	      return FNM_NOMATCH;
1354fee23f9Smrg 
1364fee23f9Smrg 	    negate = (*p == '!' || *p == '^');
1374fee23f9Smrg 	    if (negate)
1384fee23f9Smrg 	      ++p;
1394fee23f9Smrg 
1404fee23f9Smrg 	    c = *p++;
1414fee23f9Smrg 	    for (;;)
1424fee23f9Smrg 	      {
1434fee23f9Smrg 		register unsigned char cstart = c, cend = c;
1444fee23f9Smrg 
1454fee23f9Smrg 		if (!(flags & FNM_NOESCAPE) && c == '\\')
1464fee23f9Smrg 		  cstart = cend = *p++;
1474fee23f9Smrg 
1484fee23f9Smrg 		cstart = cend = FOLD (cstart);
1494fee23f9Smrg 
1504fee23f9Smrg 		if (c == '\0')
1514fee23f9Smrg 		  /* [ (unterminated) loses.  */
1524fee23f9Smrg 		  return FNM_NOMATCH;
1534fee23f9Smrg 
1544fee23f9Smrg 		c = *p++;
1554fee23f9Smrg 		c = FOLD (c);
1564fee23f9Smrg 
1574fee23f9Smrg 		if ((flags & FNM_FILE_NAME) && c == '/')
1584fee23f9Smrg 		  /* [/] can never match.  */
1594fee23f9Smrg 		  return FNM_NOMATCH;
1604fee23f9Smrg 
1614fee23f9Smrg 		if (c == '-' && *p != ']')
1624fee23f9Smrg 		  {
1634fee23f9Smrg 		    cend = *p++;
1644fee23f9Smrg 		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
1654fee23f9Smrg 		      cend = *p++;
1664fee23f9Smrg 		    if (cend == '\0')
1674fee23f9Smrg 		      return FNM_NOMATCH;
1684fee23f9Smrg 		    cend = FOLD (cend);
1694fee23f9Smrg 
1704fee23f9Smrg 		    c = *p++;
1714fee23f9Smrg 		  }
1724fee23f9Smrg 
1734fee23f9Smrg 		if (FOLD ((unsigned char)*n) >= cstart
1744fee23f9Smrg 		    && FOLD ((unsigned char)*n) <= cend)
1754fee23f9Smrg 		  goto matched;
1764fee23f9Smrg 
1774fee23f9Smrg 		if (c == ']')
1784fee23f9Smrg 		  break;
1794fee23f9Smrg 	      }
1804fee23f9Smrg 	    if (!negate)
1814fee23f9Smrg 	      return FNM_NOMATCH;
1824fee23f9Smrg 	    break;
1834fee23f9Smrg 
1844fee23f9Smrg 	  matched:;
1854fee23f9Smrg 	    /* Skip the rest of the [...] that already matched.  */
1864fee23f9Smrg 	    while (c != ']')
1874fee23f9Smrg 	      {
1884fee23f9Smrg 		if (c == '\0')
1894fee23f9Smrg 		  /* [... (unterminated) loses.  */
1904fee23f9Smrg 		  return FNM_NOMATCH;
1914fee23f9Smrg 
1924fee23f9Smrg 		c = *p++;
1934fee23f9Smrg 		if (!(flags & FNM_NOESCAPE) && c == '\\')
1944fee23f9Smrg 		  /* XXX 1003.2d11 is unclear if this is right.  */
1954fee23f9Smrg 		  ++p;
1964fee23f9Smrg 	      }
1974fee23f9Smrg 	    if (negate)
1984fee23f9Smrg 	      return FNM_NOMATCH;
1994fee23f9Smrg 	  }
2004fee23f9Smrg 	  break;
2014fee23f9Smrg 
2024fee23f9Smrg 	default:
2034fee23f9Smrg 	  if (c != FOLD ((unsigned char)*n))
2044fee23f9Smrg 	    return FNM_NOMATCH;
2054fee23f9Smrg 	}
2064fee23f9Smrg 
2074fee23f9Smrg       ++n;
2084fee23f9Smrg     }
2094fee23f9Smrg 
2104fee23f9Smrg   if (*n == '\0')
2114fee23f9Smrg     return 0;
2124fee23f9Smrg 
2134fee23f9Smrg   if ((flags & FNM_LEADING_DIR) && *n == '/')
2144fee23f9Smrg     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
2154fee23f9Smrg     return 0;
2164fee23f9Smrg 
2174fee23f9Smrg   return FNM_NOMATCH;
2184fee23f9Smrg }
2194fee23f9Smrg 
2204fee23f9Smrg #endif	/* _LIBC or not __GNU_LIBRARY__.  */
221