blob: a168a4b0c74aacd9757563e776bcc9e50b354e15 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
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 <string.h>
10#include "libxml.h"
11#ifdef LIBXML_AUTOMATA_ENABLED
12
Daniel Veillard84d70a42002-09-16 10:51:38 +000013#include <libxml/tree.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000014#include <libxml/xmlautomata.h>
15
16static 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
29static void
30testRegexpFile(const char *filename) {
31 FILE *input;
William M. Brack272693c2003-11-14 16:20:34 +000032 char expr[5000];
Daniel Veillard4255d502002-04-16 15:50:10 +000033 int len;
34 int ret;
35 int i;
36 xmlAutomataPtr am;
37 xmlAutomataStatePtr states[1000];
38 xmlRegexpPtr regexp = NULL;
Daniel Veillard118aed72002-09-24 14:13:13 +000039 xmlRegExecCtxtPtr exec = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000040
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 }
57 states[0] = xmlAutomataGetInitState(am);
58 if (states[0] == NULL) {
59 xmlGenericError(xmlGenericErrorContext,
60 "Cannot get start state\n");
61 xmlFreeAutomata(am);
62 fclose(input);
63 }
64 ret = 0;
65
William M. Brack272693c2003-11-14 16:20:34 +000066 while (fgets(expr, 4500, input) != NULL) {
67 if (expr[0] == '#')
Daniel Veillard4255d502002-04-16 15:50:10 +000068 continue;
William M. Brack272693c2003-11-14 16:20:34 +000069 len = strlen(expr);
Daniel Veillard4255d502002-04-16 15:50:10 +000070 len--;
71 while ((len >= 0) &&
William M. Brack272693c2003-11-14 16:20:34 +000072 ((expr[len] == '\n') || (expr[len] == '\t') ||
73 (expr[len] == '\r') || (expr[len] == ' '))) len--;
74 expr[len + 1] = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000075 if (len >= 0) {
William M. Brack272693c2003-11-14 16:20:34 +000076 if ((am != NULL) && (expr[0] == 't') && (expr[1] == ' ')) {
77 char *ptr = &expr[2];
Daniel Veillard4255d502002-04-16 15:50:10 +000078 int from, to;
79
80 from = scanNumber(&ptr);
81 if (*ptr != ' ') {
82 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +000083 "Bad line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +000084 break;
85 }
86 if (states[from] == NULL)
87 states[from] = xmlAutomataNewState(am);
88 ptr++;
89 to = scanNumber(&ptr);
90 if (*ptr != ' ') {
91 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +000092 "Bad line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +000093 break;
94 }
95 if (states[to] == NULL)
96 states[to] = xmlAutomataNewState(am);
97 ptr++;
98 xmlAutomataNewTransition(am, states[from], states[to],
99 BAD_CAST ptr, NULL);
William M. Brack272693c2003-11-14 16:20:34 +0000100 } else if ((am != NULL) && (expr[0] == 'e') && (expr[1] == ' ')) {
101 char *ptr = &expr[2];
Daniel Veillard4255d502002-04-16 15:50:10 +0000102 int from, to;
103
104 from = scanNumber(&ptr);
105 if (*ptr != ' ') {
106 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +0000107 "Bad line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +0000108 break;
109 }
110 if (states[from] == NULL)
111 states[from] = xmlAutomataNewState(am);
112 ptr++;
113 to = scanNumber(&ptr);
114 if (states[to] == NULL)
115 states[to] = xmlAutomataNewState(am);
116 xmlAutomataNewEpsilon(am, states[from], states[to]);
William M. Brack272693c2003-11-14 16:20:34 +0000117 } else if ((am != NULL) && (expr[0] == 'f') && (expr[1] == ' ')) {
118 char *ptr = &expr[2];
Daniel Veillard4255d502002-04-16 15:50:10 +0000119 int state;
120
121 state = scanNumber(&ptr);
122 if (states[state] == NULL) {
123 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +0000124 "Bad state %d : %s\n", state, expr);
Daniel Veillard4255d502002-04-16 15:50:10 +0000125 break;
126 }
127 xmlAutomataSetFinalState(am, states[state]);
William M. Brack272693c2003-11-14 16:20:34 +0000128 } else if ((am != NULL) && (expr[0] == 'c') && (expr[1] == ' ')) {
129 char *ptr = &expr[2];
Daniel Veillard4255d502002-04-16 15:50:10 +0000130 int from, to;
131 int min, max;
132
133 from = scanNumber(&ptr);
134 if (*ptr != ' ') {
135 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +0000136 "Bad line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +0000137 break;
138 }
139 if (states[from] == NULL)
140 states[from] = xmlAutomataNewState(am);
141 ptr++;
142 to = scanNumber(&ptr);
143 if (*ptr != ' ') {
144 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +0000145 "Bad line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +0000146 break;
147 }
148 if (states[to] == NULL)
149 states[to] = xmlAutomataNewState(am);
150 ptr++;
151 min = scanNumber(&ptr);
152 if (*ptr != ' ') {
153 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +0000154 "Bad line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +0000155 break;
156 }
157 ptr++;
158 max = scanNumber(&ptr);
159 if (*ptr != ' ') {
160 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +0000161 "Bad line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +0000162 break;
163 }
164 ptr++;
165 xmlAutomataNewCountTrans(am, states[from], states[to],
166 BAD_CAST ptr, min, max, NULL);
William M. Brack272693c2003-11-14 16:20:34 +0000167 } else if ((am != NULL) && (expr[0] == '-') && (expr[1] == '-')) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000168 /* end of the automata */
169 regexp = xmlAutomataCompile(am);
170 xmlFreeAutomata(am);
171 am = NULL;
172 if (regexp == NULL) {
173 xmlGenericError(xmlGenericErrorContext,
174 "Failed to compile the automata");
175 break;
176 }
William M. Brack272693c2003-11-14 16:20:34 +0000177 } else if ((expr[0] == '=') && (expr[1] == '>')) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000178 if (regexp == NULL) {
179 printf("=> failed not compiled\n");
180 } else {
181 if (exec == NULL)
182 exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
183 if (ret == 0) {
184 ret = xmlRegExecPushString(exec, NULL, NULL);
185 }
186 if (ret == 1)
187 printf("=> Passed\n");
188 else if ((ret == 0) || (ret == -1))
189 printf("=> Failed\n");
190 else if (ret < 0)
191 printf("=> Error\n");
192 xmlRegFreeExecCtxt(exec);
193 exec = NULL;
194 }
195 ret = 0;
196 } else if (regexp != NULL) {
197 if (exec == NULL)
198 exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
William M. Brack272693c2003-11-14 16:20:34 +0000199 ret = xmlRegExecPushString(exec, BAD_CAST expr, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000200 } else {
201 xmlGenericError(xmlGenericErrorContext,
William M. Brack272693c2003-11-14 16:20:34 +0000202 "Unexpected line %s\n", expr);
Daniel Veillard4255d502002-04-16 15:50:10 +0000203 }
204 }
205 }
206 fclose(input);
207 if (regexp != NULL)
208 xmlRegFreeRegexp(regexp);
209 if (exec != NULL)
210 xmlRegFreeExecCtxt(exec);
211 if (am != NULL)
212 xmlFreeAutomata(am);
213}
214
215int main(int argc, char **argv) {
216
217 xmlInitMemory();
218
219 if (argc == 1) {
220 int ret;
221 xmlAutomataPtr am;
222 xmlAutomataStatePtr start, cur;
223 xmlRegexpPtr regexp;
224 xmlRegExecCtxtPtr exec;
225
226 am = xmlNewAutomata();
227 start = xmlAutomataGetInitState(am);
228
229 /* generate a[ba]*a */
230 cur = xmlAutomataNewTransition(am, start, NULL, BAD_CAST"a", NULL);
231 xmlAutomataNewTransition(am, cur, cur, BAD_CAST"b", NULL);
232 xmlAutomataNewTransition(am, cur, cur, BAD_CAST"a", NULL);
233 cur = xmlAutomataNewCountTrans(am, cur, NULL, BAD_CAST"a", 2, 3, NULL);
234 xmlAutomataSetFinalState(am, cur);
235
236 /* compile it in a regexp and free the automata */
237 regexp = xmlAutomataCompile(am);
238 xmlFreeAutomata(am);
239
240 /* test the regexp */
241 xmlRegexpPrint(stdout, regexp);
242 exec = xmlRegNewExecCtxt(regexp, NULL, NULL);
243 ret = xmlRegExecPushString(exec, BAD_CAST"a", NULL);
244 if (ret == 1)
245 printf("final\n");
246 else if (ret < 0)
247 printf("error\n");
248 ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
249 if (ret == 1)
250 printf("final\n");
251 else if (ret < 0)
252 printf("error\n");
253 ret =xmlRegExecPushString(exec, BAD_CAST"b", NULL);
254 if (ret == 1)
255 printf("final\n");
256 else if (ret < 0)
257 printf("error\n");
258 ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
259 if (ret == 1)
260 printf("final\n");
261 else if (ret < 0)
262 printf("error\n");
263 ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
264 if (ret == 1)
265 printf("final\n");
266 else if (ret < 0)
267 printf("error\n");
268 ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
269 if (ret == 1)
270 printf("final\n");
271 else if (ret < 0)
272 printf("error\n");
273 ret =xmlRegExecPushString(exec, BAD_CAST"a", NULL);
274 if (ret == 1)
275 printf("final\n");
276 else if (ret < 0)
277 printf("error\n");
278 if (ret == 0) {
279 ret = xmlRegExecPushString(exec, NULL, NULL);
280 if (ret == 1)
281 printf("final\n");
282 else if (ret < 0)
283 printf("error\n");
284 }
285 xmlRegFreeExecCtxt(exec);
286
287 /* free the regexp */
288 xmlRegFreeRegexp(regexp);
289 } else {
290 int i;
291
292 for (i = 1;i < argc;i++)
293 testRegexpFile(argv[i]);
294 }
295
296 xmlCleanupParser();
297 xmlMemoryDump();
298 return(0);
299}
300
301#else
302#include <stdio.h>
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000303int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000304 printf("%s : Automata support not compiled in\n", argv[0]);
305 return(0);
306}
307#endif /* LIBXML_AUTOMATA_ENABLED */