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