fnmatch.c revision 33965
133965Sjdp/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. 233965Sjdp 333965SjdpNOTE: The canonical source of this file is maintained with the GNU C Library. 433965SjdpBugs can be reported to bug-glibc@prep.ai.mit.edu. 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 1833965SjdpFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 1933965Sjdp 2033965Sjdp#ifdef HAVE_CONFIG_H 2133965Sjdp#if defined (CONFIG_BROKETS) 2233965Sjdp/* We use <config.h> instead of "config.h" so that a compilation 2333965Sjdp using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h 2433965Sjdp (which it would do because it found this file in $srcdir). */ 2533965Sjdp#include <config.h> 2633965Sjdp#else 2733965Sjdp#include "config.h" 2833965Sjdp#endif 2933965Sjdp#endif 3033965Sjdp 3133965Sjdp 3233965Sjdp#ifndef _GNU_SOURCE 3333965Sjdp#define _GNU_SOURCE 3433965Sjdp#endif 3533965Sjdp 3633965Sjdp/* This code to undef const added in libiberty. */ 3733965Sjdp#ifndef __STDC__ 3833965Sjdp/* This is a separate conditional since some stdc systems 3933965Sjdp reject `defined (const)'. */ 4033965Sjdp#ifndef const 4133965Sjdp#define const 4233965Sjdp#endif 4333965Sjdp#endif 4433965Sjdp 4533965Sjdp#include <errno.h> 4633965Sjdp#include <fnmatch.h> 4733965Sjdp#include <ctype.h> 4833965Sjdp 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 6833965Sjdpfnmatch (pattern, string, flags) 6933965Sjdp const char *pattern; 7033965Sjdp const char *string; 7133965Sjdp int flags; 7233965Sjdp{ 7333965Sjdp register const char *p = pattern, *n = string; 7433965Sjdp register char c; 7533965Sjdp 7633965Sjdp/* Note that this evalutes C many times. */ 7733965Sjdp#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c)) 7833965Sjdp 7933965Sjdp while ((c = *p++) != '\0') 8033965Sjdp { 8133965Sjdp c = FOLD (c); 8233965Sjdp 8333965Sjdp switch (c) 8433965Sjdp { 8533965Sjdp case '?': 8633965Sjdp if (*n == '\0') 8733965Sjdp return FNM_NOMATCH; 8833965Sjdp else if ((flags & FNM_FILE_NAME) && *n == '/') 8933965Sjdp return FNM_NOMATCH; 9033965Sjdp else if ((flags & FNM_PERIOD) && *n == '.' && 9133965Sjdp (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 9233965Sjdp return FNM_NOMATCH; 9333965Sjdp break; 9433965Sjdp 9533965Sjdp case '\\': 9633965Sjdp if (!(flags & FNM_NOESCAPE)) 9733965Sjdp { 9833965Sjdp c = *p++; 9933965Sjdp c = FOLD (c); 10033965Sjdp } 10133965Sjdp if (FOLD (*n) != c) 10233965Sjdp return FNM_NOMATCH; 10333965Sjdp break; 10433965Sjdp 10533965Sjdp case '*': 10633965Sjdp if ((flags & FNM_PERIOD) && *n == '.' && 10733965Sjdp (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 10833965Sjdp return FNM_NOMATCH; 10933965Sjdp 11033965Sjdp for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) 11133965Sjdp if (((flags & FNM_FILE_NAME) && *n == '/') || 11233965Sjdp (c == '?' && *n == '\0')) 11333965Sjdp return FNM_NOMATCH; 11433965Sjdp 11533965Sjdp if (c == '\0') 11633965Sjdp return 0; 11733965Sjdp 11833965Sjdp { 11933965Sjdp char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; 12033965Sjdp c1 = FOLD (c1); 12133965Sjdp for (--p; *n != '\0'; ++n) 12233965Sjdp if ((c == '[' || FOLD (*n) == c1) && 12333965Sjdp fnmatch (p, n, flags & ~FNM_PERIOD) == 0) 12433965Sjdp return 0; 12533965Sjdp return FNM_NOMATCH; 12633965Sjdp } 12733965Sjdp 12833965Sjdp case '[': 12933965Sjdp { 13033965Sjdp /* Nonzero if the sense of the character class is inverted. */ 13133965Sjdp register int not; 13233965Sjdp 13333965Sjdp if (*n == '\0') 13433965Sjdp return FNM_NOMATCH; 13533965Sjdp 13633965Sjdp if ((flags & FNM_PERIOD) && *n == '.' && 13733965Sjdp (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 13833965Sjdp return FNM_NOMATCH; 13933965Sjdp 14033965Sjdp not = (*p == '!' || *p == '^'); 14133965Sjdp if (not) 14233965Sjdp ++p; 14333965Sjdp 14433965Sjdp c = *p++; 14533965Sjdp for (;;) 14633965Sjdp { 14733965Sjdp register char cstart = c, cend = c; 14833965Sjdp 14933965Sjdp if (!(flags & FNM_NOESCAPE) && c == '\\') 15033965Sjdp cstart = cend = *p++; 15133965Sjdp 15233965Sjdp cstart = cend = FOLD (cstart); 15333965Sjdp 15433965Sjdp if (c == '\0') 15533965Sjdp /* [ (unterminated) loses. */ 15633965Sjdp return FNM_NOMATCH; 15733965Sjdp 15833965Sjdp c = *p++; 15933965Sjdp c = FOLD (c); 16033965Sjdp 16133965Sjdp if ((flags & FNM_FILE_NAME) && c == '/') 16233965Sjdp /* [/] can never match. */ 16333965Sjdp return FNM_NOMATCH; 16433965Sjdp 16533965Sjdp if (c == '-' && *p != ']') 16633965Sjdp { 16733965Sjdp cend = *p++; 16833965Sjdp if (!(flags & FNM_NOESCAPE) && cend == '\\') 16933965Sjdp cend = *p++; 17033965Sjdp if (cend == '\0') 17133965Sjdp return FNM_NOMATCH; 17233965Sjdp cend = FOLD (cend); 17333965Sjdp 17433965Sjdp c = *p++; 17533965Sjdp } 17633965Sjdp 17733965Sjdp if (FOLD (*n) >= cstart && FOLD (*n) <= cend) 17833965Sjdp goto matched; 17933965Sjdp 18033965Sjdp if (c == ']') 18133965Sjdp break; 18233965Sjdp } 18333965Sjdp if (!not) 18433965Sjdp return FNM_NOMATCH; 18533965Sjdp break; 18633965Sjdp 18733965Sjdp matched:; 18833965Sjdp /* Skip the rest of the [...] that already matched. */ 18933965Sjdp while (c != ']') 19033965Sjdp { 19133965Sjdp if (c == '\0') 19233965Sjdp /* [... (unterminated) loses. */ 19333965Sjdp return FNM_NOMATCH; 19433965Sjdp 19533965Sjdp c = *p++; 19633965Sjdp if (!(flags & FNM_NOESCAPE) && c == '\\') 19733965Sjdp /* XXX 1003.2d11 is unclear if this is right. */ 19833965Sjdp ++p; 19933965Sjdp } 20033965Sjdp if (not) 20133965Sjdp return FNM_NOMATCH; 20233965Sjdp } 20333965Sjdp break; 20433965Sjdp 20533965Sjdp default: 20633965Sjdp if (c != FOLD (*n)) 20733965Sjdp return FNM_NOMATCH; 20833965Sjdp } 20933965Sjdp 21033965Sjdp ++n; 21133965Sjdp } 21233965Sjdp 21333965Sjdp if (*n == '\0') 21433965Sjdp return 0; 21533965Sjdp 21633965Sjdp if ((flags & FNM_LEADING_DIR) && *n == '/') 21733965Sjdp /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ 21833965Sjdp return 0; 21933965Sjdp 22033965Sjdp return FNM_NOMATCH; 22133965Sjdp} 22233965Sjdp 22333965Sjdp#endif /* _LIBC or not __GNU_LIBRARY__. */ 224