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