fnmatch.c revision 77298
1/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. 2 3NOTE: This source is derived from an old version taken from the GNU C 4Library (glibc). 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 <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) 62extern int errno; 63#endif 64 65/* Match STRING against the filename pattern PATTERN, returning zero if 66 it matches, nonzero if not. */ 67int 68fnmatch (pattern, string, flags) 69 const char *pattern; 70 const char *string; 71 int flags; 72{ 73 register const char *p = pattern, *n = string; 74 register unsigned char c; 75 76#define FOLD(c) ((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c)) 77 78 while ((c = *p++) != '\0') 79 { 80 c = FOLD (c); 81 82 switch (c) 83 { 84 case '?': 85 if (*n == '\0') 86 return FNM_NOMATCH; 87 else if ((flags & FNM_FILE_NAME) && *n == '/') 88 return FNM_NOMATCH; 89 else if ((flags & FNM_PERIOD) && *n == '.' && 90 (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 91 return FNM_NOMATCH; 92 break; 93 94 case '\\': 95 if (!(flags & FNM_NOESCAPE)) 96 { 97 c = *p++; 98 c = FOLD (c); 99 } 100 if (FOLD ((unsigned char)*n) != c) 101 return FNM_NOMATCH; 102 break; 103 104 case '*': 105 if ((flags & FNM_PERIOD) && *n == '.' && 106 (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 107 return FNM_NOMATCH; 108 109 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) 110 if (((flags & FNM_FILE_NAME) && *n == '/') || 111 (c == '?' && *n == '\0')) 112 return FNM_NOMATCH; 113 114 if (c == '\0') 115 return 0; 116 117 { 118 unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; 119 c1 = FOLD (c1); 120 for (--p; *n != '\0'; ++n) 121 if ((c == '[' || FOLD ((unsigned char)*n) == c1) && 122 fnmatch (p, n, flags & ~FNM_PERIOD) == 0) 123 return 0; 124 return FNM_NOMATCH; 125 } 126 127 case '[': 128 { 129 /* Nonzero if the sense of the character class is inverted. */ 130 register int not; 131 132 if (*n == '\0') 133 return FNM_NOMATCH; 134 135 if ((flags & FNM_PERIOD) && *n == '.' && 136 (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 137 return FNM_NOMATCH; 138 139 not = (*p == '!' || *p == '^'); 140 if (not) 141 ++p; 142 143 c = *p++; 144 for (;;) 145 { 146 register unsigned char cstart = c, cend = c; 147 148 if (!(flags & FNM_NOESCAPE) && c == '\\') 149 cstart = cend = *p++; 150 151 cstart = cend = FOLD (cstart); 152 153 if (c == '\0') 154 /* [ (unterminated) loses. */ 155 return FNM_NOMATCH; 156 157 c = *p++; 158 c = FOLD (c); 159 160 if ((flags & FNM_FILE_NAME) && c == '/') 161 /* [/] can never match. */ 162 return FNM_NOMATCH; 163 164 if (c == '-' && *p != ']') 165 { 166 cend = *p++; 167 if (!(flags & FNM_NOESCAPE) && cend == '\\') 168 cend = *p++; 169 if (cend == '\0') 170 return FNM_NOMATCH; 171 cend = FOLD (cend); 172 173 c = *p++; 174 } 175 176 if (FOLD ((unsigned char)*n) >= cstart 177 && FOLD ((unsigned char)*n) <= cend) 178 goto matched; 179 180 if (c == ']') 181 break; 182 } 183 if (!not) 184 return FNM_NOMATCH; 185 break; 186 187 matched:; 188 /* Skip the rest of the [...] that already matched. */ 189 while (c != ']') 190 { 191 if (c == '\0') 192 /* [... (unterminated) loses. */ 193 return FNM_NOMATCH; 194 195 c = *p++; 196 if (!(flags & FNM_NOESCAPE) && c == '\\') 197 /* XXX 1003.2d11 is unclear if this is right. */ 198 ++p; 199 } 200 if (not) 201 return FNM_NOMATCH; 202 } 203 break; 204 205 default: 206 if (c != FOLD ((unsigned char)*n)) 207 return FNM_NOMATCH; 208 } 209 210 ++n; 211 } 212 213 if (*n == '\0') 214 return 0; 215 216 if ((flags & FNM_LEADING_DIR) && *n == '/') 217 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ 218 return 0; 219 220 return FNM_NOMATCH; 221} 222 223#endif /* _LIBC or not __GNU_LIBRARY__. */ 224