root/third_party/libxml/src/testRegexp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. testRegexp
  2. testRegexpFile
  3. runFileTest
  4. testReduce
  5. exprDebug
  6. usage
  7. main
  8. main

/*
 * testRegexp.c: simple module for testing regular expressions
 *
 * See Copyright for the status of this software.
 *
 * Daniel Veillard <veillard@redhat.com>
 */

#include "libxml.h"
#ifdef LIBXML_REGEXP_ENABLED
#include <string.h>

#include <libxml/tree.h>
#include <libxml/xmlregexp.h>

static int repeat = 0;
static int debug = 0;

static void testRegexp(xmlRegexpPtr comp, const char *value) {
    int ret;

    ret = xmlRegexpExec(comp, (const xmlChar *) value);
    if (ret == 1)
        printf("%s: Ok\n", value);
    else if (ret == 0)
        printf("%s: Fail\n", value);
    else
        printf("%s: Error: %d\n", value, ret);
    if (repeat) {
        int j;
        for (j = 0;j < 999999;j++)
            xmlRegexpExec(comp, (const xmlChar *) value);
    }
}

static void
testRegexpFile(const char *filename) {
    xmlRegexpPtr comp = NULL;
    FILE *input;
    char expression[5000];
    int len;

    input = fopen(filename, "r");
    if (input == NULL) {
        xmlGenericError(xmlGenericErrorContext,
                "Cannot open %s for reading\n", filename);
        return;
    }
    while (fgets(expression, 4500, input) != NULL) {
        len = strlen(expression);
        len--;
        while ((len >= 0) && 
               ((expression[len] == '\n') || (expression[len] == '\t') ||
                (expression[len] == '\r') || (expression[len] == ' '))) len--;
        expression[len + 1] = 0;      
        if (len >= 0) {
            if (expression[0] == '#')
                continue;
            if ((expression[0] == '=') && (expression[1] == '>')) {
                char *pattern = &expression[2];

                if (comp != NULL) {
                    xmlRegFreeRegexp(comp);
                    comp = NULL;
                }
                printf("Regexp: %s\n", pattern) ;
                comp = xmlRegexpCompile((const xmlChar *) pattern);
                if (comp == NULL) {
                    printf("   failed to compile\n");
                    break;
                }
            } else if (comp == NULL) {
                printf("Regexp: %s\n", expression) ;
                comp = xmlRegexpCompile((const xmlChar *) expression);
                if (comp == NULL) {
                    printf("   failed to compile\n");
                    break;
                }
            } else if (comp != NULL) {
                testRegexp(comp, expression);
            }
        }
    }
    fclose(input);
    if (comp != NULL)
        xmlRegFreeRegexp(comp);
}

#ifdef LIBXML_EXPR_ENABLED
static void
runFileTest(xmlExpCtxtPtr ctxt, const char *filename) {
    xmlExpNodePtr expr = NULL, sub;
    FILE *input;
    char expression[5000];
    int len;

    input = fopen(filename, "r");
    if (input == NULL) {
        xmlGenericError(xmlGenericErrorContext,
                "Cannot open %s for reading\n", filename);
        return;
    }
    while (fgets(expression, 4500, input) != NULL) {
        len = strlen(expression);
        len--;
        while ((len >= 0) && 
               ((expression[len] == '\n') || (expression[len] == '\t') ||
                (expression[len] == '\r') || (expression[len] == ' '))) len--;
        expression[len + 1] = 0;      
        if (len >= 0) {
            if (expression[0] == '#')
                continue;
            if ((expression[0] == '=') && (expression[1] == '>')) {
                char *str = &expression[2];

                if (expr != NULL) {
                    xmlExpFree(ctxt, expr);
                    if (xmlExpCtxtNbNodes(ctxt) != 0) 
                        printf(" Parse/free of Expression leaked %d\n",
                               xmlExpCtxtNbNodes(ctxt));
                    expr = NULL;
                }
                printf("Expression: %s\n", str) ;
                expr = xmlExpParse(ctxt, str);
                if (expr == NULL) {
                    printf("   parsing Failed\n");
                    break;
                }
            } else if (expr != NULL) {
                int expect = -1;
                int nodes1, nodes2;

                if (expression[0] == '0')
                    expect = 0;
                if (expression[0] == '1')
                    expect = 1;
                printf("Subexp: %s", expression + 2) ;
                nodes1 = xmlExpCtxtNbNodes(ctxt);
                sub = xmlExpParse(ctxt, expression + 2);
                if (sub == NULL) {
                    printf("   parsing Failed\n");
                    break;
                } else {
                    int ret;
                    
                    nodes2 = xmlExpCtxtNbNodes(ctxt);
                    ret = xmlExpSubsume(ctxt, expr, sub);

                    if ((expect == 1) && (ret == 1)) {
                        printf(" => accept, Ok\n");
                    } else if ((expect == 0) && (ret == 0)) {
                        printf(" => reject, Ok\n");
                    } else if ((expect == 1) && (ret == 0)) {
                        printf(" => reject, Failed\n");
                    } else if ((expect == 0) && (ret == 1)) {
                        printf(" => accept, Failed\n");
                    } else {
                        printf(" => fail internally\n");
                    }
                    if (xmlExpCtxtNbNodes(ctxt) > nodes2) {
                        printf(" Subsume leaked %d\n",
                               xmlExpCtxtNbNodes(ctxt) - nodes2);
                        nodes1 += xmlExpCtxtNbNodes(ctxt) - nodes2;
                    }
                    xmlExpFree(ctxt, sub);
                    if (xmlExpCtxtNbNodes(ctxt) > nodes1) {
                        printf(" Parse/free leaked %d\n",
                               xmlExpCtxtNbNodes(ctxt) - nodes1);
                    }
                }

            }
        }
    }
    if (expr != NULL) {
        xmlExpFree(ctxt, expr);
        if (xmlExpCtxtNbNodes(ctxt) != 0) 
            printf(" Parse/free of Expression leaked %d\n",
                   xmlExpCtxtNbNodes(ctxt));
    }
    fclose(input);
}

static void 
testReduce(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, const char *tst) {
    xmlBufferPtr xmlExpBuf;
    xmlExpNodePtr sub, deriv;
    xmlExpBuf = xmlBufferCreate();

    sub = xmlExpParse(ctxt, tst);
    if (sub == NULL) {
        printf("Subset %s failed to parse\n", tst);
        return;
    }
    xmlExpDump(xmlExpBuf, sub);
    printf("Subset parsed as: %s\n",
           (const char *) xmlBufferContent(xmlExpBuf));
    deriv = xmlExpExpDerive(ctxt, expr, sub);
    if (deriv == NULL) {
        printf("Derivation led to an internal error, report this !\n");
        return;
    } else {
        xmlBufferEmpty(xmlExpBuf);
        xmlExpDump(xmlExpBuf, deriv);
        if (xmlExpIsNillable(deriv))
            printf("Resulting nillable derivation: %s\n",
                   (const char *) xmlBufferContent(xmlExpBuf));
        else
            printf("Resulting derivation: %s\n",
                   (const char *) xmlBufferContent(xmlExpBuf));
        xmlExpFree(ctxt, deriv);
    }
    xmlExpFree(ctxt, sub);
}

static void 
exprDebug(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr) {
    xmlBufferPtr xmlExpBuf;
    xmlExpNodePtr deriv;
    const char *list[40];
    int ret;

    xmlExpBuf = xmlBufferCreate();

    if (expr == NULL) {
        printf("Failed to parse\n");
        return;
    }
    xmlExpDump(xmlExpBuf, expr);
    printf("Parsed as: %s\n", (const char *) xmlBufferContent(xmlExpBuf));
    printf("Max token input = %d\n", xmlExpMaxToken(expr));
    if (xmlExpIsNillable(expr) == 1)
        printf("Is nillable\n");
    ret = xmlExpGetLanguage(ctxt, expr, (const xmlChar **) &list[0], 40);
    if (ret < 0)
        printf("Failed to get list: %d\n", ret);
    else {
        int i;

        printf("Language has %d strings, testing string derivations\n", ret);
        for (i = 0;i < ret;i++) {
            deriv = xmlExpStringDerive(ctxt, expr, BAD_CAST list[i], -1);
            if (deriv == NULL) {
                printf("  %s -> derivation failed\n", list[i]);
            } else {
                xmlBufferEmpty(xmlExpBuf);
                xmlExpDump(xmlExpBuf, deriv);
                printf("  %s -> %s\n", list[i],
                       (const char *) xmlBufferContent(xmlExpBuf));
            }
            xmlExpFree(ctxt, deriv);
        }
    }
    xmlBufferFree(xmlExpBuf);
}
#endif

static void usage(const char *name) {
    fprintf(stderr, "Usage: %s [flags]\n", name);
    fprintf(stderr, "Testing tool for libxml2 string and pattern regexps\n");
    fprintf(stderr, "   --debug: switch on debugging\n");
    fprintf(stderr, "   --repeat: loop on the operation\n");
#ifdef LIBXML_EXPR_ENABLED
    fprintf(stderr, "   --expr: test xmlExp and not xmlRegexp\n");
#endif
    fprintf(stderr, "   --input filename: use the given filename for regexp\n");
    fprintf(stderr, "   --input filename: use the given filename for exp\n");
}

int main(int argc, char **argv) {
    xmlRegexpPtr comp = NULL;
#ifdef LIBXML_EXPR_ENABLED
    xmlExpNodePtr expr = NULL;
    int use_exp = 0;
    xmlExpCtxtPtr ctxt = NULL;
#endif
    const char *pattern = NULL;
    char *filename = NULL;
    int i;

    xmlInitMemory();

    if (argc <= 1) {
        usage(argv[0]);
        return(1);
    }
    for (i = 1; i < argc ; i++) {
        if (!strcmp(argv[i], "-"))
            break;

        if (argv[i][0] != '-')
            continue;
        if (!strcmp(argv[i], "--"))
            break;

        if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
            debug++;
        } else if ((!strcmp(argv[i], "-repeat")) ||
                 (!strcmp(argv[i], "--repeat"))) {
            repeat++;
#ifdef LIBXML_EXPR_ENABLED
        } else if ((!strcmp(argv[i], "-expr")) ||
                 (!strcmp(argv[i], "--expr"))) {
            use_exp++;
#endif
        } else if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "-f")) ||
                   (!strcmp(argv[i], "--input")))
            filename = argv[++i];
        else {
            fprintf(stderr, "Unknown option %s\n", argv[i]);
            usage(argv[0]);
        }
    }

#ifdef LIBXML_EXPR_ENABLED
    if (use_exp)
        ctxt = xmlExpNewCtxt(0, NULL);
#endif

    if (filename != NULL) {
#ifdef LIBXML_EXPR_ENABLED
        if (use_exp)
            runFileTest(ctxt, filename);
        else
#endif
            testRegexpFile(filename);
    } else {
        int  data = 0;
#ifdef LIBXML_EXPR_ENABLED

        if (use_exp) {
            for (i = 1; i < argc ; i++) {
                if (strcmp(argv[i], "--") == 0)
                    data = 1;
                else if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0) ||
                    (data == 1)) {
                    if (pattern == NULL) {
                        pattern = argv[i];
                        printf("Testing expr %s:\n", pattern);
                        expr = xmlExpParse(ctxt, pattern);
                        if (expr == NULL) {
                            printf("   failed to compile\n");
                            break;
                        }
                        if (debug) {
                            exprDebug(ctxt, expr);
                        }
                    } else {
                        testReduce(ctxt, expr, argv[i]);
                    }
                }
            }
            if (expr != NULL) {
                xmlExpFree(ctxt, expr);
                expr = NULL;
            }
        } else
#endif
        {
            for (i = 1; i < argc ; i++) {
                if (strcmp(argv[i], "--") == 0)
                    data = 1;
                else if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0) ||
                         (data == 1)) {
                    if (pattern == NULL) {
                        pattern = argv[i];
                        printf("Testing %s:\n", pattern);
                        comp = xmlRegexpCompile((const xmlChar *) pattern);
                        if (comp == NULL) {
                            printf("   failed to compile\n");
                            break;
                        }
                        if (debug)
                            xmlRegexpPrint(stdout, comp);
                    } else {
                        testRegexp(comp, argv[i]);
                    }
                }
            }
            if (comp != NULL)
                xmlRegFreeRegexp(comp);
        }
    }
#ifdef LIBXML_EXPR_ENABLED
    if (ctxt != NULL) {
        printf("Ops: %d nodes, %d cons\n",
               xmlExpCtxtNbNodes(ctxt), xmlExpCtxtNbCons(ctxt));
        xmlExpFreeCtxt(ctxt);
    }
#endif
    xmlCleanupParser();
    xmlMemoryDump();
    return(0);
}

#else
#include <stdio.h>
int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
    printf("%s : Regexp support not compiled in\n", argv[0]);
    return(0);
}
#endif /* LIBXML_REGEXP_ENABLED */

/* [<][>][^][v][top][bottom][index][help] */