#include #include typedef struct RE RE; RE* RE_compile(char *); int RE_match(RE *, char *); char *RE_start(RE *); char *RE_end(RE *); void RE_free(RE *); int yes(char *, char *, char *); int no(char *, char *); int err(char *); RE *lre; /* last regular expression; used by yes, no, err */ int main(int argc, char *argv[]) { char buf[1000], regexp[1000], str[1000], result[1000]; char *p; int nfail = 0, line, nf, stat, ntest = 0; /* input: x axb a[x]b x abc x* "" [] x*a abxab [a]bxab conventions: literal "" is replaced by empty string so empty fields can be used literal @ is replaced by ' ' so \s and \S can be tested */ for (line = 1; fgets(buf, sizeof buf, stdin) != NULL; line++) { buf[strlen(buf)-1] = 0; /* kill \n */ if (strlen(buf) == 0) /* skip blank lines */ continue; stat = 0; lre = 0; regexp[0] = str[0] = result[0] = 0; nf = sscanf(buf, "%s %s %s", regexp, str, result); if (strcmp(regexp, "\"\"") == 0) regexp[0] = 0; if (strcmp(str, "\"\"") == 0) str[0] = 0; if (strcmp(result, "\"\"") == 0) result[0] = 0; for (p = result; (p = strchr(result, '@')) != NULL; ) *p = ' '; for (p = str; (p = strchr(str, '@')) != NULL; ) *p = ' '; for (p = result; (p = strchr(result, '@')) != NULL; ) *p = ' '; switch (nf) { case 3: /* should match */ stat = yes(regexp, str, result); if (stat > 0) { char *start, *end; start = RE_start(lre); end = RE_end(lre); if (start == NULL) { printf("start == NULL\n"); } else if (end == NULL) { printf("end == NULL\n"); } else if (start >= str && start <= end && end >= str+strlen(str)) { printf("start = '%s', end = '%s'\n", start, end); } else { printf("start or end invalid\n"); } } RE_free(lre); break; case 2: /* should not match */ stat = no(regexp, str); RE_free(lre); break; default: /* die?? */ printf("bad test %3d: %s\n", line, buf); break; } if (stat > 0) printf("failure at line %3d %s\n", line, buf); nfail += stat; ntest++; } printf("%d fail %d tests\n", nfail, ntest); return nfail; } int yes(char *regexp, char *str, char *result) { lre = RE_compile(regexp); if (lre == NULL) return 1; if (!RE_match(lre, str)) return 1; if (RE_start(lre) > RE_end(lre)) return 1; if (RE_start(lre) == NULL) /* if there's a match, should be a string */ return 1; if (RE_end(lre) == NULL) /* these tests not fully thought out */ return 1; if (result[RE_start(lre)-str] != '[') { printf("bad [\n"); return 1; } if (result[RE_end(lre)-str+1] != ']') { printf("bad ]\n"); return 1; } return 0; } int no(char *regexp, char *str) { lre = RE_compile(regexp); if (lre == NULL) return 1; if (RE_match(lre, str)) return 1; return 0; } int err(char *regexp) { lre = RE_compile(regexp); if (lre != NULL) return 1; return 0; }