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