Back to index

php5  5.3.10
Defines | Functions
fnmatch.c File Reference
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include "fnmatch.h"

Go to the source code of this file.

Defines

#define EOS   '\0'

Functions

static const char * rangematch (const char *, char, int)
PHPAPI int fnmatch (const char *pattern, const char *string, int flags)

Define Documentation

#define EOS   '\0'

Definition at line 55 of file fnmatch.c.


Function Documentation

PHPAPI int fnmatch ( const char *  pattern,
const char *  string,
int  flags 
)

Definition at line 59 of file fnmatch.c.

{
       const char *stringstart;
       char c, test;

       for (stringstart = string;;)
              switch (c = *pattern++) {
              case EOS:
                     if ((flags & FNM_LEADING_DIR) && *string == '/')
                            return (0);
                     return (*string == EOS ? 0 : FNM_NOMATCH);
              case '?':
                     if (*string == EOS)
                            return (FNM_NOMATCH);
                     if (*string == '/' && (flags & FNM_PATHNAME))
                            return (FNM_NOMATCH);
                     if (*string == '.' && (flags & FNM_PERIOD) &&
                         (string == stringstart ||
                         ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
                            return (FNM_NOMATCH);
                     ++string;
                     break;
              case '*':
                     c = *pattern;
                     /* Collapse multiple stars. */
                     while (c == '*')
                            c = *++pattern;

                     if (*string == '.' && (flags & FNM_PERIOD) &&
                         (string == stringstart ||
                         ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
                            return (FNM_NOMATCH);

                     /* Optimize for pattern with * at end or before /. */
                     if (c == EOS)
                            if (flags & FNM_PATHNAME)
                                   return ((flags & FNM_LEADING_DIR) ||
                                       strchr(string, '/') == NULL ?
                                       0 : FNM_NOMATCH);
                            else
                                   return (0);
                     else if (c == '/' && flags & FNM_PATHNAME) {
                            if ((string = strchr(string, '/')) == NULL)
                                   return (FNM_NOMATCH);
                            break;
                     }

                     /* General case, use recursion. */
                     while ((test = *string) != EOS) {
                            if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
                                   return (0);
                            if (test == '/' && flags & FNM_PATHNAME)
                                   break;
                            ++string;
                     }
                     return (FNM_NOMATCH);
              case '[':
                     if (*string == EOS)
                            return (FNM_NOMATCH);
                     if (*string == '/' && flags & FNM_PATHNAME)
                            return (FNM_NOMATCH);
                     if ((pattern =
                         rangematch(pattern, *string, flags)) == NULL)
                            return (FNM_NOMATCH);
                     ++string;
                     break;
              case '\\':
                     if (!(flags & FNM_NOESCAPE)) {
                            if ((c = *pattern++) == EOS) {
                                   c = '\\';
                                   --pattern;
                            }
                     }
                     /* FALLTHROUGH */
              default:
                     if (c == *string)
                            ;
                     else if ((flags & FNM_CASEFOLD) &&
                             (tolower((unsigned char)c) ==
                              tolower((unsigned char)*string)))
                            ;
                     else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
                          (c == '/' && string != stringstart ||
                          string == stringstart+1 && *stringstart == '/') )
                            return (0);
                     else
                            return (FNM_NOMATCH);
                     string++;
                     break;
              }
       /* NOTREACHED */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char * rangematch ( const char *  pattern,
char  test,
int  flags 
) [static]

Definition at line 153 of file fnmatch.c.

{
       int negate, ok;
       char c, c2;

       /*
        * A bracket expression starting with an unquoted circumflex
        * character produces unspecified results (IEEE 1003.2-1992,
        * 3.13.2).  This implementation treats it like '!', for
        * consistency with the regular expression syntax.
        * J.T. Conklin (conklin@ngai.kaleida.com)
        */
       if ( (negate = (*pattern == '!' || *pattern == '^')) )
              ++pattern;

       if (flags & FNM_CASEFOLD)
              test = tolower((unsigned char)test);

       for (ok = 0; (c = *pattern++) != ']';) {
              if (c == '\\' && !(flags & FNM_NOESCAPE))
                     c = *pattern++;
              if (c == EOS)
                     return (NULL);

              if (flags & FNM_CASEFOLD)
                     c = tolower((unsigned char)c);

              if (*pattern == '-'
                  && (c2 = *(pattern+1)) != EOS && c2 != ']') {
                     pattern += 2;
                     if (c2 == '\\' && !(flags & FNM_NOESCAPE))
                            c2 = *pattern++;
                     if (c2 == EOS)
                            return (NULL);

                     if (flags & FNM_CASEFOLD)
                            c2 = tolower((unsigned char)c2);

                     if ((unsigned char)c <= (unsigned char)test &&
                         (unsigned char)test <= (unsigned char)c2)
                            ok = 1;
              } else if (c == test)
                     ok = 1;
       }
       return (ok == negate ? NULL : pattern);
}

Here is the caller graph for this function: