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