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