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