source: buchla-68k/orig/GEMDOS/FMATCH.C@ 30c03a4

Last change on this file since 30c03a4 was 3ae31e9, checked in by Thomas Lopatic <thomas@…>, 8 years ago

Imported original source code.

  • Property mode set to 100755
File size: 7.5 KB
Line 
1/*
2 =============================================================================
3 fmatch.c -- match file name to wildcard pattern
4 Version 1 -- 1987-03-22
5
6 Usenet public domain source code.
7 =============================================================================
8*/
9
10#include "stdio.h"
11
12#define ASTERISK '*' /* The '*' metacharacter */
13#define QUESTION '?' /* The '?' metacharacter */
14#define LEFT_BR '[' /* The '[' metacharacter */
15#define RIGHT_BR ']' /* The ']' metacharacter */
16
17#define IS_OCTAL(ch) (ch >= '0' && ch <= '7')
18
19typedef int BOOLEAN;
20
21#define VOID int
22#define TRUE 1
23#define FALSE 0
24#define EOS '\000'
25
26static BOOLEAN do_list ();
27static char nextch ();
28static VOID list_parse ();
29
30/*
31 */
32
33/*
34 * FUNCTION
35 *
36 * match test string for wildcard match
37 *
38 * SYNOPSIS
39 *
40 * BOOLEAN match (string, pattern)
41 * register char *string;
42 * register char *pattern;
43 *
44 * DESCRIPTION
45 *
46 * Test string for match using pattern. The pattern may
47 * contain the normal shell metacharacters for pattern
48 * matching. The '*' character matches any string,
49 * including the null string. The '?' character matches
50 * any single character. A list of characters enclosed
51 * in '[' and ']' matches any character in the list.
52 * If the first character following the beginning '['
53 * is a '!' then any character not in the list is matched.
54 *
55 */
56
57/*
58 */
59
60/*
61 * PSEUDO CODE
62 *
63 * Begin match
64 * Switch on type of pattern character
65 * Case ASTERISK:
66 * Attempt to match asterisk
67 * Break
68 * Case QUESTION MARK:
69 * Attempt to match question mark
70 * Break
71 * Case EOS:
72 * Match is result of EOS on string test
73 * Break
74 * Case default:
75 * If explicit match then
76 * Match is result of submatch
77 * Else
78 * Match is FALSE
79 * End if
80 * Break
81 * End switch
82 * Return result of match test
83 * End match
84 *
85 */
86
87static BOOLEAN match (string, pattern)
88register char *string;
89register char *pattern;
90{
91 register BOOLEAN ismatch;
92
93 ismatch = FALSE;
94 switch (*pattern) {
95
96 case ASTERISK:
97 pattern++;
98 do {
99 ismatch = match (string, pattern);
100 } while (!ismatch && *string++ != EOS);
101 break;
102
103 case QUESTION:
104 if (*string != EOS) {
105 ismatch = match (++string, ++pattern);
106 }
107 break;
108
109 case EOS:
110 if (*string == EOS) {
111 ismatch = TRUE;
112 }
113 break;
114
115 case LEFT_BR:
116 if (*string != EOS) {
117 ismatch = do_list (string, pattern);
118 }
119 break;
120
121 default:
122 if (tolower(*string) == tolower(*pattern)) {
123 string++;
124 pattern++;
125 ismatch = match (string, pattern);
126 } else {
127 ismatch = FALSE;
128 }
129 break;
130 }
131 return (ismatch);
132}
133
134/*
135 */
136
137/*
138 * FUNCTION
139 *
140 * do_list process a list and following substring
141 *
142 * SYNOPSIS
143 *
144 * static BOOLEAN do_list (string, pattern)
145 * register char *string;
146 * register char *pattern;
147 *
148 * DESCRIPTION
149 *
150 * Called when a list is found in the pattern. Returns
151 * TRUE if the current character matches the list and
152 * the remaining substring matches the remaining pattern.
153 *
154 * Returns FALSE if either the current character fails to
155 * match the list or the list matches but the remaining
156 * substring and subpattern's don't.
157 *
158 * RESTRICTIONS
159 *
160 * The mechanism used to match characters in an inclusive
161 * pair (I.E. [a-d]) may not be portable to machines
162 * in which the native character set is not ASCII.
163 *
164 * The rules implemented here are:
165 *
166 * (1) The backslash character may be
167 * used to quote any special character.
168 * I.E. "\]" and "\-" anywhere in list,
169 * or "\!" at start of list.
170 *
171 * (2) The sequence \nnn becomes the character
172 * given by nnn (in octal).
173 *
174 * (3) Any non-escaped ']' marks the end of list.
175 *
176 * (4) A list beginning with the special character
177 * '!' matches any character NOT in list.
178 * The '!' character is only special if it
179 * is the first character in the list.
180 *
181 */
182
183/*
184* /
185
186/*
187 * PSEUDO CODE
188 *
189 * Begin do_list
190 * Default result is no match
191 * Skip over the opening left bracket
192 * If the next pattern character is a '!' then
193 * List match gives FALSE
194 * Skip over the '!' character
195 * Else
196 * List match gives TRUE
197 * End if
198 * While not at closing bracket or EOS
199 * Get lower and upper bounds
200 * If character in bounds then
201 * Result is same as sense flag.
202 * Skip over rest of list
203 * End if
204 * End while
205 * If match found then
206 * If not at end of pattern then
207 * Call match with rest of pattern
208 * End if
209 * End if
210 * Return match result
211 * End do_list
212 *
213 */
214
215static BOOLEAN do_list (string, pattern)
216register char *string;
217char *pattern;
218{
219 register BOOLEAN ismatch;
220 register BOOLEAN if_found;
221 register BOOLEAN if_not_found;
222 auto char lower;
223 auto char upper;
224
225 pattern++;
226
227 if (*pattern == '!') {
228 if_found = FALSE;
229 if_not_found = TRUE;
230 pattern++;
231 } else {
232 if_found = TRUE;
233 if_not_found = FALSE;
234 }
235
236 ismatch = if_not_found;
237
238 while (*pattern != ']' && *pattern != EOS) {
239 list_parse (&pattern, &lower, &upper);
240
241 if (*string >= lower && *string <= upper) {
242 ismatch = if_found;
243
244 while (*pattern != ']' && *pattern != EOS) {pattern++;}
245 }
246 }
247
248 if (*pattern++ != ']') {
249 fprintf (stderr, "warning - character class error\n");
250 } else {
251
252 if (ismatch) {
253 ismatch = match (++string, pattern);
254 }
255 }
256
257 return (ismatch);
258}
259
260/*
261 */
262
263/*
264 * FUNCTION
265 *
266 * list_parse parse part of list into lower and upper bounds
267 *
268 * SYNOPSIS
269 *
270 * static VOID list_parse (patp, lowp, highp)
271 * char **patp;
272 * char *lowp;
273 * char *highp;
274 *
275 * DESCRIPTION
276 *
277 * Given pointer to a pattern pointer (patp), pointer to
278 * a place to store lower bound (lowp), and pointer to a
279 * place to store upper bound (highp), parses part of
280 * the list, updating the pattern pointer in the process.
281 *
282 * For list characters which are not part of a range,
283 * the lower and upper bounds are set to that character.
284 *
285 */
286
287static VOID list_parse (patp, lowp, highp)
288char **patp;
289char *lowp;
290char *highp;
291{
292 *lowp = nextch (patp);
293 if (**patp == '-') {
294 (*patp)++;
295 *highp = nextch (patp);
296 } else {
297 *highp = *lowp;
298 }
299}
300
301/*
302 */
303
304/*
305 * FUNCTION
306 *
307 * nextch determine next character in a pattern
308 *
309 * SYNOPSIS
310 *
311 * static char nextch (patp)
312 * char **patp;
313 *
314 * DESCRIPTION
315 *
316 * Given pointer to a pointer to a pattern, uses the pattern
317 * pointer to determine the next character in the pattern,
318 * subject to translation of backslash-char and backslash-octal
319 * sequences.
320 *
321 * The character pointer is updated to point at the next pattern
322 * character to be processed.
323 *
324 */
325
326static char nextch (patp)
327char **patp;
328{
329 register char ch;
330 register char chsum;
331 register int count;
332
333 ch = *(*patp)++;
334 if (ch == '\\') {
335 ch = *(*patp)++;
336 if (IS_OCTAL (ch)) {
337 chsum = 0;
338 for (count = 0; count < 3 && IS_OCTAL (ch); count++) {
339 chsum *= 8;
340 chsum += ch - '0';
341 ch = *(*patp)++;
342 }
343 (*patp)--;
344 ch = chsum;
345 }
346 }
347 return (ch);
348}
349
350/*
351 * Filename match - here, *.* matches everything
352 */
353
354BOOLEAN fmatch (string, pattern)
355char *string;
356char *pattern;
357{
358 char *ptr;
359
360 if(*string && !strcmp(pattern, "*.*"))
361 return(TRUE);
362 return(match(string, pattern));
363}
Note: See TracBrowser for help on using the repository browser.