| /* |
| * testRegexp.c: simple module for testing regular expressions |
| * |
| * See Copyright for the status of this software. |
| * |
| * Daniel Veillard <veillard@redhat.com> |
| */ |
| |
| #include <string.h> |
| #include "libxml.h" |
| #ifdef LIBXML_AUTOMATA_ENABLED |
| |
| #include <libxml/tree.h> |
| #include <libxml/xmlautomata.h> |
| |
| static int scanNumber(char **ptr) { |
| int ret = 0; |
| char *cur; |
| |
| cur = *ptr; |
| while ((*cur >= '0') && (*cur <= '9')) { |
| ret = ret * 10 + (*cur - '0'); |
| cur++; |
| } |
| *ptr = cur; |
| return(ret); |
| } |
| |
| static void |
| testRegexpFile(const char *filename) { |
| FILE *input; |
| char exp[5000]; |
| int len; |
| int ret; |
| int i; |
| xmlAutomataPtr am; |
| xmlAutomataStatePtr states[1000]; |
| xmlRegexpPtr regexp = NULL; |
| xmlRegExecCtxtPtr exec = NULL; |
| |
| for (i = 0;i<1000;i++) |
| states[i] = NULL; |
| |
| input = fopen(filename, "r"); |
| if (input == NULL) { |
| xmlGenericError(xmlGenericErrorContext, |
| "Cannot open %s for reading\n", filename); |
| return; |
| } |
| |
| am = xmlNewAutomata(); |
| if (am == NULL) { |
| xmlGenericError(xmlGenericErrorContext, |
| "Cannot create automata\n"); |
| fclose(input); |
| } |
| states[0] = xmlAutomataGetInitState(am); |
| if (states[0] == NULL) { |
| xmlGenericError(xmlGenericErrorContext, |
| "Cannot get start state\n"); |
| xmlFreeAutomata(am); |
| fclose(input); |
| } |
| ret = 0; |
| |
| while (fgets(exp, 4500, input) != NULL) { |
| if (exp[0] == '#') |
| continue; |
| len = strlen(exp); |
| len--; |
| while ((len >= 0) && |
| ((exp[len] == '\n') || (exp[len] == '\t') || |
| (exp[len] == '\r') || (exp[len] == ' '))) len--; |
| exp[len + 1] = 0; |
| if (len >= 0) { |
| if ((am != NULL) && (exp[0] == 't') && (exp[1] == ' ')) { |
| char *ptr = &exp[2]; |
| int from, to; |
| |
| from = scanNumber(&ptr); |
| if (*ptr != ' ') { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad line %s\n", exp); |
| break; |
| } |
| if (states[from] == NULL) |
| states[from] = xmlAutomataNewState(am); |
| ptr++; |
| to = scanNumber(&ptr); |
| if (*ptr != ' ') { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad line %s\n", exp); |
| break; |
| } |
| if (states[to] == NULL) |
| states[to] = xmlAutomataNewState(am); |
| ptr++; |
| xmlAutomataNewTransition(am, states[from], states[to], |
| BAD_CAST ptr, NULL); |
| } else if ((am != NULL) && (exp[0] == 'e') && (exp[1] == ' ')) { |
| char *ptr = &exp[2]; |
| int from, to; |
| |
| from = scanNumber(&ptr); |
| if (*ptr != ' ') { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad line %s\n", exp); |
| break; |
| } |
| if (states[from] == NULL) |
| states[from] = xmlAutomataNewState(am); |
| ptr++; |
| to = scanNumber(&ptr); |
| if (states[to] == NULL) |
| states[to] = xmlAutomataNewState(am); |
| xmlAutomataNewEpsilon(am, states[from], states[to]); |
| } else if ((am != NULL) && (exp[0] == 'f') && (exp[1] == ' ')) { |
| char *ptr = &exp[2]; |
| int state; |
| |
| state = scanNumber(&ptr); |
| if (states[state] == NULL) { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad state %d : %s\n", state, exp); |
| break; |
| } |
| xmlAutomataSetFinalState(am, states[state]); |
| } else if ((am != NULL) && (exp[0] == 'c') && (exp[1] == ' ')) { |
| char *ptr = &exp[2]; |
| int from, to; |
| int min, max; |
| |
| from = scanNumber(&ptr); |
| if (*ptr != ' ') { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad line %s\n", exp); |
| break; |
| } |
| if (states[from] == NULL) |
| states[from] = xmlAutomataNewState(am); |
| ptr++; |
| to = scanNumber(&ptr); |
| if (*ptr != ' ') { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad line %s\n", exp); |
| break; |
| } |
| if (states[to] == NULL) |
| states[to] = xmlAutomataNewState(am); |
| ptr++; |
| min = scanNumber(&ptr); |
| if (*ptr != ' ') { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad line %s\n", exp); |
| break; |
| } |
| ptr++; |
| max = scanNumber(&ptr); |
| if (*ptr != ' ') { |
| xmlGenericError(xmlGenericErrorContext, |
| "Bad line %s\n", exp); |
| break; |
| } |
| ptr++; |
| xmlAutomataNewCountTrans(am, states[from], states[to], |
| BAD_CAST ptr, min, max, NULL); |
| } else if ((am != NULL) && (exp[0] == '-') && (exp[1] == '-')) { |
| /* end of the automata */ |
| regexp = xmlAutomataCompile(am); |
| xmlFreeAutomata(am); |
| am = NULL; |
| if (regexp == NULL) { |
| xmlGenericError(xmlGenericErrorContext, |
| "Failed to compile the automata"); |
| break; |
| } |
| } else if ((exp[0] == '=') && (exp[1] == '>')) { |
| if (regexp == NULL) { |
| printf("=> failed not compiled\n"); |
| } else { |
| if (exec == NULL) |
| exec = xmlRegNewExecCtxt(regexp, NULL, NULL); |
| if (ret == 0) { |
| ret = xmlRegExecPushString(exec, NULL, NULL); |
| } |
| if (ret == 1) |
| printf("=> Passed\n"); |
| else if ((ret == 0) || (ret == -1)) |
| printf("=> Failed\n"); |
| else if (ret < 0) |
| printf("=> Error\n"); |
| xmlRegFreeExecCtxt(exec); |
| exec = NULL; |
| } |
| ret = 0; |
| } else if (regexp != NULL) { |
| if (exec == NULL) |
| exec = xmlRegNewExecCtxt(regexp, NULL, NULL); |
| ret = xmlRegExecPushString(exec, BAD_CAST exp, NULL); |
| } else { |
| xmlGenericError(xmlGenericErrorContext, |
| "Unexpected line %s\n", exp); |
| } |
| } |
| } |
| fclose(input); |
| if (regexp != NULL) |
| xmlRegFreeRegexp(regexp); |
| if (exec != NULL) |
| xmlRegFreeExecCtxt(exec); |
| if (am != NULL) |
| xmlFreeAutomata(am); |
| } |
| |
| int main(int argc, char **argv) { |
| |
| xmlInitMemory(); |
| |
| if (argc == 1) { |
| int ret; |
| xmlAutomataPtr am; |
| xmlAutomataStatePtr start, cur; |
| xmlRegexpPtr regexp; |
| xmlRegExecCtxtPtr exec; |
| |
| am = xmlNewAutomata(); |
| start = xmlAutomataGetInitState(am); |
| |
| /* generate a[ba]*a */ |
| cur = xmlAutomataNewTransition(am, start, NULL, BAD_CAST"a", NULL); |
| xmlAutomataNewTransition(am, cur, cur, BAD_CAST"b", NULL); |
| xmlAutomataNewTransition(am, cur, cur, BAD_CAST"a", NULL); |
| cur = xmlAutomataNewCountTrans(am, cur, NULL, BAD_CAST"a", 2, 3, NULL); |
| xmlAutomataSetFinalState(am, cur); |
| |
| /* compile it in a regexp and free the automata */ |
| regexp = xmlAutomataCompile(am); |
| xmlFreeAutomata(am); |
| |
| /* test the regexp */ |
| xmlRegexpPrint(stdout, regexp); |
| exec = xmlRegNewExecCtxt(regexp, NULL, NULL); |
| ret = xmlRegExecPushString(exec, BAD_CAST"a", NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| ret =xmlRegExecPushString(exec, BAD_CAST"b", NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| if (ret == 0) { |
| ret = xmlRegExecPushString(exec, NULL, NULL); |
| if (ret == 1) |
| printf("final\n"); |
| else if (ret < 0) |
| printf("error\n"); |
| } |
| xmlRegFreeExecCtxt(exec); |
| |
| /* free the regexp */ |
| xmlRegFreeRegexp(regexp); |
| } else { |
| int i; |
| |
| for (i = 1;i < argc;i++) |
| testRegexpFile(argv[i]); |
| } |
| |
| xmlCleanupParser(); |
| xmlMemoryDump(); |
| return(0); |
| } |
| |
| #else |
| #include <stdio.h> |
| int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { |
| printf("%s : Automata support not compiled in\n", argv[0]); |
| return(0); |
| } |
| #endif /* LIBXML_AUTOMATA_ENABLED */ |