#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <fnmatch.h>
Defines | |
#define | EOS '\0' |
#define | RANGE_MATCH 1 |
#define | RANGE_NOMATCH 0 |
#define | RANGE_ERROR (-1) |
Functions | |
static int | rangematch (const char *, char, int, char **) |
int | fnmatch (const char *pattern, const char *string, int flags) |
#define EOS '\0' |
Referenced by fnmatch(), and rangematch().
#define RANGE_MATCH 1 |
Referenced by fnmatch(), and rangematch().
#define RANGE_NOMATCH 0 |
Referenced by fnmatch(), and rangematch().
#define RANGE_ERROR (-1) |
Referenced by fnmatch(), and rangematch().
static int rangematch | ( | const char * | pattern, | |
char | test, | |||
int | flags, | |||
char ** | newp | |||
) | [static] |
References EOS, RANGE_ERROR, RANGE_MATCH, and RANGE_NOMATCH.
Referenced by fnmatch().
00167 { 00168 int negate, ok; 00169 char c, c2; 00170 00171 /* 00172 * A bracket expression starting with an unquoted circumflex 00173 * character produces unspecified results (IEEE 1003.2-1992, 00174 * 3.13.2). This implementation treats it like '!', for 00175 * consistency with the regular expression syntax. 00176 * J.T. Conklin (conklin@ngai.kaleida.com) 00177 */ 00178 if ((negate = (*pattern == '!' || *pattern == '^'))) 00179 ++pattern; 00180 00181 if (flags & FNM_CASEFOLD) 00182 test = tolower((unsigned char)test); 00183 00184 /* 00185 * A right bracket shall lose its special meaning and represent 00186 * itself in a bracket expression if it occurs first in the list. 00187 * -- POSIX.2 2.8.3.2 00188 */ 00189 ok = 0; 00190 c = *pattern++; 00191 do { 00192 if (c == '\\' && !(flags & FNM_NOESCAPE)) 00193 c = *pattern++; 00194 if (c == EOS) 00195 return (RANGE_ERROR); 00196 if (c == '/' && (flags & FNM_PATHNAME)) 00197 return (RANGE_NOMATCH); 00198 if ((flags & FNM_CASEFOLD)) 00199 c = tolower((unsigned char)c); 00200 if (*pattern == '-' 00201 && (c2 = *(pattern+1)) != EOS && c2 != ']') { 00202 pattern += 2; 00203 if (c2 == '\\' && !(flags & FNM_NOESCAPE)) 00204 c2 = *pattern++; 00205 if (c2 == EOS) 00206 return (RANGE_ERROR); 00207 if (flags & FNM_CASEFOLD) 00208 c2 = tolower((unsigned char)c2); 00209 if (c <= test && test <= c2) 00210 ok = 1; 00211 } else if (c == test) 00212 ok = 1; 00213 } while ((c = *pattern++) != ']'); 00214 00215 *newp = (char *)pattern; 00216 return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); 00217 }
int fnmatch | ( | const char * | pattern, | |
const char * | string, | |||
int | flags | |||
) |
References EOS, RANGE_ERROR, RANGE_MATCH, RANGE_NOMATCH, and rangematch().
Referenced by BLCMDtotalenergy::isMatch(), BLCMDntuple::matches(), and BLCommand::matchList().
00067 { 00068 const char *stringstart; 00069 char *newp; 00070 char c, test; 00071 00072 for (stringstart = string;;) 00073 switch (c = *pattern++) { 00074 case EOS: 00075 if ((flags & FNM_LEADING_DIR) && *string == '/') 00076 return (0); 00077 return (*string == EOS ? 0 : FNM_NOMATCH); 00078 case '?': 00079 if (*string == EOS) 00080 return (FNM_NOMATCH); 00081 if (*string == '/' && (flags & FNM_PATHNAME)) 00082 return (FNM_NOMATCH); 00083 if (*string == '.' && (flags & FNM_PERIOD) && 00084 (string == stringstart || 00085 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) 00086 return (FNM_NOMATCH); 00087 ++string; 00088 break; 00089 case '*': 00090 c = *pattern; 00091 /* Collapse multiple stars. */ 00092 while (c == '*') 00093 c = *++pattern; 00094 00095 if (*string == '.' && (flags & FNM_PERIOD) && 00096 (string == stringstart || 00097 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) 00098 return (FNM_NOMATCH); 00099 00100 /* Optimize for pattern with * at end or before /. */ 00101 if (c == EOS) { 00102 if (flags & FNM_PATHNAME) 00103 return ((flags & FNM_LEADING_DIR) || 00104 strchr(string, '/') == NULL ? 00105 0 : FNM_NOMATCH); 00106 else 00107 return (0); 00108 } else if (c == '/' && (flags & FNM_PATHNAME)) { 00109 if ((string = strchr(string, '/')) == NULL) 00110 return (FNM_NOMATCH); 00111 break; 00112 } 00113 00114 /* General case, use recursion. */ 00115 while ((test = *string) != EOS) { 00116 if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) 00117 return (0); 00118 if (test == '/' && (flags & FNM_PATHNAME)) 00119 break; 00120 ++string; 00121 } 00122 return (FNM_NOMATCH); 00123 case '[': 00124 if (*string == EOS) 00125 return (FNM_NOMATCH); 00126 if (*string == '/' && (flags & FNM_PATHNAME)) 00127 return (FNM_NOMATCH); 00128 if (*string == '.' && (flags & FNM_PERIOD) && 00129 (string == stringstart || 00130 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) 00131 return (FNM_NOMATCH); 00132 00133 switch (rangematch(pattern, *string, flags, &newp)) { 00134 case RANGE_ERROR: 00135 /* not a good range, treat as normal text */ 00136 goto normal; 00137 case RANGE_MATCH: 00138 pattern = newp; 00139 break; 00140 case RANGE_NOMATCH: 00141 return (FNM_NOMATCH); 00142 } 00143 ++string; 00144 break; 00145 case '\\': 00146 if (!(flags & FNM_NOESCAPE)) { 00147 if ((c = *pattern++) == EOS) { 00148 c = '\\'; 00149 --pattern; 00150 } 00151 } 00152 /* FALLTHROUGH */ 00153 default: 00154 normal: 00155 if (c != *string && !((flags & FNM_CASEFOLD) && 00156 (tolower((unsigned char)c) == 00157 tolower((unsigned char)*string)))) 00158 return (FNM_NOMATCH); 00159 ++string; 00160 break; 00161 } 00162 /* NOTREACHED */ 00163 }