Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4973 right-hear 1
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
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
}