|  | /* Copyright (C) 1991-2022 Free Software Foundation, Inc. | 
|  |  | 
|  | NOTE: This source is derived from an old version taken from the GNU C | 
|  | Library (glibc). | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify it | 
|  | under the terms of the GNU General Public License as published by the | 
|  | Free Software Foundation; either version 2, or (at your option) any | 
|  | later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program; if not, write to the Free Software | 
|  | Foundation, 51 Franklin Street - Fifth Floor, | 
|  | Boston, MA 02110-1301, USA.  */ | 
|  |  | 
|  | #ifdef HAVE_CONFIG_H | 
|  | #if defined (CONFIG_BROKETS) | 
|  | /* We use <config.h> instead of "config.h" so that a compilation | 
|  | using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h | 
|  | (which it would do because it found this file in $srcdir).  */ | 
|  | #include <config.h> | 
|  | #else | 
|  | #include "config.h" | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  |  | 
|  | #ifndef _GNU_SOURCE | 
|  | #define _GNU_SOURCE | 
|  | #endif | 
|  |  | 
|  | /* This code to undef const added in libiberty.  */ | 
|  | #ifndef __STDC__ | 
|  | /* This is a separate conditional since some stdc systems | 
|  | reject `defined (const)'.  */ | 
|  | #ifndef const | 
|  | #define const | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #include <errno.h> | 
|  | #include <fnmatch.h> | 
|  | #include <safe-ctype.h> | 
|  |  | 
|  | /* Comment out all this code if we are using the GNU C Library, and are not | 
|  | actually compiling the library itself.  This code is part of the GNU C | 
|  | Library, but also included in many other GNU distributions.  Compiling | 
|  | and linking in this code is a waste when using the GNU C library | 
|  | (especially if it is a shared library).  Rather than having every GNU | 
|  | program understand `configure --with-gnu-libc' and omit the object files, | 
|  | it is simpler to just do this in the source for each such file.  */ | 
|  |  | 
|  | #if defined (_LIBC) || !defined (__GNU_LIBRARY__) | 
|  |  | 
|  |  | 
|  | #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) | 
|  | extern int errno; | 
|  | #endif | 
|  |  | 
|  | /* Match STRING against the filename pattern PATTERN, returning zero if | 
|  | it matches, nonzero if not.  */ | 
|  | int | 
|  | fnmatch (const char *pattern, const char *string, int flags) | 
|  | { | 
|  | register const char *p = pattern, *n = string; | 
|  | register unsigned char c; | 
|  |  | 
|  | #define FOLD(c)	((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c)) | 
|  |  | 
|  | while ((c = *p++) != '\0') | 
|  | { | 
|  | c = FOLD (c); | 
|  |  | 
|  | switch (c) | 
|  | { | 
|  | case '?': | 
|  | if (*n == '\0') | 
|  | return FNM_NOMATCH; | 
|  | else if ((flags & FNM_FILE_NAME) && *n == '/') | 
|  | return FNM_NOMATCH; | 
|  | else if ((flags & FNM_PERIOD) && *n == '.' && | 
|  | (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) | 
|  | return FNM_NOMATCH; | 
|  | break; | 
|  |  | 
|  | case '\\': | 
|  | if (!(flags & FNM_NOESCAPE)) | 
|  | { | 
|  | c = *p++; | 
|  | c = FOLD (c); | 
|  | } | 
|  | if (FOLD ((unsigned char)*n) != c) | 
|  | return FNM_NOMATCH; | 
|  | break; | 
|  |  | 
|  | case '*': | 
|  | if ((flags & FNM_PERIOD) && *n == '.' && | 
|  | (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) | 
|  | return FNM_NOMATCH; | 
|  |  | 
|  | for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) | 
|  | if (((flags & FNM_FILE_NAME) && *n == '/') || | 
|  | (c == '?' && *n == '\0')) | 
|  | return FNM_NOMATCH; | 
|  |  | 
|  | if (c == '\0') | 
|  | return 0; | 
|  |  | 
|  | { | 
|  | unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; | 
|  | c1 = FOLD (c1); | 
|  | for (--p; *n != '\0'; ++n) | 
|  | if ((c == '[' || FOLD ((unsigned char)*n) == c1) && | 
|  | fnmatch (p, n, flags & ~FNM_PERIOD) == 0) | 
|  | return 0; | 
|  | return FNM_NOMATCH; | 
|  | } | 
|  |  | 
|  | case '[': | 
|  | { | 
|  | /* Nonzero if the sense of the character class is inverted.  */ | 
|  | register int negate; | 
|  |  | 
|  | if (*n == '\0') | 
|  | return FNM_NOMATCH; | 
|  |  | 
|  | if ((flags & FNM_PERIOD) && *n == '.' && | 
|  | (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) | 
|  | return FNM_NOMATCH; | 
|  |  | 
|  | negate = (*p == '!' || *p == '^'); | 
|  | if (negate) | 
|  | ++p; | 
|  |  | 
|  | c = *p++; | 
|  | for (;;) | 
|  | { | 
|  | register unsigned char cstart = c, cend = c; | 
|  |  | 
|  | if (!(flags & FNM_NOESCAPE) && c == '\\') | 
|  | cstart = cend = *p++; | 
|  |  | 
|  | cstart = cend = FOLD (cstart); | 
|  |  | 
|  | if (c == '\0') | 
|  | /* [ (unterminated) loses.  */ | 
|  | return FNM_NOMATCH; | 
|  |  | 
|  | c = *p++; | 
|  | c = FOLD (c); | 
|  |  | 
|  | if ((flags & FNM_FILE_NAME) && c == '/') | 
|  | /* [/] can never match.  */ | 
|  | return FNM_NOMATCH; | 
|  |  | 
|  | if (c == '-' && *p != ']') | 
|  | { | 
|  | cend = *p++; | 
|  | if (!(flags & FNM_NOESCAPE) && cend == '\\') | 
|  | cend = *p++; | 
|  | if (cend == '\0') | 
|  | return FNM_NOMATCH; | 
|  | cend = FOLD (cend); | 
|  |  | 
|  | c = *p++; | 
|  | } | 
|  |  | 
|  | if (FOLD ((unsigned char)*n) >= cstart | 
|  | && FOLD ((unsigned char)*n) <= cend) | 
|  | goto matched; | 
|  |  | 
|  | if (c == ']') | 
|  | break; | 
|  | } | 
|  | if (!negate) | 
|  | return FNM_NOMATCH; | 
|  | break; | 
|  |  | 
|  | matched:; | 
|  | /* Skip the rest of the [...] that already matched.  */ | 
|  | while (c != ']') | 
|  | { | 
|  | if (c == '\0') | 
|  | /* [... (unterminated) loses.  */ | 
|  | return FNM_NOMATCH; | 
|  |  | 
|  | c = *p++; | 
|  | if (!(flags & FNM_NOESCAPE) && c == '\\') | 
|  | /* XXX 1003.2d11 is unclear if this is right.  */ | 
|  | ++p; | 
|  | } | 
|  | if (negate) | 
|  | return FNM_NOMATCH; | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | if (c != FOLD ((unsigned char)*n)) | 
|  | return FNM_NOMATCH; | 
|  | } | 
|  |  | 
|  | ++n; | 
|  | } | 
|  |  | 
|  | if (*n == '\0') | 
|  | return 0; | 
|  |  | 
|  | if ((flags & FNM_LEADING_DIR) && *n == '/') | 
|  | /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */ | 
|  | return 0; | 
|  |  | 
|  | return FNM_NOMATCH; | 
|  | } | 
|  |  | 
|  | #endif	/* _LIBC or not __GNU_LIBRARY__.  */ |