(root)/
gcc-13.2.0/
libiberty/
fnmatch.c
       1  /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
       2  
       3  NOTE: This source is derived from an old version taken from the GNU C
       4  Library (glibc).
       5  
       6  This program is free software; you can redistribute it and/or modify it
       7  under the terms of the GNU General Public License as published by the
       8  Free Software Foundation; either version 2, or (at your option) any
       9  later version.
      10  
      11  This program is distributed in the hope that it will be useful,
      12  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  GNU General Public License for more details.
      15  
      16  You should have received a copy of the GNU General Public License
      17  along with this program; if not, write to the Free Software
      18  Foundation, 51 Franklin Street - Fifth Floor,
      19  Boston, MA 02110-1301, USA.  */
      20  
      21  #ifdef HAVE_CONFIG_H
      22  #if defined (CONFIG_BROKETS)
      23  /* We use <config.h> instead of "config.h" so that a compilation
      24     using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
      25     (which it would do because it found this file in $srcdir).  */
      26  #include <config.h>
      27  #else
      28  #include "config.h"
      29  #endif
      30  #endif
      31  
      32  
      33  #ifndef _GNU_SOURCE
      34  #define _GNU_SOURCE
      35  #endif
      36  
      37  /* This code to undef const added in libiberty.  */
      38  #ifndef __STDC__
      39  /* This is a separate conditional since some stdc systems
      40     reject `defined (const)'.  */
      41  #ifndef const
      42  #define const
      43  #endif
      44  #endif
      45  
      46  #include <errno.h>
      47  #include <fnmatch.h>
      48  #include <safe-ctype.h>
      49  
      50  /* Comment out all this code if we are using the GNU C Library, and are not
      51     actually compiling the library itself.  This code is part of the GNU C
      52     Library, but also included in many other GNU distributions.  Compiling
      53     and linking in this code is a waste when using the GNU C library
      54     (especially if it is a shared library).  Rather than having every GNU
      55     program understand `configure --with-gnu-libc' and omit the object files,
      56     it is simpler to just do this in the source for each such file.  */
      57  
      58  #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
      59  
      60  
      61  #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
      62  extern int errno;
      63  #endif
      64  
      65  /* Match STRING against the filename pattern PATTERN, returning zero if
      66     it matches, nonzero if not.  */
      67  int
      68  fnmatch (const char *pattern, const char *string, int flags)
      69  {
      70    register const char *p = pattern, *n = string;
      71    register unsigned char c;
      72  
      73  #define FOLD(c)	((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
      74  
      75    while ((c = *p++) != '\0')
      76      {
      77        c = FOLD (c);
      78  
      79        switch (c)
      80  	{
      81  	case '?':
      82  	  if (*n == '\0')
      83  	    return FNM_NOMATCH;
      84  	  else if ((flags & FNM_FILE_NAME) && *n == '/')
      85  	    return FNM_NOMATCH;
      86  	  else if ((flags & FNM_PERIOD) && *n == '.' &&
      87  		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
      88  	    return FNM_NOMATCH;
      89  	  break;
      90  
      91  	case '\\':
      92  	  if (!(flags & FNM_NOESCAPE))
      93  	    {
      94  	      c = *p++;
      95  	      c = FOLD (c);
      96  	    }
      97  	  if (FOLD ((unsigned char)*n) != c)
      98  	    return FNM_NOMATCH;
      99  	  break;
     100  
     101  	case '*':
     102  	  if ((flags & FNM_PERIOD) && *n == '.' &&
     103  	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
     104  	    return FNM_NOMATCH;
     105  
     106  	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
     107  	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
     108  		(c == '?' && *n == '\0'))
     109  	      return FNM_NOMATCH;
     110  
     111  	  if (c == '\0')
     112  	    return 0;
     113  
     114  	  {
     115  	    unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
     116  	    c1 = FOLD (c1);
     117  	    for (--p; *n != '\0'; ++n)
     118  	      if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
     119  		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
     120  		return 0;
     121  	    return FNM_NOMATCH;
     122  	  }
     123  
     124  	case '[':
     125  	  {
     126  	    /* Nonzero if the sense of the character class is inverted.  */
     127  	    register int negate;
     128  
     129  	    if (*n == '\0')
     130  	      return FNM_NOMATCH;
     131  
     132  	    if ((flags & FNM_PERIOD) && *n == '.' &&
     133  		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
     134  	      return FNM_NOMATCH;
     135  
     136  	    negate = (*p == '!' || *p == '^');
     137  	    if (negate)
     138  	      ++p;
     139  
     140  	    c = *p++;
     141  	    for (;;)
     142  	      {
     143  		register unsigned char cstart = c, cend = c;
     144  
     145  		if (!(flags & FNM_NOESCAPE) && c == '\\')
     146  		  cstart = cend = *p++;
     147  
     148  		cstart = cend = FOLD (cstart);
     149  
     150  		if (c == '\0')
     151  		  /* [ (unterminated) loses.  */
     152  		  return FNM_NOMATCH;
     153  
     154  		c = *p++;
     155  		c = FOLD (c);
     156  
     157  		if ((flags & FNM_FILE_NAME) && c == '/')
     158  		  /* [/] can never match.  */
     159  		  return FNM_NOMATCH;
     160  
     161  		if (c == '-' && *p != ']')
     162  		  {
     163  		    cend = *p++;
     164  		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
     165  		      cend = *p++;
     166  		    if (cend == '\0')
     167  		      return FNM_NOMATCH;
     168  		    cend = FOLD (cend);
     169  
     170  		    c = *p++;
     171  		  }
     172  
     173  		if (FOLD ((unsigned char)*n) >= cstart
     174  		    && FOLD ((unsigned char)*n) <= cend)
     175  		  goto matched;
     176  
     177  		if (c == ']')
     178  		  break;
     179  	      }
     180  	    if (!negate)
     181  	      return FNM_NOMATCH;
     182  	    break;
     183  
     184  	  matched:;
     185  	    /* Skip the rest of the [...] that already matched.  */
     186  	    while (c != ']')
     187  	      {
     188  		if (c == '\0')
     189  		  /* [... (unterminated) loses.  */
     190  		  return FNM_NOMATCH;
     191  
     192  		c = *p++;
     193  		if (!(flags & FNM_NOESCAPE) && c == '\\')
     194  		  /* XXX 1003.2d11 is unclear if this is right.  */
     195  		  ++p;
     196  	      }
     197  	    if (negate)
     198  	      return FNM_NOMATCH;
     199  	  }
     200  	  break;
     201  
     202  	default:
     203  	  if (c != FOLD ((unsigned char)*n))
     204  	    return FNM_NOMATCH;
     205  	}
     206  
     207        ++n;
     208      }
     209  
     210    if (*n == '\0')
     211      return 0;
     212  
     213    if ((flags & FNM_LEADING_DIR) && *n == '/')
     214      /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
     215      return 0;
     216  
     217    return FNM_NOMATCH;
     218  }
     219  
     220  #endif	/* _LIBC or not __GNU_LIBRARY__.  */