xref: /netbsd-src/external/gpl3/gdb/dist/libiberty/fnmatch.c (revision 7e120ff03ede3fe64e2c8620c01465d528502ddb)
1*7e120ff0Schristos /* Copyright (C) 1991-2024 Free Software Foundation, Inc.
298b9484cSchristos 
398b9484cSchristos NOTE: This source is derived from an old version taken from the GNU C
498b9484cSchristos Library (glibc).
598b9484cSchristos 
698b9484cSchristos This program is free software; you can redistribute it and/or modify it
798b9484cSchristos under the terms of the GNU General Public License as published by the
898b9484cSchristos Free Software Foundation; either version 2, or (at your option) any
998b9484cSchristos later version.
1098b9484cSchristos 
1198b9484cSchristos This program is distributed in the hope that it will be useful,
1298b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1398b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1498b9484cSchristos GNU General Public License for more details.
1598b9484cSchristos 
1698b9484cSchristos You should have received a copy of the GNU General Public License
1798b9484cSchristos along with this program; if not, write to the Free Software
1898b9484cSchristos Foundation, 51 Franklin Street - Fifth Floor,
1998b9484cSchristos Boston, MA 02110-1301, USA.  */
2098b9484cSchristos 
2198b9484cSchristos #ifdef HAVE_CONFIG_H
2298b9484cSchristos #if defined (CONFIG_BROKETS)
2398b9484cSchristos /* We use <config.h> instead of "config.h" so that a compilation
2498b9484cSchristos    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
2598b9484cSchristos    (which it would do because it found this file in $srcdir).  */
2698b9484cSchristos #include <config.h>
2798b9484cSchristos #else
2898b9484cSchristos #include "config.h"
2998b9484cSchristos #endif
3098b9484cSchristos #endif
3198b9484cSchristos 
3298b9484cSchristos 
3398b9484cSchristos #ifndef _GNU_SOURCE
3498b9484cSchristos #define _GNU_SOURCE
3598b9484cSchristos #endif
3698b9484cSchristos 
3798b9484cSchristos /* This code to undef const added in libiberty.  */
3898b9484cSchristos #ifndef __STDC__
3998b9484cSchristos /* This is a separate conditional since some stdc systems
4098b9484cSchristos    reject `defined (const)'.  */
4198b9484cSchristos #ifndef const
4298b9484cSchristos #define const
4398b9484cSchristos #endif
4498b9484cSchristos #endif
4598b9484cSchristos 
4698b9484cSchristos #include <errno.h>
4798b9484cSchristos #include <fnmatch.h>
4898b9484cSchristos #include <safe-ctype.h>
4998b9484cSchristos 
5098b9484cSchristos /* Comment out all this code if we are using the GNU C Library, and are not
5198b9484cSchristos    actually compiling the library itself.  This code is part of the GNU C
5298b9484cSchristos    Library, but also included in many other GNU distributions.  Compiling
5398b9484cSchristos    and linking in this code is a waste when using the GNU C library
5498b9484cSchristos    (especially if it is a shared library).  Rather than having every GNU
5598b9484cSchristos    program understand `configure --with-gnu-libc' and omit the object files,
5698b9484cSchristos    it is simpler to just do this in the source for each such file.  */
5798b9484cSchristos 
5898b9484cSchristos #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
5998b9484cSchristos 
6098b9484cSchristos 
6198b9484cSchristos #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
6298b9484cSchristos extern int errno;
6398b9484cSchristos #endif
6498b9484cSchristos 
6598b9484cSchristos /* Match STRING against the filename pattern PATTERN, returning zero if
6698b9484cSchristos    it matches, nonzero if not.  */
6798b9484cSchristos int
6898b9484cSchristos fnmatch (const char *pattern, const char *string, int flags)
6998b9484cSchristos {
7098b9484cSchristos   register const char *p = pattern, *n = string;
7198b9484cSchristos   register unsigned char c;
7298b9484cSchristos 
7398b9484cSchristos #define FOLD(c)	((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
7498b9484cSchristos 
7598b9484cSchristos   while ((c = *p++) != '\0')
7698b9484cSchristos     {
7798b9484cSchristos       c = FOLD (c);
7898b9484cSchristos 
7998b9484cSchristos       switch (c)
8098b9484cSchristos 	{
8198b9484cSchristos 	case '?':
8298b9484cSchristos 	  if (*n == '\0')
8398b9484cSchristos 	    return FNM_NOMATCH;
8498b9484cSchristos 	  else if ((flags & FNM_FILE_NAME) && *n == '/')
8598b9484cSchristos 	    return FNM_NOMATCH;
8698b9484cSchristos 	  else if ((flags & FNM_PERIOD) && *n == '.' &&
8798b9484cSchristos 		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
8898b9484cSchristos 	    return FNM_NOMATCH;
8998b9484cSchristos 	  break;
9098b9484cSchristos 
9198b9484cSchristos 	case '\\':
9298b9484cSchristos 	  if (!(flags & FNM_NOESCAPE))
9398b9484cSchristos 	    {
9498b9484cSchristos 	      c = *p++;
9598b9484cSchristos 	      c = FOLD (c);
9698b9484cSchristos 	    }
9798b9484cSchristos 	  if (FOLD ((unsigned char)*n) != c)
9898b9484cSchristos 	    return FNM_NOMATCH;
9998b9484cSchristos 	  break;
10098b9484cSchristos 
10198b9484cSchristos 	case '*':
10298b9484cSchristos 	  if ((flags & FNM_PERIOD) && *n == '.' &&
10398b9484cSchristos 	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
10498b9484cSchristos 	    return FNM_NOMATCH;
10598b9484cSchristos 
10698b9484cSchristos 	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
10798b9484cSchristos 	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
10898b9484cSchristos 		(c == '?' && *n == '\0'))
10998b9484cSchristos 	      return FNM_NOMATCH;
11098b9484cSchristos 
11198b9484cSchristos 	  if (c == '\0')
11298b9484cSchristos 	    return 0;
11398b9484cSchristos 
11498b9484cSchristos 	  {
11598b9484cSchristos 	    unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
11698b9484cSchristos 	    c1 = FOLD (c1);
11798b9484cSchristos 	    for (--p; *n != '\0'; ++n)
11898b9484cSchristos 	      if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
11998b9484cSchristos 		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
12098b9484cSchristos 		return 0;
12198b9484cSchristos 	    return FNM_NOMATCH;
12298b9484cSchristos 	  }
12398b9484cSchristos 
12498b9484cSchristos 	case '[':
12598b9484cSchristos 	  {
12698b9484cSchristos 	    /* Nonzero if the sense of the character class is inverted.  */
12798b9484cSchristos 	    register int negate;
12898b9484cSchristos 
12998b9484cSchristos 	    if (*n == '\0')
13098b9484cSchristos 	      return FNM_NOMATCH;
13198b9484cSchristos 
13298b9484cSchristos 	    if ((flags & FNM_PERIOD) && *n == '.' &&
13398b9484cSchristos 		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
13498b9484cSchristos 	      return FNM_NOMATCH;
13598b9484cSchristos 
13698b9484cSchristos 	    negate = (*p == '!' || *p == '^');
13798b9484cSchristos 	    if (negate)
13898b9484cSchristos 	      ++p;
13998b9484cSchristos 
14098b9484cSchristos 	    c = *p++;
14198b9484cSchristos 	    for (;;)
14298b9484cSchristos 	      {
14398b9484cSchristos 		register unsigned char cstart = c, cend = c;
14498b9484cSchristos 
14598b9484cSchristos 		if (!(flags & FNM_NOESCAPE) && c == '\\')
14698b9484cSchristos 		  cstart = cend = *p++;
14798b9484cSchristos 
14898b9484cSchristos 		cstart = cend = FOLD (cstart);
14998b9484cSchristos 
15098b9484cSchristos 		if (c == '\0')
15198b9484cSchristos 		  /* [ (unterminated) loses.  */
15298b9484cSchristos 		  return FNM_NOMATCH;
15398b9484cSchristos 
15498b9484cSchristos 		c = *p++;
15598b9484cSchristos 		c = FOLD (c);
15698b9484cSchristos 
15798b9484cSchristos 		if ((flags & FNM_FILE_NAME) && c == '/')
15898b9484cSchristos 		  /* [/] can never match.  */
15998b9484cSchristos 		  return FNM_NOMATCH;
16098b9484cSchristos 
16198b9484cSchristos 		if (c == '-' && *p != ']')
16298b9484cSchristos 		  {
16398b9484cSchristos 		    cend = *p++;
16498b9484cSchristos 		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
16598b9484cSchristos 		      cend = *p++;
16698b9484cSchristos 		    if (cend == '\0')
16798b9484cSchristos 		      return FNM_NOMATCH;
16898b9484cSchristos 		    cend = FOLD (cend);
16998b9484cSchristos 
17098b9484cSchristos 		    c = *p++;
17198b9484cSchristos 		  }
17298b9484cSchristos 
17398b9484cSchristos 		if (FOLD ((unsigned char)*n) >= cstart
17498b9484cSchristos 		    && FOLD ((unsigned char)*n) <= cend)
17598b9484cSchristos 		  goto matched;
17698b9484cSchristos 
17798b9484cSchristos 		if (c == ']')
17898b9484cSchristos 		  break;
17998b9484cSchristos 	      }
18098b9484cSchristos 	    if (!negate)
18198b9484cSchristos 	      return FNM_NOMATCH;
18298b9484cSchristos 	    break;
18398b9484cSchristos 
18498b9484cSchristos 	  matched:;
18598b9484cSchristos 	    /* Skip the rest of the [...] that already matched.  */
18698b9484cSchristos 	    while (c != ']')
18798b9484cSchristos 	      {
18898b9484cSchristos 		if (c == '\0')
18998b9484cSchristos 		  /* [... (unterminated) loses.  */
19098b9484cSchristos 		  return FNM_NOMATCH;
19198b9484cSchristos 
19298b9484cSchristos 		c = *p++;
19398b9484cSchristos 		if (!(flags & FNM_NOESCAPE) && c == '\\')
19498b9484cSchristos 		  /* XXX 1003.2d11 is unclear if this is right.  */
19598b9484cSchristos 		  ++p;
19698b9484cSchristos 	      }
19798b9484cSchristos 	    if (negate)
19898b9484cSchristos 	      return FNM_NOMATCH;
19998b9484cSchristos 	  }
20098b9484cSchristos 	  break;
20198b9484cSchristos 
20298b9484cSchristos 	default:
20398b9484cSchristos 	  if (c != FOLD ((unsigned char)*n))
20498b9484cSchristos 	    return FNM_NOMATCH;
20598b9484cSchristos 	}
20698b9484cSchristos 
20798b9484cSchristos       ++n;
20898b9484cSchristos     }
20998b9484cSchristos 
21098b9484cSchristos   if (*n == '\0')
21198b9484cSchristos     return 0;
21298b9484cSchristos 
21398b9484cSchristos   if ((flags & FNM_LEADING_DIR) && *n == '/')
21498b9484cSchristos     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
21598b9484cSchristos     return 0;
21698b9484cSchristos 
21798b9484cSchristos   return FNM_NOMATCH;
21898b9484cSchristos }
21998b9484cSchristos 
22098b9484cSchristos #endif	/* _LIBC or not __GNU_LIBRARY__.  */
221