fnmatch.c revision 302408
118334Speter/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. 218334Speter 318334SpeterNOTE: This source is derived from an old version taken from the GNU C 452284SobrienLibrary (glibc). 518334Speter 618334SpeterThis program is free software; you can redistribute it and/or modify it 718334Speterunder the terms of the GNU General Public License as published by the 818334SpeterFree Software Foundation; either version 2, or (at your option) any 918334Speterlater version. 1018334Speter 1118334SpeterThis program is distributed in the hope that it will be useful, 1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1418334SpeterGNU General Public License for more details. 1518334Speter 1618334SpeterYou should have received a copy of the GNU General Public License 1718334Speteralong with this program; if not, write to the Free Software 1818334SpeterFoundation, 51 Franklin Street - Fifth Floor, 1918334SpeterBoston, MA 02110-1301, USA. */ 2018334Speter 2118334Speter#ifdef HAVE_CONFIG_H 2218334Speter#if defined (CONFIG_BROKETS) 2318334Speter/* We use <config.h> instead of "config.h" so that a compilation 2418334Speter using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h 2550397Sobrien (which it would do because it found this file in $srcdir). */ 2652284Sobrien#include <config.h> 2718334Speter#else 2818334Speter#include "config.h" 2918334Speter#endif 3018334Speter#endif 3118334Speter 3218334Speter 3318334Speter#ifndef _GNU_SOURCE 3418334Speter#define _GNU_SOURCE 3518334Speter#endif 3618334Speter 3718334Speter/* This code to undef const added in libiberty. */ 3818334Speter#ifndef __STDC__ 3952284Sobrien/* This is a separate conditional since some stdc systems 4018334Speter reject `defined (const)'. */ 4152284Sobrien#ifndef const 4252284Sobrien#define const 4350397Sobrien#endif 4452284Sobrien#endif 4552284Sobrien 4652284Sobrien#include <errno.h> 4718334Speter#include <fnmatch.h> 4852284Sobrien#include <safe-ctype.h> 4918334Speter 5052284Sobrien/* Comment out all this code if we are using the GNU C Library, and are not 5152284Sobrien actually compiling the library itself. This code is part of the GNU C 5252284Sobrien Library, but also included in many other GNU distributions. Compiling 5352284Sobrien and linking in this code is a waste when using the GNU C library 5452284Sobrien (especially if it is a shared library). Rather than having every GNU 5552284Sobrien program understand `configure --with-gnu-libc' and omit the object files, 5652284Sobrien it is simpler to just do this in the source for each such file. */ 5752284Sobrien 5818334Speter#if defined (_LIBC) || !defined (__GNU_LIBRARY__) 5952284Sobrien 6052284Sobrien 6152284Sobrien#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) 6252284Sobrienextern int errno; 6352284Sobrien#endif 6452284Sobrien 6552284Sobrien/* Match STRING against the filename pattern PATTERN, returning zero if 6652284Sobrien it matches, nonzero if not. */ 6718334Speterint 6852284Sobrienfnmatch (const char *pattern, const char *string, int flags) 6918334Speter{ 7052284Sobrien register const char *p = pattern, *n = string; 7152284Sobrien register unsigned char c; 7252284Sobrien 7352284Sobrien#define FOLD(c) ((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c)) 7418334Speter 7552284Sobrien while ((c = *p++) != '\0') 7652284Sobrien { 7718334Speter c = FOLD (c); 7852284Sobrien 7952284Sobrien switch (c) 8052284Sobrien { 8152284Sobrien case '?': 8252284Sobrien if (*n == '\0') 8318334Speter return FNM_NOMATCH; 8452284Sobrien else if ((flags & FNM_FILE_NAME) && *n == '/') 8552284Sobrien return FNM_NOMATCH; 8618334Speter else if ((flags & FNM_PERIOD) && *n == '.' && 8752284Sobrien (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 8852284Sobrien return FNM_NOMATCH; 8952284Sobrien break; 9052284Sobrien 9152284Sobrien case '\\': 9252284Sobrien if (!(flags & FNM_NOESCAPE)) 9352284Sobrien { 9452284Sobrien c = *p++; 9552284Sobrien c = FOLD (c); 9652284Sobrien } 9752284Sobrien if (FOLD ((unsigned char)*n) != c) 9852284Sobrien return FNM_NOMATCH; 9952284Sobrien break; 10052284Sobrien 10152284Sobrien case '*': 10252284Sobrien if ((flags & FNM_PERIOD) && *n == '.' && 10352284Sobrien (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 10452284Sobrien return FNM_NOMATCH; 10552284Sobrien 10618334Speter for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) 10752284Sobrien if (((flags & FNM_FILE_NAME) && *n == '/') || 10818334Speter (c == '?' && *n == '\0')) 10918334Speter return FNM_NOMATCH; 11018334Speter 11118334Speter if (c == '\0') 11218334Speter return 0; 11318334Speter 11418334Speter { 11518334Speter unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; 11618334Speter c1 = FOLD (c1); 11718334Speter for (--p; *n != '\0'; ++n) 11818334Speter if ((c == '[' || FOLD ((unsigned char)*n) == c1) && 11918334Speter fnmatch (p, n, flags & ~FNM_PERIOD) == 0) 12018334Speter return 0; 12118334Speter return FNM_NOMATCH; 12218334Speter } 12350397Sobrien 12452284Sobrien case '[': 12552284Sobrien { 12618334Speter /* Nonzero if the sense of the character class is inverted. */ 12752284Sobrien register int negate; 12818334Speter 12918334Speter if (*n == '\0') 13018334Speter return FNM_NOMATCH; 13118334Speter 13252284Sobrien if ((flags & FNM_PERIOD) && *n == '.' && 13352284Sobrien (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) 13418334Speter return FNM_NOMATCH; 13518334Speter 13618334Speter negate = (*p == '!' || *p == '^'); 13718334Speter if (negate) 13818334Speter ++p; 13918334Speter 14018334Speter c = *p++; 14118334Speter for (;;) 14218334Speter { 14318334Speter register unsigned char cstart = c, cend = c; 14418334Speter 14518334Speter if (!(flags & FNM_NOESCAPE) && c == '\\') 14618334Speter cstart = cend = *p++; 14718334Speter 14818334Speter cstart = cend = FOLD (cstart); 14918334Speter 15018334Speter if (c == '\0') 15118334Speter /* [ (unterminated) loses. */ 15218334Speter return FNM_NOMATCH; 15318334Speter 15418334Speter c = *p++; 15552284Sobrien c = FOLD (c); 15618334Speter 15718334Speter if ((flags & FNM_FILE_NAME) && c == '/') 15818334Speter /* [/] can never match. */ 15952284Sobrien return FNM_NOMATCH; 16018334Speter 16152284Sobrien if (c == '-' && *p != ']') 16218334Speter { 16318334Speter cend = *p++; 16418334Speter if (!(flags & FNM_NOESCAPE) && cend == '\\') 16518334Speter cend = *p++; 16618334Speter if (cend == '\0') 16718334Speter return FNM_NOMATCH; 16818334Speter cend = FOLD (cend); 16950397Sobrien 17018334Speter c = *p++; 17152284Sobrien } 17218334Speter 17318334Speter if (FOLD ((unsigned char)*n) >= cstart 17418334Speter && FOLD ((unsigned char)*n) <= cend) 17518334Speter goto matched; 17652284Sobrien 17718334Speter if (c == ']') 17818334Speter break; 17918334Speter } 18018334Speter if (!negate) 18118334Speter return FNM_NOMATCH; 18218334Speter break; 18318334Speter 18418334Speter matched:; 18552284Sobrien /* Skip the rest of the [...] that already matched. */ 18618334Speter while (c != ']') 18718334Speter { 18852284Sobrien if (c == '\0') 18918334Speter /* [... (unterminated) loses. */ 19018334Speter return FNM_NOMATCH; 19150397Sobrien 19250397Sobrien c = *p++; 19352284Sobrien if (!(flags & FNM_NOESCAPE) && c == '\\') 19452284Sobrien /* XXX 1003.2d11 is unclear if this is right. */ 19518334Speter ++p; 19618334Speter } 19718334Speter if (negate) 19818334Speter return FNM_NOMATCH; 19918334Speter } 20018334Speter break; 20118334Speter 20218334Speter default: 20318334Speter if (c != FOLD ((unsigned char)*n)) 20418334Speter return FNM_NOMATCH; 20518334Speter } 20618334Speter 20718334Speter ++n; 20818334Speter } 20918334Speter 21018334Speter if (*n == '\0') 21118334Speter return 0; 21218334Speter 21318334Speter if ((flags & FNM_LEADING_DIR) && *n == '/') 21418334Speter /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ 21518334Speter return 0; 21618334Speter 21718334Speter return FNM_NOMATCH; 21818334Speter} 21918334Speter 22018334Speter#endif /* _LIBC or not __GNU_LIBRARY__. */ 22118334Speter