Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <libc/stubs.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <fnmatch.h>
  7.  
  8. #define EOS     '\0'
  9.  
  10. static const char *rangematch(const char *pattern, char test, int nocase);
  11.  
  12. #define isslash(c) ((c) == '\\' || (c) == '/')
  13.  
  14. static const char *
  15. find_slash(const char *s)
  16. {
  17.   while (*s)
  18.   {
  19.     if (isslash(*s))
  20.       return s;
  21.     s++;
  22.   }
  23.   return 0;
  24. }
  25.  
  26. static const char *
  27. rangematch(const char *pattern, char test, int nocase)
  28. {
  29.   char c, c2;
  30.   int negate, ok;
  31.  
  32.   if ((negate = (*pattern == '!')))
  33.     ++pattern;
  34.  
  35.   for (ok = 0; (c = *pattern++) != ']';)
  36.   {
  37.     if (c == 0)
  38.       return 0;                 /* illegal pattern */
  39.     if (*pattern == '-' && (c2 = pattern[1]) != 0 && c2 != ']')
  40.     {
  41.       if (c <= test && test <= c2)
  42.         ok = 1;
  43.       if (nocase && toupper(c) <= toupper(test) && toupper(test) <= toupper(c2))
  44.         ok = 1;
  45.       pattern += 2;
  46.     }
  47.     else if (c == test)
  48.       ok = 1;
  49.     else if (nocase && (toupper(c) == toupper(test)))
  50.       ok = 1;
  51.   }
  52.   return ok == negate ? NULL : pattern;
  53. }
  54.  
  55. int
  56. fnmatch(const char *pattern, const char *string, int flags)
  57. {
  58.   char c;
  59.   char test;
  60.  
  61.   for (;;)
  62.     switch ((c = *pattern++))
  63.     {
  64.     case 0:
  65.       return *string == 0 ? 0 : FNM_NOMATCH;
  66.      
  67.     case '?':
  68.       if ((test = *string++) == 0 ||
  69.           (isslash(test) && (flags & FNM_PATHNAME)))
  70.         return(FNM_NOMATCH);
  71.       break;
  72.      
  73.     case '*':
  74.       c = *pattern;
  75.       /* collapse multiple stars */
  76.       while (c == '*')
  77.         c = *++pattern;
  78.  
  79.       /* optimize for pattern with * at end or before / */
  80.       if (c == 0)
  81.         if (flags & FNM_PATHNAME)
  82.           return find_slash(string) ? FNM_NOMATCH : 0;
  83.         else
  84.           return 0;
  85.       else if (isslash(c) && flags & FNM_PATHNAME)
  86.       {
  87.         if ((string = find_slash(string)) == NULL)
  88.           return FNM_NOMATCH;
  89.         break;
  90.       }
  91.  
  92.       /* general case, use recursion */
  93.       while ((test = *string) != 0)
  94.       {
  95.         if (fnmatch(pattern, string, flags) == 0)
  96.           return(0);
  97.         if (isslash(test) && flags & FNM_PATHNAME)
  98.           break;
  99.         ++string;
  100.       }
  101.       return FNM_NOMATCH;
  102.      
  103.     case '[':
  104.       if ((test = *string++) == 0 ||
  105.           (isslash(test) && flags & FNM_PATHNAME))
  106.         return FNM_NOMATCH;
  107.       if ((pattern = rangematch(pattern, test, flags & FNM_NOCASE)) == NULL)
  108.         return FNM_NOMATCH;
  109.       break;
  110.      
  111.     case '\\':
  112.       if (!(flags & FNM_NOESCAPE) && pattern[1] && strchr("*?[\\", pattern[1]))
  113.       {
  114.         if ((c = *pattern++) == 0)
  115.         {
  116.           c = '\\';
  117.           --pattern;
  118.         }
  119.         if (c != *string++)
  120.           return FNM_NOMATCH;
  121.         break;
  122.       }
  123.       /* FALLTHROUGH */
  124.      
  125.     default:
  126.       if (isslash(c) && isslash(*string))
  127.       {
  128.         string++;
  129.         break;
  130.       }
  131.       if (flags & FNM_NOCASE)
  132.       {
  133.         if (toupper(c) != toupper(*string++))
  134.           return FNM_NOMATCH;
  135.       }
  136.       else
  137.       {
  138.         if (c != *string++)
  139.           return FNM_NOMATCH;
  140.       }
  141.       break;
  142.     }
  143. }
  144.