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