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