source: trunk/third/diffutils/fnmatch.c @ 16149

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