ms_fnmatch test program
[tridge/junkcode.git] / fnmatch / ms_fnmatch.c
diff --git a/fnmatch/ms_fnmatch.c b/fnmatch/ms_fnmatch.c
new file mode 100644 (file)
index 0000000..c605c64
--- /dev/null
@@ -0,0 +1,173 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <ctype.h>
+
+/*
+  the original, recursive function. Needs replacing, but with exactly
+  the same output
+*/
+static int fnmatch_orig(const char *p, const char *n)
+{
+       char c;
+
+       while ((c = *p++)) {
+               switch (c) {
+               case '?':
+                       if (! *n) return -1;
+                       n++;
+                       break;
+
+               case '>':
+                       if (n[0] == '.') {
+                               if (! n[1] && fnmatch_orig(p, n+1) == 0) return 0;
+                               if (fnmatch_orig(p, n) == 0) return 0;
+                               return -1;
+                       }
+                       if (! *n) return fnmatch_orig(p, n);
+                       n++;
+                       break;
+
+               case '*':
+                       for (; *n; n++) {
+                               if (fnmatch_orig(p, n) == 0) return 0;
+                       }
+                       break;
+
+               case '<':
+                       for (; *n; n++) {
+                               if (fnmatch_orig(p, n) == 0) return 0;
+                               if (*n == '.' && !strchr(n+1,'.')) {
+                                       n++;
+                                       break;
+                               }
+                       }
+                       break;
+
+               case '"':
+                       if (*n == 0 && fnmatch_orig(p, n) == 0) return 0;
+                       if (*n != '.') return -1;
+                       n++;
+                       break;
+
+               default:
+                       if (c != *n && toupper(c) != toupper(*n)) return -1;
+                       n++;
+               }
+       }
+       
+       if (! *n) return 0;
+       
+       return -1;
+}
+
+
+/*
+  the new, hopefully better function. Fiddle this until it works and is fast
+*/
+static int fnmatch_test(const char *p, const char *n)
+{
+       char c;
+
+       while ((c = *p++)) {
+               switch (c) {
+               case '?':
+                       if (! *n) return -1;
+                       n++;
+                       break;
+
+               case '>':
+                       if (n[0] == '.') {
+                               if (! n[1] && fnmatch_test(p, n+1) == 0) return 0;
+                               if (fnmatch_test(p, n) == 0) return 0;
+                               return -1;
+                       }
+                       if (! *n) return fnmatch_test(p, n);
+                       n++;
+                       break;
+
+               case '*':
+                       for (; *n; n++) {
+                               if (fnmatch_test(p, n) == 0) return 0;
+                       }
+                       break;
+
+               case '<':
+                       for (; *n; n++) {
+                               if (fnmatch_test(p, n) == 0) return 0;
+                               if (*n == '.' && !strchr(n+1,'.')) {
+                                       n++;
+                                       break;
+                               }
+                       }
+                       break;
+
+               case '"':
+                       if (*n == 0 && fnmatch_test(p, n) == 0) return 0;
+                       if (*n != '.') return -1;
+                       n++;
+                       break;
+
+               default:
+                       if (c != *n && toupper(c) != toupper(*n)) return -1;
+                       n++;
+               }
+       }
+       
+       if (! *n) return 0;
+       
+       return -1;
+}
+
+
+static void randstring(char *s, int len, const char *chars)
+{
+       while (len--) {
+               *s++ = chars[random() % strlen(chars)];
+       }
+       *s = 0;
+}
+
+
+int main(void)
+{
+       int i;
+       srandom(time(NULL));
+
+       alarm(2);
+       fnmatch_test("********************************************.dat", "foobar.txt");
+       fnmatch_test("*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<*<.dat", "foobar.txt");
+       alarm(0);
+
+       for (i=0;i<100000;i++) {
+               int len1 = random() % 20;
+               int len2 = random() % 20;
+               char *p = malloc(len1+1);
+               char *n = malloc(len2+1);
+               int ret1, ret2;
+
+               randstring(p, len1, "*?<>\".abc");
+               randstring(n, len2, "abc.");
+
+               ret1 = fnmatch_orig(p, n);
+               ret2 = fnmatch_test(p, n);
+
+               if (ret1 != ret2) {
+                       printf("mismatch: ret1=%d ret2=%d pattern='%s' string='%s'\n",
+                              ret1, ret2, p, n);
+                       free(p);
+                       free(n);
+                       exit(0);
+               }
+
+               free(p);
+               free(n);
+               printf("%d\r", i);
+               fflush(stdout);
+       }
+
+       printf("ALL OK\n");
+       return 0;
+}