* fnmatch.h, fnmatch.c: New files.
[deliverable/binutils-gdb.git] / ld / fnmatch.c
CommitLineData
86bc0974
ILT
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
32#ifndef _GNU_SOURCE
33#define _GNU_SOURCE
34#endif
35
36#include <errno.h>
37#include <fnmatch.h>
38#include <ctype.h>
39
40
41/* Comment out all this code if we are using the GNU C Library, and are not
42 actually compiling the library itself. This code is part of the GNU C
43 Library, but also included in many other GNU distributions. Compiling
44 and linking in this code is a waste when using the GNU C library
45 (especially if it is a shared library). Rather than having every GNU
46 program understand `configure --with-gnu-libc' and omit the object files,
47 it is simpler to just do this in the source for each such file. */
48
49#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
50
51
52#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
53extern int errno;
54#endif
55
56/* Match STRING against the filename pattern PATTERN, returning zero if
57 it matches, nonzero if not. */
58int
59fnmatch (pattern, string, flags)
60 const char *pattern;
61 const char *string;
62 int flags;
63{
64 register const char *p = pattern, *n = string;
65 register char c;
66
67/* Note that this evalutes C many times. */
68#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
69
70 while ((c = *p++) != '\0')
71 {
72 c = FOLD (c);
73
74 switch (c)
75 {
76 case '?':
77 if (*n == '\0')
78 return FNM_NOMATCH;
79 else if ((flags & FNM_FILE_NAME) && *n == '/')
80 return FNM_NOMATCH;
81 else if ((flags & FNM_PERIOD) && *n == '.' &&
82 (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
83 return FNM_NOMATCH;
84 break;
85
86 case '\\':
87 if (!(flags & FNM_NOESCAPE))
88 {
89 c = *p++;
90 c = FOLD (c);
91 }
92 if (FOLD (*n) != c)
93 return FNM_NOMATCH;
94 break;
95
96 case '*':
97 if ((flags & FNM_PERIOD) && *n == '.' &&
98 (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
99 return FNM_NOMATCH;
100
101 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
102 if (((flags & FNM_FILE_NAME) && *n == '/') ||
103 (c == '?' && *n == '\0'))
104 return FNM_NOMATCH;
105
106 if (c == '\0')
107 return 0;
108
109 {
110 char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
111 c1 = FOLD (c1);
112 for (--p; *n != '\0'; ++n)
113 if ((c == '[' || FOLD (*n) == c1) &&
114 fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
115 return 0;
116 return FNM_NOMATCH;
117 }
118
119 case '[':
120 {
121 /* Nonzero if the sense of the character class is inverted. */
122 register int not;
123
124 if (*n == '\0')
125 return FNM_NOMATCH;
126
127 if ((flags & FNM_PERIOD) && *n == '.' &&
128 (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
129 return FNM_NOMATCH;
130
131 not = (*p == '!' || *p == '^');
132 if (not)
133 ++p;
134
135 c = *p++;
136 for (;;)
137 {
138 register char cstart = c, cend = c;
139
140 if (!(flags & FNM_NOESCAPE) && c == '\\')
141 cstart = cend = *p++;
142
143 cstart = cend = FOLD (cstart);
144
145 if (c == '\0')
146 /* [ (unterminated) loses. */
147 return FNM_NOMATCH;
148
149 c = *p++;
150 c = FOLD (c);
151
152 if ((flags & FNM_FILE_NAME) && c == '/')
153 /* [/] can never match. */
154 return FNM_NOMATCH;
155
156 if (c == '-' && *p != ']')
157 {
158 cend = *p++;
159 if (!(flags & FNM_NOESCAPE) && cend == '\\')
160 cend = *p++;
161 if (cend == '\0')
162 return FNM_NOMATCH;
163 cend = FOLD (cend);
164
165 c = *p++;
166 }
167
168 if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
169 goto matched;
170
171 if (c == ']')
172 break;
173 }
174 if (!not)
175 return FNM_NOMATCH;
176 break;
177
178 matched:;
179 /* Skip the rest of the [...] that already matched. */
180 while (c != ']')
181 {
182 if (c == '\0')
183 /* [... (unterminated) loses. */
184 return FNM_NOMATCH;
185
186 c = *p++;
187 if (!(flags & FNM_NOESCAPE) && c == '\\')
188 /* XXX 1003.2d11 is unclear if this is right. */
189 ++p;
190 }
191 if (not)
192 return FNM_NOMATCH;
193 }
194 break;
195
196 default:
197 if (c != FOLD (*n))
198 return FNM_NOMATCH;
199 }
200
201 ++n;
202 }
203
204 if (*n == '\0')
205 return 0;
206
207 if ((flags & FNM_LEADING_DIR) && *n == '/')
208 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
209 return 0;
210
211 return FNM_NOMATCH;
212}
213
214#endif /* _LIBC or not __GNU_LIBRARY__. */
This page took 0.03196 seconds and 4 git commands to generate.