3a5fc2a9c2f4d9223e33598d3412f433448e2d8e
[tridge/junkcode.git] / fnmatch / ms_fnmatch.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <time.h>
6 #include <signal.h>
7 #include <ctype.h>
8
9 /*
10   the original, recursive function. Needs replacing, but with exactly
11   the same output
12 */
13 static int fnmatch_orig(const char *p, const char *n)
14 {
15         char c;
16
17         while ((c = *p++)) {
18                 switch (c) {
19                 case '?':
20                         if (! *n) return -1;
21                         n++;
22                         break;
23
24                 case '>':
25                         if (n[0] == '.') {
26                                 if (! n[1] && fnmatch_orig(p, n+1) == 0) return 0;
27                                 if (fnmatch_orig(p, n) == 0) return 0;
28                                 return -1;
29                         }
30                         if (! *n) return fnmatch_orig(p, n);
31                         n++;
32                         break;
33
34                 case '*':
35                         for (; *n; n++) {
36                                 if (fnmatch_orig(p, n) == 0) return 0;
37                         }
38                         break;
39
40                 case '<':
41                         for (; *n; n++) {
42                                 if (fnmatch_orig(p, n) == 0) return 0;
43                                 if (*n == '.' && !strchr(n+1,'.')) {
44                                         n++;
45                                         break;
46                                 }
47                         }
48                         break;
49
50                 case '"':
51                         if (*n == 0 && fnmatch_orig(p, n) == 0) return 0;
52                         if (*n != '.') return -1;
53                         n++;
54                         break;
55
56                 default:
57                         if (c != *n && toupper(c) != toupper(*n)) return -1;
58                         n++;
59                 }
60         }
61         
62         if (! *n) return 0;
63         
64         return -1;
65 }
66
67
68 /*
69   the new, hopefully better function. Fiddle this until it works and is fast
70 */
71 static int fnmatch_test(const char *p, const char *n)
72 {
73         char c;
74
75         while ((c = *p++)) {
76                 switch (c) {
77                 case '?':
78                         if (! *n) return -1;
79                         n++;
80                         break;
81
82                 case '>':
83                         if (n[0] == '.') {
84                                 if (! n[1] && fnmatch_test(p, n+1) == 0) return 0;
85                                 if (fnmatch_test(p, n) == 0) return 0;
86                                 return -1;
87                         }
88                         if (! *n) return fnmatch_test(p, n);
89                         n++;
90                         break;
91
92                 case '*':
93                         for (; *n; n++) {
94                                 if (fnmatch_test(p, n) == 0) return 0;
95                         }
96                         break;
97
98                 case '<':
99                         for (; *n; n++) {
100                                 if (fnmatch_test(p, n) == 0) return 0;
101                                 if (*n == '.' && !strchr(n+1,'.')) {
102                                         n++;
103                                         break;
104                                 }
105                         }
106                         break;
107
108                 case '"':
109                         if (*n == 0 && fnmatch_test(p, n) == 0) return 0;
110                         if (*n != '.') return -1;
111                         n++;
112                         break;
113
114                 default:
115                         if (c != *n && toupper(c) != toupper(*n)) return -1;
116                         n++;
117                 }
118         }
119         
120         if (! *n) return 0;
121         
122         return -1;
123 }
124
125
126 static void randstring(char *s, int len, const char *chars)
127 {
128         while (len--) {
129                 *s++ = chars[random() % strlen(chars)];
130         }
131         *s = 0;
132 }
133
134 static void sig_alrm(int sig)
135 {
136         printf("Too slow!!\n");
137         exit(0);
138 }
139
140 int main(void)
141 {
142         int i;
143         srandom(time(NULL));
144
145         signal(SIGALRM, sig_alrm);
146
147         alarm(2);
148         fnmatch_test("********************************************.dat", "foobar.txt");
149         fnmatch_test("*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<.dat", "foobar.txt");
150         alarm(0);
151
152         for (i=0;i<100000;i++) {
153                 int len1 = random() % 20;
154                 int len2 = random() % 20;
155                 char *p = malloc(len1+1);
156                 char *n = malloc(len2+1);
157                 int ret1, ret2;
158
159                 randstring(p, len1, "*?<>\".abc");
160                 randstring(n, len2, "abc.");
161
162                 ret1 = fnmatch_orig(p, n);
163                 ret2 = fnmatch_test(p, n);
164
165                 if (ret1 != ret2) {
166                         printf("mismatch: ret1=%d ret2=%d pattern='%s' string='%s'\n",
167                                ret1, ret2, p, n);
168                         free(p);
169                         free(n);
170                         exit(0);
171                 }
172
173                 free(p);
174                 free(n);
175                 printf("%d\r", i);
176                 fflush(stdout);
177         }
178
179         printf("ALL OK\n");
180         return 0;
181 }