fnmatch.cc File Reference

#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 Documentation

#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().


Function Documentation

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 }

g4beamline