1/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public License as 6 published by the Free Software Foundation; either version 2 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public 15 License along with this library; see the file COPYING.LIB. If not, 16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 Boston, MA 02111-1307, USA. */ 18 19#if HAVE_CONFIG_H 20# include <config.h> 21#endif 22 23/* Enable GNU extensions in fnmatch.h. */ 24#ifndef _GNU_SOURCE 25# define _GNU_SOURCE 1 26#endif 27 28#include <errno.h> 29#include <fnmatch.h> 30#include <ctype.h> 31 32#if HAVE_STRING_H || defined _LIBC 33# include <string.h> 34#else 35# include <strings.h> 36#endif 37 38#if defined STDC_HEADERS || defined _LIBC 39# include <stdlib.h> 40#endif 41 42/* For platforms which support the ISO C amendment 1 functionality we 43 support user defined character classes. */ 44#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) 45/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ 46# include <wchar.h> 47# include <wctype.h> 48#endif 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 NO_FNMATCH || defined NO_FNMATCH_CASEFOLD || \ 59 defined _LIBC || !defined __GNU_LIBRARY__ 60 61 62# if defined STDC_HEADERS || !defined isascii 63# define ISASCII(c) 1 64# else 65# define ISASCII(c) isascii(c) 66# endif 67 68# ifdef isblank 69# define ISBLANK(c) (ISASCII (c) && isblank (c)) 70# else 71# define ISBLANK(c) ((c) ==' ' || (c) =='\t') 72# endif 73# ifdef isgraph 74# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) 75# else 76# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) 77# endif 78 79# define ISPRINT(c) (ISASCII (c) && isprint (c)) 80# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) 81# define ISALNUM(c) (ISASCII (c) && isalnum (c)) 82# define ISALPHA(c) (ISASCII (c) && isalpha (c)) 83# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) 84# define ISLOWER(c) (ISASCII (c) && islower (c)) 85# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) 86# define ISSPACE(c) (ISASCII (c) && isspace (c)) 87# define ISUPPER(c) (ISASCII (c) && isupper (c)) 88# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) 89 90# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) 91 92# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) 93/* The GNU C library provides support for user-defined character classes 94 and the functions from ISO C amendment 1. */ 95# ifdef CHARCLASS_NAME_MAX 96# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX 97# else 98/* This shouldn't happen but some implementation might still have this 99 problem. Use a reasonable default value. */ 100# define CHAR_CLASS_MAX_LENGTH 256 101# endif 102 103# ifdef _LIBC 104# define IS_CHAR_CLASS(string) __wctype (string) 105# else 106# define IS_CHAR_CLASS(string) wctype (string) 107# endif 108# else 109# define CHAR_CLASS_MAX_LENGTH 6/* Namely, `xdigit'. */ 110 111# define IS_CHAR_CLASS(string) \ 112 (STREQ (string,"alpha") || STREQ (string,"upper") \ 113 || STREQ (string,"lower") || STREQ (string,"digit") \ 114 || STREQ (string,"alnum") || STREQ (string,"xdigit") \ 115 || STREQ (string,"space") || STREQ (string,"print") \ 116 || STREQ (string,"punct") || STREQ (string,"graph") \ 117 || STREQ (string,"cntrl") || STREQ (string,"blank")) 118# endif 119 120/* Avoid depending on library functions or files 121 whose names are inconsistent. */ 122 123# if !defined _LIBC && !defined getenv 124externchar*getenv(); 125# endif 126 127# ifndef errno 128externint errno; 129# endif 130 131# ifndef NULL 132# define NULL 0 133# endif 134 135/* This function doesn't exist on most systems. */ 136 137# if !defined HAVE___STRCHRNUL && !defined _LIBC 138static char* 139__strchrnul(const char*s,int c) 140 141 142{ 143char*result =strchr(s, c); 144if(result == NULL) 145 result =strchr(s,'\0'); 146return result; 147} 148# endif 149 150# ifndef internal_function 151/* Inside GNU libc we mark some function in a special way. In other 152 environments simply ignore the marking. */ 153# define internal_function 154# endif 155 156/* Match STRING against the filename pattern PATTERN, returning zero if 157 it matches, nonzero if not. */ 158static int internal_fnmatch __P((const char*pattern,const char*string, 159int no_leading_period,int flags)) 160 internal_function; 161static int 162internal_function 163internal_fnmatch(const char*pattern,const char*string,int no_leading_period,int flags) 164 165 166 167 168{ 169registerconst char*p = pattern, *n = string; 170registerunsigned char c; 171 172/* Note that this evaluates C many times. */ 173# ifdef _LIBC 174# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) 175# else 176# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) 177# endif 178 179while((c = *p++) !='\0') 180{ 181 c =FOLD(c); 182 183switch(c) 184{ 185case'?': 186if(*n =='\0') 187return FNM_NOMATCH; 188else if(*n =='/'&& (flags & FNM_FILE_NAME)) 189return FNM_NOMATCH; 190else if(*n =='.'&& no_leading_period 191&& (n == string 192|| (n[-1] =='/'&& (flags & FNM_FILE_NAME)))) 193return FNM_NOMATCH; 194break; 195 196case'\\': 197if(!(flags & FNM_NOESCAPE)) 198{ 199 c = *p++; 200if(c =='\0') 201/* Trailing \ loses. */ 202return FNM_NOMATCH; 203 c =FOLD(c); 204} 205if(FOLD((unsigned char) *n) != c) 206return FNM_NOMATCH; 207break; 208 209case'*': 210if(*n =='.'&& no_leading_period 211&& (n == string 212|| (n[-1] =='/'&& (flags & FNM_FILE_NAME)))) 213return FNM_NOMATCH; 214 215for(c = *p++; c =='?'|| c =='*'; c = *p++) 216{ 217if(*n =='/'&& (flags & FNM_FILE_NAME)) 218/* A slash does not match a wildcard under FNM_FILE_NAME. */ 219return FNM_NOMATCH; 220else if(c =='?') 221{ 222/* A ? needs to match one character. */ 223if(*n =='\0') 224/* There isn't another character; no match. */ 225return FNM_NOMATCH; 226else 227/* One character of the string is consumed in matching 228 this ? wildcard, so *??? won't match if there are 229 less than three characters. */ 230++n; 231} 232} 233 234if(c =='\0') 235/* The wildcard(s) is/are the last element of the pattern. 236 If the name is a file name and contains another slash 237 this does mean it cannot match. */ 238return((flags & FNM_FILE_NAME) &&strchr(n,'/') != NULL 239? FNM_NOMATCH :0); 240else 241{ 242const char*endp; 243 244 endp =__strchrnul(n, (flags & FNM_FILE_NAME) ?'/':'\0'); 245 246if(c =='[') 247{ 248int flags2 = ((flags & FNM_FILE_NAME) 249? flags : (flags & ~FNM_PERIOD)); 250 251for(--p; n < endp; ++n) 252if(internal_fnmatch(p, n, 253(no_leading_period 254&& (n == string 255|| (n[-1] =='/' 256&& (flags 257& FNM_FILE_NAME)))), 258 flags2) 259==0) 260return0; 261} 262else if(c =='/'&& (flags & FNM_FILE_NAME)) 263{ 264while(*n !='\0'&& *n !='/') 265++n; 266if(*n =='/' 267&& (internal_fnmatch(p, n +1, flags & FNM_PERIOD, 268 flags) ==0)) 269return0; 270} 271else 272{ 273int flags2 = ((flags & FNM_FILE_NAME) 274? flags : (flags & ~FNM_PERIOD)); 275 276if(c =='\\'&& !(flags & FNM_NOESCAPE)) 277 c = *p; 278 c =FOLD(c); 279for(--p; n < endp; ++n) 280if(FOLD((unsigned char) *n) == c 281&& (internal_fnmatch(p, n, 282(no_leading_period 283&& (n == string 284|| (n[-1] =='/' 285&& (flags 286& FNM_FILE_NAME)))), 287 flags2) ==0)) 288return0; 289} 290} 291 292/* If we come here no match is possible with the wildcard. */ 293return FNM_NOMATCH; 294 295case'[': 296{ 297/* Nonzero if the sense of the character class is inverted. */ 298static int posixly_correct; 299registerintnot; 300char cold; 301 302if(posixly_correct ==0) 303 posixly_correct =getenv("POSIXLY_CORRECT") != NULL ?1: -1; 304 305if(*n =='\0') 306return FNM_NOMATCH; 307 308if(*n =='.'&& no_leading_period && (n == string 309|| (n[-1] =='/' 310&& (flags 311& FNM_FILE_NAME)))) 312return FNM_NOMATCH; 313 314if(*n =='/'&& (flags & FNM_FILE_NAME)) 315/* `/' cannot be matched. */ 316return FNM_NOMATCH; 317 318not= (*p =='!'|| (posixly_correct <0&& *p =='^')); 319if(not) 320++p; 321 322 c = *p++; 323for(;;) 324{ 325unsigned char fn =FOLD((unsigned char) *n); 326 327if(!(flags & FNM_NOESCAPE) && c =='\\') 328{ 329if(*p =='\0') 330return FNM_NOMATCH; 331 c =FOLD((unsigned char) *p); 332++p; 333 334if(c == fn) 335goto matched; 336} 337else if(c =='['&& *p ==':') 338{ 339/* Leave room for the null. */ 340char str[CHAR_CLASS_MAX_LENGTH +1]; 341size_t c1 =0; 342# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) 343wctype_t wt; 344# endif 345const char*startp = p; 346 347for(;;) 348{ 349if(c1 > CHAR_CLASS_MAX_LENGTH) 350/* The name is too long and therefore the pattern 351 is ill-formed. */ 352return FNM_NOMATCH; 353 354 c = *++p; 355if(c ==':'&& p[1] ==']') 356{ 357 p +=2; 358break; 359} 360if(c <'a'|| c >='z') 361{ 362/* This cannot possibly be a character class name. 363 Match it as a normal range. */ 364 p = startp; 365 c ='['; 366goto normal_bracket; 367} 368 str[c1++] = c; 369} 370 str[c1] ='\0'; 371 372# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) 373 wt =IS_CHAR_CLASS(str); 374if(wt ==0) 375/* Invalid character class name. */ 376return FNM_NOMATCH; 377 378if(__iswctype(__btowc((unsigned char) *n), wt)) 379goto matched; 380# else 381if((STREQ(str,"alnum") &&ISALNUM((unsigned char) *n)) 382|| (STREQ(str,"alpha") &&ISALPHA((unsigned char) *n)) 383|| (STREQ(str,"blank") &&ISBLANK((unsigned char) *n)) 384|| (STREQ(str,"cntrl") &&ISCNTRL((unsigned char) *n)) 385|| (STREQ(str,"digit") &&ISDIGIT((unsigned char) *n)) 386|| (STREQ(str,"graph") &&ISGRAPH((unsigned char) *n)) 387|| (STREQ(str,"lower") &&ISLOWER((unsigned char) *n)) 388|| (STREQ(str,"print") &&ISPRINT((unsigned char) *n)) 389|| (STREQ(str,"punct") &&ISPUNCT((unsigned char) *n)) 390|| (STREQ(str,"space") &&ISSPACE((unsigned char) *n)) 391|| (STREQ(str,"upper") &&ISUPPER((unsigned char) *n)) 392|| (STREQ(str,"xdigit") &&ISXDIGIT((unsigned char) *n))) 393goto matched; 394# endif 395} 396else if(c =='\0') 397/* [ (unterminated) loses. */ 398return FNM_NOMATCH; 399else 400{ 401 normal_bracket: 402if(FOLD(c) == fn) 403goto matched; 404 405 cold = c; 406 c = *p++; 407 408if(c =='-'&& *p !=']') 409{ 410/* It is a range. */ 411unsigned char cend = *p++; 412if(!(flags & FNM_NOESCAPE) && cend =='\\') 413 cend = *p++; 414if(cend =='\0') 415return FNM_NOMATCH; 416 417if(cold <= fn && fn <=FOLD(cend)) 418goto matched; 419 420 c = *p++; 421} 422} 423 424if(c ==']') 425break; 426} 427 428if(!not) 429return FNM_NOMATCH; 430break; 431 432 matched: 433/* Skip the rest of the [...] that already matched. */ 434while(c !=']') 435{ 436if(c =='\0') 437/* [... (unterminated) loses. */ 438return FNM_NOMATCH; 439 440 c = *p++; 441if(!(flags & FNM_NOESCAPE) && c =='\\') 442{ 443if(*p =='\0') 444return FNM_NOMATCH; 445/* XXX 1003.2d11 is unclear if this is right. */ 446++p; 447} 448else if(c =='['&& *p ==':') 449{ 450do 451if(*++p =='\0') 452return FNM_NOMATCH; 453while(*p !=':'|| p[1] ==']'); 454 p +=2; 455 c = *p; 456} 457} 458if(not) 459return FNM_NOMATCH; 460} 461break; 462 463default: 464if(c !=FOLD((unsigned char) *n)) 465return FNM_NOMATCH; 466} 467 468++n; 469} 470 471if(*n =='\0') 472return0; 473 474if((flags & FNM_LEADING_DIR) && *n =='/') 475/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ 476return0; 477 478return FNM_NOMATCH; 479 480# undef FOLD 481} 482 483 484int 485fnmatch(const char*pattern,const char*string,int flags) 486 487 488 489{ 490returninternal_fnmatch(pattern, string, flags & FNM_PERIOD, flags); 491} 492 493#endif/* _LIBC or not __GNU_LIBRARY__. */