xref: /aosp_15_r20/external/mtools/match.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1*d5c9a868SElliott Hughes /*  Copyright 1986-1992 Emmet P. Gray.
2*d5c9a868SElliott Hughes  *  Copyright 1996-1998,2001,2002,2008,2009 Alain Knaff.
3*d5c9a868SElliott Hughes  *  This file is part of mtools.
4*d5c9a868SElliott Hughes  *
5*d5c9a868SElliott Hughes  *  Mtools is free software: you can redistribute it and/or modify
6*d5c9a868SElliott Hughes  *  it under the terms of the GNU General Public License as published by
7*d5c9a868SElliott Hughes  *  the Free Software Foundation, either version 3 of the License, or
8*d5c9a868SElliott Hughes  *  (at your option) any later version.
9*d5c9a868SElliott Hughes  *
10*d5c9a868SElliott Hughes  *  Mtools is distributed in the hope that it will be useful,
11*d5c9a868SElliott Hughes  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*d5c9a868SElliott Hughes  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*d5c9a868SElliott Hughes  *  GNU General Public License for more details.
14*d5c9a868SElliott Hughes  *
15*d5c9a868SElliott Hughes  *  You should have received a copy of the GNU General Public License
16*d5c9a868SElliott Hughes  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
17*d5c9a868SElliott Hughes  *
18*d5c9a868SElliott Hughes  * Do shell-style pattern matching for '?', '\', '[..]', and '*' wildcards.
19*d5c9a868SElliott Hughes  * Returns 1 if match, 0 if not.
20*d5c9a868SElliott Hughes  */
21*d5c9a868SElliott Hughes 
22*d5c9a868SElliott Hughes #include "sysincludes.h"
23*d5c9a868SElliott Hughes #include "mtools.h"
24*d5c9a868SElliott Hughes 
25*d5c9a868SElliott Hughes 
casecmp(wchar_t a,wchar_t b)26*d5c9a868SElliott Hughes static int casecmp(wchar_t a, wchar_t b)
27*d5c9a868SElliott Hughes {
28*d5c9a868SElliott Hughes 	return towupper((wint_t)a) == towupper((wint_t)b);
29*d5c9a868SElliott Hughes }
30*d5c9a868SElliott Hughes 
exactcmp(wchar_t a,wchar_t b)31*d5c9a868SElliott Hughes static int exactcmp(wchar_t a,wchar_t b)
32*d5c9a868SElliott Hughes {
33*d5c9a868SElliott Hughes 	return a == b;
34*d5c9a868SElliott Hughes }
35*d5c9a868SElliott Hughes 
36*d5c9a868SElliott Hughes 
is_in_range(wchar_t ch,const wchar_t ** p,int * reverse)37*d5c9a868SElliott Hughes static int is_in_range(wchar_t ch, const wchar_t **p, int *reverse) {
38*d5c9a868SElliott Hughes 	wchar_t first, last;
39*d5c9a868SElliott Hughes 	int found=0;
40*d5c9a868SElliott Hughes 	if (**p == '^') {
41*d5c9a868SElliott Hughes 		*reverse = 1;
42*d5c9a868SElliott Hughes 		(*p)++;
43*d5c9a868SElliott Hughes 	} else
44*d5c9a868SElliott Hughes 		*reverse=0;
45*d5c9a868SElliott Hughes 	while( (first = **p) != ']') {
46*d5c9a868SElliott Hughes 		if(!first)
47*d5c9a868SElliott Hughes 			/* Malformed pattern, range not closed */
48*d5c9a868SElliott Hughes 			return 0;
49*d5c9a868SElliott Hughes 		if(*(++(*p)) == '-') {
50*d5c9a868SElliott Hughes 			last = *(++(*p));
51*d5c9a868SElliott Hughes 			if(last==']') {
52*d5c9a868SElliott Hughes 				/* Last "-" in range designates itself */
53*d5c9a868SElliott Hughes 				if(ch == first || ch == '-')
54*d5c9a868SElliott Hughes 					found = 1;
55*d5c9a868SElliott Hughes 				break;
56*d5c9a868SElliott Hughes 			}
57*d5c9a868SElliott Hughes 			(*p)++;
58*d5c9a868SElliott Hughes 
59*d5c9a868SElliott Hughes 			/* a proper range */
60*d5c9a868SElliott Hughes 			if(ch >= first && ch <= last)
61*d5c9a868SElliott Hughes 				found = 1;
62*d5c9a868SElliott Hughes 		} else
63*d5c9a868SElliott Hughes 			/* a Just one character */
64*d5c9a868SElliott Hughes 			if(ch == first)
65*d5c9a868SElliott Hughes 				found = 1;
66*d5c9a868SElliott Hughes 	}
67*d5c9a868SElliott Hughes 	return found;
68*d5c9a868SElliott Hughes }
69*d5c9a868SElliott Hughes 
parse_range(const wchar_t ** p,const wchar_t * s,wchar_t * out,int (* compfn)(wchar_t a,wchar_t b))70*d5c9a868SElliott Hughes static int parse_range(const wchar_t **p, const wchar_t *s, wchar_t *out,
71*d5c9a868SElliott Hughes 		       int (*compfn)(wchar_t a, wchar_t b))
72*d5c9a868SElliott Hughes {
73*d5c9a868SElliott Hughes 	int reverse;
74*d5c9a868SElliott Hughes 	const wchar_t *p0 = *p;
75*d5c9a868SElliott Hughes 	const wchar_t *p1 = *p;
76*d5c9a868SElliott Hughes 	if(out)
77*d5c9a868SElliott Hughes 		*out = *s;
78*d5c9a868SElliott Hughes 	if(is_in_range(*s, p, &reverse))
79*d5c9a868SElliott Hughes 		return 1 ^ reverse;
80*d5c9a868SElliott Hughes 	if(compfn == exactcmp)
81*d5c9a868SElliott Hughes 		return reverse;
82*d5c9a868SElliott Hughes 	if(is_in_range((wchar_t)towlower((wint_t)*s), &p0, &reverse)) {
83*d5c9a868SElliott Hughes 		if(out)
84*d5c9a868SElliott Hughes 			*out = (wchar_t)towlower((wint_t)*s);
85*d5c9a868SElliott Hughes 		return 1 ^ reverse;
86*d5c9a868SElliott Hughes 	}
87*d5c9a868SElliott Hughes 	if(is_in_range((wchar_t)towupper((wint_t)*s), &p1, &reverse)) {
88*d5c9a868SElliott Hughes 		if(out)
89*d5c9a868SElliott Hughes 			*out = (wchar_t)towupper((wint_t)*s);
90*d5c9a868SElliott Hughes 		return 1 ^ reverse;
91*d5c9a868SElliott Hughes 	}
92*d5c9a868SElliott Hughes 	return reverse;
93*d5c9a868SElliott Hughes }
94*d5c9a868SElliott Hughes 
95*d5c9a868SElliott Hughes 
_match(const wchar_t * s,const wchar_t * p,wchar_t * out,int Case,int length,int (* compfn)(wchar_t a,wchar_t b))96*d5c9a868SElliott Hughes static int _match(const wchar_t *s, const wchar_t *p, wchar_t *out, int Case,
97*d5c9a868SElliott Hughes 		  int length,
98*d5c9a868SElliott Hughes 		  int (*compfn) (wchar_t a, wchar_t b))
99*d5c9a868SElliott Hughes {
100*d5c9a868SElliott Hughes 	for (; *p != '\0' && length; ) {
101*d5c9a868SElliott Hughes 		switch (*p) {
102*d5c9a868SElliott Hughes 			case '?':	/* match any one character */
103*d5c9a868SElliott Hughes 				if (*s == '\0')
104*d5c9a868SElliott Hughes 					return(0);
105*d5c9a868SElliott Hughes 				if(out)
106*d5c9a868SElliott Hughes 					*(out++) = *s;
107*d5c9a868SElliott Hughes 				break;
108*d5c9a868SElliott Hughes 			case '*':	/* match everything */
109*d5c9a868SElliott Hughes 				while (*p == '*' && length) {
110*d5c9a868SElliott Hughes 					p++;
111*d5c9a868SElliott Hughes 					length--;
112*d5c9a868SElliott Hughes 				}
113*d5c9a868SElliott Hughes 
114*d5c9a868SElliott Hughes 					/* search for next char in pattern */
115*d5c9a868SElliott Hughes 				while(*s) {
116*d5c9a868SElliott Hughes 					if(_match(s, p, out, Case, length,
117*d5c9a868SElliott Hughes 						  compfn))
118*d5c9a868SElliott Hughes 						return 1;
119*d5c9a868SElliott Hughes 					if(out)
120*d5c9a868SElliott Hughes 						*out++ = *s;
121*d5c9a868SElliott Hughes 					s++;
122*d5c9a868SElliott Hughes 				}
123*d5c9a868SElliott Hughes 				continue;
124*d5c9a868SElliott Hughes 			case '[':	 /* match range of characters */
125*d5c9a868SElliott Hughes 				p++;
126*d5c9a868SElliott Hughes 				length--;
127*d5c9a868SElliott Hughes 				if(!parse_range(&p, s, out++, compfn))
128*d5c9a868SElliott Hughes 					return 0;
129*d5c9a868SElliott Hughes 				break;
130*d5c9a868SElliott Hughes 			case '\\':	/* Literal match with next character */
131*d5c9a868SElliott Hughes 				p++;
132*d5c9a868SElliott Hughes 				length--;
133*d5c9a868SElliott Hughes 				/* fall thru */
134*d5c9a868SElliott Hughes 			default:
135*d5c9a868SElliott Hughes 				if (!compfn(*s,*p))
136*d5c9a868SElliott Hughes 					return(0);
137*d5c9a868SElliott Hughes 				if(out)
138*d5c9a868SElliott Hughes 					*(out++) = *p;
139*d5c9a868SElliott Hughes 				break;
140*d5c9a868SElliott Hughes 		}
141*d5c9a868SElliott Hughes 		p++;
142*d5c9a868SElliott Hughes 		length--;
143*d5c9a868SElliott Hughes 		s++;
144*d5c9a868SElliott Hughes 	}
145*d5c9a868SElliott Hughes 	if(out)
146*d5c9a868SElliott Hughes 		*out = '\0';
147*d5c9a868SElliott Hughes 
148*d5c9a868SElliott Hughes 					/* string ended prematurely ? */
149*d5c9a868SElliott Hughes 	if (*s != '\0')
150*d5c9a868SElliott Hughes 		return(0);
151*d5c9a868SElliott Hughes 	else
152*d5c9a868SElliott Hughes 		return(1);
153*d5c9a868SElliott Hughes }
154*d5c9a868SElliott Hughes 
155*d5c9a868SElliott Hughes 
match(const wchar_t * s,const wchar_t * p,wchar_t * out,int Case,int length)156*d5c9a868SElliott Hughes int match(const wchar_t *s, const wchar_t *p, wchar_t *out, int Case, int length)
157*d5c9a868SElliott Hughes {
158*d5c9a868SElliott Hughes 	int (*compfn)(wchar_t a, wchar_t b);
159*d5c9a868SElliott Hughes 
160*d5c9a868SElliott Hughes 	if(Case)
161*d5c9a868SElliott Hughes 		compfn = casecmp;
162*d5c9a868SElliott Hughes 	else
163*d5c9a868SElliott Hughes 		/*compfn = exactcmp;*/
164*d5c9a868SElliott Hughes 		compfn = casecmp;
165*d5c9a868SElliott Hughes 	return _match(s, p, out, Case, length, compfn);
166*d5c9a868SElliott Hughes }
167*d5c9a868SElliott Hughes 
168