blob: fd09fa1c628fd96a965cfb692e49899af26d7c6c [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_REGEXP_ENABLED
12#include <libxml/tree.h>
13#include <libxml/xmlregexp.h>
14
Daniel Veillard24505b02005-07-28 23:49:35 +000015static int repeat = 0;
16static int debug = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017
18static void testRegexp(xmlRegexpPtr comp, const char *value) {
19 int ret;
20
21 ret = xmlRegexpExec(comp, (const xmlChar *) value);
22 if (ret == 1)
23 printf("%s: Ok\n", value);
24 else if (ret == 0)
25 printf("%s: Fail\n", value);
26 else
27 printf("%s: Error: %d\n", value, ret);
28 if (repeat) {
29 int j;
30 for (j = 0;j < 999999;j++)
31 xmlRegexpExec(comp, (const xmlChar *) value);
32 }
33}
34
35static void
36testRegexpFile(const char *filename) {
37 xmlRegexpPtr comp = NULL;
38 FILE *input;
39 char expression[5000];
40 int len;
41
42 input = fopen(filename, "r");
43 if (input == NULL) {
44 xmlGenericError(xmlGenericErrorContext,
45 "Cannot open %s for reading\n", filename);
46 return;
47 }
48 while (fgets(expression, 4500, input) != NULL) {
49 len = strlen(expression);
50 len--;
51 while ((len >= 0) &&
52 ((expression[len] == '\n') || (expression[len] == '\t') ||
53 (expression[len] == '\r') || (expression[len] == ' '))) len--;
54 expression[len + 1] = 0;
55 if (len >= 0) {
56 if (expression[0] == '#')
57 continue;
58 if ((expression[0] == '=') && (expression[1] == '>')) {
59 char *pattern = &expression[2];
60
61 if (comp != NULL) {
62 xmlRegFreeRegexp(comp);
63 comp = NULL;
64 }
65 printf("Regexp: %s\n", pattern) ;
66 comp = xmlRegexpCompile((const xmlChar *) pattern);
67 if (comp == NULL) {
68 printf(" failed to compile\n");
69 break;
70 }
71 } else if (comp == NULL) {
72 printf("Regexp: %s\n", expression) ;
73 comp = xmlRegexpCompile((const xmlChar *) expression);
74 if (comp == NULL) {
75 printf(" failed to compile\n");
76 break;
77 }
78 } else if (comp != NULL) {
79 testRegexp(comp, expression);
80 }
81 }
82 }
83 fclose(input);
84 if (comp != NULL)
85 xmlRegFreeRegexp(comp);
86}
87
Daniel Veillard465a0002005-08-22 12:07:04 +000088#ifdef LIBXML_EXPR_ENABLED
89static void
90runFileTest(xmlExpCtxtPtr ctxt, const char *filename) {
91 xmlExpNodePtr expr = NULL, sub;
92 FILE *input;
93 char expression[5000];
94 int len;
95
96 input = fopen(filename, "r");
97 if (input == NULL) {
98 xmlGenericError(xmlGenericErrorContext,
99 "Cannot open %s for reading\n", filename);
100 return;
101 }
102 while (fgets(expression, 4500, input) != NULL) {
103 len = strlen(expression);
104 len--;
105 while ((len >= 0) &&
106 ((expression[len] == '\n') || (expression[len] == '\t') ||
107 (expression[len] == '\r') || (expression[len] == ' '))) len--;
108 expression[len + 1] = 0;
109 if (len >= 0) {
110 if (expression[0] == '#')
111 continue;
112 if ((expression[0] == '=') && (expression[1] == '>')) {
113 char *str = &expression[2];
114
115 if (expr != NULL) {
116 xmlExpFree(ctxt, expr);
117 if (xmlExpCtxtNbNodes(ctxt) != 0)
118 printf(" Parse/free of Expression leaked %d\n",
119 xmlExpCtxtNbNodes(ctxt));
120 expr = NULL;
121 }
122 printf("Expression: %s\n", str) ;
123 expr = xmlExpParse(ctxt, str);
124 if (expr == NULL) {
125 printf(" parsing Failed\n");
126 break;
127 }
128 } else if (expr != NULL) {
129 int expect = -1;
130 int nodes1, nodes2;
131
132 if (expression[0] == '0')
133 expect = 0;
134 if (expression[0] == '1')
135 expect = 1;
136 printf("Subexp: %s", expression + 2) ;
137 nodes1 = xmlExpCtxtNbNodes(ctxt);
138 sub = xmlExpParse(ctxt, expression + 2);
139 if (sub == NULL) {
140 printf(" parsing Failed\n");
141 break;
142 } else {
143 int ret;
144
145 nodes2 = xmlExpCtxtNbNodes(ctxt);
146 ret = xmlExpSubsume(ctxt, expr, sub);
147
148 if ((expect == 1) && (ret == 1)) {
149 printf(" => accept, Ok\n");
150 } else if ((expect == 0) && (ret == 0)) {
151 printf(" => reject, Ok\n");
152 } else if ((expect == 1) && (ret == 0)) {
153 printf(" => reject, Failed\n");
154 } else if ((expect == 0) && (ret == 1)) {
155 printf(" => accept, Failed\n");
156 } else {
157 printf(" => fail internally\n");
158 }
159 if (xmlExpCtxtNbNodes(ctxt) > nodes2) {
160 printf(" Subsume leaked %d\n",
161 xmlExpCtxtNbNodes(ctxt) - nodes2);
162 nodes1 += xmlExpCtxtNbNodes(ctxt) - nodes2;
163 }
164 xmlExpFree(ctxt, sub);
165 if (xmlExpCtxtNbNodes(ctxt) > nodes1) {
166 printf(" Parse/free leaked %d\n",
167 xmlExpCtxtNbNodes(ctxt) - nodes1);
168 }
169 }
170
171 }
172 }
173 }
174 if (expr != NULL) {
175 xmlExpFree(ctxt, expr);
176 if (xmlExpCtxtNbNodes(ctxt) != 0)
177 printf(" Parse/free of Expression leaked %d\n",
178 xmlExpCtxtNbNodes(ctxt));
179 }
180 fclose(input);
181}
182#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000183
184static void usage(const char *name) {
Daniel Veillard465a0002005-08-22 12:07:04 +0000185 fprintf(stderr, "Usage: %s [flags]\n", name);
186 fprintf(stderr, "Testing tool for libxml2 string and pattern regexps\n");
187 fprintf(stderr, " --debug: switch on debugging\n");
188 fprintf(stderr, " --repeat: loop on the operation\n");
189#ifdef LIBXML_EXPR_ENABLED
190 fprintf(stderr, " --expr: test xmlExp and not xmlRegexp\n");
191#endif
192 fprintf(stderr, " --input filename: use the given filename for regexp\n");
193 fprintf(stderr, " --input filename: use the given filename for exp\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000194}
195
196int main(int argc, char **argv) {
197 xmlRegexpPtr comp = NULL;
Daniel Veillard465a0002005-08-22 12:07:04 +0000198#ifdef LIBXML_EXPR_ENABLED
199 xmlExpNodePtr expr = NULL;
200 int use_exp = 0;
201 xmlExpCtxtPtr ctxt = NULL;
202#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000203 const char *pattern = NULL;
204 char *filename = NULL;
205 int i;
206
207 xmlInitMemory();
208
209 if (argc <= 1) {
210 usage(argv[0]);
211 return(1);
212 }
213 for (i = 1; i < argc ; i++) {
214 if (!strcmp(argv[i], "-"))
215 break;
216
217 if (argv[i][0] != '-')
218 continue;
219 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
220 debug++;
221 } else if ((!strcmp(argv[i], "-repeat")) ||
222 (!strcmp(argv[i], "--repeat"))) {
223 repeat++;
Daniel Veillard465a0002005-08-22 12:07:04 +0000224#ifdef LIBXML_EXPR_ENABLED
225 } else if ((!strcmp(argv[i], "-expr")) ||
226 (!strcmp(argv[i], "--expr"))) {
227 use_exp++;
228#endif
229 } else if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "-f")) ||
230 (!strcmp(argv[i], "--input")))
Daniel Veillard4255d502002-04-16 15:50:10 +0000231 filename = argv[++i];
232 else {
233 fprintf(stderr, "Unknown option %s\n", argv[i]);
234 usage(argv[0]);
235 }
236 }
Daniel Veillard465a0002005-08-22 12:07:04 +0000237
238#ifdef LIBXML_EXPR_ENABLED
239 if (use_exp)
240 ctxt = xmlExpNewCtxt(0, NULL);
241#endif
242
Daniel Veillard4255d502002-04-16 15:50:10 +0000243 if (filename != NULL) {
Daniel Veillard465a0002005-08-22 12:07:04 +0000244#ifdef LIBXML_EXPR_ENABLED
245 if (use_exp)
246 runFileTest(ctxt, filename);
247 else
248#endif
249 testRegexpFile(filename);
Daniel Veillard4255d502002-04-16 15:50:10 +0000250 } else {
251 for (i = 1; i < argc ; i++) {
252 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
253 if (pattern == NULL) {
254 pattern = argv[i];
255 printf("Testing %s:\n", pattern);
256 comp = xmlRegexpCompile((const xmlChar *) pattern);
257 if (comp == NULL) {
258 printf(" failed to compile\n");
259 break;
260 }
261 if (debug)
262 xmlRegexpPrint(stdout, comp);
263 } else {
264 testRegexp(comp, argv[i]);
265 }
266 }
267 }
268 if (comp != NULL)
269 xmlRegFreeRegexp(comp);
270 }
Daniel Veillard465a0002005-08-22 12:07:04 +0000271#ifdef LIBXML_EXPR_ENABLED
272 if (ctxt != NULL) {
273 printf("Ops: %d nodes, %d cons\n",
274 xmlExpCtxtNbNodes(ctxt), xmlExpCtxtNbCons(ctxt));
275 xmlExpFreeCtxt(ctxt);
276 }
277#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000278 xmlCleanupParser();
Daniel Veillard99c394d2005-07-14 12:58:49 +0000279 xmlMemoryDump();
Daniel Veillard4255d502002-04-16 15:50:10 +0000280 return(0);
281}
282
283#else
284#include <stdio.h>
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000285int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000286 printf("%s : Regexp support not compiled in\n", argv[0]);
287 return(0);
288}
289#endif /* LIBXML_REGEXP_ENABLED */