Blame testRegexp.c

Packit 423ecb
/*
Packit 423ecb
 * testRegexp.c: simple module for testing regular expressions
Packit 423ecb
 *
Packit 423ecb
 * See Copyright for the status of this software.
Packit 423ecb
 *
Packit 423ecb
 * Daniel Veillard <veillard@redhat.com>
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
#include "libxml.h"
Packit 423ecb
#ifdef LIBXML_REGEXP_ENABLED
Packit 423ecb
#include <string.h>
Packit 423ecb
Packit 423ecb
#include <libxml/tree.h>
Packit 423ecb
#include <libxml/xmlregexp.h>
Packit 423ecb
Packit 423ecb
static int repeat = 0;
Packit 423ecb
static int debug = 0;
Packit 423ecb
Packit 423ecb
static void testRegexp(xmlRegexpPtr comp, const char *value) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    ret = xmlRegexpExec(comp, (const xmlChar *) value);
Packit 423ecb
    if (ret == 1)
Packit 423ecb
	printf("%s: Ok\n", value);
Packit 423ecb
    else if (ret == 0)
Packit 423ecb
	printf("%s: Fail\n", value);
Packit 423ecb
    else
Packit 423ecb
	printf("%s: Error: %d\n", value, ret);
Packit 423ecb
    if (repeat) {
Packit 423ecb
	int j;
Packit 423ecb
	for (j = 0;j < 999999;j++)
Packit 423ecb
	    xmlRegexpExec(comp, (const xmlChar *) value);
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static void
Packit 423ecb
testRegexpFile(const char *filename) {
Packit 423ecb
    xmlRegexpPtr comp = NULL;
Packit 423ecb
    FILE *input;
Packit 423ecb
    char expression[5000];
Packit 423ecb
    int len;
Packit 423ecb
Packit 423ecb
    input = fopen(filename, "r");
Packit 423ecb
    if (input == NULL) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		"Cannot open %s for reading\n", filename);
Packit 423ecb
	return;
Packit 423ecb
    }
Packit 423ecb
    while (fgets(expression, 4500, input) != NULL) {
Packit 423ecb
	len = strlen(expression);
Packit 423ecb
	len--;
Packit 423ecb
	while ((len >= 0) &&
Packit 423ecb
	       ((expression[len] == '\n') || (expression[len] == '\t') ||
Packit 423ecb
		(expression[len] == '\r') || (expression[len] == ' '))) len--;
Packit 423ecb
	expression[len + 1] = 0;
Packit 423ecb
	if (len >= 0) {
Packit 423ecb
	    if (expression[0] == '#')
Packit 423ecb
		continue;
Packit 423ecb
	    if ((expression[0] == '=') && (expression[1] == '>')) {
Packit 423ecb
		char *pattern = &expression[2];
Packit 423ecb
Packit 423ecb
		if (comp != NULL) {
Packit 423ecb
		    xmlRegFreeRegexp(comp);
Packit 423ecb
		    comp = NULL;
Packit 423ecb
		}
Packit 423ecb
		printf("Regexp: %s\n", pattern) ;
Packit 423ecb
		comp = xmlRegexpCompile((const xmlChar *) pattern);
Packit 423ecb
		if (comp == NULL) {
Packit 423ecb
		    printf("   failed to compile\n");
Packit 423ecb
		    break;
Packit 423ecb
		}
Packit 423ecb
	    } else if (comp == NULL) {
Packit 423ecb
		printf("Regexp: %s\n", expression) ;
Packit 423ecb
		comp = xmlRegexpCompile((const xmlChar *) expression);
Packit 423ecb
		if (comp == NULL) {
Packit 423ecb
		    printf("   failed to compile\n");
Packit 423ecb
		    break;
Packit 423ecb
		}
Packit 423ecb
	    } else if (comp != NULL) {
Packit 423ecb
		testRegexp(comp, expression);
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    fclose(input);
Packit 423ecb
    if (comp != NULL)
Packit 423ecb
	xmlRegFreeRegexp(comp);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
static void
Packit 423ecb
runFileTest(xmlExpCtxtPtr ctxt, const char *filename) {
Packit 423ecb
    xmlExpNodePtr expr = NULL, sub;
Packit 423ecb
    FILE *input;
Packit 423ecb
    char expression[5000];
Packit 423ecb
    int len;
Packit 423ecb
Packit 423ecb
    input = fopen(filename, "r");
Packit 423ecb
    if (input == NULL) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
		"Cannot open %s for reading\n", filename);
Packit 423ecb
	return;
Packit 423ecb
    }
Packit 423ecb
    while (fgets(expression, 4500, input) != NULL) {
Packit 423ecb
	len = strlen(expression);
Packit 423ecb
	len--;
Packit 423ecb
	while ((len >= 0) &&
Packit 423ecb
	       ((expression[len] == '\n') || (expression[len] == '\t') ||
Packit 423ecb
		(expression[len] == '\r') || (expression[len] == ' '))) len--;
Packit 423ecb
	expression[len + 1] = 0;
Packit 423ecb
	if (len >= 0) {
Packit 423ecb
	    if (expression[0] == '#')
Packit 423ecb
		continue;
Packit 423ecb
	    if ((expression[0] == '=') && (expression[1] == '>')) {
Packit 423ecb
		char *str = &expression[2];
Packit 423ecb
Packit 423ecb
		if (expr != NULL) {
Packit 423ecb
		    xmlExpFree(ctxt, expr);
Packit 423ecb
		    if (xmlExpCtxtNbNodes(ctxt) != 0)
Packit 423ecb
		        printf(" Parse/free of Expression leaked %d\n",
Packit 423ecb
			       xmlExpCtxtNbNodes(ctxt));
Packit 423ecb
		    expr = NULL;
Packit 423ecb
		}
Packit 423ecb
		printf("Expression: %s\n", str) ;
Packit 423ecb
		expr = xmlExpParse(ctxt, str);
Packit 423ecb
		if (expr == NULL) {
Packit 423ecb
		    printf("   parsing Failed\n");
Packit 423ecb
		    break;
Packit 423ecb
		}
Packit 423ecb
	    } else if (expr != NULL) {
Packit 423ecb
	        int expect = -1;
Packit 423ecb
		int nodes1, nodes2;
Packit 423ecb
Packit 423ecb
		if (expression[0] == '0')
Packit 423ecb
		    expect = 0;
Packit 423ecb
		if (expression[0] == '1')
Packit 423ecb
		    expect = 1;
Packit 423ecb
		printf("Subexp: %s", expression + 2) ;
Packit 423ecb
		nodes1 = xmlExpCtxtNbNodes(ctxt);
Packit 423ecb
		sub = xmlExpParse(ctxt, expression + 2);
Packit 423ecb
		if (sub == NULL) {
Packit 423ecb
		    printf("   parsing Failed\n");
Packit 423ecb
		    break;
Packit 423ecb
		} else {
Packit 423ecb
		    int ret;
Packit 423ecb
Packit 423ecb
		    nodes2 = xmlExpCtxtNbNodes(ctxt);
Packit 423ecb
		    ret = xmlExpSubsume(ctxt, expr, sub);
Packit 423ecb
Packit 423ecb
		    if ((expect == 1) && (ret == 1)) {
Packit 423ecb
			printf(" => accept, Ok\n");
Packit 423ecb
		    } else if ((expect == 0) && (ret == 0)) {
Packit 423ecb
		        printf(" => reject, Ok\n");
Packit 423ecb
		    } else if ((expect == 1) && (ret == 0)) {
Packit 423ecb
			printf(" => reject, Failed\n");
Packit 423ecb
		    } else if ((expect == 0) && (ret == 1)) {
Packit 423ecb
			printf(" => accept, Failed\n");
Packit 423ecb
		    } else {
Packit 423ecb
		        printf(" => fail internally\n");
Packit 423ecb
		    }
Packit 423ecb
		    if (xmlExpCtxtNbNodes(ctxt) > nodes2) {
Packit 423ecb
		        printf(" Subsume leaked %d\n",
Packit 423ecb
			       xmlExpCtxtNbNodes(ctxt) - nodes2);
Packit 423ecb
			nodes1 += xmlExpCtxtNbNodes(ctxt) - nodes2;
Packit 423ecb
		    }
Packit 423ecb
		    xmlExpFree(ctxt, sub);
Packit 423ecb
		    if (xmlExpCtxtNbNodes(ctxt) > nodes1) {
Packit 423ecb
		        printf(" Parse/free leaked %d\n",
Packit 423ecb
			       xmlExpCtxtNbNodes(ctxt) - nodes1);
Packit 423ecb
		    }
Packit 423ecb
		}
Packit 423ecb
Packit 423ecb
	    }
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    if (expr != NULL) {
Packit 423ecb
	xmlExpFree(ctxt, expr);
Packit 423ecb
	if (xmlExpCtxtNbNodes(ctxt) != 0)
Packit 423ecb
	    printf(" Parse/free of Expression leaked %d\n",
Packit 423ecb
		   xmlExpCtxtNbNodes(ctxt));
Packit 423ecb
    }
Packit 423ecb
    fclose(input);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static void
Packit 423ecb
testReduce(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, const char *tst) {
Packit 423ecb
    xmlBufferPtr xmlExpBuf;
Packit 423ecb
    xmlExpNodePtr sub, deriv;
Packit 423ecb
    xmlExpBuf = xmlBufferCreate();
Packit 423ecb
Packit 423ecb
    sub = xmlExpParse(ctxt, tst);
Packit 423ecb
    if (sub == NULL) {
Packit 423ecb
        printf("Subset %s failed to parse\n", tst);
Packit 423ecb
	return;
Packit 423ecb
    }
Packit 423ecb
    xmlExpDump(xmlExpBuf, sub);
Packit 423ecb
    printf("Subset parsed as: %s\n",
Packit 423ecb
           (const char *) xmlBufferContent(xmlExpBuf));
Packit 423ecb
    deriv = xmlExpExpDerive(ctxt, expr, sub);
Packit 423ecb
    if (deriv == NULL) {
Packit 423ecb
        printf("Derivation led to an internal error, report this !\n");
Packit 423ecb
	return;
Packit 423ecb
    } else {
Packit 423ecb
        xmlBufferEmpty(xmlExpBuf);
Packit 423ecb
	xmlExpDump(xmlExpBuf, deriv);
Packit 423ecb
	if (xmlExpIsNillable(deriv))
Packit 423ecb
	    printf("Resulting nillable derivation: %s\n",
Packit 423ecb
	           (const char *) xmlBufferContent(xmlExpBuf));
Packit 423ecb
	else
Packit 423ecb
	    printf("Resulting derivation: %s\n",
Packit 423ecb
	           (const char *) xmlBufferContent(xmlExpBuf));
Packit 423ecb
	xmlExpFree(ctxt, deriv);
Packit 423ecb
    }
Packit 423ecb
    xmlExpFree(ctxt, sub);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static void
Packit 423ecb
exprDebug(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr) {
Packit 423ecb
    xmlBufferPtr xmlExpBuf;
Packit 423ecb
    xmlExpNodePtr deriv;
Packit 423ecb
    const char *list[40];
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    xmlExpBuf = xmlBufferCreate();
Packit 423ecb
Packit 423ecb
    if (expr == NULL) {
Packit 423ecb
        printf("Failed to parse\n");
Packit 423ecb
	return;
Packit 423ecb
    }
Packit 423ecb
    xmlExpDump(xmlExpBuf, expr);
Packit 423ecb
    printf("Parsed as: %s\n", (const char *) xmlBufferContent(xmlExpBuf));
Packit 423ecb
    printf("Max token input = %d\n", xmlExpMaxToken(expr));
Packit 423ecb
    if (xmlExpIsNillable(expr) == 1)
Packit 423ecb
	printf("Is nillable\n");
Packit 423ecb
    ret = xmlExpGetLanguage(ctxt, expr, (const xmlChar **) &list[0], 40);
Packit 423ecb
    if (ret < 0)
Packit 423ecb
	printf("Failed to get list: %d\n", ret);
Packit 423ecb
    else {
Packit 423ecb
	int i;
Packit 423ecb
Packit 423ecb
	printf("Language has %d strings, testing string derivations\n", ret);
Packit 423ecb
	for (i = 0;i < ret;i++) {
Packit 423ecb
	    deriv = xmlExpStringDerive(ctxt, expr, BAD_CAST list[i], -1);
Packit 423ecb
	    if (deriv == NULL) {
Packit 423ecb
		printf("  %s -> derivation failed\n", list[i]);
Packit 423ecb
	    } else {
Packit 423ecb
		xmlBufferEmpty(xmlExpBuf);
Packit 423ecb
		xmlExpDump(xmlExpBuf, deriv);
Packit 423ecb
		printf("  %s -> %s\n", list[i],
Packit 423ecb
		       (const char *) xmlBufferContent(xmlExpBuf));
Packit 423ecb
	    }
Packit 423ecb
	    xmlExpFree(ctxt, deriv);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    xmlBufferFree(xmlExpBuf);
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
static void usage(const char *name) {
Packit 423ecb
    fprintf(stderr, "Usage: %s [flags]\n", name);
Packit 423ecb
    fprintf(stderr, "Testing tool for libxml2 string and pattern regexps\n");
Packit 423ecb
    fprintf(stderr, "   --debug: switch on debugging\n");
Packit 423ecb
    fprintf(stderr, "   --repeat: loop on the operation\n");
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
    fprintf(stderr, "   --expr: test xmlExp and not xmlRegexp\n");
Packit 423ecb
#endif
Packit 423ecb
    fprintf(stderr, "   --input filename: use the given filename for regexp\n");
Packit 423ecb
    fprintf(stderr, "   --input filename: use the given filename for exp\n");
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
int main(int argc, char **argv) {
Packit 423ecb
    xmlRegexpPtr comp = NULL;
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
    xmlExpNodePtr expr = NULL;
Packit 423ecb
    int use_exp = 0;
Packit 423ecb
    xmlExpCtxtPtr ctxt = NULL;
Packit 423ecb
#endif
Packit 423ecb
    const char *pattern = NULL;
Packit 423ecb
    char *filename = NULL;
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    xmlInitMemory();
Packit 423ecb
Packit 423ecb
    if (argc <= 1) {
Packit 423ecb
	usage(argv[0]);
Packit 423ecb
	return(1);
Packit 423ecb
    }
Packit 423ecb
    for (i = 1; i < argc ; i++) {
Packit 423ecb
	if (!strcmp(argv[i], "-"))
Packit 423ecb
	    break;
Packit 423ecb
Packit 423ecb
	if (argv[i][0] != '-')
Packit 423ecb
	    continue;
Packit 423ecb
	if (!strcmp(argv[i], "--"))
Packit 423ecb
	    break;
Packit 423ecb
Packit 423ecb
	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
Packit 423ecb
	    debug++;
Packit 423ecb
	} else if ((!strcmp(argv[i], "-repeat")) ||
Packit 423ecb
	         (!strcmp(argv[i], "--repeat"))) {
Packit 423ecb
	    repeat++;
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
	} else if ((!strcmp(argv[i], "-expr")) ||
Packit 423ecb
	         (!strcmp(argv[i], "--expr"))) {
Packit 423ecb
	    use_exp++;
Packit 423ecb
#endif
Packit 423ecb
	} else if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "-f")) ||
Packit 423ecb
		   (!strcmp(argv[i], "--input")))
Packit 423ecb
	    filename = argv[++i];
Packit 423ecb
        else {
Packit 423ecb
	    fprintf(stderr, "Unknown option %s\n", argv[i]);
Packit 423ecb
	    usage(argv[0]);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
    if (use_exp)
Packit 423ecb
	ctxt = xmlExpNewCtxt(0, NULL);
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    if (filename != NULL) {
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
        if (use_exp)
Packit 423ecb
	    runFileTest(ctxt, filename);
Packit 423ecb
	else
Packit 423ecb
#endif
Packit 423ecb
	    testRegexpFile(filename);
Packit 423ecb
    } else {
Packit 423ecb
        int  data = 0;
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
Packit 423ecb
        if (use_exp) {
Packit 423ecb
	    for (i = 1; i < argc ; i++) {
Packit 423ecb
	        if (strcmp(argv[i], "--") == 0)
Packit 423ecb
		    data = 1;
Packit 423ecb
		else if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0) ||
Packit 423ecb
		    (data == 1)) {
Packit 423ecb
		    if (pattern == NULL) {
Packit 423ecb
			pattern = argv[i];
Packit 423ecb
			printf("Testing expr %s:\n", pattern);
Packit 423ecb
			expr = xmlExpParse(ctxt, pattern);
Packit 423ecb
			if (expr == NULL) {
Packit 423ecb
			    printf("   failed to compile\n");
Packit 423ecb
			    break;
Packit 423ecb
			}
Packit 423ecb
			if (debug) {
Packit 423ecb
			    exprDebug(ctxt, expr);
Packit 423ecb
			}
Packit 423ecb
		    } else {
Packit 423ecb
			testReduce(ctxt, expr, argv[i]);
Packit 423ecb
		    }
Packit 423ecb
		}
Packit 423ecb
	    }
Packit 423ecb
	    if (expr != NULL) {
Packit 423ecb
		xmlExpFree(ctxt, expr);
Packit 423ecb
		expr = NULL;
Packit 423ecb
	    }
Packit 423ecb
	} else
Packit 423ecb
#endif
Packit 423ecb
        {
Packit 423ecb
	    for (i = 1; i < argc ; i++) {
Packit 423ecb
	        if (strcmp(argv[i], "--") == 0)
Packit 423ecb
		    data = 1;
Packit 423ecb
		else if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0) ||
Packit 423ecb
		         (data == 1)) {
Packit 423ecb
		    if (pattern == NULL) {
Packit 423ecb
			pattern = argv[i];
Packit 423ecb
			printf("Testing %s:\n", pattern);
Packit 423ecb
			comp = xmlRegexpCompile((const xmlChar *) pattern);
Packit 423ecb
			if (comp == NULL) {
Packit 423ecb
			    printf("   failed to compile\n");
Packit 423ecb
			    break;
Packit 423ecb
			}
Packit 423ecb
			if (debug)
Packit 423ecb
			    xmlRegexpPrint(stdout, comp);
Packit 423ecb
		    } else {
Packit 423ecb
			testRegexp(comp, argv[i]);
Packit 423ecb
		    }
Packit 423ecb
		}
Packit 423ecb
	    }
Packit 423ecb
	    if (comp != NULL)
Packit 423ecb
		xmlRegFreeRegexp(comp);
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
#ifdef LIBXML_EXPR_ENABLED
Packit 423ecb
    if (ctxt != NULL) {
Packit 423ecb
	printf("Ops: %d nodes, %d cons\n",
Packit 423ecb
	       xmlExpCtxtNbNodes(ctxt), xmlExpCtxtNbCons(ctxt));
Packit 423ecb
	xmlExpFreeCtxt(ctxt);
Packit 423ecb
    }
Packit 423ecb
#endif
Packit 423ecb
    xmlCleanupParser();
Packit 423ecb
    xmlMemoryDump();
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#else
Packit 423ecb
#include <stdio.h>
Packit 423ecb
int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
Packit 423ecb
    printf("%s : Regexp support not compiled in\n", argv[0]);
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
#endif /* LIBXML_REGEXP_ENABLED */