14255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/*
24255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * testRegexp.c: simple module for testing regular expressions
34255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
44255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * See Copyright for the status of this software.
54255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
64255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Daniel Veillard <veillard@redhat.com>
74255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
84255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
94255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include "libxml.h"
104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef LIBXML_REGEXP_ENABLED
11c1099be5eb3e78ae6cef1b2c39b21e7b36a59035William M. Brack#include <string.h>
12c1099be5eb3e78ae6cef1b2c39b21e7b36a59035William M. Brack
134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/tree.h>
144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/xmlregexp.h>
154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1624505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillardstatic int repeat = 0;
1724505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillardstatic int debug = 0;
184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void testRegexp(xmlRegexpPtr comp, const char *value) {
204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlRegexpExec(comp, (const xmlChar *) value);
234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == 1)
244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("%s: Ok\n", value);
254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else if (ret == 0)
264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("%s: Fail\n", value);
274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else
284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("%s: Error: %d\n", value, ret);
294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (repeat) {
304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int j;
314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (j = 0;j < 999999;j++)
324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegexpExec(comp, (const xmlChar *) value);
334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
374255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardtestRegexpFile(const char *filename) {
384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr comp = NULL;
394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    FILE *input;
404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    char expression[5000];
414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int len;
424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    input = fopen(filename, "r");
444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (input == NULL) {
454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        xmlGenericError(xmlGenericErrorContext,
464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		"Cannot open %s for reading\n", filename);
474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while (fgets(expression, 4500, input) != NULL) {
504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	len = strlen(expression);
514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	len--;
52f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	while ((len >= 0) &&
534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       ((expression[len] == '\n') || (expression[len] == '\t') ||
544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		(expression[len] == '\r') || (expression[len] == ' '))) len--;
55f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	expression[len + 1] = 0;
564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (len >= 0) {
574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (expression[0] == '#')
584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		continue;
594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if ((expression[0] == '=') && (expression[1] == '>')) {
604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		char *pattern = &expression[2];
614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (comp != NULL) {
634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlRegFreeRegexp(comp);
644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    comp = NULL;
654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("Regexp: %s\n", pattern) ;
674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		comp = xmlRegexpCompile((const xmlChar *) pattern);
684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (comp == NULL) {
694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("   failed to compile\n");
704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    break;
714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (comp == NULL) {
734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("Regexp: %s\n", expression) ;
744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		comp = xmlRegexpCompile((const xmlChar *) expression);
754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (comp == NULL) {
764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("   failed to compile\n");
774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    break;
784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (comp != NULL) {
804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		testRegexp(comp, expression);
814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fclose(input);
854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (comp != NULL)
864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegFreeRegexp(comp);
874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
89465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
90465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic void
91465a000b1080427bd62d89a925409b7db78616acDaniel VeillardrunFileTest(xmlExpCtxtPtr ctxt, const char *filename) {
92465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr expr = NULL, sub;
93465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    FILE *input;
94465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    char expression[5000];
95465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    int len;
96465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
97465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    input = fopen(filename, "r");
98465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (input == NULL) {
99465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
100465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		"Cannot open %s for reading\n", filename);
101465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	return;
102465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
103465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while (fgets(expression, 4500, input) != NULL) {
104465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	len = strlen(expression);
105465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	len--;
106f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	while ((len >= 0) &&
107465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	       ((expression[len] == '\n') || (expression[len] == '\t') ||
108465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		(expression[len] == '\r') || (expression[len] == ' '))) len--;
109f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	expression[len + 1] = 0;
110465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (len >= 0) {
111465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if (expression[0] == '#')
112465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		continue;
113465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((expression[0] == '=') && (expression[1] == '>')) {
114465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		char *str = &expression[2];
115465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
116465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		if (expr != NULL) {
117465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    xmlExpFree(ctxt, expr);
118f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    if (xmlExpCtxtNbNodes(ctxt) != 0)
119465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		        printf(" Parse/free of Expression leaked %d\n",
120465a000b1080427bd62d89a925409b7db78616acDaniel Veillard			       xmlExpCtxtNbNodes(ctxt));
121465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    expr = NULL;
122465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		}
123465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		printf("Expression: %s\n", str) ;
124465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		expr = xmlExpParse(ctxt, str);
125465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		if (expr == NULL) {
126465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    printf("   parsing Failed\n");
127465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    break;
128465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		}
129465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if (expr != NULL) {
130465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        int expect = -1;
131465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		int nodes1, nodes2;
132465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
133465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		if (expression[0] == '0')
134465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    expect = 0;
135465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		if (expression[0] == '1')
136465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    expect = 1;
137465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		printf("Subexp: %s", expression + 2) ;
138465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		nodes1 = xmlExpCtxtNbNodes(ctxt);
139465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		sub = xmlExpParse(ctxt, expression + 2);
140465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		if (sub == NULL) {
141465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    printf("   parsing Failed\n");
142465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    break;
143465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		} else {
144465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    int ret;
145f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
146465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    nodes2 = xmlExpCtxtNbNodes(ctxt);
147465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    ret = xmlExpSubsume(ctxt, expr, sub);
148465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
149465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    if ((expect == 1) && (ret == 1)) {
150465a000b1080427bd62d89a925409b7db78616acDaniel Veillard			printf(" => accept, Ok\n");
151465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    } else if ((expect == 0) && (ret == 0)) {
152465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		        printf(" => reject, Ok\n");
153465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    } else if ((expect == 1) && (ret == 0)) {
154465a000b1080427bd62d89a925409b7db78616acDaniel Veillard			printf(" => reject, Failed\n");
155465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    } else if ((expect == 0) && (ret == 1)) {
156465a000b1080427bd62d89a925409b7db78616acDaniel Veillard			printf(" => accept, Failed\n");
157465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    } else {
158465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		        printf(" => fail internally\n");
159465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    }
160465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    if (xmlExpCtxtNbNodes(ctxt) > nodes2) {
161465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		        printf(" Subsume leaked %d\n",
162465a000b1080427bd62d89a925409b7db78616acDaniel Veillard			       xmlExpCtxtNbNodes(ctxt) - nodes2);
163465a000b1080427bd62d89a925409b7db78616acDaniel Veillard			nodes1 += xmlExpCtxtNbNodes(ctxt) - nodes2;
164465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    }
165465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    xmlExpFree(ctxt, sub);
166465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    if (xmlExpCtxtNbNodes(ctxt) > nodes1) {
167465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		        printf(" Parse/free leaked %d\n",
168465a000b1080427bd62d89a925409b7db78616acDaniel Veillard			       xmlExpCtxtNbNodes(ctxt) - nodes1);
169465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		    }
170465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		}
171465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
172465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    }
173465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
174465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
175465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (expr != NULL) {
176465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	xmlExpFree(ctxt, expr);
177f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (xmlExpCtxtNbNodes(ctxt) != 0)
178465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    printf(" Parse/free of Expression leaked %d\n",
179465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		   xmlExpCtxtNbNodes(ctxt));
180465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
181465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fclose(input);
182465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
1830090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
184f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillardstatic void
1850090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel VeillardtestReduce(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, const char *tst) {
1860090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlBufferPtr xmlExpBuf;
1870090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlExpNodePtr sub, deriv;
1880090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlExpBuf = xmlBufferCreate();
1890090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
1900090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    sub = xmlExpParse(ctxt, tst);
1910090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (sub == NULL) {
1920090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        printf("Subset %s failed to parse\n", tst);
1930090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	return;
1940090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
195a4181227e9ba5cee43b568e9ea2cb99fb2adef2aDaniel Veillard    xmlExpDump(xmlExpBuf, sub);
1960090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    printf("Subset parsed as: %s\n",
1970090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard           (const char *) xmlBufferContent(xmlExpBuf));
1980090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    deriv = xmlExpExpDerive(ctxt, expr, sub);
1990090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (deriv == NULL) {
2000090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        printf("Derivation led to an internal error, report this !\n");
2010090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	return;
2020090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    } else {
2030090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        xmlBufferEmpty(xmlExpBuf);
2040090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	xmlExpDump(xmlExpBuf, deriv);
2050090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	if (xmlExpIsNillable(deriv))
2060090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    printf("Resulting nillable derivation: %s\n",
2070090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	           (const char *) xmlBufferContent(xmlExpBuf));
2080090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	else
2090090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    printf("Resulting derivation: %s\n",
2100090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	           (const char *) xmlBufferContent(xmlExpBuf));
2110090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	xmlExpFree(ctxt, deriv);
2120090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
2130090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlExpFree(ctxt, sub);
2140090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard}
2150090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
216f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillardstatic void
2170090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel VeillardexprDebug(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr) {
2180090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlBufferPtr xmlExpBuf;
2190090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlExpNodePtr deriv;
2200090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    const char *list[40];
2210090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    int ret;
2220090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
2230090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlExpBuf = xmlBufferCreate();
2240090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
2250090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (expr == NULL) {
2260090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        printf("Failed to parse\n");
2270090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	return;
2280090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
2290090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlExpDump(xmlExpBuf, expr);
2300090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    printf("Parsed as: %s\n", (const char *) xmlBufferContent(xmlExpBuf));
2310090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    printf("Max token input = %d\n", xmlExpMaxToken(expr));
2320090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (xmlExpIsNillable(expr) == 1)
2330090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	printf("Is nillable\n");
2340090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    ret = xmlExpGetLanguage(ctxt, expr, (const xmlChar **) &list[0], 40);
2350090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (ret < 0)
2360090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	printf("Failed to get list: %d\n", ret);
2370090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    else {
2380090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	int i;
2390090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
2400090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	printf("Language has %d strings, testing string derivations\n", ret);
2410090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	for (i = 0;i < ret;i++) {
2420090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    deriv = xmlExpStringDerive(ctxt, expr, BAD_CAST list[i], -1);
2430090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    if (deriv == NULL) {
2440090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		printf("  %s -> derivation failed\n", list[i]);
2450090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    } else {
2460090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		xmlBufferEmpty(xmlExpBuf);
2470090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		xmlExpDump(xmlExpBuf, deriv);
2480090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		printf("  %s -> %s\n", list[i],
2490090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		       (const char *) xmlBufferContent(xmlExpBuf));
2500090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    }
2510090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    xmlExpFree(ctxt, deriv);
2520090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	}
2530090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
2540090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    xmlBufferFree(xmlExpBuf);
2550090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard}
256465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#endif
2574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void usage(const char *name) {
259465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fprintf(stderr, "Usage: %s [flags]\n", name);
260465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fprintf(stderr, "Testing tool for libxml2 string and pattern regexps\n");
261465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fprintf(stderr, "   --debug: switch on debugging\n");
262465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fprintf(stderr, "   --repeat: loop on the operation\n");
263465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
264465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fprintf(stderr, "   --expr: test xmlExp and not xmlRegexp\n");
265465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#endif
266465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fprintf(stderr, "   --input filename: use the given filename for regexp\n");
267465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    fprintf(stderr, "   --input filename: use the given filename for exp\n");
2684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
2694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardint main(int argc, char **argv) {
2714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr comp = NULL;
272465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
273465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr expr = NULL;
274465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    int use_exp = 0;
275465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpCtxtPtr ctxt = NULL;
276465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#endif
2774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    const char *pattern = NULL;
2784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    char *filename = NULL;
2794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
2804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlInitMemory();
2824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (argc <= 1) {
2844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	usage(argv[0]);
2854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
2864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
2874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 1; i < argc ; i++) {
2884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (!strcmp(argv[i], "-"))
2894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
2904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (argv[i][0] != '-')
2924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    continue;
2933066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard	if (!strcmp(argv[i], "--"))
2943066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard	    break;
2953066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard
2964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
2974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    debug++;
2984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if ((!strcmp(argv[i], "-repeat")) ||
2994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	         (!strcmp(argv[i], "--repeat"))) {
3004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    repeat++;
301465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
302465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	} else if ((!strcmp(argv[i], "-expr")) ||
303465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	         (!strcmp(argv[i], "--expr"))) {
304465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    use_exp++;
305465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#endif
306465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	} else if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "-f")) ||
307465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		   (!strcmp(argv[i], "--input")))
3084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    filename = argv[++i];
3094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        else {
3104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(stderr, "Unknown option %s\n", argv[i]);
3114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    usage(argv[0]);
3124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
3134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
314465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
315465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
316465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (use_exp)
317465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ctxt = xmlExpNewCtxt(0, NULL);
318465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#endif
319465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
3204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (filename != NULL) {
321465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
322465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        if (use_exp)
323465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    runFileTest(ctxt, filename);
324465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	else
325465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#endif
326465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    testRegexpFile(filename);
3274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
3283066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard        int  data = 0;
3290090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#ifdef LIBXML_EXPR_ENABLED
3303066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard
3310090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        if (use_exp) {
3320090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    for (i = 1; i < argc ; i++) {
3333066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard	        if (strcmp(argv[i], "--") == 0)
3343066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard		    data = 1;
3353066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard		else if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0) ||
3363066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard		    (data == 1)) {
3370090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		    if (pattern == NULL) {
3380090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			pattern = argv[i];
3390090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			printf("Testing expr %s:\n", pattern);
3400090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			expr = xmlExpParse(ctxt, pattern);
3410090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			if (expr == NULL) {
3420090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			    printf("   failed to compile\n");
3430090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			    break;
3440090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			}
3450090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			if (debug) {
3460090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			    exprDebug(ctxt, expr);
3470090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			}
3480090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		    } else {
3490090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			testReduce(ctxt, expr, argv[i]);
3504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
3514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
3524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
3533066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard	    if (expr != NULL) {
3540090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		xmlExpFree(ctxt, expr);
3553066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard		expr = NULL;
3563066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard	    }
3570090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	} else
3580090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#endif
3590090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        {
3600090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    for (i = 1; i < argc ; i++) {
3613066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard	        if (strcmp(argv[i], "--") == 0)
3623066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard		    data = 1;
3633066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard		else if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0) ||
3643066351275d72ff2ae8db57213084bb1719f5a46Daniel Veillard		         (data == 1)) {
3650090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		    if (pattern == NULL) {
3660090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			pattern = argv[i];
3670090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			printf("Testing %s:\n", pattern);
3680090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			comp = xmlRegexpCompile((const xmlChar *) pattern);
3690090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			if (comp == NULL) {
3700090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			    printf("   failed to compile\n");
3710090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			    break;
3720090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			}
3730090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			if (debug)
3740090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			    xmlRegexpPrint(stdout, comp);
3750090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		    } else {
3760090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard			testRegexp(comp, argv[i]);
3770090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		    }
3780090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		}
3790090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    }
3800090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	    if (comp != NULL)
3810090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard		xmlRegFreeRegexp(comp);
3820090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        }
3834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
384465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
385465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (ctxt != NULL) {
386465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	printf("Ops: %d nodes, %d cons\n",
387465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	       xmlExpCtxtNbNodes(ctxt), xmlExpCtxtNbCons(ctxt));
388465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	xmlExpFreeCtxt(ctxt);
389465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
390465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#endif
3914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlCleanupParser();
39299c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard    xmlMemoryDump();
3934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
3944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
3954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#else
3974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <stdio.h>
398a9cce9cd0d7aff3ec318b5d8d376da131b6aaad4Daniel Veillardint main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
3994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("%s : Regexp support not compiled in\n", argv[0]);
4004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
4014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
4024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif /* LIBXML_REGEXP_ENABLED */
403