1 /* Copyright (C) 1991, 1992, 1993 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__. */ 221