fnmatch.c revision 218822
133965Sjdp/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. 233965Sjdp 377298SobrienNOTE: This source is derived from an old version taken from the GNU C 477298SobrienLibrary (glibc). 533965Sjdp 633965SjdpThis program is free software; you can redistribute it and/or modify it 733965Sjdpunder the terms of the GNU General Public License as published by the 833965SjdpFree Software Foundation; either version 2, or (at your option) any 933965Sjdplater version. 1033965Sjdp 1133965SjdpThis program is distributed in the hope that it will be useful, 1233965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1333965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1433965SjdpGNU General Public License for more details. 1533965Sjdp 1633965SjdpYou should have received a copy of the GNU General Public License 1733965Sjdpalong with this program; if not, write to the Free Software 18218822SdimFoundation, 51 Franklin Street - Fifth Floor, 19218822SdimBoston, MA 02110-1301, USA. */ 2033965Sjdp 2133965Sjdp#ifdef HAVE_CONFIG_H 2233965Sjdp#if defined (CONFIG_BROKETS) 2333965Sjdp/* We use <config.h> instead of "config.h" so that a compilation 2433965Sjdp using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h 2533965Sjdp (which it would do because it found this file in $srcdir). */ 2633965Sjdp#include <config.h> 2733965Sjdp#else 2833965Sjdp#include "config.h" 2933965Sjdp#endif 3033965Sjdp#endif 3133965Sjdp 3233965Sjdp 3333965Sjdp#ifndef _GNU_SOURCE 3433965Sjdp#define _GNU_SOURCE 3533965Sjdp#endif 3633965Sjdp 3733965Sjdp/* This code to undef const added in libiberty. */ 3833965Sjdp#ifndef __STDC__ 3933965Sjdp/* This is a separate conditional since some stdc systems 4033965Sjdp reject `defined (const)'. */ 4133965Sjdp#ifndef const 4233965Sjdp#define const 4333965Sjdp#endif 4433965Sjdp#endif 4533965Sjdp 4633965Sjdp#include <errno.h> 4733965Sjdp#include <fnmatch.h> 4877298Sobrien#include <safe-ctype.h> 4933965Sjdp 5033965Sjdp/* Comment out all this code if we are using the GNU C Library, and are not 5133965Sjdp actually compiling the library itself. This code is part of the GNU C 5233965Sjdp Library, but also included in many other GNU distributions. Compiling 5333965Sjdp and linking in this code is a waste when using the GNU C library 5433965Sjdp (especially if it is a shared library). Rather than having every GNU 5533965Sjdp program understand `configure --with-gnu-libc' and omit the object files, 5633965Sjdp it is simpler to just do this in the source for each such file. */ 5733965Sjdp 5833965Sjdp#if defined (_LIBC) || !defined (__GNU_LIBRARY__) 5933965Sjdp 6033965Sjdp 6133965Sjdp#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) 6233965Sjdpextern int errno; 6333965Sjdp#endif 6433965Sjdp 6533965Sjdp/* Match STRING against the filename pattern PATTERN, returning zero if 6633965Sjdp it matches, nonzero if not. */ 6733965Sjdpint 68218822Sdimfnmatch (const char *pattern, const char *string, int flags) 6933965Sjdp{ 7033965Sjdp register const char *p = pattern, *n = string; 7160484Sobrien register unsigned char c; 7233965Sjdp 7377298Sobrien#define FOLD(c) ((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c)) 7433965Sjdp 7533965Sjdp while ((c = *p++) != '\0') 7633965Sjdp { 7733965Sjdp c = FOLD (c); 7833965Sjdp 7933965Sjdp switch (c) 8033965Sjdp { 8133965Sjdp case '?': 8233965Sjdp if (*n == '\0') 8333965Sjdp return FNM_NOMATCH; 8433965Sjdp else if ((flags & FNM_FILE_NAME) && *n == '/') 8533965Sjdp return FNM_NOMATCH; 8633965Sjdp else if ((flags & FNM_PERIOD) && *n == '.' && 8733965Sjdp (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 8833965Sjdp return FNM_NOMATCH; 8933965Sjdp break; 9033965Sjdp 9133965Sjdp case '\\': 9233965Sjdp if (!(flags & FNM_NOESCAPE)) 9333965Sjdp { 9433965Sjdp c = *p++; 9533965Sjdp c = FOLD (c); 9633965Sjdp } 9760484Sobrien if (FOLD ((unsigned char)*n) != c) 9833965Sjdp return FNM_NOMATCH; 9933965Sjdp break; 10033965Sjdp 10133965Sjdp case '*': 10233965Sjdp if ((flags & FNM_PERIOD) && *n == '.' && 10333965Sjdp (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 10433965Sjdp return FNM_NOMATCH; 10533965Sjdp 10633965Sjdp for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) 10733965Sjdp if (((flags & FNM_FILE_NAME) && *n == '/') || 10833965Sjdp (c == '?' && *n == '\0')) 10933965Sjdp return FNM_NOMATCH; 11033965Sjdp 11133965Sjdp if (c == '\0') 11233965Sjdp return 0; 11333965Sjdp 11433965Sjdp { 11560484Sobrien unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; 11633965Sjdp c1 = FOLD (c1); 11733965Sjdp for (--p; *n != '\0'; ++n) 11860484Sobrien if ((c == '[' || FOLD ((unsigned char)*n) == c1) && 11933965Sjdp fnmatch (p, n, flags & ~FNM_PERIOD) == 0) 12033965Sjdp return 0; 12133965Sjdp return FNM_NOMATCH; 12233965Sjdp } 12333965Sjdp 12433965Sjdp case '[': 12533965Sjdp { 12633965Sjdp /* Nonzero if the sense of the character class is inverted. */ 127218822Sdim register int negate; 12833965Sjdp 12933965Sjdp if (*n == '\0') 13033965Sjdp return FNM_NOMATCH; 13133965Sjdp 13233965Sjdp if ((flags & FNM_PERIOD) && *n == '.' && 13333965Sjdp (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 13433965Sjdp return FNM_NOMATCH; 13533965Sjdp 136218822Sdim negate = (*p == '!' || *p == '^'); 137218822Sdim if (negate) 13833965Sjdp ++p; 13933965Sjdp 14033965Sjdp c = *p++; 14133965Sjdp for (;;) 14233965Sjdp { 14360484Sobrien register unsigned char cstart = c, cend = c; 14433965Sjdp 14533965Sjdp if (!(flags & FNM_NOESCAPE) && c == '\\') 14633965Sjdp cstart = cend = *p++; 14733965Sjdp 14833965Sjdp cstart = cend = FOLD (cstart); 14933965Sjdp 15033965Sjdp if (c == '\0') 15133965Sjdp /* [ (unterminated) loses. */ 15233965Sjdp return FNM_NOMATCH; 15333965Sjdp 15433965Sjdp c = *p++; 15533965Sjdp c = FOLD (c); 15633965Sjdp 15733965Sjdp if ((flags & FNM_FILE_NAME) && c == '/') 15833965Sjdp /* [/] can never match. */ 15933965Sjdp return FNM_NOMATCH; 16033965Sjdp 16133965Sjdp if (c == '-' && *p != ']') 16233965Sjdp { 16333965Sjdp cend = *p++; 16433965Sjdp if (!(flags & FNM_NOESCAPE) && cend == '\\') 16533965Sjdp cend = *p++; 16633965Sjdp if (cend == '\0') 16733965Sjdp return FNM_NOMATCH; 16833965Sjdp cend = FOLD (cend); 16933965Sjdp 17033965Sjdp c = *p++; 17133965Sjdp } 17233965Sjdp 17360484Sobrien if (FOLD ((unsigned char)*n) >= cstart 17460484Sobrien && FOLD ((unsigned char)*n) <= cend) 17533965Sjdp goto matched; 17633965Sjdp 17733965Sjdp if (c == ']') 17833965Sjdp break; 17933965Sjdp } 180218822Sdim if (!negate) 18133965Sjdp return FNM_NOMATCH; 18233965Sjdp break; 18333965Sjdp 18433965Sjdp matched:; 18533965Sjdp /* Skip the rest of the [...] that already matched. */ 18633965Sjdp while (c != ']') 18733965Sjdp { 18833965Sjdp if (c == '\0') 18933965Sjdp /* [... (unterminated) loses. */ 19033965Sjdp return FNM_NOMATCH; 19133965Sjdp 19233965Sjdp c = *p++; 19333965Sjdp if (!(flags & FNM_NOESCAPE) && c == '\\') 19433965Sjdp /* XXX 1003.2d11 is unclear if this is right. */ 19533965Sjdp ++p; 19633965Sjdp } 197218822Sdim if (negate) 19833965Sjdp return FNM_NOMATCH; 19933965Sjdp } 20033965Sjdp break; 20133965Sjdp 20233965Sjdp default: 20360484Sobrien if (c != FOLD ((unsigned char)*n)) 20433965Sjdp return FNM_NOMATCH; 20533965Sjdp } 20633965Sjdp 20733965Sjdp ++n; 20833965Sjdp } 20933965Sjdp 21033965Sjdp if (*n == '\0') 21133965Sjdp return 0; 21233965Sjdp 21333965Sjdp if ((flags & FNM_LEADING_DIR) && *n == '/') 21433965Sjdp /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ 21533965Sjdp return 0; 21633965Sjdp 21733965Sjdp return FNM_NOMATCH; 21833965Sjdp} 21933965Sjdp 22033965Sjdp#endif /* _LIBC or not __GNU_LIBRARY__. */ 221