/ libxml2 / testAutomata.c
testAutomata.c
  1  /*
  2   * testRegexp.c: simple module for testing regular expressions
  3   *
  4   * See Copyright for the status of this software.
  5   *
  6   * Daniel Veillard <veillard@redhat.com>
  7   */
  8  
  9  #include "libxml.h"
 10  #ifdef LIBXML_AUTOMATA_ENABLED
 11  #include <string.h>
 12  
 13  #include <libxml/tree.h>
 14  #include <libxml/xmlautomata.h>
 15  
 16  static int scanNumber(char **ptr) {
 17      int ret = 0;
 18      char *cur;
 19  
 20      cur = *ptr;
 21      while ((*cur >= '0') && (*cur <= '9')) {
 22  	ret = ret * 10 + (*cur - '0');
 23  	cur++;
 24      }
 25      *ptr = cur;
 26      return(ret);
 27  }
 28  
 29  static void
 30  testRegexpFile(const char *filename) {
 31      FILE *input;
 32      char expr[5000];
 33      int len;
 34      int ret;
 35      int i;
 36      xmlAutomataPtr am;
 37      xmlAutomataStatePtr states[1000];
 38      xmlRegexpPtr regexp = NULL;
 39      xmlRegExecCtxtPtr exec = NULL;
 40  
 41      for (i = 0;i<1000;i++)
 42  	states[i] = NULL;
 43  
 44      input = fopen(filename, "r");
 45      if (input == NULL) {
 46          xmlGenericError(xmlGenericErrorContext,
 47  		"Cannot open %s for reading\n", filename);
 48  	return;
 49      }
 50  
 51      am = xmlNewAutomata();
 52      if (am == NULL) {
 53          xmlGenericError(xmlGenericErrorContext,
 54  		"Cannot create automata\n");
 55  	fclose(input);
 56  	return;
 57      }
 58      states[0] = xmlAutomataGetInitState(am);
 59      if (states[0] == NULL) {
 60          xmlGenericError(xmlGenericErrorContext,
 61  		"Cannot get start state\n");
 62  	xmlFreeAutomata(am);
 63  	fclose(input);
 64  	return;
 65      }
 66      ret = 0;
 67  
 68      while (fgets(expr, 4500, input) != NULL) {
 69  	if (expr[0] == '#')
 70  	    continue;
 71  	len = strlen(expr);
 72  	len--;
 73  	while ((len >= 0) &&
 74  	       ((expr[len] == '\n') || (expr[len] == '\t') ||
 75  		(expr[len] == '\r') || (expr[len] == ' '))) len--;
 76  	expr[len + 1] = 0;
 77  	if (len >= 0) {
 78  	    if ((am != NULL) && (expr[0] == 't') && (expr[1] == ' ')) {
 79  		char *ptr = &expr[2];
 80  		int from, to;
 81  
 82  		from = scanNumber(&ptr);
 83  		if (*ptr != ' ') {
 84  		    xmlGenericError(xmlGenericErrorContext,
 85  			    "Bad line %s\n", expr);
 86  		    break;
 87  		}
 88  		if (states[from] == NULL)
 89  		    states[from] = xmlAutomataNewState(am);
 90  		ptr++;
 91  		to = scanNumber(&ptr);
 92  		if (*ptr != ' ') {
 93  		    xmlGenericError(xmlGenericErrorContext,
 94  			    "Bad line %s\n", expr);
 95  		    break;
 96  		}
 97  		if (states[to] == NULL)
 98  		    states[to] = xmlAutomataNewState(am);
 99  		ptr++;
100  		xmlAutomataNewTransition(am, states[from], states[to],
101  			                 BAD_CAST ptr, NULL);
102  	    } else if ((am != NULL) && (expr[0] == 'e') && (expr[1] == ' ')) {
103  		char *ptr = &expr[2];
104  		int from, to;
105  
106  		from = scanNumber(&ptr);
107  		if (*ptr != ' ') {
108  		    xmlGenericError(xmlGenericErrorContext,
109  			    "Bad line %s\n", expr);
110  		    break;
111  		}
112  		if (states[from] == NULL)
113  		    states[from] = xmlAutomataNewState(am);
114  		ptr++;
115  		to = scanNumber(&ptr);
116  		if (states[to] == NULL)
117  		    states[to] = xmlAutomataNewState(am);
118  		xmlAutomataNewEpsilon(am, states[from], states[to]);
119  	    } else if ((am != NULL) && (expr[0] == 'f') && (expr[1] == ' ')) {
120  		char *ptr = &expr[2];
121  		int state;
122  
123  		state = scanNumber(&ptr);
124  		if (states[state] == NULL) {
125  		    xmlGenericError(xmlGenericErrorContext,
126  			    "Bad state %d : %s\n", state, expr);
127  		    break;
128  		}
129  		xmlAutomataSetFinalState(am, states[state]);
130  	    } else if ((am != NULL) && (expr[0] == 'c') && (expr[1] == ' ')) {
131  		char *ptr = &expr[2];
132  		int from, to;
133  		int min, max;
134  
135  		from = scanNumber(&ptr);
136  		if (*ptr != ' ') {
137  		    xmlGenericError(xmlGenericErrorContext,
138  			    "Bad line %s\n", expr);
139  		    break;
140  		}
141  		if (states[from] == NULL)
142  		    states[from] = xmlAutomataNewState(am);
143  		ptr++;
144  		to = scanNumber(&ptr);
145  		if (*ptr != ' ') {
146  		    xmlGenericError(xmlGenericErrorContext,
147  			    "Bad line %s\n", expr);
148  		    break;
149  		}
150  		if (states[to] == NULL)
151  		    states[to] = xmlAutomataNewState(am);
152  		ptr++;
153  		min = scanNumber(&ptr);
154  		if (*ptr != ' ') {
155  		    xmlGenericError(xmlGenericErrorContext,
156  			    "Bad line %s\n", expr);
157  		    break;
158  		}
159  		ptr++;
160  		max = scanNumber(&ptr);
161  		if (*ptr != ' ') {
162  		    xmlGenericError(xmlGenericErrorContext,
163  			    "Bad line %s\n", expr);
164  		    break;
165  		}
166  		ptr++;
167  		xmlAutomataNewCountTrans(am, states[from], states[to],
168  			                 BAD_CAST ptr, min, max, NULL);
169  	    } else if ((am != NULL) && (expr[0] == '-') && (expr[1] == '-')) {
170  		/* end of the automata */
171  		regexp = xmlAutomataCompile(am);
172  		xmlFreeAutomata(am);
173  		am = NULL;
174  		if (regexp == NULL) {
175  		    xmlGenericError(xmlGenericErrorContext,
176  			    "Failed to compile the automata");
177  		    break;
178  		}
179  	    } else if ((expr[0] == '=') && (expr[1] == '>')) {
180  		if (regexp == NULL) {
181  		    printf("=> failed not compiled\n");
182  		} else {
183  		    if (exec == NULL)
184  			exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
185  		    if (ret == 0) {
186  			ret = xmlRegExecPushString(exec, NULL, NULL);
187  		    }
188  		    if (ret == 1)
189  			printf("=> Passed\n");
190  		    else if ((ret == 0) || (ret == -1))
191  			printf("=> Failed\n");
192  		    else if (ret < 0)
193  			printf("=> Error\n");
194  		    xmlRegFreeExecCtxt(exec);
195  		    exec = NULL;
196  		}
197  		ret = 0;
198  	    } else if (regexp != NULL) {
199  		if (exec == NULL)
200  		    exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
201  		ret = xmlRegExecPushString(exec, BAD_CAST expr, NULL);
202  	    } else {
203  		xmlGenericError(xmlGenericErrorContext,
204  			"Unexpected line %s\n", expr);
205  	    }
206  	}
207      }
208      fclose(input);
209      if (regexp != NULL)
210  	xmlRegFreeRegexp(regexp);
211      if (exec != NULL)
212  	xmlRegFreeExecCtxt(exec);
213      if (am != NULL)
214  	xmlFreeAutomata(am);
215  }
216  
217  int main(int argc, char **argv) {
218  
219      xmlInitMemory();
220  
221      if (argc == 1) {
222  	int ret;
223  	xmlAutomataPtr am;
224  	xmlAutomataStatePtr start, cur;
225  	xmlRegexpPtr regexp;
226  	xmlRegExecCtxtPtr exec;
227  
228  	am = xmlNewAutomata();
229  	start = xmlAutomataGetInitState(am);
230  
231  	/* generate a[ba]*a */
232  	cur = xmlAutomataNewTransition(am, start, NULL, BAD_CAST"a", NULL);
233  	xmlAutomataNewTransition(am, cur, cur, BAD_CAST"b", NULL);
234  	xmlAutomataNewTransition(am, cur, cur, BAD_CAST"a", NULL);
235  	cur = xmlAutomataNewCountTrans(am, cur, NULL, BAD_CAST"a", 2, 3, NULL);
236  	xmlAutomataSetFinalState(am, cur);
237  
238  	/* compile it in a regexp and free the automata */
239  	regexp = xmlAutomataCompile(am);
240  	xmlFreeAutomata(am);
241  
242  	/* test the regexp */
243  	xmlRegexpPrint(stdout, regexp);
244  	exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
245  	ret = xmlRegExecPushString(exec, BAD_CAST"a", NULL);
246  	if (ret == 1)
247  	    printf("final\n");
248  	else if (ret < 0)
249  	    printf("error\n");
250  	ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
251  	if (ret == 1)
252  	    printf("final\n");
253  	else if (ret < 0)
254  	    printf("error\n");
255  	ret =xmlRegExecPushString(exec, BAD_CAST"b", NULL);
256  	if (ret == 1)
257  	    printf("final\n");
258  	else if (ret < 0)
259  	    printf("error\n");
260  	ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
261  	if (ret == 1)
262  	    printf("final\n");
263  	else if (ret < 0)
264  	    printf("error\n");
265  	ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
266  	if (ret == 1)
267  	    printf("final\n");
268  	else if (ret < 0)
269  	    printf("error\n");
270  	ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
271  	if (ret == 1)
272  	    printf("final\n");
273  	else if (ret < 0)
274  	    printf("error\n");
275  	ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
276  	if (ret == 1)
277  	    printf("final\n");
278  	else if (ret < 0)
279  	    printf("error\n");
280  	if (ret == 0) {
281  	    ret = xmlRegExecPushString(exec, NULL, NULL);
282  	    if (ret == 1)
283  		printf("final\n");
284  	    else if (ret < 0)
285  		printf("error\n");
286  	}
287  	xmlRegFreeExecCtxt(exec);
288  
289  	/* free the regexp */
290  	xmlRegFreeRegexp(regexp);
291      } else {
292  	int i;
293  
294  	for (i = 1;i < argc;i++)
295  	    testRegexpFile(argv[i]);
296      }
297  
298      xmlCleanupParser();
299      xmlMemoryDump();
300      return(0);
301  }
302  
303  #else
304  #include <stdio.h>
305  int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
306      printf("%s : Automata support not compiled in\n", argv[0]);
307      return(0);
308  }
309  #endif /* LIBXML_AUTOMATA_ENABLED */