Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

nanomud-fnmatch.c File Reference

#include <errno.h>
#include "fnmatch.h"
#include <ctype.h>
#include <strings.h>

Include dependency graph for nanomud-fnmatch.c:

Include dependency graph

Go to the source code of this file.

Defines

#define _GNU_SOURCE   1
#define CHAR_CLASS_MAX_LENGTH   6
#define FOLD(c)   ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
#define IS_CHAR_CLASS(string)
#define ISALNUM(c)   (ISASCII (c) && isalnum (c))
#define ISALPHA(c)   (ISASCII (c) && isalpha (c))
#define ISASCII(c)   1
#define ISBLANK(c)   ((c) == ' ' || (c) == '\t')
#define ISCNTRL(c)   (ISASCII (c) && iscntrl (c))
#define ISDIGIT(c)   (ISASCII (c) && isdigit (c))
#define ISGRAPH(c)   (ISASCII (c) && isprint (c) && !isspace (c))
#define ISLOWER(c)   (ISASCII (c) && islower (c))
#define ISPRINT(c)   (ISASCII (c) && isprint (c))
#define ISPUNCT(c)   (ISASCII (c) && ispunct (c))
#define ISSPACE(c)   (ISASCII (c) && isspace (c))
#define ISUPPER(c)   (ISASCII (c) && isupper (c))
#define ISXDIGIT(c)   (ISASCII (c) && isxdigit (c))
#define STREQ(s1, s2)   ((strcmp (s1, s2) == 0))

Functions

int internal_fnmatch __P ((const char *pattern, const char *string, int no_leading_period, int flags))
char * __strchrnul (const char *s, int c)
int fnmatch (char *pattern, const char *string, int flags) const
char * getenv (const char *name)

Variables

int errno


Define Documentation

#define _GNU_SOURCE   1
 

Definition at line 26 of file nanomud-fnmatch.c.

#define CHAR_CLASS_MAX_LENGTH   6
 

Definition at line 109 of file nanomud-fnmatch.c.

Referenced by __P().

#define FOLD  )     ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
 

Referenced by __P().

#define IS_CHAR_CLASS string   ) 
 

Value:

(STREQ (string, "alpha") || STREQ (string, "upper")               \
    || STREQ (string, "lower") || STREQ (string, "digit")             \
    || STREQ (string, "alnum") || STREQ (string, "xdigit")            \
    || STREQ (string, "space") || STREQ (string, "print")             \
    || STREQ (string, "punct") || STREQ (string, "graph")             \
    || STREQ (string, "cntrl") || STREQ (string, "blank"))

Definition at line 111 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISALNUM  )     (ISASCII (c) && isalnum (c))
 

Definition at line 81 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISALPHA  )     (ISASCII (c) && isalpha (c))
 

Definition at line 82 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISASCII  )     1
 

Definition at line 63 of file nanomud-fnmatch.c.

#define ISBLANK  )     ((c) == ' ' || (c) == '\t')
 

Definition at line 71 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISCNTRL  )     (ISASCII (c) && iscntrl (c))
 

Definition at line 83 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISDIGIT  )     (ISASCII (c) && isdigit (c))
 

Definition at line 80 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISGRAPH  )     (ISASCII (c) && isprint (c) && !isspace (c))
 

Definition at line 76 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISLOWER  )     (ISASCII (c) && islower (c))
 

Definition at line 84 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISPRINT  )     (ISASCII (c) && isprint (c))
 

Definition at line 79 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISPUNCT  )     (ISASCII (c) && ispunct (c))
 

Definition at line 85 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISSPACE  )     (ISASCII (c) && isspace (c))
 

Definition at line 86 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISUPPER  )     (ISASCII (c) && isupper (c))
 

Definition at line 87 of file nanomud-fnmatch.c.

Referenced by __P().

#define ISXDIGIT  )     (ISASCII (c) && isxdigit (c))
 

Definition at line 88 of file nanomud-fnmatch.c.

Referenced by __P().

#define STREQ s1,
s2   )     ((strcmp (s1, s2) == 0))
 

Definition at line 90 of file nanomud-fnmatch.c.

Referenced by __P().


Function Documentation

int internal_fnmatch __P (const char *pattern, const char *string,int no_leading_period, int flags)   )  [static]
 

Definition at line 152 of file nanomud-fnmatch.c.

References __strchrnul(), CHAR_CLASS_MAX_LENGTH, FNM_FILE_NAME, FNM_NOMATCH, FNM_PERIOD, FOLD, getenv(), IS_CHAR_CLASS, ISALNUM, ISALPHA, ISBLANK, ISCNTRL, ISDIGIT, ISGRAPH, ISLOWER, ISPRINT, ISPUNCT, ISSPACE, ISUPPER, ISXDIGIT, and STREQ.

00162 {
00163   register const char *p = pattern, *n = string;
00164   register unsigned char c;
00165 
00166 /* Note that this evaluates C many times.  */
00167 # ifdef _LIBC
00168 #  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
00169 # else
00170 #  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
00171 # endif
00172 
00173   while ((c = *p++) != '\0')
00174     {
00175       c = FOLD (c);
00176 
00177       switch (c)
00178     {
00179     case '?':
00180       if (*n == '\0')
00181         return FNM_NOMATCH;
00182       else if (*n == '/' && (flags & FNM_FILE_NAME))
00183         return FNM_NOMATCH;
00184       else if (*n == '.' && no_leading_period
00185            && (n == string
00186                || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
00187         return FNM_NOMATCH;
00188       break;
00189 
00190     case '\\':
00191       if (!(flags & FNM_NOESCAPE))
00192         {
00193           c = *p++;
00194           if (c == '\0')
00195         /* Trailing \ loses.  */
00196         return FNM_NOMATCH;
00197           c = FOLD (c);
00198         }
00199       if (FOLD ((unsigned char) *n) != c)
00200         return FNM_NOMATCH;
00201       break;
00202 
00203     case '*':
00204       if (*n == '.' && no_leading_period
00205           && (n == string
00206           || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
00207         return FNM_NOMATCH;
00208 
00209       for (c = *p++; c == '?' || c == '*'; c = *p++)
00210         {
00211           if (*n == '/' && (flags & FNM_FILE_NAME))
00212         /* A slash does not match a wildcard under FNM_FILE_NAME.  */
00213         return FNM_NOMATCH;
00214           else if (c == '?')
00215         {
00216           /* A ? needs to match one character.  */
00217           if (*n == '\0')
00218             /* There isn't another character; no match.  */
00219             return FNM_NOMATCH;
00220           else
00221             /* One character of the string is consumed in matching
00222                this ? wildcard, so *??? won't match if there are
00223                less than three characters.  */
00224             ++n;
00225         }
00226         }
00227 
00228       if (c == '\0')
00229         /* The wildcard(s) is/are the last element of the pattern.
00230            If the name is a file name and contains another slash
00231            this does mean it cannot match.  */
00232         return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
00233             ? FNM_NOMATCH : 0);
00234       else
00235         {
00236           const char *endp;
00237 
00238           endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
00239 
00240           if (c == '[')
00241         {
00242           int flags2 = ((flags & FNM_FILE_NAME)
00243                 ? flags : (flags & ~FNM_PERIOD));
00244 
00245           for (--p; n < endp; ++n)
00246             if (internal_fnmatch (p, n,
00247                       (no_leading_period
00248                        && (n == string
00249                            || (n[-1] == '/'
00250                            && (flags
00251                                & FNM_FILE_NAME)))),
00252                       flags2)
00253             == 0)
00254               return 0;
00255         }
00256           else if (c == '/' && (flags & FNM_FILE_NAME))
00257         {
00258           while (*n != '\0' && *n != '/')
00259             ++n;
00260           if (*n == '/'
00261               && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
00262                         flags) == 0))
00263             return 0;
00264         }
00265           else
00266         {
00267           int flags2 = ((flags & FNM_FILE_NAME)
00268                 ? flags : (flags & ~FNM_PERIOD));
00269 
00270           if (c == '\\' && !(flags & FNM_NOESCAPE))
00271             c = *p;
00272           c = FOLD (c);
00273           for (--p; n < endp; ++n)
00274             if (FOLD ((unsigned char) *n) == c
00275             && (internal_fnmatch (p, n,
00276                           (no_leading_period
00277                            && (n == string
00278                            || (n[-1] == '/'
00279                                && (flags
00280                                & FNM_FILE_NAME)))),
00281                           flags2) == 0))
00282               return 0;
00283         }
00284         }
00285 
00286       /* If we come here no match is possible with the wildcard.  */
00287       return FNM_NOMATCH;
00288 
00289     case '[':
00290       {
00291         /* Nonzero if the sense of the character class is inverted.  */
00292         static int posixly_correct;
00293         register int not;
00294         char cold;
00295 
00296         if (posixly_correct == 0)
00297           posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
00298 
00299         if (*n == '\0')
00300           return FNM_NOMATCH;
00301 
00302         if (*n == '.' && no_leading_period && (n == string
00303                            || (n[-1] == '/'
00304                                && (flags
00305                                & FNM_FILE_NAME))))
00306           return FNM_NOMATCH;
00307 
00308         if (*n == '/' && (flags & FNM_FILE_NAME))
00309           /* `/' cannot be matched.  */
00310           return FNM_NOMATCH;
00311 
00312         not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
00313         if (not)
00314           ++p;
00315 
00316         c = *p++;
00317         for (;;)
00318           {
00319         unsigned char fn = FOLD ((unsigned char) *n);
00320 
00321         if (!(flags & FNM_NOESCAPE) && c == '\\')
00322           {
00323             if (*p == '\0')
00324               return FNM_NOMATCH;
00325             c = FOLD ((unsigned char) *p);
00326             ++p;
00327 
00328             if (c == fn)
00329               goto matched;
00330           }
00331         else if (c == '[' && *p == ':')
00332           {
00333             /* Leave room for the null.  */
00334             char str[CHAR_CLASS_MAX_LENGTH + 1];
00335             size_t c1 = 0;
00336 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
00337             wctype_t wt;
00338 # endif
00339             const char *startp = p;
00340 
00341             for (;;)
00342               {
00343             if (c1 == CHAR_CLASS_MAX_LENGTH)
00344               /* The name is too long and therefore the pattern
00345                  is ill-formed.  */
00346               return FNM_NOMATCH;
00347 
00348             c = *++p;
00349             if (c == ':' && p[1] == ']')
00350               {
00351                 p += 2;
00352                 break;
00353               }
00354             if (c < 'a' || c >= 'z')
00355               {
00356                 /* This cannot possibly be a character class name.
00357                    Match it as a normal range.  */
00358                 p = startp;
00359                 c = '[';
00360                 goto normal_bracket;
00361               }
00362             str[c1++] = c;
00363               }
00364             str[c1] = '\0';
00365 
00366 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
00367             wt = IS_CHAR_CLASS (str);
00368             if (wt == 0)
00369               /* Invalid character class name.  */
00370               return FNM_NOMATCH;
00371 
00372             if (__iswctype (__btowc ((unsigned char) *n), wt))
00373               goto matched;
00374 # else
00375             if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
00376             || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
00377             || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
00378             || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
00379             || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
00380             || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
00381             || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
00382             || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
00383             || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
00384             || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
00385             || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
00386             || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
00387               goto matched;
00388 # endif
00389           }
00390         else if (c == '\0')
00391           /* [ (unterminated) loses.  */
00392           return FNM_NOMATCH;
00393         else
00394           {
00395           normal_bracket:
00396             if (FOLD (c) == fn)
00397               goto matched;
00398 
00399             cold = c;
00400             c = *p++;
00401 
00402             if (c == '-' && *p != ']')
00403               {
00404             /* It is a range.  */
00405             unsigned char cend = *p++;
00406             if (!(flags & FNM_NOESCAPE) && cend == '\\')
00407               cend = *p++;
00408             if (cend == '\0')
00409               return FNM_NOMATCH;
00410 
00411             if (cold <= fn && fn <= FOLD (cend))
00412               goto matched;
00413 
00414             c = *p++;
00415               }
00416           }
00417 
00418         if (c == ']')
00419           break;
00420           }
00421 
00422         if (!not)
00423           return FNM_NOMATCH;
00424         break;
00425 
00426       matched:
00427         /* Skip the rest of the [...] that already matched.  */
00428         while (c != ']')
00429           {
00430         if (c == '\0')
00431           /* [... (unterminated) loses.  */
00432           return FNM_NOMATCH;
00433 
00434         c = *p++;
00435         if (!(flags & FNM_NOESCAPE) && c == '\\')
00436           {
00437             if (*p == '\0')
00438               return FNM_NOMATCH;
00439             /* XXX 1003.2d11 is unclear if this is right.  */
00440             ++p;
00441           }
00442         else if (c == '[' && *p == ':')
00443           {
00444             do
00445               if (*++p == '\0')
00446             return FNM_NOMATCH;
00447             while (*p != ':' || p[1] == ']');
00448             p += 2;
00449             c = *p;
00450           }
00451           }
00452         if (not)
00453           return FNM_NOMATCH;
00454       }
00455       break;
00456 
00457     default:
00458       if (c != FOLD ((unsigned char) *n))
00459         return FNM_NOMATCH;
00460     }
00461 
00462       ++n;
00463     }
00464 
00465   if (*n == '\0')
00466     return 0;
00467 
00468   if ((flags & FNM_LEADING_DIR) && *n == '/')
00469     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
00470     return 0;
00471 
00472   return FNM_NOMATCH;
00473 
00474 # undef FOLD
00475 }

Here is the call graph for this function:

char* __strchrnul const char *  s,
int  c
[static]
 

Definition at line 135 of file nanomud-fnmatch.c.

Referenced by __P().

00136 {
00137   char *result = strchr (s, c);
00138   if (result == NULL)
00139     result = strchr (s, '\0');
00140   return result;
00141 }

int fnmatch char *  pattern,
const char *  string,
int  flags
const
 

Definition at line 479 of file nanomud-fnmatch.c.

References FNM_PERIOD.

00483 {
00484   return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
00485 }

char* getenv const char *  name  ) 
 

Referenced by __P().


Variable Documentation

int errno
 


Generated on Sat May 14 02:47:18 2005 for Nanomud by  doxygen 1.3.9.1