]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/cvs/lib/fnmatch.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / cvs / lib / fnmatch.c
1 /* Copyright (C) 1992 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.  */
13
14 /* Modified slightly by Brian Berliner <berliner@sun.com> and
15    Jim Blandy <jimb@cyclic.com> for CVS use */
16
17 #ifdef HAVE_CONFIG_H
18 # include "config.h"
19 #endif
20
21 #include "system.h"
22
23 /* IGNORE(@ */
24 /* #include <ansidecl.h> */
25 /* @) */
26 #include <errno.h>
27 #include "fnmatch.h"
28
29 #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
30 extern int errno;
31 #endif
32
33 /* Match STRING against the filename pattern PATTERN, returning zero if
34    it matches, nonzero if not.  */
35 int
36 #if __STDC__
37 fnmatch (const char *pattern, const char *string, int flags)
38 #else
39 fnmatch (pattern, string, flags)
40     char *pattern;
41     char *string;
42     int flags;
43 #endif
44 {
45   register const char *p = pattern, *n = string;
46   register char c;
47
48   if ((flags & ~__FNM_FLAGS) != 0)
49     {
50       errno = EINVAL;
51       return -1;
52     }
53
54   while ((c = *p++) != '\0')
55     {
56       switch (c)
57         {
58         case '?':
59           if (*n == '\0')
60             return FNM_NOMATCH;
61           else if ((flags & FNM_PATHNAME) && *n == '/')
62             return FNM_NOMATCH;
63           else if ((flags & FNM_PERIOD) && *n == '.' &&
64                    (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
65             return FNM_NOMATCH;
66           break;
67           
68         case '\\':
69           if (!(flags & FNM_NOESCAPE))
70             c = *p++;
71           if (FOLD_FN_CHAR (*n) != FOLD_FN_CHAR (c))
72             return FNM_NOMATCH;
73           break;
74           
75         case '*':
76           if ((flags & FNM_PERIOD) && *n == '.' &&
77               (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
78             return FNM_NOMATCH;
79           
80           for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
81             if (((flags & FNM_PATHNAME) && *n == '/') ||
82                 (c == '?' && *n == '\0'))
83               return FNM_NOMATCH;
84           
85           if (c == '\0')
86             return 0;
87           
88           {
89             char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
90             for (--p; *n != '\0'; ++n)
91               if ((c == '[' || FOLD_FN_CHAR (*n) == FOLD_FN_CHAR (c1)) &&
92                   fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
93                 return 0;
94             return FNM_NOMATCH;
95           }
96           
97         case '[':
98           {
99             /* Nonzero if the sense of the character class is inverted.  */
100             register int not;
101             
102             if (*n == '\0')
103               return FNM_NOMATCH;
104             
105             if ((flags & FNM_PERIOD) && *n == '.' &&
106                 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
107               return FNM_NOMATCH;
108             
109             not = (*p == '!' || *p == '^');
110             if (not)
111               ++p;
112             
113             c = *p++;
114             for (;;)
115               {
116                 register char cstart = c, cend = c;
117                 
118                 if (!(flags & FNM_NOESCAPE) && c == '\\')
119                   cstart = cend = *p++;
120                 
121                 if (c == '\0')
122                   /* [ (unterminated) loses.  */
123                   return FNM_NOMATCH;
124                 
125                 c = *p++;
126                 
127                 if ((flags & FNM_PATHNAME) && c == '/')
128                   /* [/] can never match.  */
129                   return FNM_NOMATCH;
130                 
131                 if (c == '-' && *p != ']')
132                   {
133                     cend = *p++;
134                     if (!(flags & FNM_NOESCAPE) && cend == '\\')
135                       cend = *p++;
136                     if (cend == '\0')
137                       return FNM_NOMATCH;
138                     c = *p++;
139                   }
140                 
141                 if (*n >= cstart && *n <= cend)
142                   goto matched;
143                 
144                 if (c == ']')
145                   break;
146               }
147             if (!not)
148               return FNM_NOMATCH;
149             break;
150             
151           matched:;
152             /* Skip the rest of the [...] that already matched.  */
153             while (c != ']')
154               {
155                 if (c == '\0')
156                   /* [... (unterminated) loses.  */
157                   return FNM_NOMATCH;
158                 
159                 c = *p++;
160                 if (!(flags & FNM_NOESCAPE) && c == '\\')
161                   /* 1003.2d11 is unclear if this is right.  %%% */
162                   ++p;
163               }
164             if (not)
165               return FNM_NOMATCH;
166           }
167           break;
168           
169         default:
170           if (FOLD_FN_CHAR (c) != FOLD_FN_CHAR (*n))
171             return FNM_NOMATCH;
172         }
173       
174       ++n;
175     }
176
177   if (*n == '\0')
178     return 0;
179
180   return FNM_NOMATCH;
181 }