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