xref: /netbsd-src/external/gpl3/binutils.old/dist/libiberty/fnmatch.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1*e992f068Schristos /* Copyright (C) 1991-2022 Free Software Foundation, Inc.
216dce513Schristos 
316dce513Schristos NOTE: This source is derived from an old version taken from the GNU C
416dce513Schristos Library (glibc).
516dce513Schristos 
616dce513Schristos This program is free software; you can redistribute it and/or modify it
716dce513Schristos under the terms of the GNU General Public License as published by the
816dce513Schristos Free Software Foundation; either version 2, or (at your option) any
916dce513Schristos later version.
1016dce513Schristos 
1116dce513Schristos This program is distributed in the hope that it will be useful,
1216dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1316dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1416dce513Schristos GNU General Public License for more details.
1516dce513Schristos 
1616dce513Schristos You should have received a copy of the GNU General Public License
1716dce513Schristos along with this program; if not, write to the Free Software
1816dce513Schristos Foundation, 51 Franklin Street - Fifth Floor,
1916dce513Schristos Boston, MA 02110-1301, USA.  */
2016dce513Schristos 
2116dce513Schristos #ifdef HAVE_CONFIG_H
2216dce513Schristos #if defined (CONFIG_BROKETS)
2316dce513Schristos /* We use <config.h> instead of "config.h" so that a compilation
2416dce513Schristos    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
2516dce513Schristos    (which it would do because it found this file in $srcdir).  */
2616dce513Schristos #include <config.h>
2716dce513Schristos #else
2816dce513Schristos #include "config.h"
2916dce513Schristos #endif
3016dce513Schristos #endif
3116dce513Schristos 
3216dce513Schristos 
3316dce513Schristos #ifndef _GNU_SOURCE
3416dce513Schristos #define _GNU_SOURCE
3516dce513Schristos #endif
3616dce513Schristos 
3716dce513Schristos /* This code to undef const added in libiberty.  */
3816dce513Schristos #ifndef __STDC__
3916dce513Schristos /* This is a separate conditional since some stdc systems
4016dce513Schristos    reject `defined (const)'.  */
4116dce513Schristos #ifndef const
4216dce513Schristos #define const
4316dce513Schristos #endif
4416dce513Schristos #endif
4516dce513Schristos 
4616dce513Schristos #include <errno.h>
4716dce513Schristos #include <fnmatch.h>
4816dce513Schristos #include <safe-ctype.h>
4916dce513Schristos 
5016dce513Schristos /* Comment out all this code if we are using the GNU C Library, and are not
5116dce513Schristos    actually compiling the library itself.  This code is part of the GNU C
5216dce513Schristos    Library, but also included in many other GNU distributions.  Compiling
5316dce513Schristos    and linking in this code is a waste when using the GNU C library
5416dce513Schristos    (especially if it is a shared library).  Rather than having every GNU
5516dce513Schristos    program understand `configure --with-gnu-libc' and omit the object files,
5616dce513Schristos    it is simpler to just do this in the source for each such file.  */
5716dce513Schristos 
5816dce513Schristos #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
5916dce513Schristos 
6016dce513Schristos 
6116dce513Schristos #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
6216dce513Schristos extern int errno;
6316dce513Schristos #endif
6416dce513Schristos 
6516dce513Schristos /* Match STRING against the filename pattern PATTERN, returning zero if
6616dce513Schristos    it matches, nonzero if not.  */
6716dce513Schristos int
fnmatch(const char * pattern,const char * string,int flags)6816dce513Schristos fnmatch (const char *pattern, const char *string, int flags)
6916dce513Schristos {
7016dce513Schristos   register const char *p = pattern, *n = string;
7116dce513Schristos   register unsigned char c;
7216dce513Schristos 
7316dce513Schristos #define FOLD(c)	((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
7416dce513Schristos 
7516dce513Schristos   while ((c = *p++) != '\0')
7616dce513Schristos     {
7716dce513Schristos       c = FOLD (c);
7816dce513Schristos 
7916dce513Schristos       switch (c)
8016dce513Schristos 	{
8116dce513Schristos 	case '?':
8216dce513Schristos 	  if (*n == '\0')
8316dce513Schristos 	    return FNM_NOMATCH;
8416dce513Schristos 	  else if ((flags & FNM_FILE_NAME) && *n == '/')
8516dce513Schristos 	    return FNM_NOMATCH;
8616dce513Schristos 	  else if ((flags & FNM_PERIOD) && *n == '.' &&
8716dce513Schristos 		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
8816dce513Schristos 	    return FNM_NOMATCH;
8916dce513Schristos 	  break;
9016dce513Schristos 
9116dce513Schristos 	case '\\':
9216dce513Schristos 	  if (!(flags & FNM_NOESCAPE))
9316dce513Schristos 	    {
9416dce513Schristos 	      c = *p++;
9516dce513Schristos 	      c = FOLD (c);
9616dce513Schristos 	    }
9716dce513Schristos 	  if (FOLD ((unsigned char)*n) != c)
9816dce513Schristos 	    return FNM_NOMATCH;
9916dce513Schristos 	  break;
10016dce513Schristos 
10116dce513Schristos 	case '*':
10216dce513Schristos 	  if ((flags & FNM_PERIOD) && *n == '.' &&
10316dce513Schristos 	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
10416dce513Schristos 	    return FNM_NOMATCH;
10516dce513Schristos 
10616dce513Schristos 	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
10716dce513Schristos 	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
10816dce513Schristos 		(c == '?' && *n == '\0'))
10916dce513Schristos 	      return FNM_NOMATCH;
11016dce513Schristos 
11116dce513Schristos 	  if (c == '\0')
11216dce513Schristos 	    return 0;
11316dce513Schristos 
11416dce513Schristos 	  {
11516dce513Schristos 	    unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
11616dce513Schristos 	    c1 = FOLD (c1);
11716dce513Schristos 	    for (--p; *n != '\0'; ++n)
11816dce513Schristos 	      if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
11916dce513Schristos 		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
12016dce513Schristos 		return 0;
12116dce513Schristos 	    return FNM_NOMATCH;
12216dce513Schristos 	  }
12316dce513Schristos 
12416dce513Schristos 	case '[':
12516dce513Schristos 	  {
12616dce513Schristos 	    /* Nonzero if the sense of the character class is inverted.  */
12716dce513Schristos 	    register int negate;
12816dce513Schristos 
12916dce513Schristos 	    if (*n == '\0')
13016dce513Schristos 	      return FNM_NOMATCH;
13116dce513Schristos 
13216dce513Schristos 	    if ((flags & FNM_PERIOD) && *n == '.' &&
13316dce513Schristos 		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
13416dce513Schristos 	      return FNM_NOMATCH;
13516dce513Schristos 
13616dce513Schristos 	    negate = (*p == '!' || *p == '^');
13716dce513Schristos 	    if (negate)
13816dce513Schristos 	      ++p;
13916dce513Schristos 
14016dce513Schristos 	    c = *p++;
14116dce513Schristos 	    for (;;)
14216dce513Schristos 	      {
14316dce513Schristos 		register unsigned char cstart = c, cend = c;
14416dce513Schristos 
14516dce513Schristos 		if (!(flags & FNM_NOESCAPE) && c == '\\')
14616dce513Schristos 		  cstart = cend = *p++;
14716dce513Schristos 
14816dce513Schristos 		cstart = cend = FOLD (cstart);
14916dce513Schristos 
15016dce513Schristos 		if (c == '\0')
15116dce513Schristos 		  /* [ (unterminated) loses.  */
15216dce513Schristos 		  return FNM_NOMATCH;
15316dce513Schristos 
15416dce513Schristos 		c = *p++;
15516dce513Schristos 		c = FOLD (c);
15616dce513Schristos 
15716dce513Schristos 		if ((flags & FNM_FILE_NAME) && c == '/')
15816dce513Schristos 		  /* [/] can never match.  */
15916dce513Schristos 		  return FNM_NOMATCH;
16016dce513Schristos 
16116dce513Schristos 		if (c == '-' && *p != ']')
16216dce513Schristos 		  {
16316dce513Schristos 		    cend = *p++;
16416dce513Schristos 		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
16516dce513Schristos 		      cend = *p++;
16616dce513Schristos 		    if (cend == '\0')
16716dce513Schristos 		      return FNM_NOMATCH;
16816dce513Schristos 		    cend = FOLD (cend);
16916dce513Schristos 
17016dce513Schristos 		    c = *p++;
17116dce513Schristos 		  }
17216dce513Schristos 
17316dce513Schristos 		if (FOLD ((unsigned char)*n) >= cstart
17416dce513Schristos 		    && FOLD ((unsigned char)*n) <= cend)
17516dce513Schristos 		  goto matched;
17616dce513Schristos 
17716dce513Schristos 		if (c == ']')
17816dce513Schristos 		  break;
17916dce513Schristos 	      }
18016dce513Schristos 	    if (!negate)
18116dce513Schristos 	      return FNM_NOMATCH;
18216dce513Schristos 	    break;
18316dce513Schristos 
18416dce513Schristos 	  matched:;
18516dce513Schristos 	    /* Skip the rest of the [...] that already matched.  */
18616dce513Schristos 	    while (c != ']')
18716dce513Schristos 	      {
18816dce513Schristos 		if (c == '\0')
18916dce513Schristos 		  /* [... (unterminated) loses.  */
19016dce513Schristos 		  return FNM_NOMATCH;
19116dce513Schristos 
19216dce513Schristos 		c = *p++;
19316dce513Schristos 		if (!(flags & FNM_NOESCAPE) && c == '\\')
19416dce513Schristos 		  /* XXX 1003.2d11 is unclear if this is right.  */
19516dce513Schristos 		  ++p;
19616dce513Schristos 	      }
19716dce513Schristos 	    if (negate)
19816dce513Schristos 	      return FNM_NOMATCH;
19916dce513Schristos 	  }
20016dce513Schristos 	  break;
20116dce513Schristos 
20216dce513Schristos 	default:
20316dce513Schristos 	  if (c != FOLD ((unsigned char)*n))
20416dce513Schristos 	    return FNM_NOMATCH;
20516dce513Schristos 	}
20616dce513Schristos 
20716dce513Schristos       ++n;
20816dce513Schristos     }
20916dce513Schristos 
21016dce513Schristos   if (*n == '\0')
21116dce513Schristos     return 0;
21216dce513Schristos 
21316dce513Schristos   if ((flags & FNM_LEADING_DIR) && *n == '/')
21416dce513Schristos     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
21516dce513Schristos     return 0;
21616dce513Schristos 
21716dce513Schristos   return FNM_NOMATCH;
21816dce513Schristos }
21916dce513Schristos 
22016dce513Schristos #endif	/* _LIBC or not __GNU_LIBRARY__.  */
221