1 /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
2 
3    NOTE: The canonical source of this file is maintained with the GNU C
4    Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
5 
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19 
20 #if HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23 
24 #include <errno.h>
25 #include <fnmatch.h>
26 #include <ctype.h>
27 
28 #if defined (STDC_HEADERS) || !defined (isascii)
29 # define ISASCII(c) 1
30 #else
31 # define ISASCII(c) isascii(c)
32 #endif
33 
34 #define ISUPPER(c) (ISASCII (c) && isupper (c))
35 
36 
37 /* Comment out all this code if we are using the GNU C Library, and are not
38    actually compiling the library itself.  This code is part of the GNU C
39    Library, but also included in many other GNU distributions.  Compiling
40    and linking in this code is a waste when using the GNU C library
41    (especially if it is a shared library).  Rather than having every GNU
42    program understand `configure --with-gnu-libc' and omit the object files,
43    it is simpler to just do this in the source for each such file.  */
44 
45 #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
46 
47 
48 # ifndef errno
49 extern int errno;
50 # endif
51 
52 /* Match STRING against the filename pattern PATTERN, returning zero if
53    it matches, nonzero if not.  */
54 int
fnmatch(pattern,string,flags)55 fnmatch (pattern, string, flags)
56      const char *pattern;
57      const char *string;
58      int flags;
59 {
60   register const char *p = pattern, *n = string;
61   register char c;
62 
63 /* Note that this evalutes C many times.  */
64 # define FOLD(c)	((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
65 
66   while ((c = *p++) != '\0')
67     {
68       c = FOLD (c);
69 
70       switch (c)
71 	{
72 	case '?':
73 	  if (*n == '\0')
74 	    return FNM_NOMATCH;
75 	  else if ((flags & FNM_FILE_NAME) && *n == '/')
76 	    return FNM_NOMATCH;
77 	  else if ((flags & FNM_PERIOD) && *n == '.' &&
78 		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
79 	    return FNM_NOMATCH;
80 	  break;
81 
82 	case '\\':
83 	  if (!(flags & FNM_NOESCAPE))
84 	    {
85 	      c = *p++;
86 	      c = FOLD (c);
87 	    }
88 	  if (FOLD (*n) != c)
89 	    return FNM_NOMATCH;
90 	  break;
91 
92 	case '*':
93 	  if ((flags & FNM_PERIOD) && *n == '.' &&
94 	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
95 	    return FNM_NOMATCH;
96 
97 	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
98 	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
99 		(c == '?' && *n == '\0'))
100 	      return FNM_NOMATCH;
101 
102 	  if (c == '\0')
103 	    return 0;
104 
105 	  {
106 	    char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
107 	    c1 = FOLD (c1);
108 	    for (--p; *n != '\0'; ++n)
109 	      if ((c == '[' || FOLD (*n) == c1) &&
110 		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
111 		return 0;
112 	    return FNM_NOMATCH;
113 	  }
114 
115 	case '[':
116 	  {
117 	    /* Nonzero if the sense of the character class is inverted.  */
118 	    register int not;
119 
120 	    if (*n == '\0')
121 	      return FNM_NOMATCH;
122 
123 	    if ((flags & FNM_PERIOD) && *n == '.' &&
124 		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
125 	      return FNM_NOMATCH;
126 
127 	    not = (*p == '!' || *p == '^');
128 	    if (not)
129 	      ++p;
130 
131 	    c = *p++;
132 	    for (;;)
133 	      {
134 		register char cstart = c, cend = c;
135 
136 		if (!(flags & FNM_NOESCAPE) && c == '\\')
137 		  cstart = cend = *p++;
138 
139 		cstart = cend = FOLD (cstart);
140 
141 		if (c == '\0')
142 		  /* [ (unterminated) loses.  */
143 		  return FNM_NOMATCH;
144 
145 		c = *p++;
146 		c = FOLD (c);
147 
148 		if ((flags & FNM_FILE_NAME) && c == '/')
149 		  /* [/] can never match.  */
150 		  return FNM_NOMATCH;
151 
152 		if (c == '-' && *p != ']')
153 		  {
154 		    cend = *p++;
155 		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
156 		      cend = *p++;
157 		    if (cend == '\0')
158 		      return FNM_NOMATCH;
159 		    cend = FOLD (cend);
160 
161 		    c = *p++;
162 		  }
163 
164 		if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
165 		  goto matched;
166 
167 		if (c == ']')
168 		  break;
169 	      }
170 	    if (!not)
171 	      return FNM_NOMATCH;
172 	    break;
173 
174 	  matched:;
175 	    /* Skip the rest of the [...] that already matched.  */
176 	    while (c != ']')
177 	      {
178 		if (c == '\0')
179 		  /* [... (unterminated) loses.  */
180 		  return FNM_NOMATCH;
181 
182 		c = *p++;
183 		if (!(flags & FNM_NOESCAPE) && c == '\\')
184 		  /* XXX 1003.2d11 is unclear if this is right.  */
185 		  ++p;
186 	      }
187 	    if (not)
188 	      return FNM_NOMATCH;
189 	  }
190 	  break;
191 
192 	default:
193 	  if (c != FOLD (*n))
194 	    return FNM_NOMATCH;
195 	}
196 
197       ++n;
198     }
199 
200   if (*n == '\0')
201     return 0;
202 
203   if ((flags & FNM_LEADING_DIR) && *n == '/')
204     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
205     return 0;
206 
207   return FNM_NOMATCH;
208 
209 # undef FOLD
210 }
211 
212 #endif	/* _LIBC or not __GNU_LIBRARY__.  */
213