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