fnmatch.c revision 60484
11590Srgrimes/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. 21590Srgrimes 31590SrgrimesNOTE: The canonical source of this file is maintained with the GNU C Library. 41590SrgrimesBugs can be reported to bug-glibc@prep.ai.mit.edu. 51590Srgrimes 61590SrgrimesThis program is free software; you can redistribute it and/or modify it 71590Srgrimesunder the terms of the GNU General Public License as published by the 81590SrgrimesFree Software Foundation; either version 2, or (at your option) any 91590Srgrimeslater version. 101590Srgrimes 111590SrgrimesThis program is distributed in the hope that it will be useful, 121590Srgrimesbut WITHOUT ANY WARRANTY; without even the implied warranty of 131590SrgrimesMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141590SrgrimesGNU General Public License for more details. 151590Srgrimes 161590SrgrimesYou should have received a copy of the GNU General Public License 171590Srgrimesalong with this program; if not, write to the Free Software 181590SrgrimesFoundation, 59 Temple Place - Suite 330, 191590SrgrimesBoston, MA 02111-1307, USA. */ 201590Srgrimes 211590Srgrimes#ifdef HAVE_CONFIG_H 221590Srgrimes#if defined (CONFIG_BROKETS) 231590Srgrimes/* We use <config.h> instead of "config.h" so that a compilation 241590Srgrimes using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h 251590Srgrimes (which it would do because it found this file in $srcdir). */ 261590Srgrimes#include <config.h> 271590Srgrimes#else 281590Srgrimes#include "config.h" 291590Srgrimes#endif 301590Srgrimes#endif 311590Srgrimes 321590Srgrimes 331590Srgrimes#ifndef _GNU_SOURCE 341590Srgrimes#define _GNU_SOURCE 351590Srgrimes#endif 361590Srgrimes 371590Srgrimes/* This code to undef const added in libiberty. */ 381590Srgrimes#ifndef __STDC__ 391590Srgrimes/* This is a separate conditional since some stdc systems 401590Srgrimes reject `defined (const)'. */ 411590Srgrimes#ifndef const 421590Srgrimes#define const 431590Srgrimes#endif 441590Srgrimes#endif 451590Srgrimes 461590Srgrimes#include <errno.h> 471590Srgrimes#include <fnmatch.h> 481590Srgrimes#include <ctype.h> 498874Srgrimes 501590Srgrimes 511590Srgrimes/* Comment out all this code if we are using the GNU C Library, and are not 521590Srgrimes actually compiling the library itself. This code is part of the GNU C 531590Srgrimes Library, but also included in many other GNU distributions. Compiling 541590Srgrimes and linking in this code is a waste when using the GNU C library 551590Srgrimes (especially if it is a shared library). Rather than having every GNU 561590Srgrimes program understand `configure --with-gnu-libc' and omit the object files, 571590Srgrimes it is simpler to just do this in the source for each such file. */ 581590Srgrimes 591590Srgrimes#if defined (_LIBC) || !defined (__GNU_LIBRARY__) 601590Srgrimes 611590Srgrimes 621590Srgrimes#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) 631590Srgrimesextern int errno; 641590Srgrimes#endif 651590Srgrimes 661590Srgrimes/* Match STRING against the filename pattern PATTERN, returning zero if 671590Srgrimes it matches, nonzero if not. */ 681590Srgrimesint 691590Srgrimesfnmatch (pattern, string, flags) 701590Srgrimes const char *pattern; 711590Srgrimes const char *string; 721590Srgrimes int flags; 731590Srgrimes{ 741590Srgrimes register const char *p = pattern, *n = string; 751590Srgrimes register unsigned char c; 761590Srgrimes 771590Srgrimes/* Note that this evalutes C many times. */ 781590Srgrimes#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c)) 791590Srgrimes 801590Srgrimes while ((c = *p++) != '\0') 811590Srgrimes { 821590Srgrimes c = FOLD (c); 831590Srgrimes 841590Srgrimes switch (c) 851590Srgrimes { 861590Srgrimes case '?': 871590Srgrimes if (*n == '\0') 881590Srgrimes return FNM_NOMATCH; 891590Srgrimes else if ((flags & FNM_FILE_NAME) && *n == '/') 901590Srgrimes return FNM_NOMATCH; 911590Srgrimes else if ((flags & FNM_PERIOD) && *n == '.' && 921590Srgrimes (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 931590Srgrimes return FNM_NOMATCH; 941590Srgrimes break; 951590Srgrimes 961590Srgrimes case '\\': 971590Srgrimes if (!(flags & FNM_NOESCAPE)) 981590Srgrimes { 991590Srgrimes c = *p++; 1001590Srgrimes c = FOLD (c); 1013138Sache } 1023138Sache if (FOLD ((unsigned char)*n) != c) 1033138Sache return FNM_NOMATCH; 1041590Srgrimes break; 1051590Srgrimes 1061590Srgrimes case '*': 1071590Srgrimes 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