1 /* Copyright (C) 1992 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 The GNU C 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 The GNU C 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 /* Modified slightly by Brian Berliner <berliner@sun.com> and 15 Jim Blandy <jimb@cyclic.com> for CVS use */ 16 17 #ifdef HAVE_CONFIG_H 18 #include "config.h" 19 #endif 20 21 #include "system.h" 22 23 /* IGNORE(@ */ 24 /* #include <ansidecl.h> */ 25 /* @) */ 26 #include <errno.h> 27 #include <fnmatch.h> 28 29 #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) 30 extern int errno; 31 #endif 32 33 /* Match STRING against the filename pattern PATTERN, returning zero if 34 it matches, nonzero if not. */ 35 int 36 #if __STDC__ 37 fnmatch (const char *pattern, const char *string, int flags) 38 #else 39 fnmatch (pattern, string, flags) 40 char *pattern; 41 char *string; 42 int flags; 43 #endif 44 { 45 register const char *p = pattern, *n = string; 46 register char c; 47 48 if ((flags & ~__FNM_FLAGS) != 0) 49 { 50 errno = EINVAL; 51 return -1; 52 } 53 54 while ((c = *p++) != '\0') 55 { 56 switch (c) 57 { 58 case '?': 59 if (*n == '\0') 60 return FNM_NOMATCH; 61 else if ((flags & FNM_PATHNAME) && *n == '/') 62 return FNM_NOMATCH; 63 else if ((flags & FNM_PERIOD) && *n == '.' && 64 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 65 return FNM_NOMATCH; 66 break; 67 68 case '\\': 69 if (!(flags & FNM_NOESCAPE)) 70 c = *p++; 71 if (FOLD_FN_CHAR (*n) != FOLD_FN_CHAR (c)) 72 return FNM_NOMATCH; 73 break; 74 75 case '*': 76 if ((flags & FNM_PERIOD) && *n == '.' && 77 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 78 return FNM_NOMATCH; 79 80 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) 81 if (((flags & FNM_PATHNAME) && *n == '/') || 82 (c == '?' && *n == '\0')) 83 return FNM_NOMATCH; 84 85 if (c == '\0') 86 return 0; 87 88 { 89 char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; 90 for (--p; *n != '\0'; ++n) 91 if ((c == '[' || FOLD_FN_CHAR (*n) == FOLD_FN_CHAR (c1)) && 92 fnmatch(p, n, flags & ~FNM_PERIOD) == 0) 93 return 0; 94 return FNM_NOMATCH; 95 } 96 97 case '[': 98 { 99 /* Nonzero if the sense of the character class is inverted. */ 100 register int not; 101 102 if (*n == '\0') 103 return FNM_NOMATCH; 104 105 if ((flags & FNM_PERIOD) && *n == '.' && 106 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 107 return FNM_NOMATCH; 108 109 not = (*p == '!' || *p == '^'); 110 if (not) 111 ++p; 112 113 c = *p++; 114 for (;;) 115 { 116 register char cstart = c, cend = c; 117 118 if (!(flags & FNM_NOESCAPE) && c == '\\') 119 cstart = cend = *p++; 120 121 if (c == '\0') 122 /* [ (unterminated) loses. */ 123 return FNM_NOMATCH; 124 125 c = *p++; 126 127 if ((flags & FNM_PATHNAME) && c == '/') 128 /* [/] can never match. */ 129 return FNM_NOMATCH; 130 131 if (c == '-' && *p != ']') 132 { 133 cend = *p++; 134 if (!(flags & FNM_NOESCAPE) && cend == '\\') 135 cend = *p++; 136 if (cend == '\0') 137 return FNM_NOMATCH; 138 c = *p++; 139 } 140 141 if (*n >= cstart && *n <= cend) 142 goto matched; 143 144 if (c == ']') 145 break; 146 } 147 if (!not) 148 return FNM_NOMATCH; 149 break; 150 151 matched:; 152 /* Skip the rest of the [...] that already matched. */ 153 while (c != ']') 154 { 155 if (c == '\0') 156 /* [... (unterminated) loses. */ 157 return FNM_NOMATCH; 158 159 c = *p++; 160 if (!(flags & FNM_NOESCAPE) && c == '\\') 161 /* 1003.2d11 is unclear if this is right. %%% */ 162 ++p; 163 } 164 if (not) 165 return FNM_NOMATCH; 166 } 167 break; 168 169 default: 170 if (FOLD_FN_CHAR (c) != FOLD_FN_CHAR (*n)) 171 return FNM_NOMATCH; 172 } 173 174 ++n; 175 } 176 177 if (*n == '\0') 178 return 0; 179 180 return FNM_NOMATCH; 181 } 182