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