xref: /dpdk/lib/eal/windows/include/fnmatch.h (revision 1fcd0b17993579c717976fc2e502c1b236b87fba)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2*1fcd0b17SBruce Richardson  * Copyright (c) 1989, 1993, 1994
3*1fcd0b17SBruce Richardson  *	The Regents of the University of California.  All rights reserved.
4*1fcd0b17SBruce Richardson  *
5*1fcd0b17SBruce Richardson  * This code is derived from software contributed to Berkeley by
6*1fcd0b17SBruce Richardson  * Guido van Rossum.
799a2dd95SBruce Richardson  */
899a2dd95SBruce Richardson #ifndef _FNMATCH_H_
999a2dd95SBruce Richardson #define _FNMATCH_H_
1099a2dd95SBruce Richardson 
11*1fcd0b17SBruce Richardson /*
12*1fcd0b17SBruce Richardson  * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
13*1fcd0b17SBruce Richardson  * Compares a filename or pathname to a pattern.
1499a2dd95SBruce Richardson  */
1599a2dd95SBruce Richardson 
16*1fcd0b17SBruce Richardson #include <ctype.h>
17*1fcd0b17SBruce Richardson #include <string.h>
18*1fcd0b17SBruce Richardson #include <stdio.h>
1999a2dd95SBruce Richardson 
2099a2dd95SBruce Richardson #define FNM_NOMATCH 1
2199a2dd95SBruce Richardson 
2299a2dd95SBruce Richardson #define FNM_NOESCAPE 0x01
2399a2dd95SBruce Richardson #define FNM_PATHNAME 0x02
2499a2dd95SBruce Richardson #define FNM_PERIOD 0x04
2599a2dd95SBruce Richardson #define FNM_LEADING_DIR 0x08
2699a2dd95SBruce Richardson #define FNM_CASEFOLD 0x10
2799a2dd95SBruce Richardson #define FNM_PREFIX_DIRS 0x20
2899a2dd95SBruce Richardson 
29*1fcd0b17SBruce Richardson #define FNM_EOS	'\0'
30*1fcd0b17SBruce Richardson 
31*1fcd0b17SBruce Richardson static inline const char *
fnm_rangematch(const char * pattern,char test,int flags)32*1fcd0b17SBruce Richardson fnm_rangematch(const char *pattern, char test, int flags)
33*1fcd0b17SBruce Richardson {
34*1fcd0b17SBruce Richardson 	int negate, ok;
35*1fcd0b17SBruce Richardson 	char c, c2;
36*1fcd0b17SBruce Richardson 
37*1fcd0b17SBruce Richardson 	/*
38*1fcd0b17SBruce Richardson 	 * A bracket expression starting with an unquoted circumflex
39*1fcd0b17SBruce Richardson 	 * character produces unspecified results (IEEE 1003.2-1992,
40*1fcd0b17SBruce Richardson 	 * 3.13.2).  This implementation treats it like '!', for
41*1fcd0b17SBruce Richardson 	 * consistency with the regular expression syntax.
42*1fcd0b17SBruce Richardson 	 * J.T. Conklin (conklin@ngai.kaleida.com)
43*1fcd0b17SBruce Richardson 	 */
44*1fcd0b17SBruce Richardson 	negate = (*pattern == '!' || *pattern == '^');
45*1fcd0b17SBruce Richardson 	if (negate)
46*1fcd0b17SBruce Richardson 		++pattern;
47*1fcd0b17SBruce Richardson 
48*1fcd0b17SBruce Richardson 	if (flags & FNM_CASEFOLD)
49*1fcd0b17SBruce Richardson 		test = tolower((unsigned char)test);
50*1fcd0b17SBruce Richardson 
51*1fcd0b17SBruce Richardson 	for (ok = 0; (c = *pattern++) != ']';) {
52*1fcd0b17SBruce Richardson 		if (c == '\\' && !(flags & FNM_NOESCAPE))
53*1fcd0b17SBruce Richardson 			c = *pattern++;
54*1fcd0b17SBruce Richardson 		if (c == FNM_EOS)
55*1fcd0b17SBruce Richardson 			return (NULL);
56*1fcd0b17SBruce Richardson 
57*1fcd0b17SBruce Richardson 		if (flags & FNM_CASEFOLD)
58*1fcd0b17SBruce Richardson 			c = tolower((unsigned char)c);
59*1fcd0b17SBruce Richardson 
60*1fcd0b17SBruce Richardson 		c2 = *(pattern + 1);
61*1fcd0b17SBruce Richardson 		if (*pattern == '-' && c2 != FNM_EOS && c2 != ']') {
62*1fcd0b17SBruce Richardson 			pattern += 2;
63*1fcd0b17SBruce Richardson 			if (c2 == '\\' && !(flags & FNM_NOESCAPE))
64*1fcd0b17SBruce Richardson 				c2 = *pattern++;
65*1fcd0b17SBruce Richardson 			if (c2 == FNM_EOS)
66*1fcd0b17SBruce Richardson 				return (NULL);
67*1fcd0b17SBruce Richardson 
68*1fcd0b17SBruce Richardson 			if (flags & FNM_CASEFOLD)
69*1fcd0b17SBruce Richardson 				c2 = tolower((unsigned char)c2);
70*1fcd0b17SBruce Richardson 
71*1fcd0b17SBruce Richardson 			if ((unsigned char)c <= (unsigned char)test &&
72*1fcd0b17SBruce Richardson 			    (unsigned char)test <= (unsigned char)c2)
73*1fcd0b17SBruce Richardson 				ok = 1;
74*1fcd0b17SBruce Richardson 		} else if (c == test)
75*1fcd0b17SBruce Richardson 			ok = 1;
76*1fcd0b17SBruce Richardson 	}
77*1fcd0b17SBruce Richardson 	return (ok == negate ? NULL : pattern);
78*1fcd0b17SBruce Richardson }
79*1fcd0b17SBruce Richardson 
8099a2dd95SBruce Richardson /**
817be78d02SJosh Soref  * This function is used for searching a given string source
8299a2dd95SBruce Richardson  * with the given regular expression pattern.
8399a2dd95SBruce Richardson  *
8499a2dd95SBruce Richardson  * @param pattern
854a6672c2SStephen Hemminger  *	regular expression notation describing the pattern to match
8699a2dd95SBruce Richardson  *
8799a2dd95SBruce Richardson  * @param string
887be78d02SJosh Soref  *	source string to search for the pattern
8999a2dd95SBruce Richardson  *
9099a2dd95SBruce Richardson  * @param flag
9199a2dd95SBruce Richardson  *	containing information about the pattern
9299a2dd95SBruce Richardson  *
9399a2dd95SBruce Richardson  * @return
9499a2dd95SBruce Richardson  *	if the pattern is found then return 0 or else FNM_NOMATCH
9599a2dd95SBruce Richardson  */
96*1fcd0b17SBruce Richardson static inline int
fnmatch(const char * pattern,const char * string,int flags)97*1fcd0b17SBruce Richardson fnmatch(const char *pattern, const char *string, int flags)
98*1fcd0b17SBruce Richardson {
99*1fcd0b17SBruce Richardson 	const char *stringstart;
100*1fcd0b17SBruce Richardson 	char c, test;
10199a2dd95SBruce Richardson 
102*1fcd0b17SBruce Richardson 	for (stringstart = string;;)
103*1fcd0b17SBruce Richardson 		switch (c = *pattern++) {
104*1fcd0b17SBruce Richardson 		case FNM_EOS:
105*1fcd0b17SBruce Richardson 			if ((flags & FNM_LEADING_DIR) && *string == '/')
106*1fcd0b17SBruce Richardson 				return (0);
107*1fcd0b17SBruce Richardson 			return (*string == FNM_EOS ? 0 : FNM_NOMATCH);
108*1fcd0b17SBruce Richardson 		case '?':
109*1fcd0b17SBruce Richardson 			if (*string == FNM_EOS)
110*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
111*1fcd0b17SBruce Richardson 			if (*string == '/' && (flags & FNM_PATHNAME))
112*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
113*1fcd0b17SBruce Richardson 			if (*string == '.' && (flags & FNM_PERIOD) &&
114*1fcd0b17SBruce Richardson 			    (string == stringstart ||
115*1fcd0b17SBruce Richardson 			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
116*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
117*1fcd0b17SBruce Richardson 			++string;
118*1fcd0b17SBruce Richardson 			break;
119*1fcd0b17SBruce Richardson 		case '*':
120*1fcd0b17SBruce Richardson 			c = *pattern;
121*1fcd0b17SBruce Richardson 			/* Collapse multiple stars. */
122*1fcd0b17SBruce Richardson 			while (c == '*')
123*1fcd0b17SBruce Richardson 				c = *++pattern;
124*1fcd0b17SBruce Richardson 
125*1fcd0b17SBruce Richardson 			if (*string == '.' && (flags & FNM_PERIOD) &&
126*1fcd0b17SBruce Richardson 			    (string == stringstart ||
127*1fcd0b17SBruce Richardson 			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
128*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
129*1fcd0b17SBruce Richardson 
130*1fcd0b17SBruce Richardson 			/* Optimize for pattern with * at end or before /. */
131*1fcd0b17SBruce Richardson 			if (c == FNM_EOS)
132*1fcd0b17SBruce Richardson 				if (flags & FNM_PATHNAME)
133*1fcd0b17SBruce Richardson 					return ((flags & FNM_LEADING_DIR) ||
134*1fcd0b17SBruce Richardson 					    strchr(string, '/') == NULL ?
135*1fcd0b17SBruce Richardson 					    0 : FNM_NOMATCH);
136*1fcd0b17SBruce Richardson 				else
137*1fcd0b17SBruce Richardson 					return (0);
138*1fcd0b17SBruce Richardson 			else if (c == '/' && flags & FNM_PATHNAME) {
139*1fcd0b17SBruce Richardson 				string = strchr(string, '/');
140*1fcd0b17SBruce Richardson 				if (string == NULL)
141*1fcd0b17SBruce Richardson 					return (FNM_NOMATCH);
142*1fcd0b17SBruce Richardson 				break;
14399a2dd95SBruce Richardson 			}
144*1fcd0b17SBruce Richardson 
145*1fcd0b17SBruce Richardson 			/* General case, use recursion. */
146*1fcd0b17SBruce Richardson 			while ((test = *string) != FNM_EOS) {
147*1fcd0b17SBruce Richardson 				if (!fnmatch(pattern, string,
148*1fcd0b17SBruce Richardson 					flags & ~FNM_PERIOD))
149*1fcd0b17SBruce Richardson 					return (0);
150*1fcd0b17SBruce Richardson 				if (test == '/' && flags & FNM_PATHNAME)
151*1fcd0b17SBruce Richardson 					break;
152*1fcd0b17SBruce Richardson 				++string;
153*1fcd0b17SBruce Richardson 			}
154*1fcd0b17SBruce Richardson 			return (FNM_NOMATCH);
155*1fcd0b17SBruce Richardson 		case '[':
156*1fcd0b17SBruce Richardson 			if (*string == FNM_EOS)
157*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
158*1fcd0b17SBruce Richardson 			if (*string == '/' && flags & FNM_PATHNAME)
159*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
160*1fcd0b17SBruce Richardson 			pattern = fnm_rangematch(pattern, *string, flags);
161*1fcd0b17SBruce Richardson 			if (pattern == NULL)
162*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
163*1fcd0b17SBruce Richardson 			++string;
164*1fcd0b17SBruce Richardson 			break;
165*1fcd0b17SBruce Richardson 		case '\\':
166*1fcd0b17SBruce Richardson 			if (!(flags & FNM_NOESCAPE)) {
167*1fcd0b17SBruce Richardson 				c = *pattern++;
168*1fcd0b17SBruce Richardson 				if (c == FNM_EOS) {
169*1fcd0b17SBruce Richardson 					c = '\\';
170*1fcd0b17SBruce Richardson 					--pattern;
171*1fcd0b17SBruce Richardson 				}
172*1fcd0b17SBruce Richardson 			}
173*1fcd0b17SBruce Richardson 			/* FALLTHROUGH */
174*1fcd0b17SBruce Richardson 		default:
175*1fcd0b17SBruce Richardson 			if (c == *string)
176*1fcd0b17SBruce Richardson 				;
177*1fcd0b17SBruce Richardson 			else if ((flags & FNM_CASEFOLD) &&
178*1fcd0b17SBruce Richardson 				 (tolower((unsigned char)c) ==
179*1fcd0b17SBruce Richardson 				  tolower((unsigned char)*string)))
180*1fcd0b17SBruce Richardson 				;
181*1fcd0b17SBruce Richardson 			else if ((flags & FNM_PREFIX_DIRS) && *string == FNM_EOS &&
182*1fcd0b17SBruce Richardson 			     ((c == '/' && string != stringstart) ||
183*1fcd0b17SBruce Richardson 			     (string == stringstart+1 && *stringstart == '/')))
184*1fcd0b17SBruce Richardson 				return (0);
185*1fcd0b17SBruce Richardson 			else
186*1fcd0b17SBruce Richardson 				return (FNM_NOMATCH);
187*1fcd0b17SBruce Richardson 			string++;
188*1fcd0b17SBruce Richardson 			break;
189*1fcd0b17SBruce Richardson 		}
190*1fcd0b17SBruce Richardson 	/* NOTREACHED */
191*1fcd0b17SBruce Richardson }
19299a2dd95SBruce Richardson 
19399a2dd95SBruce Richardson #endif /* _FNMATCH_H_ */
194