Another update from Larry:
[oweals/busybox.git] / libbb / check_wildcard_match.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) tons of folks.  Tracking down who wrote what
6  * isn't something I'm going to worry about...  If you wrote something
7  * here, please feel free to acknowledge your work.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  * Based in part on code from sash, Copyright (c) 1999 by David I. Bell 
24  * Permission has been granted to redistribute this code under the GPL.
25  *
26  */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include "libbb.h"
31
32
33 /*
34  * Routine to see if a text string is matched by a wildcard pattern.
35  * Returns TRUE if the text is matched, or FALSE if it is not matched
36  * or if the pattern is invalid.
37  *  *           matches zero or more characters
38  *  ?           matches a single character
39  *  [abc]       matches 'a', 'b' or 'c'
40  *  \c          quotes character c
41  * Adapted from code written by Ingo Wilken, and
42  * then taken from sash, Copyright (c) 1999 by David I. Bell
43  * Permission is granted to use, distribute, or modify this source,
44  * provided that this copyright notice remains intact.
45  * Permission to distribute this code under the GPL has been granted.
46  */
47 extern int check_wildcard_match(const char *text, const char *pattern)
48 {
49         const char *retryPat;
50         const char *retryText;
51         int ch;
52         int found;
53         int len;
54
55         retryPat = NULL;
56         retryText = NULL;
57
58         while (*text || *pattern) {
59                 ch = *pattern++;
60
61                 switch (ch) {
62                 case '*':
63                         retryPat = pattern;
64                         retryText = text;
65                         break;
66
67                 case '[':
68                         found = FALSE;
69
70                         while ((ch = *pattern++) != ']') {
71                                 if (ch == '\\')
72                                         ch = *pattern++;
73
74                                 if (ch == '\0')
75                                         return FALSE;
76
77                                 if (*text == ch)
78                                         found = TRUE;
79                         }
80                         len=strlen(text);
81                         if (found == FALSE && len!=0) {
82                                 return FALSE;
83                         }
84                         if (found == TRUE) {
85                                 if (strlen(pattern)==0 && len==1) {
86                                         return TRUE;
87                                 }
88                                 if (len!=0) {
89                                         text++;
90                                         continue;
91                                 }
92                         }
93
94                         /* fall into next case */
95
96                 case '?':
97                         if (*text++ == '\0')
98                                 return FALSE;
99
100                         break;
101
102                 case '\\':
103                         ch = *pattern++;
104
105                         if (ch == '\0')
106                                 return FALSE;
107
108                         /* fall into next case */
109
110                 default:
111                         if (*text == ch) {
112                                 if (*text)
113                                         text++;
114                                 break;
115                         }
116
117                         if (*text) {
118                                 pattern = retryPat;
119                                 text = ++retryText;
120                                 break;
121                         }
122
123                         return FALSE;
124                 }
125
126                 if (pattern == NULL)
127                         return FALSE;
128         }
129
130         return TRUE;
131 }
132
133
134 /* END CODE */
135 /*
136 Local Variables:
137 c-file-style: "linux"
138 c-basic-offset: 4
139 tab-width: 4
140 End:
141 */