Edit

kc3-lang/libxml2/xmllint.c

Branch :

  • Show log

    Commit

  • Author : Fabien Degomme
    Date : 2015-10-23 19:35:02
    Hash : b40c1940
    Message : Fix a small error in xmllint --format description Obviously it operates on the output not the input

  • xmllint.c
  • /*
     * xmllint.c : a small tester program for XML input.
     *
     * See Copyright for the status of this software.
     *
     * daniel@veillard.com
     */
    
    #include "libxml.h"
    
    #include <string.h>
    #include <stdarg.h>
    #include <assert.h>
    
    #if defined (_WIN32) && !defined(__CYGWIN__)
    #if defined (_MSC_VER) || defined(__BORLANDC__)
    #include <winsock2.h>
    #pragma comment(lib, "ws2_32.lib")
    #define gettimeofday(p1,p2)
    #endif /* _MSC_VER */
    #endif /* _WIN32 */
    
    #ifdef HAVE_SYS_TIME_H
    #include <sys/time.h>
    #endif
    #ifdef HAVE_TIME_H
    #include <time.h>
    #endif
    
    #ifdef __MINGW32__
    #define _WINSOCKAPI_
    #include <wsockcompat.h>
    #include <winsock2.h>
    #undef XML_SOCKLEN_T
    #define XML_SOCKLEN_T unsigned int
    #endif
    
    #ifdef HAVE_SYS_TIMEB_H
    #include <sys/timeb.h>
    #endif
    
    #ifdef HAVE_SYS_TYPES_H
    #include <sys/types.h>
    #endif
    #ifdef HAVE_SYS_STAT_H
    #include <sys/stat.h>
    #endif
    #ifdef HAVE_FCNTL_H
    #include <fcntl.h>
    #endif
    #ifdef HAVE_UNISTD_H
    #include <unistd.h>
    #endif
    #ifdef HAVE_SYS_MMAN_H
    #include <sys/mman.h>
    /* seems needed for Solaris */
    #ifndef MAP_FAILED
    #define MAP_FAILED ((void *) -1)
    #endif
    #endif
    #ifdef HAVE_STDLIB_H
    #include <stdlib.h>
    #endif
    #ifdef HAVE_LIBREADLINE
    #include <readline/readline.h>
    #ifdef HAVE_LIBHISTORY
    #include <readline/history.h>
    #endif
    #endif
    
    #include <libxml/xmlmemory.h>
    #include <libxml/parser.h>
    #include <libxml/parserInternals.h>
    #include <libxml/HTMLparser.h>
    #include <libxml/HTMLtree.h>
    #include <libxml/tree.h>
    #include <libxml/xpath.h>
    #include <libxml/debugXML.h>
    #include <libxml/xmlerror.h>
    #ifdef LIBXML_XINCLUDE_ENABLED
    #include <libxml/xinclude.h>
    #endif
    #ifdef LIBXML_CATALOG_ENABLED
    #include <libxml/catalog.h>
    #endif
    #include <libxml/globals.h>
    #include <libxml/xmlreader.h>
    #ifdef LIBXML_SCHEMATRON_ENABLED
    #include <libxml/schematron.h>
    #endif
    #ifdef LIBXML_SCHEMAS_ENABLED
    #include <libxml/relaxng.h>
    #include <libxml/xmlschemas.h>
    #endif
    #ifdef LIBXML_PATTERN_ENABLED
    #include <libxml/pattern.h>
    #endif
    #ifdef LIBXML_C14N_ENABLED
    #include <libxml/c14n.h>
    #endif
    #ifdef LIBXML_OUTPUT_ENABLED
    #include <libxml/xmlsave.h>
    #endif
    
    #ifndef XML_XML_DEFAULT_CATALOG
    #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
    #endif
    
    typedef enum {
        XMLLINT_RETURN_OK = 0,	/* No error */
        XMLLINT_ERR_UNCLASS = 1,	/* Unclassified */
        XMLLINT_ERR_DTD = 2,	/* Error in DTD */
        XMLLINT_ERR_VALID = 3,	/* Validation error */
        XMLLINT_ERR_RDFILE = 4,	/* CtxtReadFile error */
        XMLLINT_ERR_SCHEMACOMP = 5,	/* Schema compilation */
        XMLLINT_ERR_OUT = 6,	/* Error writing output */
        XMLLINT_ERR_SCHEMAPAT = 7,	/* Error in schema pattern */
        XMLLINT_ERR_RDREGIS = 8,	/* Error in Reader registration */
        XMLLINT_ERR_MEM = 9,	/* Out of memory error */
        XMLLINT_ERR_XPATH = 10	/* XPath evaluation error */
    } xmllintReturnCode;
    #ifdef LIBXML_DEBUG_ENABLED
    static int shell = 0;
    static int debugent = 0;
    #endif
    static int debug = 0;
    static int maxmem = 0;
    #ifdef LIBXML_TREE_ENABLED
    static int copy = 0;
    #endif /* LIBXML_TREE_ENABLED */
    static int recovery = 0;
    static int noent = 0;
    static int noenc = 0;
    static int noblanks = 0;
    static int noout = 0;
    static int nowrap = 0;
    #ifdef LIBXML_OUTPUT_ENABLED
    static int format = 0;
    static const char *output = NULL;
    static int compress = 0;
    static int oldout = 0;
    #endif /* LIBXML_OUTPUT_ENABLED */
    #ifdef LIBXML_VALID_ENABLED
    static int valid = 0;
    static int postvalid = 0;
    static char * dtdvalid = NULL;
    static char * dtdvalidfpi = NULL;
    #endif
    #ifdef LIBXML_SCHEMAS_ENABLED
    static char * relaxng = NULL;
    static xmlRelaxNGPtr relaxngschemas = NULL;
    static char * schema = NULL;
    static xmlSchemaPtr wxschemas = NULL;
    #endif
    #ifdef LIBXML_SCHEMATRON_ENABLED
    static char * schematron = NULL;
    static xmlSchematronPtr wxschematron = NULL;
    #endif
    static int repeat = 0;
    static int insert = 0;
    #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
    static int html = 0;
    static int xmlout = 0;
    #endif
    static int htmlout = 0;
    #if defined(LIBXML_HTML_ENABLED)
    static int nodefdtd = 0;
    #endif
    #ifdef LIBXML_PUSH_ENABLED
    static int push = 0;
    static int pushsize = 4096;
    #endif /* LIBXML_PUSH_ENABLED */
    #ifdef HAVE_MMAP
    static int memory = 0;
    #endif
    static int testIO = 0;
    static char *encoding = NULL;
    #ifdef LIBXML_XINCLUDE_ENABLED
    static int xinclude = 0;
    #endif
    static int dtdattrs = 0;
    static int loaddtd = 0;
    static xmllintReturnCode progresult = XMLLINT_RETURN_OK;
    static int timing = 0;
    static int generate = 0;
    static int dropdtd = 0;
    #ifdef LIBXML_CATALOG_ENABLED
    static int catalogs = 0;
    static int nocatalogs = 0;
    #endif
    #ifdef LIBXML_C14N_ENABLED
    static int canonical = 0;
    static int canonical_11 = 0;
    static int exc_canonical = 0;
    #endif
    #ifdef LIBXML_READER_ENABLED
    static int stream = 0;
    static int walker = 0;
    #endif /* LIBXML_READER_ENABLED */
    static int chkregister = 0;
    static int nbregister = 0;
    #ifdef LIBXML_SAX1_ENABLED
    static int sax1 = 0;
    #endif /* LIBXML_SAX1_ENABLED */
    #ifdef LIBXML_PATTERN_ENABLED
    static const char *pattern = NULL;
    static xmlPatternPtr patternc = NULL;
    static xmlStreamCtxtPtr patstream = NULL;
    #endif
    #ifdef LIBXML_XPATH_ENABLED
    static const char *xpathquery = NULL;
    #endif
    static int options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
    static int sax = 0;
    static int oldxml10 = 0;
    
    /************************************************************************
     *									*
     *		 Entity loading control and customization.		*
     *									*
     ************************************************************************/
    #define MAX_PATHS 64
    #ifdef _WIN32
    # define PATH_SEPARATOR ';'
    #else
    # define PATH_SEPARATOR ':'
    #endif
    static xmlChar *paths[MAX_PATHS + 1];
    static int nbpaths = 0;
    static int load_trace = 0;
    
    static
    void parsePath(const xmlChar *path) {
        const xmlChar *cur;
    
        if (path == NULL)
    	return;
        while (*path != 0) {
    	if (nbpaths >= MAX_PATHS) {
    	    fprintf(stderr, "MAX_PATHS reached: too many paths\n");
    	    return;
    	}
    	cur = path;
    	while ((*cur == ' ') || (*cur == PATH_SEPARATOR))
    	    cur++;
    	path = cur;
    	while ((*cur != 0) && (*cur != ' ') && (*cur != PATH_SEPARATOR))
    	    cur++;
    	if (cur != path) {
    	    paths[nbpaths] = xmlStrndup(path, cur - path);
    	    if (paths[nbpaths] != NULL)
    		nbpaths++;
    	    path = cur;
    	}
        }
    }
    
    static xmlExternalEntityLoader defaultEntityLoader = NULL;
    
    static xmlParserInputPtr
    xmllintExternalEntityLoader(const char *URL, const char *ID,
    			     xmlParserCtxtPtr ctxt) {
        xmlParserInputPtr ret;
        warningSAXFunc warning = NULL;
        errorSAXFunc err = NULL;
    
        int i;
        const char *lastsegment = URL;
        const char *iter = URL;
    
        if ((nbpaths > 0) && (iter != NULL)) {
    	while (*iter != 0) {
    	    if (*iter == '/')
    		lastsegment = iter + 1;
    	    iter++;
    	}
        }
    
        if ((ctxt != NULL) && (ctxt->sax != NULL)) {
    	warning = ctxt->sax->warning;
    	err = ctxt->sax->error;
    	ctxt->sax->warning = NULL;
    	ctxt->sax->error = NULL;
        }
    
        if (defaultEntityLoader != NULL) {
    	ret = defaultEntityLoader(URL, ID, ctxt);
    	if (ret != NULL) {
    	    if (warning != NULL)
    		ctxt->sax->warning = warning;
    	    if (err != NULL)
    		ctxt->sax->error = err;
    	    if (load_trace) {
    		fprintf \
    			(stderr,
    			 "Loaded URL=\"%s\" ID=\"%s\"\n",
    			 URL ? URL : "(null)",
    			 ID ? ID : "(null)");
    	    }
    	    return(ret);
    	}
        }
        for (i = 0;i < nbpaths;i++) {
    	xmlChar *newURL;
    
    	newURL = xmlStrdup((const xmlChar *) paths[i]);
    	newURL = xmlStrcat(newURL, (const xmlChar *) "/");
    	newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
    	if (newURL != NULL) {
    	    ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
    	    if (ret != NULL) {
    		if (warning != NULL)
    		    ctxt->sax->warning = warning;
    		if (err != NULL)
    		    ctxt->sax->error = err;
    		if (load_trace) {
    		    fprintf \
    			(stderr,
    			 "Loaded URL=\"%s\" ID=\"%s\"\n",
    			 newURL,
    			 ID ? ID : "(null)");
    		}
    		xmlFree(newURL);
    		return(ret);
    	    }
    	    xmlFree(newURL);
    	}
        }
        if (err != NULL)
            ctxt->sax->error = err;
        if (warning != NULL) {
    	ctxt->sax->warning = warning;
    	if (URL != NULL)
    	    warning(ctxt, "failed to load external entity \"%s\"\n", URL);
    	else if (ID != NULL)
    	    warning(ctxt, "failed to load external entity \"%s\"\n", ID);
        }
        return(NULL);
    }
    /************************************************************************
     *									*
     * Memory allocation consumption debugging				*
     *									*
     ************************************************************************/
    
    static void
    OOM(void)
    {
        fprintf(stderr, "Ran out of memory needs > %d bytes\n", maxmem);
        progresult = XMLLINT_ERR_MEM;
    }
    
    static void
    myFreeFunc(void *mem)
    {
        xmlMemFree(mem);
    }
    static void *
    myMallocFunc(size_t size)
    {
        void *ret;
    
        ret = xmlMemMalloc(size);
        if (ret != NULL) {
            if (xmlMemUsed() > maxmem) {
                OOM();
                xmlMemFree(ret);
                return (NULL);
            }
        }
        return (ret);
    }
    static void *
    myReallocFunc(void *mem, size_t size)
    {
        void *ret;
    
        ret = xmlMemRealloc(mem, size);
        if (ret != NULL) {
            if (xmlMemUsed() > maxmem) {
                OOM();
                xmlMemFree(ret);
                return (NULL);
            }
        }
        return (ret);
    }
    static char *
    myStrdupFunc(const char *str)
    {
        char *ret;
    
        ret = xmlMemoryStrdup(str);
        if (ret != NULL) {
            if (xmlMemUsed() > maxmem) {
                OOM();
                xmlFree(ret);
                return (NULL);
            }
        }
        return (ret);
    }
    /************************************************************************
     *									*
     * Internal timing routines to remove the necessity to have		*
     * unix-specific function calls.					*
     *									*
     ************************************************************************/
    
    #ifndef HAVE_GETTIMEOFDAY
    #ifdef HAVE_SYS_TIMEB_H
    #ifdef HAVE_SYS_TIME_H
    #ifdef HAVE_FTIME
    
    static int
    my_gettimeofday(struct timeval *tvp, void *tzp)
    {
    	struct timeb timebuffer;
    
    	ftime(&timebuffer);
    	if (tvp) {
    		tvp->tv_sec = timebuffer.time;
    		tvp->tv_usec = timebuffer.millitm * 1000L;
    	}
    	return (0);
    }
    #define HAVE_GETTIMEOFDAY 1
    #define gettimeofday my_gettimeofday
    
    #endif /* HAVE_FTIME */
    #endif /* HAVE_SYS_TIME_H */
    #endif /* HAVE_SYS_TIMEB_H */
    #endif /* !HAVE_GETTIMEOFDAY */
    
    #if defined(HAVE_GETTIMEOFDAY)
    static struct timeval begin, end;
    
    /*
     * startTimer: call where you want to start timing
     */
    static void
    startTimer(void)
    {
        gettimeofday(&begin, NULL);
    }
    
    /*
     * endTimer: call where you want to stop timing and to print out a
     *           message about the timing performed; format is a printf
     *           type argument
     */
    static void XMLCDECL
    endTimer(const char *fmt, ...)
    {
        long msec;
        va_list ap;
    
        gettimeofday(&end, NULL);
        msec = end.tv_sec - begin.tv_sec;
        msec *= 1000;
        msec += (end.tv_usec - begin.tv_usec) / 1000;
    
    #ifndef HAVE_STDARG_H
    #error "endTimer required stdarg functions"
    #endif
        va_start(ap, fmt);
        vfprintf(stderr, fmt, ap);
        va_end(ap);
    
        fprintf(stderr, " took %ld ms\n", msec);
    }
    #elif defined(HAVE_TIME_H)
    /*
     * No gettimeofday function, so we have to make do with calling clock.
     * This is obviously less accurate, but there's little we can do about
     * that.
     */
    #ifndef CLOCKS_PER_SEC
    #define CLOCKS_PER_SEC 100
    #endif
    
    static clock_t begin, end;
    static void
    startTimer(void)
    {
        begin = clock();
    }
    static void XMLCDECL
    endTimer(const char *fmt, ...)
    {
        long msec;
        va_list ap;
    
        end = clock();
        msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
    
    #ifndef HAVE_STDARG_H
    #error "endTimer required stdarg functions"
    #endif
        va_start(ap, fmt);
        vfprintf(stderr, fmt, ap);
        va_end(ap);
        fprintf(stderr, " took %ld ms\n", msec);
    }
    #else
    
    /*
     * We don't have a gettimeofday or time.h, so we just don't do timing
     */
    static void
    startTimer(void)
    {
        /*
         * Do nothing
         */
    }
    static void XMLCDECL
    endTimer(char *format, ...)
    {
        /*
         * We cannot do anything because we don't have a timing function
         */
    #ifdef HAVE_STDARG_H
        va_list ap;
        va_start(ap, format);
        vfprintf(stderr, format, ap);
        va_end(ap);
        fprintf(stderr, " was not timed\n");
    #else
        /* We don't have gettimeofday, time or stdarg.h, what crazy world is
         * this ?!
         */
    #endif
    }
    #endif
    /************************************************************************
     *									*
     *			HTML ouput					*
     *									*
     ************************************************************************/
    static char buffer[50000];
    
    static void
    xmlHTMLEncodeSend(void) {
        char *result;
    
        result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
        if (result) {
    	xmlGenericError(xmlGenericErrorContext, "%s", result);
    	xmlFree(result);
        }
        buffer[0] = 0;
    }
    
    /**
     * xmlHTMLPrintFileInfo:
     * @input:  an xmlParserInputPtr input
     *
     * Displays the associated file and line informations for the current input
     */
    
    static void
    xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
        int len;
        xmlGenericError(xmlGenericErrorContext, "<p>");
    
        len = strlen(buffer);
        if (input != NULL) {
    	if (input->filename) {
    	    snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
    		    input->line);
    	} else {
    	    snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
    	}
        }
        xmlHTMLEncodeSend();
    }
    
    /**
     * xmlHTMLPrintFileContext:
     * @input:  an xmlParserInputPtr input
     *
     * Displays current context within the input content for error tracking
     */
    
    static void
    xmlHTMLPrintFileContext(xmlParserInputPtr input) {
        const xmlChar *cur, *base;
        int len;
        int n;
    
        if (input == NULL) return;
        xmlGenericError(xmlGenericErrorContext, "<pre>\n");
        cur = input->cur;
        base = input->base;
        while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
    	cur--;
        }
        n = 0;
        while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
            cur--;
        if ((*cur == '\n') || (*cur == '\r')) cur++;
        base = cur;
        n = 0;
        while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
    	len = strlen(buffer);
            snprintf(&buffer[len], sizeof(buffer) - len, "%c",
    		    (unsigned char) *cur++);
    	n++;
        }
        len = strlen(buffer);
        snprintf(&buffer[len], sizeof(buffer) - len, "\n");
        cur = input->cur;
        while ((*cur == '\n') || (*cur == '\r'))
    	cur--;
        n = 0;
        while ((cur != base) && (n++ < 80)) {
    	len = strlen(buffer);
            snprintf(&buffer[len], sizeof(buffer) - len, " ");
            base++;
        }
        len = strlen(buffer);
        snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
        xmlHTMLEncodeSend();
        xmlGenericError(xmlGenericErrorContext, "</pre>");
    }
    
    /**
     * xmlHTMLError:
     * @ctx:  an XML parser context
     * @msg:  the message to display/transmit
     * @...:  extra parameters for the message display
     *
     * Display and format an error messages, gives file, line, position and
     * extra parameters.
     */
    static void XMLCDECL
    xmlHTMLError(void *ctx, const char *msg, ...)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
        xmlParserInputPtr input;
        va_list args;
        int len;
    
        buffer[0] = 0;
        input = ctxt->input;
        if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
            input = ctxt->inputTab[ctxt->inputNr - 2];
        }
    
        xmlHTMLPrintFileInfo(input);
    
        xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
        va_start(args, msg);
        len = strlen(buffer);
        vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
        va_end(args);
        xmlHTMLEncodeSend();
        xmlGenericError(xmlGenericErrorContext, "</p>\n");
    
        xmlHTMLPrintFileContext(input);
        xmlHTMLEncodeSend();
    }
    
    /**
     * xmlHTMLWarning:
     * @ctx:  an XML parser context
     * @msg:  the message to display/transmit
     * @...:  extra parameters for the message display
     *
     * Display and format a warning messages, gives file, line, position and
     * extra parameters.
     */
    static void XMLCDECL
    xmlHTMLWarning(void *ctx, const char *msg, ...)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
        xmlParserInputPtr input;
        va_list args;
        int len;
    
        buffer[0] = 0;
        input = ctxt->input;
        if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
            input = ctxt->inputTab[ctxt->inputNr - 2];
        }
    
    
        xmlHTMLPrintFileInfo(input);
    
        xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
        va_start(args, msg);
        len = strlen(buffer);
        vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
        va_end(args);
        xmlHTMLEncodeSend();
        xmlGenericError(xmlGenericErrorContext, "</p>\n");
    
        xmlHTMLPrintFileContext(input);
        xmlHTMLEncodeSend();
    }
    
    /**
     * xmlHTMLValidityError:
     * @ctx:  an XML parser context
     * @msg:  the message to display/transmit
     * @...:  extra parameters for the message display
     *
     * Display and format an validity error messages, gives file,
     * line, position and extra parameters.
     */
    static void XMLCDECL
    xmlHTMLValidityError(void *ctx, const char *msg, ...)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
        xmlParserInputPtr input;
        va_list args;
        int len;
    
        buffer[0] = 0;
        input = ctxt->input;
        if ((input->filename == NULL) && (ctxt->inputNr > 1))
            input = ctxt->inputTab[ctxt->inputNr - 2];
    
        xmlHTMLPrintFileInfo(input);
    
        xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
        len = strlen(buffer);
        va_start(args, msg);
        vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
        va_end(args);
        xmlHTMLEncodeSend();
        xmlGenericError(xmlGenericErrorContext, "</p>\n");
    
        xmlHTMLPrintFileContext(input);
        xmlHTMLEncodeSend();
        progresult = XMLLINT_ERR_VALID;
    }
    
    /**
     * xmlHTMLValidityWarning:
     * @ctx:  an XML parser context
     * @msg:  the message to display/transmit
     * @...:  extra parameters for the message display
     *
     * Display and format a validity warning messages, gives file, line,
     * position and extra parameters.
     */
    static void XMLCDECL
    xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
    {
        xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
        xmlParserInputPtr input;
        va_list args;
        int len;
    
        buffer[0] = 0;
        input = ctxt->input;
        if ((input->filename == NULL) && (ctxt->inputNr > 1))
            input = ctxt->inputTab[ctxt->inputNr - 2];
    
        xmlHTMLPrintFileInfo(input);
    
        xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
        va_start(args, msg);
        len = strlen(buffer);
        vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
        va_end(args);
        xmlHTMLEncodeSend();
        xmlGenericError(xmlGenericErrorContext, "</p>\n");
    
        xmlHTMLPrintFileContext(input);
        xmlHTMLEncodeSend();
    }
    
    /************************************************************************
     *									*
     *			Shell Interface					*
     *									*
     ************************************************************************/
    #ifdef LIBXML_DEBUG_ENABLED
    #ifdef LIBXML_XPATH_ENABLED
    /**
     * xmlShellReadline:
     * @prompt:  the prompt value
     *
     * Read a string
     *
     * Returns a pointer to it or NULL on EOF the caller is expected to
     *     free the returned string.
     */
    static char *
    xmlShellReadline(char *prompt) {
    #ifdef HAVE_LIBREADLINE
        char *line_read;
    
        /* Get a line from the user. */
        line_read = readline (prompt);
    
        /* If the line has any text in it, save it on the history. */
        if (line_read && *line_read)
    	add_history (line_read);
    
        return (line_read);
    #else
        char line_read[501];
        char *ret;
        int len;
    
        if (prompt != NULL)
    	fprintf(stdout, "%s", prompt);
        if (!fgets(line_read, 500, stdin))
            return(NULL);
        line_read[500] = 0;
        len = strlen(line_read);
        ret = (char *) malloc(len + 1);
        if (ret != NULL) {
    	memcpy (ret, line_read, len + 1);
        }
        return(ret);
    #endif
    }
    #endif /* LIBXML_XPATH_ENABLED */
    #endif /* LIBXML_DEBUG_ENABLED */
    
    /************************************************************************
     *									*
     *			I/O Interfaces					*
     *									*
     ************************************************************************/
    
    static int myRead(FILE *f, char * buf, int len) {
        return(fread(buf, 1, len, f));
    }
    static void myClose(FILE *f) {
      if (f != stdin) {
        fclose(f);
      }
    }
    
    /************************************************************************
     *									*
     *			SAX based tests					*
     *									*
     ************************************************************************/
    
    /*
     * empty SAX block
     */
    static xmlSAXHandler emptySAXHandlerStruct = {
        NULL, /* internalSubset */
        NULL, /* isStandalone */
        NULL, /* hasInternalSubset */
        NULL, /* hasExternalSubset */
        NULL, /* resolveEntity */
        NULL, /* getEntity */
        NULL, /* entityDecl */
        NULL, /* notationDecl */
        NULL, /* attributeDecl */
        NULL, /* elementDecl */
        NULL, /* unparsedEntityDecl */
        NULL, /* setDocumentLocator */
        NULL, /* startDocument */
        NULL, /* endDocument */
        NULL, /* startElement */
        NULL, /* endElement */
        NULL, /* reference */
        NULL, /* characters */
        NULL, /* ignorableWhitespace */
        NULL, /* processingInstruction */
        NULL, /* comment */
        NULL, /* xmlParserWarning */
        NULL, /* xmlParserError */
        NULL, /* xmlParserError */
        NULL, /* getParameterEntity */
        NULL, /* cdataBlock; */
        NULL, /* externalSubset; */
        XML_SAX2_MAGIC,
        NULL,
        NULL, /* startElementNs */
        NULL, /* endElementNs */
        NULL  /* xmlStructuredErrorFunc */
    };
    
    static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
    extern xmlSAXHandlerPtr debugSAXHandler;
    static int callbacks;
    
    /**
     * isStandaloneDebug:
     * @ctxt:  An XML parser context
     *
     * Is this document tagged standalone ?
     *
     * Returns 1 if true
     */
    static int
    isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (noout)
    	return(0);
        fprintf(stdout, "SAX.isStandalone()\n");
        return(0);
    }
    
    /**
     * hasInternalSubsetDebug:
     * @ctxt:  An XML parser context
     *
     * Does this document has an internal subset
     *
     * Returns 1 if true
     */
    static int
    hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (noout)
    	return(0);
        fprintf(stdout, "SAX.hasInternalSubset()\n");
        return(0);
    }
    
    /**
     * hasExternalSubsetDebug:
     * @ctxt:  An XML parser context
     *
     * Does this document has an external subset
     *
     * Returns 1 if true
     */
    static int
    hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (noout)
    	return(0);
        fprintf(stdout, "SAX.hasExternalSubset()\n");
        return(0);
    }
    
    /**
     * internalSubsetDebug:
     * @ctxt:  An XML parser context
     *
     * Does this document has an internal subset
     */
    static void
    internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
    	       const xmlChar *ExternalID, const xmlChar *SystemID)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.internalSubset(%s,", name);
        if (ExternalID == NULL)
    	fprintf(stdout, " ,");
        else
    	fprintf(stdout, " %s,", ExternalID);
        if (SystemID == NULL)
    	fprintf(stdout, " )\n");
        else
    	fprintf(stdout, " %s)\n", SystemID);
    }
    
    /**
     * externalSubsetDebug:
     * @ctxt:  An XML parser context
     *
     * Does this document has an external subset
     */
    static void
    externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
    	       const xmlChar *ExternalID, const xmlChar *SystemID)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.externalSubset(%s,", name);
        if (ExternalID == NULL)
    	fprintf(stdout, " ,");
        else
    	fprintf(stdout, " %s,", ExternalID);
        if (SystemID == NULL)
    	fprintf(stdout, " )\n");
        else
    	fprintf(stdout, " %s)\n", SystemID);
    }
    
    /**
     * resolveEntityDebug:
     * @ctxt:  An XML parser context
     * @publicId: The public ID of the entity
     * @systemId: The system ID of the entity
     *
     * Special entity resolver, better left to the parser, it has
     * more context than the application layer.
     * The default behaviour is to NOT resolve the entities, in that case
     * the ENTITY_REF nodes are built in the structure (and the parameter
     * values).
     *
     * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
     */
    static xmlParserInputPtr
    resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
    {
        callbacks++;
        if (noout)
    	return(NULL);
        /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
    
    
        fprintf(stdout, "SAX.resolveEntity(");
        if (publicId != NULL)
    	fprintf(stdout, "%s", (char *)publicId);
        else
    	fprintf(stdout, " ");
        if (systemId != NULL)
    	fprintf(stdout, ", %s)\n", (char *)systemId);
        else
    	fprintf(stdout, ", )\n");
        return(NULL);
    }
    
    /**
     * getEntityDebug:
     * @ctxt:  An XML parser context
     * @name: The entity name
     *
     * Get an entity by name
     *
     * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
     */
    static xmlEntityPtr
    getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
    {
        callbacks++;
        if (noout)
    	return(NULL);
        fprintf(stdout, "SAX.getEntity(%s)\n", name);
        return(NULL);
    }
    
    /**
     * getParameterEntityDebug:
     * @ctxt:  An XML parser context
     * @name: The entity name
     *
     * Get a parameter entity by name
     *
     * Returns the xmlParserInputPtr
     */
    static xmlEntityPtr
    getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
    {
        callbacks++;
        if (noout)
    	return(NULL);
        fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
        return(NULL);
    }
    
    
    /**
     * entityDeclDebug:
     * @ctxt:  An XML parser context
     * @name:  the entity name
     * @type:  the entity type
     * @publicId: The public ID of the entity
     * @systemId: The system ID of the entity
     * @content: the entity value (without processing).
     *
     * An entity definition has been parsed
     */
    static void
    entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
              const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
    {
    const xmlChar *nullstr = BAD_CAST "(null)";
        /* not all libraries handle printing null pointers nicely */
        if (publicId == NULL)
            publicId = nullstr;
        if (systemId == NULL)
            systemId = nullstr;
        if (content == NULL)
            content = (xmlChar *)nullstr;
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
                name, type, publicId, systemId, content);
    }
    
    /**
     * attributeDeclDebug:
     * @ctxt:  An XML parser context
     * @name:  the attribute name
     * @type:  the attribute type
     *
     * An attribute definition has been parsed
     */
    static void
    attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
                       const xmlChar * name, int type, int def,
                       const xmlChar * defaultValue, xmlEnumerationPtr tree)
    {
        callbacks++;
        if (noout)
            return;
        if (defaultValue == NULL)
            fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
                    elem, name, type, def);
        else
            fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
                    elem, name, type, def, defaultValue);
        xmlFreeEnumeration(tree);
    }
    
    /**
     * elementDeclDebug:
     * @ctxt:  An XML parser context
     * @name:  the element name
     * @type:  the element type
     * @content: the element value (without processing).
     *
     * An element definition has been parsed
     */
    static void
    elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
    	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
                name, type);
    }
    
    /**
     * notationDeclDebug:
     * @ctxt:  An XML parser context
     * @name: The name of the notation
     * @publicId: The public ID of the entity
     * @systemId: The system ID of the entity
     *
     * What to do when a notation declaration has been parsed.
     */
    static void
    notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
    	     const xmlChar *publicId, const xmlChar *systemId)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
                (char *) name, (char *) publicId, (char *) systemId);
    }
    
    /**
     * unparsedEntityDeclDebug:
     * @ctxt:  An XML parser context
     * @name: The name of the entity
     * @publicId: The public ID of the entity
     * @systemId: The system ID of the entity
     * @notationName: the name of the notation
     *
     * What to do when an unparsed entity declaration is parsed
     */
    static void
    unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
    		   const xmlChar *publicId, const xmlChar *systemId,
    		   const xmlChar *notationName)
    {
    const xmlChar *nullstr = BAD_CAST "(null)";
    
        if (publicId == NULL)
            publicId = nullstr;
        if (systemId == NULL)
            systemId = nullstr;
        if (notationName == NULL)
            notationName = nullstr;
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
                (char *) name, (char *) publicId, (char *) systemId,
    	    (char *) notationName);
    }
    
    /**
     * setDocumentLocatorDebug:
     * @ctxt:  An XML parser context
     * @loc: A SAX Locator
     *
     * Receive the document locator at startup, actually xmlDefaultSAXLocator
     * Everything is available on the context, so this is useless in our case.
     */
    static void
    setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.setDocumentLocator()\n");
    }
    
    /**
     * startDocumentDebug:
     * @ctxt:  An XML parser context
     *
     * called when the document start being processed.
     */
    static void
    startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.startDocument()\n");
    }
    
    /**
     * endDocumentDebug:
     * @ctxt:  An XML parser context
     *
     * called when the document end has been detected.
     */
    static void
    endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.endDocument()\n");
    }
    
    /**
     * startElementDebug:
     * @ctxt:  An XML parser context
     * @name:  The element name
     *
     * called when an opening tag has been processed.
     */
    static void
    startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
    {
        int i;
    
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.startElement(%s", (char *) name);
        if (atts != NULL) {
            for (i = 0;(atts[i] != NULL);i++) {
    	    fprintf(stdout, ", %s='", atts[i++]);
    	    if (atts[i] != NULL)
    	        fprintf(stdout, "%s'", atts[i]);
    	}
        }
        fprintf(stdout, ")\n");
    }
    
    /**
     * endElementDebug:
     * @ctxt:  An XML parser context
     * @name:  The element name
     *
     * called when the end of an element has been detected.
     */
    static void
    endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
    }
    
    /**
     * charactersDebug:
     * @ctxt:  An XML parser context
     * @ch:  a xmlChar string
     * @len: the number of xmlChar
     *
     * receiving some chars from the parser.
     * Question: how much at a time ???
     */
    static void
    charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
    {
        char out[40];
        int i;
    
        callbacks++;
        if (noout)
    	return;
        for (i = 0;(i<len) && (i < 30);i++)
    	out[i] = ch[i];
        out[i] = 0;
    
        fprintf(stdout, "SAX.characters(%s, %d)\n", out, len);
    }
    
    /**
     * referenceDebug:
     * @ctxt:  An XML parser context
     * @name:  The entity name
     *
     * called when an entity reference is detected.
     */
    static void
    referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.reference(%s)\n", name);
    }
    
    /**
     * ignorableWhitespaceDebug:
     * @ctxt:  An XML parser context
     * @ch:  a xmlChar string
     * @start: the first char in the string
     * @len: the number of xmlChar
     *
     * receiving some ignorable whitespaces from the parser.
     * Question: how much at a time ???
     */
    static void
    ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
    {
        char out[40];
        int i;
    
        callbacks++;
        if (noout)
    	return;
        for (i = 0;(i<len) && (i < 30);i++)
    	out[i] = ch[i];
        out[i] = 0;
        fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", out, len);
    }
    
    /**
     * processingInstructionDebug:
     * @ctxt:  An XML parser context
     * @target:  the target name
     * @data: the PI data's
     * @len: the number of xmlChar
     *
     * A processing instruction has been parsed.
     */
    static void
    processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
                          const xmlChar *data)
    {
        callbacks++;
        if (noout)
    	return;
        if (data != NULL)
    	fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
    		(char *) target, (char *) data);
        else
    	fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
    		(char *) target);
    }
    
    /**
     * cdataBlockDebug:
     * @ctx: the user data (XML parser context)
     * @value:  The pcdata content
     * @len:  the block length
     *
     * called when a pcdata block has been parsed
     */
    static void
    cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
    	    (char *) value, len);
    }
    
    /**
     * commentDebug:
     * @ctxt:  An XML parser context
     * @value:  the comment content
     *
     * A comment has been parsed.
     */
    static void
    commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.comment(%s)\n", value);
    }
    
    /**
     * warningDebug:
     * @ctxt:  An XML parser context
     * @msg:  the message to display/transmit
     * @...:  extra parameters for the message display
     *
     * Display and format a warning messages, gives file, line, position and
     * extra parameters.
     */
    static void XMLCDECL
    warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
    {
        va_list args;
    
        callbacks++;
        if (noout)
    	return;
        va_start(args, msg);
        fprintf(stdout, "SAX.warning: ");
        vfprintf(stdout, msg, args);
        va_end(args);
    }
    
    /**
     * errorDebug:
     * @ctxt:  An XML parser context
     * @msg:  the message to display/transmit
     * @...:  extra parameters for the message display
     *
     * Display and format a error messages, gives file, line, position and
     * extra parameters.
     */
    static void XMLCDECL
    errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
    {
        va_list args;
    
        callbacks++;
        if (noout)
    	return;
        va_start(args, msg);
        fprintf(stdout, "SAX.error: ");
        vfprintf(stdout, msg, args);
        va_end(args);
    }
    
    /**
     * fatalErrorDebug:
     * @ctxt:  An XML parser context
     * @msg:  the message to display/transmit
     * @...:  extra parameters for the message display
     *
     * Display and format a fatalError messages, gives file, line, position and
     * extra parameters.
     */
    static void XMLCDECL
    fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
    {
        va_list args;
    
        callbacks++;
        if (noout)
    	return;
        va_start(args, msg);
        fprintf(stdout, "SAX.fatalError: ");
        vfprintf(stdout, msg, args);
        va_end(args);
    }
    
    static xmlSAXHandler debugSAXHandlerStruct = {
        internalSubsetDebug,
        isStandaloneDebug,
        hasInternalSubsetDebug,
        hasExternalSubsetDebug,
        resolveEntityDebug,
        getEntityDebug,
        entityDeclDebug,
        notationDeclDebug,
        attributeDeclDebug,
        elementDeclDebug,
        unparsedEntityDeclDebug,
        setDocumentLocatorDebug,
        startDocumentDebug,
        endDocumentDebug,
        startElementDebug,
        endElementDebug,
        referenceDebug,
        charactersDebug,
        ignorableWhitespaceDebug,
        processingInstructionDebug,
        commentDebug,
        warningDebug,
        errorDebug,
        fatalErrorDebug,
        getParameterEntityDebug,
        cdataBlockDebug,
        externalSubsetDebug,
        1,
        NULL,
        NULL,
        NULL,
        NULL
    };
    
    xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
    
    /*
     * SAX2 specific callbacks
     */
    /**
     * startElementNsDebug:
     * @ctxt:  An XML parser context
     * @name:  The element name
     *
     * called when an opening tag has been processed.
     */
    static void
    startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
                        const xmlChar *localname,
                        const xmlChar *prefix,
                        const xmlChar *URI,
    		    int nb_namespaces,
    		    const xmlChar **namespaces,
    		    int nb_attributes,
    		    int nb_defaulted,
    		    const xmlChar **attributes)
    {
        int i;
    
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
        if (prefix == NULL)
    	fprintf(stdout, ", NULL");
        else
    	fprintf(stdout, ", %s", (char *) prefix);
        if (URI == NULL)
    	fprintf(stdout, ", NULL");
        else
    	fprintf(stdout, ", '%s'", (char *) URI);
        fprintf(stdout, ", %d", nb_namespaces);
    
        if (namespaces != NULL) {
            for (i = 0;i < nb_namespaces * 2;i++) {
    	    fprintf(stdout, ", xmlns");
    	    if (namespaces[i] != NULL)
    	        fprintf(stdout, ":%s", namespaces[i]);
    	    i++;
    	    fprintf(stdout, "='%s'", namespaces[i]);
    	}
        }
        fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
        if (attributes != NULL) {
            for (i = 0;i < nb_attributes * 5;i += 5) {
    	    if (attributes[i + 1] != NULL)
    		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
    	    else
    		fprintf(stdout, ", %s='", attributes[i]);
    	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
    		    (int)(attributes[i + 4] - attributes[i + 3]));
    	}
        }
        fprintf(stdout, ")\n");
    }
    
    /**
     * endElementDebug:
     * @ctxt:  An XML parser context
     * @name:  The element name
     *
     * called when the end of an element has been detected.
     */
    static void
    endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
                      const xmlChar *localname,
                      const xmlChar *prefix,
                      const xmlChar *URI)
    {
        callbacks++;
        if (noout)
    	return;
        fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
        if (prefix == NULL)
    	fprintf(stdout, ", NULL");
        else
    	fprintf(stdout, ", %s", (char *) prefix);
        if (URI == NULL)
    	fprintf(stdout, ", NULL)\n");
        else
    	fprintf(stdout, ", '%s')\n", (char *) URI);
    }
    
    static xmlSAXHandler debugSAX2HandlerStruct = {
        internalSubsetDebug,
        isStandaloneDebug,
        hasInternalSubsetDebug,
        hasExternalSubsetDebug,
        resolveEntityDebug,
        getEntityDebug,
        entityDeclDebug,
        notationDeclDebug,
        attributeDeclDebug,
        elementDeclDebug,
        unparsedEntityDeclDebug,
        setDocumentLocatorDebug,
        startDocumentDebug,
        endDocumentDebug,
        NULL,
        NULL,
        referenceDebug,
        charactersDebug,
        ignorableWhitespaceDebug,
        processingInstructionDebug,
        commentDebug,
        warningDebug,
        errorDebug,
        fatalErrorDebug,
        getParameterEntityDebug,
        cdataBlockDebug,
        externalSubsetDebug,
        XML_SAX2_MAGIC,
        NULL,
        startElementNsDebug,
        endElementNsDebug,
        NULL
    };
    
    static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
    
    static void
    testSAX(const char *filename) {
        xmlSAXHandlerPtr handler;
        const char *user_data = "user_data"; /* mostly for debugging */
        xmlParserInputBufferPtr buf = NULL;
        xmlParserInputPtr inputStream;
        xmlParserCtxtPtr ctxt = NULL;
        xmlSAXHandlerPtr old_sax = NULL;
    
        callbacks = 0;
    
        if (noout) {
            handler = emptySAXHandler;
    #ifdef LIBXML_SAX1_ENABLED
        } else if (sax1) {
            handler = debugSAXHandler;
    #endif
        } else {
            handler = debugSAX2Handler;
        }
    
        /*
         * it's not the simplest code but the most generic in term of I/O
         */
        buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
        if (buf == NULL) {
            goto error;
        }
    
    #ifdef LIBXML_SCHEMAS_ENABLED
        if (wxschemas != NULL) {
            int ret;
    	xmlSchemaValidCtxtPtr vctxt;
    
    	vctxt = xmlSchemaNewValidCtxt(wxschemas);
    	xmlSchemaSetValidErrors(vctxt,
    		(xmlSchemaValidityErrorFunc) fprintf,
    		(xmlSchemaValidityWarningFunc) fprintf,
    		stderr);
    	xmlSchemaValidateSetFilename(vctxt, filename);
    
    	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
    	                              (void *)user_data);
    	if (repeat == 0) {
    	    if (ret == 0) {
    		fprintf(stderr, "%s validates\n", filename);
    	    } else if (ret > 0) {
    		fprintf(stderr, "%s fails to validate\n", filename);
    		progresult = XMLLINT_ERR_VALID;
    	    } else {
    		fprintf(stderr, "%s validation generated an internal error\n",
    		       filename);
    		progresult = XMLLINT_ERR_VALID;
    	    }
    	}
    	xmlSchemaFreeValidCtxt(vctxt);
        } else
    #endif
        {
    	/*
    	 * Create the parser context amd hook the input
    	 */
    	ctxt = xmlNewParserCtxt();
    	if (ctxt == NULL) {
    	    xmlFreeParserInputBuffer(buf);
    	    goto error;
    	}
    	old_sax = ctxt->sax;
    	ctxt->sax = handler;
    	ctxt->userData = (void *) user_data;
    	inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
    	if (inputStream == NULL) {
    	    xmlFreeParserInputBuffer(buf);
    	    goto error;
    	}
    	inputPush(ctxt, inputStream);
    
    	/* do the parsing */
    	xmlParseDocument(ctxt);
    
    	if (ctxt->myDoc != NULL) {
    	    fprintf(stderr, "SAX generated a doc !\n");
    	    xmlFreeDoc(ctxt->myDoc);
    	    ctxt->myDoc = NULL;
    	}
        }
    
    error:
        if (ctxt != NULL) {
            ctxt->sax = old_sax;
            xmlFreeParserCtxt(ctxt);
        }
    }
    
    /************************************************************************
     *									*
     *			Stream Test processing				*
     *									*
     ************************************************************************/
    #ifdef LIBXML_READER_ENABLED
    static void processNode(xmlTextReaderPtr reader) {
        const xmlChar *name, *value;
        int type, empty;
    
        type = xmlTextReaderNodeType(reader);
        empty = xmlTextReaderIsEmptyElement(reader);
    
        if (debug) {
    	name = xmlTextReaderConstName(reader);
    	if (name == NULL)
    	    name = BAD_CAST "--";
    
    	value = xmlTextReaderConstValue(reader);
    
    
    	printf("%d %d %s %d %d",
    		xmlTextReaderDepth(reader),
    		type,
    		name,
    		empty,
    		xmlTextReaderHasValue(reader));
    	if (value == NULL)
    	    printf("\n");
    	else {
    	    printf(" %s\n", value);
    	}
        }
    #ifdef LIBXML_PATTERN_ENABLED
        if (patternc) {
            xmlChar *path = NULL;
            int match = -1;
    
    	if (type == XML_READER_TYPE_ELEMENT) {
    	    /* do the check only on element start */
    	    match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
    
    	    if (match) {
    #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
    		path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
    		printf("Node %s matches pattern %s\n", path, pattern);
    #else
                    printf("Node %s matches pattern %s\n",
                           xmlTextReaderConstName(reader), pattern);
    #endif
    	    }
    	}
    	if (patstream != NULL) {
    	    int ret;
    
    	    if (type == XML_READER_TYPE_ELEMENT) {
    		ret = xmlStreamPush(patstream,
    		                    xmlTextReaderConstLocalName(reader),
    				    xmlTextReaderConstNamespaceUri(reader));
    		if (ret < 0) {
    		    fprintf(stderr, "xmlStreamPush() failure\n");
                        xmlFreeStreamCtxt(patstream);
    		    patstream = NULL;
    		} else if (ret != match) {
    #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
    		    if (path == NULL) {
    		        path = xmlGetNodePath(
    		                       xmlTextReaderCurrentNode(reader));
    		    }
    #endif
    		    fprintf(stderr,
    		            "xmlPatternMatch and xmlStreamPush disagree\n");
                        if (path != NULL)
                            fprintf(stderr, "  pattern %s node %s\n",
                                    pattern, path);
                        else
    		        fprintf(stderr, "  pattern %s node %s\n",
    			    pattern, xmlTextReaderConstName(reader));
    		}
    
    	    }
    	    if ((type == XML_READER_TYPE_END_ELEMENT) ||
    	        ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
    	        ret = xmlStreamPop(patstream);
    		if (ret < 0) {
    		    fprintf(stderr, "xmlStreamPop() failure\n");
                        xmlFreeStreamCtxt(patstream);
    		    patstream = NULL;
    		}
    	    }
    	}
    	if (path != NULL)
    	    xmlFree(path);
        }
    #endif
    }
    
    static void streamFile(char *filename) {
        xmlTextReaderPtr reader;
        int ret;
    #ifdef HAVE_MMAP
        int fd = -1;
        struct stat info;
        const char *base = NULL;
        xmlParserInputBufferPtr input = NULL;
    
        if (memory) {
    	if (stat(filename, &info) < 0)
    	    return;
    	if ((fd = open(filename, O_RDONLY)) < 0)
    	    return;
    	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
    	if (base == (void *) MAP_FAILED) {
    	    close(fd);
    	    fprintf(stderr, "mmap failure for file %s\n", filename);
    	    progresult = XMLLINT_ERR_RDFILE;
    	    return;
    	}
    
    	reader = xmlReaderForMemory(base, info.st_size, filename,
    	                            NULL, options);
        } else
    #endif
    	reader = xmlReaderForFile(filename, NULL, options);
    #ifdef LIBXML_PATTERN_ENABLED
        if (pattern != NULL) {
            patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
    	if (patternc == NULL) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "Pattern %s failed to compile\n", pattern);
                progresult = XMLLINT_ERR_SCHEMAPAT;
    	    pattern = NULL;
    	}
        }
        if (patternc != NULL) {
            patstream = xmlPatternGetStreamCtxt(patternc);
    	if (patstream != NULL) {
    	    ret = xmlStreamPush(patstream, NULL, NULL);
    	    if (ret < 0) {
    		fprintf(stderr, "xmlStreamPush() failure\n");
    		xmlFreeStreamCtxt(patstream);
    		patstream = NULL;
                }
    	}
        }
    #endif
    
    
        if (reader != NULL) {
    #ifdef LIBXML_VALID_ENABLED
    	if (valid)
    	    xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
    	else
    #endif /* LIBXML_VALID_ENABLED */
    	    if (loaddtd)
    		xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
    #ifdef LIBXML_SCHEMAS_ENABLED
    	if (relaxng != NULL) {
    	    if ((timing) && (!repeat)) {
    		startTimer();
    	    }
    	    ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
    	    if (ret < 0) {
    		xmlGenericError(xmlGenericErrorContext,
    			"Relax-NG schema %s failed to compile\n", relaxng);
    		progresult = XMLLINT_ERR_SCHEMACOMP;
    		relaxng = NULL;
    	    }
    	    if ((timing) && (!repeat)) {
    		endTimer("Compiling the schemas");
    	    }
    	}
    	if (schema != NULL) {
    	    if ((timing) && (!repeat)) {
    		startTimer();
    	    }
    	    ret = xmlTextReaderSchemaValidate(reader, schema);
    	    if (ret < 0) {
    		xmlGenericError(xmlGenericErrorContext,
    			"XSD schema %s failed to compile\n", schema);
    		progresult = XMLLINT_ERR_SCHEMACOMP;
    		schema = NULL;
    	    }
    	    if ((timing) && (!repeat)) {
    		endTimer("Compiling the schemas");
    	    }
    	}
    #endif
    
    	/*
    	 * Process all nodes in sequence
    	 */
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    	ret = xmlTextReaderRead(reader);
    	while (ret == 1) {
    	    if ((debug)
    #ifdef LIBXML_PATTERN_ENABLED
    	        || (patternc)
    #endif
    	       )
    		processNode(reader);
    	    ret = xmlTextReaderRead(reader);
    	}
    	if ((timing) && (!repeat)) {
    #ifdef LIBXML_SCHEMAS_ENABLED
    	    if (relaxng != NULL)
    		endTimer("Parsing and validating");
    	    else
    #endif
    #ifdef LIBXML_VALID_ENABLED
    	    if (valid)
    		endTimer("Parsing and validating");
    	    else
    #endif
    	    endTimer("Parsing");
    	}
    
    #ifdef LIBXML_VALID_ENABLED
    	if (valid) {
    	    if (xmlTextReaderIsValid(reader) != 1) {
    		xmlGenericError(xmlGenericErrorContext,
    			"Document %s does not validate\n", filename);
    		progresult = XMLLINT_ERR_VALID;
    	    }
    	}
    #endif /* LIBXML_VALID_ENABLED */
    #ifdef LIBXML_SCHEMAS_ENABLED
    	if ((relaxng != NULL) || (schema != NULL)) {
    	    if (xmlTextReaderIsValid(reader) != 1) {
    		fprintf(stderr, "%s fails to validate\n", filename);
    		progresult = XMLLINT_ERR_VALID;
    	    } else {
    		fprintf(stderr, "%s validates\n", filename);
    	    }
    	}
    #endif
    	/*
    	 * Done, cleanup and status
    	 */
    	xmlFreeTextReader(reader);
    	if (ret != 0) {
    	    fprintf(stderr, "%s : failed to parse\n", filename);
    	    progresult = XMLLINT_ERR_UNCLASS;
    	}
        } else {
    	fprintf(stderr, "Unable to open %s\n", filename);
    	progresult = XMLLINT_ERR_UNCLASS;
        }
    #ifdef LIBXML_PATTERN_ENABLED
        if (patstream != NULL) {
    	xmlFreeStreamCtxt(patstream);
    	patstream = NULL;
        }
    #endif
    #ifdef HAVE_MMAP
        if (memory) {
            xmlFreeParserInputBuffer(input);
    	munmap((char *) base, info.st_size);
    	close(fd);
        }
    #endif
    }
    
    static void walkDoc(xmlDocPtr doc) {
        xmlTextReaderPtr reader;
        int ret;
    
    #ifdef LIBXML_PATTERN_ENABLED
        xmlNodePtr root;
        const xmlChar *namespaces[22];
        int i;
        xmlNsPtr ns;
    
        root = xmlDocGetRootElement(doc);
        for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
            namespaces[i++] = ns->href;
            namespaces[i++] = ns->prefix;
        }
        namespaces[i++] = NULL;
        namespaces[i] = NULL;
    
        if (pattern != NULL) {
            patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict,
    	                             0, &namespaces[0]);
    	if (patternc == NULL) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "Pattern %s failed to compile\n", pattern);
                progresult = XMLLINT_ERR_SCHEMAPAT;
    	    pattern = NULL;
    	}
        }
        if (patternc != NULL) {
            patstream = xmlPatternGetStreamCtxt(patternc);
    	if (patstream != NULL) {
    	    ret = xmlStreamPush(patstream, NULL, NULL);
    	    if (ret < 0) {
    		fprintf(stderr, "xmlStreamPush() failure\n");
    		xmlFreeStreamCtxt(patstream);
    		patstream = NULL;
                }
    	}
        }
    #endif /* LIBXML_PATTERN_ENABLED */
        reader = xmlReaderWalker(doc);
        if (reader != NULL) {
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    	ret = xmlTextReaderRead(reader);
    	while (ret == 1) {
    	    if ((debug)
    #ifdef LIBXML_PATTERN_ENABLED
    	        || (patternc)
    #endif
    	       )
    		processNode(reader);
    	    ret = xmlTextReaderRead(reader);
    	}
    	if ((timing) && (!repeat)) {
    	    endTimer("walking through the doc");
    	}
    	xmlFreeTextReader(reader);
    	if (ret != 0) {
    	    fprintf(stderr, "failed to walk through the doc\n");
    	    progresult = XMLLINT_ERR_UNCLASS;
    	}
        } else {
    	fprintf(stderr, "Failed to crate a reader from the document\n");
    	progresult = XMLLINT_ERR_UNCLASS;
        }
    #ifdef LIBXML_PATTERN_ENABLED
        if (patstream != NULL) {
    	xmlFreeStreamCtxt(patstream);
    	patstream = NULL;
        }
    #endif
    }
    #endif /* LIBXML_READER_ENABLED */
    
    #ifdef LIBXML_XPATH_ENABLED
    /************************************************************************
     *									*
     *			XPath Query                                     *
     *									*
     ************************************************************************/
    
    static void doXPathDump(xmlXPathObjectPtr cur) {
        switch(cur->type) {
            case XPATH_NODESET: {
                int i;
                xmlNodePtr node;
    #ifdef LIBXML_OUTPUT_ENABLED
                xmlSaveCtxtPtr ctxt;
    
                if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) {
                    fprintf(stderr, "XPath set is empty\n");
                    progresult = XMLLINT_ERR_XPATH;
                    break;
                }
                ctxt = xmlSaveToFd(1, NULL, 0);
                if (ctxt == NULL) {
                    fprintf(stderr, "Out of memory for XPath\n");
                    progresult = XMLLINT_ERR_MEM;
                    return;
                }
                for (i = 0;i < cur->nodesetval->nodeNr;i++) {
                    node = cur->nodesetval->nodeTab[i];
                    xmlSaveTree(ctxt, node);
                }
                xmlSaveClose(ctxt);
    #else
                printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
    #endif
    	    break;
            }
            case XPATH_BOOLEAN:
    	    if (cur->boolval) printf("true");
    	    else printf("false");
    	    break;
            case XPATH_NUMBER:
    	    switch (xmlXPathIsInf(cur->floatval)) {
    	    case 1:
    		printf("Infinity");
    		break;
    	    case -1:
    		printf("-Infinity");
    		break;
    	    default:
    		if (xmlXPathIsNaN(cur->floatval)) {
    		    printf("NaN");
    		} else {
    		    printf("%0g", cur->floatval);
    		}
    	    }
    	    break;
            case XPATH_STRING:
    	    printf("%s", (const char *) cur->stringval);
    	    break;
            case XPATH_UNDEFINED:
    	    fprintf(stderr, "XPath Object is uninitialized\n");
                progresult = XMLLINT_ERR_XPATH;
    	    break;
    	default:
    	    fprintf(stderr, "XPath object of unexpected type\n");
                progresult = XMLLINT_ERR_XPATH;
    	    break;
        }
    }
    
    static void doXPathQuery(xmlDocPtr doc, const char *query) {
        xmlXPathContextPtr ctxt;
        xmlXPathObjectPtr res;
    
        ctxt = xmlXPathNewContext(doc);
        if (ctxt == NULL) {
            fprintf(stderr, "Out of memory for XPath\n");
            progresult = XMLLINT_ERR_MEM;
            return;
        }
        ctxt->node = (xmlNodePtr) doc;
        res = xmlXPathEval(BAD_CAST query, ctxt);
        xmlXPathFreeContext(ctxt);
    
        if (res == NULL) {
            fprintf(stderr, "XPath evaluation failure\n");
            progresult = XMLLINT_ERR_XPATH;
            return;
        }
        doXPathDump(res);
        xmlXPathFreeObject(res);
    }
    #endif /* LIBXML_XPATH_ENABLED */
    
    /************************************************************************
     *									*
     *			Tree Test processing				*
     *									*
     ************************************************************************/
    static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
        xmlDocPtr doc = NULL;
    #ifdef LIBXML_TREE_ENABLED
        xmlDocPtr tmp;
    #endif /* LIBXML_TREE_ENABLED */
    
        if ((timing) && (!repeat))
    	startTimer();
    
    
    #ifdef LIBXML_TREE_ENABLED
        if (filename == NULL) {
    	if (generate) {
    	    xmlNodePtr n;
    
    	    doc = xmlNewDoc(BAD_CAST "1.0");
    	    n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
    	    xmlNodeSetContent(n, BAD_CAST "abc");
    	    xmlDocSetRootElement(doc, n);
    	}
        }
    #endif /* LIBXML_TREE_ENABLED */
    #ifdef LIBXML_HTML_ENABLED
    #ifdef LIBXML_PUSH_ENABLED
        else if ((html) && (push)) {
            FILE *f;
    
    #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
    	f = fopen(filename, "rb");
    #elif defined(__OS400__)
    	f = fopen(filename, "rb");
    #else
    	f = fopen(filename, "r");
    #endif
            if (f != NULL) {
                int res;
                char chars[4096];
                htmlParserCtxtPtr ctxt;
    
                res = fread(chars, 1, 4, f);
                if (res > 0) {
                    ctxt = htmlCreatePushParserCtxt(NULL, NULL,
                                chars, res, filename, XML_CHAR_ENCODING_NONE);
                    xmlCtxtUseOptions(ctxt, options);
                    while ((res = fread(chars, 1, pushsize, f)) > 0) {
                        htmlParseChunk(ctxt, chars, res, 0);
                    }
                    htmlParseChunk(ctxt, chars, 0, 1);
                    doc = ctxt->myDoc;
                    htmlFreeParserCtxt(ctxt);
                }
                fclose(f);
            }
        }
    #endif /* LIBXML_PUSH_ENABLED */
    #ifdef HAVE_MMAP
        else if ((html) && (memory)) {
    	int fd;
    	struct stat info;
    	const char *base;
    	if (stat(filename, &info) < 0)
    	    return;
    	if ((fd = open(filename, O_RDONLY)) < 0)
    	    return;
    	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
    	if (base == (void *) MAP_FAILED) {
    	    close(fd);
    	    fprintf(stderr, "mmap failure for file %s\n", filename);
    	    progresult = XMLLINT_ERR_RDFILE;
    	    return;
    	}
    
    	doc = htmlReadMemory((char *) base, info.st_size, filename,
    	                     NULL, options);
    
    	munmap((char *) base, info.st_size);
    	close(fd);
        }
    #endif
        else if (html) {
    	doc = htmlReadFile(filename, NULL, options);
        }
    #endif /* LIBXML_HTML_ENABLED */
        else {
    #ifdef LIBXML_PUSH_ENABLED
    	/*
    	 * build an XML tree from a string;
    	 */
    	if (push) {
    	    FILE *f;
    
    	    /* '-' Usually means stdin -<sven@zen.org> */
    	    if ((filename[0] == '-') && (filename[1] == 0)) {
    	      f = stdin;
    	    } else {
    #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
    		f = fopen(filename, "rb");
    #elif defined(__OS400__)
    		f = fopen(filename, "rb");
    #else
    		f = fopen(filename, "r");
    #endif
    	    }
    	    if (f != NULL) {
    		int ret;
    	        int res, size = 1024;
    	        char chars[1024];
                    xmlParserCtxtPtr ctxt;
    
    		/* if (repeat) size = 1024; */
    		res = fread(chars, 1, 4, f);
    		if (res > 0) {
    		    ctxt = xmlCreatePushParserCtxt(NULL, NULL,
    		                chars, res, filename);
    		    xmlCtxtUseOptions(ctxt, options);
    		    while ((res = fread(chars, 1, size, f)) > 0) {
    			xmlParseChunk(ctxt, chars, res, 0);
    		    }
    		    xmlParseChunk(ctxt, chars, 0, 1);
    		    doc = ctxt->myDoc;
    		    ret = ctxt->wellFormed;
    		    xmlFreeParserCtxt(ctxt);
    		    if (!ret) {
    			xmlFreeDoc(doc);
    			doc = NULL;
    		    }
    	        }
                    if (f != stdin)
                        fclose(f);
    	    }
    	} else
    #endif /* LIBXML_PUSH_ENABLED */
            if (testIO) {
    	    if ((filename[0] == '-') && (filename[1] == 0)) {
    	        doc = xmlReadFd(0, NULL, NULL, options);
    	    } else {
    	        FILE *f;
    
    #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
    		f = fopen(filename, "rb");
    #elif defined(__OS400__)
    		f = fopen(filename, "rb");
    #else
    		f = fopen(filename, "r");
    #endif
    		if (f != NULL) {
    		    if (rectxt == NULL)
    			doc = xmlReadIO((xmlInputReadCallback) myRead,
    					(xmlInputCloseCallback) myClose, f,
    					filename, NULL, options);
    		    else
    			doc = xmlCtxtReadIO(rectxt,
    			                (xmlInputReadCallback) myRead,
    					(xmlInputCloseCallback) myClose, f,
    					filename, NULL, options);
    		} else
    		    doc = NULL;
    	    }
    	} else if (htmlout) {
    	    xmlParserCtxtPtr ctxt;
    
    	    if (rectxt == NULL)
    		ctxt = xmlNewParserCtxt();
    	    else
    	        ctxt = rectxt;
    	    if (ctxt == NULL) {
    	        doc = NULL;
    	    } else {
    	        ctxt->sax->error = xmlHTMLError;
    	        ctxt->sax->warning = xmlHTMLWarning;
    	        ctxt->vctxt.error = xmlHTMLValidityError;
    	        ctxt->vctxt.warning = xmlHTMLValidityWarning;
    
    		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
    
    		if (rectxt == NULL)
    		    xmlFreeParserCtxt(ctxt);
    	    }
    #ifdef HAVE_MMAP
    	} else if (memory) {
    	    int fd;
    	    struct stat info;
    	    const char *base;
    	    if (stat(filename, &info) < 0)
    		return;
    	    if ((fd = open(filename, O_RDONLY)) < 0)
    		return;
    	    base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
    	    if (base == (void *) MAP_FAILED) {
    	        close(fd);
    	        fprintf(stderr, "mmap failure for file %s\n", filename);
    		progresult = XMLLINT_ERR_RDFILE;
    	        return;
    	    }
    
    	    if (rectxt == NULL)
    		doc = xmlReadMemory((char *) base, info.st_size,
    		                    filename, NULL, options);
    	    else
    		doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
    			                filename, NULL, options);
    
    	    munmap((char *) base, info.st_size);
    	    close(fd);
    #endif
    #ifdef LIBXML_VALID_ENABLED
    	} else if (valid) {
    	    xmlParserCtxtPtr ctxt = NULL;
    
    	    if (rectxt == NULL)
    		ctxt = xmlNewParserCtxt();
    	    else
    	        ctxt = rectxt;
    	    if (ctxt == NULL) {
    	        doc = NULL;
    	    } else {
    		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
    
    		if (ctxt->valid == 0)
    		    progresult = XMLLINT_ERR_RDFILE;
    		if (rectxt == NULL)
    		    xmlFreeParserCtxt(ctxt);
    	    }
    #endif /* LIBXML_VALID_ENABLED */
    	} else {
    	    if (rectxt != NULL)
    	        doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
    	    else {
    #ifdef LIBXML_SAX1_ENABLED
                    if (sax1)
    		    doc = xmlParseFile(filename);
    		else
    #endif /* LIBXML_SAX1_ENABLED */
    		doc = xmlReadFile(filename, NULL, options);
    	    }
    	}
        }
    
        /*
         * If we don't have a document we might as well give up.  Do we
         * want an error message here?  <sven@zen.org> */
        if (doc == NULL) {
    	progresult = XMLLINT_ERR_UNCLASS;
    	return;
        }
    
        if ((timing) && (!repeat)) {
    	endTimer("Parsing");
        }
    
        /*
         * Remove DOCTYPE nodes
         */
        if (dropdtd) {
    	xmlDtdPtr dtd;
    
    	dtd = xmlGetIntSubset(doc);
    	if (dtd != NULL) {
    	    xmlUnlinkNode((xmlNodePtr)dtd);
    	    xmlFreeDtd(dtd);
    	}
        }
    
    #ifdef LIBXML_XINCLUDE_ENABLED
        if (xinclude) {
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    	if (xmlXIncludeProcessFlags(doc, options) < 0)
    	    progresult = XMLLINT_ERR_UNCLASS;
    	if ((timing) && (!repeat)) {
    	    endTimer("Xinclude processing");
    	}
        }
    #endif
    
    #ifdef LIBXML_XPATH_ENABLED
        if (xpathquery != NULL) {
            doXPathQuery(doc, xpathquery);
        }
    #endif
    
    #ifdef LIBXML_DEBUG_ENABLED
    #ifdef LIBXML_XPATH_ENABLED
        /*
         * shell interaction
         */
        if (shell) {
            xmlXPathOrderDocElems(doc);
            xmlShell(doc, filename, xmlShellReadline, stdout);
        }
    #endif
    #endif
    
    #ifdef LIBXML_TREE_ENABLED
        /*
         * test intermediate copy if needed.
         */
        if (copy) {
            tmp = doc;
    	if (timing) {
    	    startTimer();
    	}
    	doc = xmlCopyDoc(doc, 1);
    	if (timing) {
    	    endTimer("Copying");
    	}
    	if (timing) {
    	    startTimer();
    	}
    	xmlFreeDoc(tmp);
    	if (timing) {
    	    endTimer("Freeing original");
    	}
        }
    #endif /* LIBXML_TREE_ENABLED */
    
    #ifdef LIBXML_VALID_ENABLED
        if ((insert) && (!html)) {
            const xmlChar* list[256];
    	int nb, i;
    	xmlNodePtr node;
    
    	if (doc->children != NULL) {
    	    node = doc->children;
    	    while ((node != NULL) && (node->last == NULL)) node = node->next;
    	    if (node != NULL) {
    		nb = xmlValidGetValidElements(node->last, NULL, list, 256);
    		if (nb < 0) {
    		    fprintf(stderr, "could not get valid list of elements\n");
    		} else if (nb == 0) {
    		    fprintf(stderr, "No element can be inserted under root\n");
    		} else {
    		    fprintf(stderr, "%d element types can be inserted under root:\n",
    		           nb);
    		    for (i = 0;i < nb;i++) {
    			 fprintf(stderr, "%s\n", (char *) list[i]);
    		    }
    		}
    	    }
    	}
        }else
    #endif /* LIBXML_VALID_ENABLED */
    #ifdef LIBXML_READER_ENABLED
        if (walker) {
            walkDoc(doc);
        }
    #endif /* LIBXML_READER_ENABLED */
    #ifdef LIBXML_OUTPUT_ENABLED
        if (noout == 0) {
            int ret;
    
    	/*
    	 * print it.
    	 */
    #ifdef LIBXML_DEBUG_ENABLED
    	if (!debug) {
    #endif
    	    if ((timing) && (!repeat)) {
    		startTimer();
    	    }
    #ifdef LIBXML_HTML_ENABLED
                if ((html) && (!xmlout)) {
    		if (compress) {
    		    htmlSaveFile(output ? output : "-", doc);
    		}
    		else if (encoding != NULL) {
    		    if (format == 1) {
    			htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
    		    }
    		    else {
    			htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
    		    }
    		}
    		else if (format == 1) {
    		    htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
    		}
    		else {
    		    FILE *out;
    		    if (output == NULL)
    			out = stdout;
    		    else {
    			out = fopen(output,"wb");
    		    }
    		    if (out != NULL) {
    			if (htmlDocDump(out, doc) < 0)
    			    progresult = XMLLINT_ERR_OUT;
    
    			if (output != NULL)
    			    fclose(out);
    		    } else {
    			fprintf(stderr, "failed to open %s\n", output);
    			progresult = XMLLINT_ERR_OUT;
    		    }
    		}
    		if ((timing) && (!repeat)) {
    		    endTimer("Saving");
    		}
    	    } else
    #endif
    #ifdef LIBXML_C14N_ENABLED
                if (canonical) {
    	        xmlChar *result = NULL;
    		int size;
    
    		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
    		if (size >= 0) {
    		    if (write(1, result, size) == -1) {
    		        fprintf(stderr, "Can't write data\n");
    		    }
    		    xmlFree(result);
    		} else {
    		    fprintf(stderr, "Failed to canonicalize\n");
    		    progresult = XMLLINT_ERR_OUT;
    		}
    	    } else if (canonical_11) {
    	        xmlChar *result = NULL;
    		int size;
    
    		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
    		if (size >= 0) {
    		    if (write(1, result, size) == -1) {
    		        fprintf(stderr, "Can't write data\n");
    		    }
    		    xmlFree(result);
    		} else {
    		    fprintf(stderr, "Failed to canonicalize\n");
    		    progresult = XMLLINT_ERR_OUT;
    		}
    	    } else
                if (exc_canonical) {
    	        xmlChar *result = NULL;
    		int size;
    
    		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
    		if (size >= 0) {
    		    if (write(1, result, size) == -1) {
    		        fprintf(stderr, "Can't write data\n");
    		    }
    		    xmlFree(result);
    		} else {
    		    fprintf(stderr, "Failed to canonicalize\n");
    		    progresult = XMLLINT_ERR_OUT;
    		}
    	    } else
    #endif
    #ifdef HAVE_MMAP
    	    if (memory) {
    		xmlChar *result;
    		int len;
    
    		if (encoding != NULL) {
    		    if (format == 1) {
    		        xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
    		    } else {
    			xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
    		    }
    		} else {
    		    if (format == 1)
    			xmlDocDumpFormatMemory(doc, &result, &len, 1);
    		    else
    			xmlDocDumpMemory(doc, &result, &len);
    		}
    		if (result == NULL) {
    		    fprintf(stderr, "Failed to save\n");
    		    progresult = XMLLINT_ERR_OUT;
    		} else {
    		    if (write(1, result, len) == -1) {
    		        fprintf(stderr, "Can't write data\n");
    		    }
    		    xmlFree(result);
    		}
    
    	    } else
    #endif /* HAVE_MMAP */
    	    if (compress) {
    		xmlSaveFile(output ? output : "-", doc);
    	    } else if (oldout) {
    	        if (encoding != NULL) {
    		    if (format == 1) {
    			ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
    						   encoding, 1);
    		    }
    		    else {
    			ret = xmlSaveFileEnc(output ? output : "-", doc,
    			                     encoding);
    		    }
    		    if (ret < 0) {
    			fprintf(stderr, "failed save to %s\n",
    				output ? output : "-");
    			progresult = XMLLINT_ERR_OUT;
    		    }
    		} else if (format == 1) {
    		    ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
    		    if (ret < 0) {
    			fprintf(stderr, "failed save to %s\n",
    				output ? output : "-");
    			progresult = XMLLINT_ERR_OUT;
    		    }
    		} else {
    		    FILE *out;
    		    if (output == NULL)
    			out = stdout;
    		    else {
    			out = fopen(output,"wb");
    		    }
    		    if (out != NULL) {
    			if (xmlDocDump(out, doc) < 0)
    			    progresult = XMLLINT_ERR_OUT;
    
    			if (output != NULL)
    			    fclose(out);
    		    } else {
    			fprintf(stderr, "failed to open %s\n", output);
    			progresult = XMLLINT_ERR_OUT;
    		    }
    		}
    	    } else {
    	        xmlSaveCtxtPtr ctxt;
    		int saveOpts = 0;
    
                    if (format == 1)
    		    saveOpts |= XML_SAVE_FORMAT;
                    else if (format == 2)
                        saveOpts |= XML_SAVE_WSNONSIG;
    
    #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
                    if (xmlout)
                        saveOpts |= XML_SAVE_AS_XML;
    #endif
    
    		if (output == NULL)
    		    ctxt = xmlSaveToFd(1, encoding, saveOpts);
    		else
    		    ctxt = xmlSaveToFilename(output, encoding, saveOpts);
    
    		if (ctxt != NULL) {
    		    if (xmlSaveDoc(ctxt, doc) < 0) {
    			fprintf(stderr, "failed save to %s\n",
    				output ? output : "-");
    			progresult = XMLLINT_ERR_OUT;
    		    }
    		    xmlSaveClose(ctxt);
    		} else {
    		    progresult = XMLLINT_ERR_OUT;
    		}
    	    }
    	    if ((timing) && (!repeat)) {
    		endTimer("Saving");
    	    }
    #ifdef LIBXML_DEBUG_ENABLED
    	} else {
    	    FILE *out;
    	    if (output == NULL)
    	        out = stdout;
    	    else {
    		out = fopen(output,"wb");
    	    }
    	    if (out != NULL) {
    		xmlDebugDumpDocument(out, doc);
    
    		if (output != NULL)
    		    fclose(out);
    	    } else {
    		fprintf(stderr, "failed to open %s\n", output);
    		progresult = XMLLINT_ERR_OUT;
    	    }
    	}
    #endif
        }
    #endif /* LIBXML_OUTPUT_ENABLED */
    
    #ifdef LIBXML_VALID_ENABLED
        /*
         * A posteriori validation test
         */
        if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
    	xmlDtdPtr dtd;
    
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    	if (dtdvalid != NULL)
    	    dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
    	else
    	    dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
    	if ((timing) && (!repeat)) {
    	    endTimer("Parsing DTD");
    	}
    	if (dtd == NULL) {
    	    if (dtdvalid != NULL)
    		xmlGenericError(xmlGenericErrorContext,
    			"Could not parse DTD %s\n", dtdvalid);
    	    else
    		xmlGenericError(xmlGenericErrorContext,
    			"Could not parse DTD %s\n", dtdvalidfpi);
    	    progresult = XMLLINT_ERR_DTD;
    	} else {
    	    xmlValidCtxtPtr cvp;
    
    	    if ((cvp = xmlNewValidCtxt()) == NULL) {
    		xmlGenericError(xmlGenericErrorContext,
    			"Couldn't allocate validation context\n");
    		exit(-1);
    	    }
    	    cvp->userData = (void *) stderr;
    	    cvp->error    = (xmlValidityErrorFunc) fprintf;
    	    cvp->warning  = (xmlValidityWarningFunc) fprintf;
    
    	    if ((timing) && (!repeat)) {
    		startTimer();
    	    }
    	    if (!xmlValidateDtd(cvp, doc, dtd)) {
    		if (dtdvalid != NULL)
    		    xmlGenericError(xmlGenericErrorContext,
    			    "Document %s does not validate against %s\n",
    			    filename, dtdvalid);
    		else
    		    xmlGenericError(xmlGenericErrorContext,
    			    "Document %s does not validate against %s\n",
    			    filename, dtdvalidfpi);
    		progresult = XMLLINT_ERR_VALID;
    	    }
    	    if ((timing) && (!repeat)) {
    		endTimer("Validating against DTD");
    	    }
    	    xmlFreeValidCtxt(cvp);
    	    xmlFreeDtd(dtd);
    	}
        } else if (postvalid) {
    	xmlValidCtxtPtr cvp;
    
    	if ((cvp = xmlNewValidCtxt()) == NULL) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "Couldn't allocate validation context\n");
    	    exit(-1);
    	}
    
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    	cvp->userData = (void *) stderr;
    	cvp->error    = (xmlValidityErrorFunc) fprintf;
    	cvp->warning  = (xmlValidityWarningFunc) fprintf;
    	if (!xmlValidateDocument(cvp, doc)) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "Document %s does not validate\n", filename);
    	    progresult = XMLLINT_ERR_VALID;
    	}
    	if ((timing) && (!repeat)) {
    	    endTimer("Validating");
    	}
    	xmlFreeValidCtxt(cvp);
        }
    #endif /* LIBXML_VALID_ENABLED */
    #ifdef LIBXML_SCHEMATRON_ENABLED
        if (wxschematron != NULL) {
    	xmlSchematronValidCtxtPtr ctxt;
    	int ret;
    	int flag;
    
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    
    	if (debug)
    	    flag = XML_SCHEMATRON_OUT_XML;
    	else
    	    flag = XML_SCHEMATRON_OUT_TEXT;
    	if (noout)
    	    flag |= XML_SCHEMATRON_OUT_QUIET;
    	ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
    #if 0
    	xmlSchematronSetValidErrors(ctxt,
    		(xmlSchematronValidityErrorFunc) fprintf,
    		(xmlSchematronValidityWarningFunc) fprintf,
    		stderr);
    #endif
    	ret = xmlSchematronValidateDoc(ctxt, doc);
    	if (ret == 0) {
    	    fprintf(stderr, "%s validates\n", filename);
    	} else if (ret > 0) {
    	    fprintf(stderr, "%s fails to validate\n", filename);
    	    progresult = XMLLINT_ERR_VALID;
    	} else {
    	    fprintf(stderr, "%s validation generated an internal error\n",
    		   filename);
    	    progresult = XMLLINT_ERR_VALID;
    	}
    	xmlSchematronFreeValidCtxt(ctxt);
    	if ((timing) && (!repeat)) {
    	    endTimer("Validating");
    	}
        }
    #endif
    #ifdef LIBXML_SCHEMAS_ENABLED
        if (relaxngschemas != NULL) {
    	xmlRelaxNGValidCtxtPtr ctxt;
    	int ret;
    
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    
    	ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
    	xmlRelaxNGSetValidErrors(ctxt,
    		(xmlRelaxNGValidityErrorFunc) fprintf,
    		(xmlRelaxNGValidityWarningFunc) fprintf,
    		stderr);
    	ret = xmlRelaxNGValidateDoc(ctxt, doc);
    	if (ret == 0) {
    	    fprintf(stderr, "%s validates\n", filename);
    	} else if (ret > 0) {
    	    fprintf(stderr, "%s fails to validate\n", filename);
    	    progresult = XMLLINT_ERR_VALID;
    	} else {
    	    fprintf(stderr, "%s validation generated an internal error\n",
    		   filename);
    	    progresult = XMLLINT_ERR_VALID;
    	}
    	xmlRelaxNGFreeValidCtxt(ctxt);
    	if ((timing) && (!repeat)) {
    	    endTimer("Validating");
    	}
        } else if (wxschemas != NULL) {
    	xmlSchemaValidCtxtPtr ctxt;
    	int ret;
    
    	if ((timing) && (!repeat)) {
    	    startTimer();
    	}
    
    	ctxt = xmlSchemaNewValidCtxt(wxschemas);
    	xmlSchemaSetValidErrors(ctxt,
    		(xmlSchemaValidityErrorFunc) fprintf,
    		(xmlSchemaValidityWarningFunc) fprintf,
    		stderr);
    	ret = xmlSchemaValidateDoc(ctxt, doc);
    	if (ret == 0) {
    	    fprintf(stderr, "%s validates\n", filename);
    	} else if (ret > 0) {
    	    fprintf(stderr, "%s fails to validate\n", filename);
    	    progresult = XMLLINT_ERR_VALID;
    	} else {
    	    fprintf(stderr, "%s validation generated an internal error\n",
    		   filename);
    	    progresult = XMLLINT_ERR_VALID;
    	}
    	xmlSchemaFreeValidCtxt(ctxt);
    	if ((timing) && (!repeat)) {
    	    endTimer("Validating");
    	}
        }
    #endif
    
    #ifdef LIBXML_DEBUG_ENABLED
    #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
        if ((debugent) && (!html))
    	xmlDebugDumpEntities(stderr, doc);
    #endif
    #endif
    
        /*
         * free it.
         */
        if ((timing) && (!repeat)) {
    	startTimer();
        }
        xmlFreeDoc(doc);
        if ((timing) && (!repeat)) {
    	endTimer("Freeing");
        }
    }
    
    /************************************************************************
     *									*
     *			Usage and Main					*
     *									*
     ************************************************************************/
    
    static void showVersion(const char *name) {
        fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
        fprintf(stderr, "   compiled with: ");
        if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
        if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
        if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
        if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
        if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
        if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
        if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
        if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
        if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP ");
        if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP ");
        if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
        if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML ");
        if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy ");
        if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N ");
        if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog ");
        if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath ");
        if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer ");
        if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude ");
        if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv ");
        if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X ");
        if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode ");
        if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps ");
        if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata ");
        if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr ");
        if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas ");
        if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron ");
        if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules ");
        if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug ");
        if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug ");
        if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug ");
        if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
        if (xmlHasFeature(XML_WITH_LZMA)) fprintf(stderr, "Lzma ");
        fprintf(stderr, "\n");
    }
    
    static void usage(const char *name) {
        printf("Usage : %s [options] XMLfiles ...\n", name);
    #ifdef LIBXML_OUTPUT_ENABLED
        printf("\tParse the XML files and output the result of the parsing\n");
    #else
        printf("\tParse the XML files\n");
    #endif /* LIBXML_OUTPUT_ENABLED */
        printf("\t--version : display the version of the XML library used\n");
    #ifdef LIBXML_DEBUG_ENABLED
        printf("\t--debug : dump a debug tree of the in-memory document\n");
        printf("\t--shell : run a navigating shell\n");
        printf("\t--debugent : debug the entities defined in the document\n");
    #else
    #ifdef LIBXML_READER_ENABLED
        printf("\t--debug : dump the nodes content when using --stream\n");
    #endif /* LIBXML_READER_ENABLED */
    #endif
    #ifdef LIBXML_TREE_ENABLED
        printf("\t--copy : used to test the internal copy implementation\n");
    #endif /* LIBXML_TREE_ENABLED */
        printf("\t--recover : output what was parsable on broken XML documents\n");
        printf("\t--huge : remove any internal arbitrary parser limits\n");
        printf("\t--noent : substitute entity references by their value\n");
        printf("\t--noenc : ignore any encoding specified inside the document\n");
        printf("\t--noout : don't output the result tree\n");
        printf("\t--path 'paths': provide a set of paths for resources\n");
        printf("\t--load-trace : print trace of all external entities loaded\n");
        printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
        printf("\t--nocompact : do not generate compact text nodes\n");
        printf("\t--htmlout : output results as HTML\n");
        printf("\t--nowrap : do not put HTML doc wrapper\n");
    #ifdef LIBXML_VALID_ENABLED
        printf("\t--valid : validate the document in addition to std well-formed check\n");
        printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
        printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
        printf("\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
    #endif /* LIBXML_VALID_ENABLED */
        printf("\t--timing : print some timings\n");
        printf("\t--output file or -o file: save to a given file\n");
        printf("\t--repeat : repeat 100 times, for timing or profiling\n");
        printf("\t--insert : ad-hoc test for valid insertions\n");
    #ifdef LIBXML_OUTPUT_ENABLED
    #ifdef HAVE_ZLIB_H
        printf("\t--compress : turn on gzip compression of output\n");
    #endif
    #endif /* LIBXML_OUTPUT_ENABLED */
    #ifdef LIBXML_HTML_ENABLED
        printf("\t--html : use the HTML parser\n");
        printf("\t--xmlout : force to use the XML serializer when using --html\n");
        printf("\t--nodefdtd : do not default HTML doctype\n");
    #endif
    #ifdef LIBXML_PUSH_ENABLED
        printf("\t--push : use the push mode of the parser\n");
        printf("\t--pushsmall : use the push mode of the parser using tiny increments\n");
    #endif /* LIBXML_PUSH_ENABLED */
    #ifdef HAVE_MMAP
        printf("\t--memory : parse from memory\n");
    #endif
        printf("\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
        printf("\t--nowarning : do not emit warnings from parser/validator\n");
        printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
        printf("\t--nocdata : replace cdata section with text nodes\n");
    #ifdef LIBXML_OUTPUT_ENABLED
        printf("\t--format : reformat/reindent the output\n");
        printf("\t--encode encoding : output in the given encoding\n");
        printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
        printf("\t--pretty STYLE : pretty-print in a particular style\n");
        printf("\t                 0 Do not pretty print\n");
        printf("\t                 1 Format the XML content, as --format\n");
        printf("\t                 2 Add whitespace inside tags, preserving content\n");
    #endif /* LIBXML_OUTPUT_ENABLED */
        printf("\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
        printf("\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
        printf("\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
    #ifdef LIBXML_C14N_ENABLED
    #endif /* LIBXML_C14N_ENABLED */
        printf("\t--nsclean : remove redundant namespace declarations\n");
        printf("\t--testIO : test user I/O support\n");
    #ifdef LIBXML_CATALOG_ENABLED
        printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
        printf("\t             otherwise XML Catalogs starting from \n");
        printf("\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
        printf("\t--nocatalogs: deactivate all catalogs\n");
    #endif
        printf("\t--auto : generate a small doc on the fly\n");
    #ifdef LIBXML_XINCLUDE_ENABLED
        printf("\t--xinclude : do XInclude processing\n");
        printf("\t--noxincludenode : same but do not generate XInclude nodes\n");
        printf("\t--nofixup-base-uris : do not fixup xml:base uris\n");
    #endif
        printf("\t--loaddtd : fetch external DTD\n");
        printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
    #ifdef LIBXML_READER_ENABLED
        printf("\t--stream : use the streaming interface to process very large files\n");
        printf("\t--walker : create a reader and walk though the resulting doc\n");
    #endif /* LIBXML_READER_ENABLED */
    #ifdef LIBXML_PATTERN_ENABLED
        printf("\t--pattern pattern_value : test the pattern support\n");
    #endif
        printf("\t--chkregister : verify the node registration code\n");
    #ifdef LIBXML_SCHEMAS_ENABLED
        printf("\t--relaxng schema : do RelaxNG validation against the schema\n");
        printf("\t--schema schema : do validation against the WXS schema\n");
    #endif
    #ifdef LIBXML_SCHEMATRON_ENABLED
        printf("\t--schematron schema : do validation against a schematron\n");
    #endif
    #ifdef LIBXML_SAX1_ENABLED
        printf("\t--sax1: use the old SAX1 interfaces for processing\n");
    #endif
        printf("\t--sax: do not build a tree but work just at the SAX level\n");
        printf("\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
    #ifdef LIBXML_XPATH_ENABLED
        printf("\t--xpath expr: evaluate the XPath expression, imply --noout\n");
    #endif
    
        printf("\nLibxml project home page: http://xmlsoft.org/\n");
        printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
    }
    
    static void registerNode(xmlNodePtr node)
    {
        node->_private = malloc(sizeof(long));
        if (node->_private == NULL) {
            fprintf(stderr, "Out of memory in xmllint:registerNode()\n");
    	exit(XMLLINT_ERR_MEM);
        }
        *(long*)node->_private = (long) 0x81726354;
        nbregister++;
    }
    
    static void deregisterNode(xmlNodePtr node)
    {
        assert(node->_private != NULL);
        assert(*(long*)node->_private == (long) 0x81726354);
        free(node->_private);
        nbregister--;
    }
    
    int
    main(int argc, char **argv) {
        int i, acount;
        int files = 0;
        int version = 0;
        const char* indent;
    
        if (argc <= 1) {
    	usage(argv[0]);
    	return(1);
        }
        LIBXML_TEST_VERSION
        for (i = 1; i < argc ; i++) {
    	if (!strcmp(argv[i], "-"))
    	    break;
    
    	if (argv[i][0] != '-')
    	    continue;
    	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
    	    debug++;
    	else
    #ifdef LIBXML_DEBUG_ENABLED
    	if ((!strcmp(argv[i], "-shell")) ||
    	         (!strcmp(argv[i], "--shell"))) {
    	    shell++;
                noout = 1;
            } else
    #endif
    #ifdef LIBXML_TREE_ENABLED
    	if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
    	    copy++;
    	else
    #endif /* LIBXML_TREE_ENABLED */
    	if ((!strcmp(argv[i], "-recover")) ||
    	         (!strcmp(argv[i], "--recover"))) {
    	    recovery++;
    	    options |= XML_PARSE_RECOVER;
    	} else if ((!strcmp(argv[i], "-huge")) ||
    	         (!strcmp(argv[i], "--huge"))) {
    	    options |= XML_PARSE_HUGE;
    	} else if ((!strcmp(argv[i], "-noent")) ||
    	         (!strcmp(argv[i], "--noent"))) {
    	    noent++;
    	    options |= XML_PARSE_NOENT;
    	} else if ((!strcmp(argv[i], "-noenc")) ||
    	         (!strcmp(argv[i], "--noenc"))) {
    	    noenc++;
    	    options |= XML_PARSE_IGNORE_ENC;
    	} else if ((!strcmp(argv[i], "-nsclean")) ||
    	         (!strcmp(argv[i], "--nsclean"))) {
    	    options |= XML_PARSE_NSCLEAN;
    	} else if ((!strcmp(argv[i], "-nocdata")) ||
    	         (!strcmp(argv[i], "--nocdata"))) {
    	    options |= XML_PARSE_NOCDATA;
    	} else if ((!strcmp(argv[i], "-nodict")) ||
    	         (!strcmp(argv[i], "--nodict"))) {
    	    options |= XML_PARSE_NODICT;
    	} else if ((!strcmp(argv[i], "-version")) ||
    	         (!strcmp(argv[i], "--version"))) {
    	    showVersion(argv[0]);
    	    version = 1;
    	} else if ((!strcmp(argv[i], "-noout")) ||
    	         (!strcmp(argv[i], "--noout")))
    	    noout++;
    #ifdef LIBXML_OUTPUT_ENABLED
    	else if ((!strcmp(argv[i], "-o")) ||
    	         (!strcmp(argv[i], "-output")) ||
    	         (!strcmp(argv[i], "--output"))) {
    	    i++;
    	    output = argv[i];
    	}
    #endif /* LIBXML_OUTPUT_ENABLED */
    	else if ((!strcmp(argv[i], "-htmlout")) ||
    	         (!strcmp(argv[i], "--htmlout")))
    	    htmlout++;
    	else if ((!strcmp(argv[i], "-nowrap")) ||
    	         (!strcmp(argv[i], "--nowrap")))
    	    nowrap++;
    #ifdef LIBXML_HTML_ENABLED
    	else if ((!strcmp(argv[i], "-html")) ||
    	         (!strcmp(argv[i], "--html"))) {
    	    html++;
            }
    	else if ((!strcmp(argv[i], "-xmlout")) ||
    	         (!strcmp(argv[i], "--xmlout"))) {
    	    xmlout++;
    	} else if ((!strcmp(argv[i], "-nodefdtd")) ||
    	         (!strcmp(argv[i], "--nodefdtd"))) {
                nodefdtd++;
    	    options |= HTML_PARSE_NODEFDTD;
            }
    #endif /* LIBXML_HTML_ENABLED */
    	else if ((!strcmp(argv[i], "-loaddtd")) ||
    	         (!strcmp(argv[i], "--loaddtd"))) {
    	    loaddtd++;
    	    options |= XML_PARSE_DTDLOAD;
    	} else if ((!strcmp(argv[i], "-dtdattr")) ||
    	         (!strcmp(argv[i], "--dtdattr"))) {
    	    loaddtd++;
    	    dtdattrs++;
    	    options |= XML_PARSE_DTDATTR;
    	}
    #ifdef LIBXML_VALID_ENABLED
    	else if ((!strcmp(argv[i], "-valid")) ||
    	         (!strcmp(argv[i], "--valid"))) {
    	    valid++;
    	    options |= XML_PARSE_DTDVALID;
    	} else if ((!strcmp(argv[i], "-postvalid")) ||
    	         (!strcmp(argv[i], "--postvalid"))) {
    	    postvalid++;
    	    loaddtd++;
    	    options |= XML_PARSE_DTDLOAD;
    	} else if ((!strcmp(argv[i], "-dtdvalid")) ||
    	         (!strcmp(argv[i], "--dtdvalid"))) {
    	    i++;
    	    dtdvalid = argv[i];
    	    loaddtd++;
    	    options |= XML_PARSE_DTDLOAD;
    	} else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
    	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
    	    i++;
    	    dtdvalidfpi = argv[i];
    	    loaddtd++;
    	    options |= XML_PARSE_DTDLOAD;
            }
    #endif /* LIBXML_VALID_ENABLED */
    	else if ((!strcmp(argv[i], "-dropdtd")) ||
    	         (!strcmp(argv[i], "--dropdtd")))
    	    dropdtd++;
    	else if ((!strcmp(argv[i], "-insert")) ||
    	         (!strcmp(argv[i], "--insert")))
    	    insert++;
    	else if ((!strcmp(argv[i], "-timing")) ||
    	         (!strcmp(argv[i], "--timing")))
    	    timing++;
    	else if ((!strcmp(argv[i], "-auto")) ||
    	         (!strcmp(argv[i], "--auto")))
    	    generate++;
    	else if ((!strcmp(argv[i], "-repeat")) ||
    	         (!strcmp(argv[i], "--repeat"))) {
    	    if (repeat)
    	        repeat *= 10;
    	    else
    	        repeat = 100;
    	}
    #ifdef LIBXML_PUSH_ENABLED
    	else if ((!strcmp(argv[i], "-push")) ||
    	         (!strcmp(argv[i], "--push")))
    	    push++;
    	else if ((!strcmp(argv[i], "-pushsmall")) ||
    	         (!strcmp(argv[i], "--pushsmall"))) {
    	    push++;
                pushsize = 10;
            }
    #endif /* LIBXML_PUSH_ENABLED */
    #ifdef HAVE_MMAP
    	else if ((!strcmp(argv[i], "-memory")) ||
    	         (!strcmp(argv[i], "--memory")))
    	    memory++;
    #endif
    	else if ((!strcmp(argv[i], "-testIO")) ||
    	         (!strcmp(argv[i], "--testIO")))
    	    testIO++;
    #ifdef LIBXML_XINCLUDE_ENABLED
    	else if ((!strcmp(argv[i], "-xinclude")) ||
    	         (!strcmp(argv[i], "--xinclude"))) {
    	    xinclude++;
    	    options |= XML_PARSE_XINCLUDE;
    	}
    	else if ((!strcmp(argv[i], "-noxincludenode")) ||
    	         (!strcmp(argv[i], "--noxincludenode"))) {
    	    xinclude++;
    	    options |= XML_PARSE_XINCLUDE;
    	    options |= XML_PARSE_NOXINCNODE;
    	}
    	else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
    	         (!strcmp(argv[i], "--nofixup-base-uris"))) {
    	    xinclude++;
    	    options |= XML_PARSE_XINCLUDE;
    	    options |= XML_PARSE_NOBASEFIX;
    	}
    #endif
    #ifdef LIBXML_OUTPUT_ENABLED
    #ifdef HAVE_ZLIB_H
    	else if ((!strcmp(argv[i], "-compress")) ||
    	         (!strcmp(argv[i], "--compress"))) {
    	    compress++;
    	    xmlSetCompressMode(9);
            }
    #endif
    #endif /* LIBXML_OUTPUT_ENABLED */
    	else if ((!strcmp(argv[i], "-nowarning")) ||
    	         (!strcmp(argv[i], "--nowarning"))) {
    	    xmlGetWarningsDefaultValue = 0;
    	    xmlPedanticParserDefault(0);
    	    options |= XML_PARSE_NOWARNING;
            }
    	else if ((!strcmp(argv[i], "-pedantic")) ||
    	         (!strcmp(argv[i], "--pedantic"))) {
    	    xmlGetWarningsDefaultValue = 1;
    	    xmlPedanticParserDefault(1);
    	    options |= XML_PARSE_PEDANTIC;
            }
    #ifdef LIBXML_DEBUG_ENABLED
    	else if ((!strcmp(argv[i], "-debugent")) ||
    		 (!strcmp(argv[i], "--debugent"))) {
    	    debugent++;
    	    xmlParserDebugEntities = 1;
    	}
    #endif
    #ifdef LIBXML_C14N_ENABLED
    	else if ((!strcmp(argv[i], "-c14n")) ||
    		 (!strcmp(argv[i], "--c14n"))) {
    	    canonical++;
    	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
    	}
    	else if ((!strcmp(argv[i], "-c14n11")) ||
    		 (!strcmp(argv[i], "--c14n11"))) {
    	    canonical_11++;
    	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
    	}
    	else if ((!strcmp(argv[i], "-exc-c14n")) ||
    		 (!strcmp(argv[i], "--exc-c14n"))) {
    	    exc_canonical++;
    	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
    	}
    #endif
    #ifdef LIBXML_CATALOG_ENABLED
    	else if ((!strcmp(argv[i], "-catalogs")) ||
    		 (!strcmp(argv[i], "--catalogs"))) {
    	    catalogs++;
    	} else if ((!strcmp(argv[i], "-nocatalogs")) ||
    		 (!strcmp(argv[i], "--nocatalogs"))) {
    	    nocatalogs++;
    	}
    #endif
    	else if ((!strcmp(argv[i], "-encode")) ||
    	         (!strcmp(argv[i], "--encode"))) {
    	    i++;
    	    encoding = argv[i];
    	    /*
    	     * OK it's for testing purposes
    	     */
    	    xmlAddEncodingAlias("UTF-8", "DVEnc");
            }
    	else if ((!strcmp(argv[i], "-noblanks")) ||
    	         (!strcmp(argv[i], "--noblanks"))) {
    	    noblanks++;
    	    xmlKeepBlanksDefault(0);
    	    options |= XML_PARSE_NOBLANKS;
            }
    	else if ((!strcmp(argv[i], "-maxmem")) ||
    	         (!strcmp(argv[i], "--maxmem"))) {
    	     i++;
    	     if (sscanf(argv[i], "%d", &maxmem) == 1) {
    	         xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc,
    		             myStrdupFunc);
    	     } else {
    	         maxmem = 0;
    	     }
            }
    	else if ((!strcmp(argv[i], "-format")) ||
    	         (!strcmp(argv[i], "--format"))) {
    	     noblanks++;
    #ifdef LIBXML_OUTPUT_ENABLED
    	     format = 1;
    #endif /* LIBXML_OUTPUT_ENABLED */
    	     xmlKeepBlanksDefault(0);
    	}
    	else if ((!strcmp(argv[i], "-pretty")) ||
    	         (!strcmp(argv[i], "--pretty"))) {
    	     i++;
    #ifdef LIBXML_OUTPUT_ENABLED
           if (argv[i] != NULL) {
    	         format = atoi(argv[i]);
    	         if (format == 1) {
    	             noblanks++;
    	             xmlKeepBlanksDefault(0);
    	         }
           }
    #endif /* LIBXML_OUTPUT_ENABLED */
    	}
    #ifdef LIBXML_READER_ENABLED
    	else if ((!strcmp(argv[i], "-stream")) ||
    	         (!strcmp(argv[i], "--stream"))) {
    	     stream++;
    	}
    	else if ((!strcmp(argv[i], "-walker")) ||
    	         (!strcmp(argv[i], "--walker"))) {
    	     walker++;
                 noout++;
    	}
    #endif /* LIBXML_READER_ENABLED */
    #ifdef LIBXML_SAX1_ENABLED
    	else if ((!strcmp(argv[i], "-sax1")) ||
    	         (!strcmp(argv[i], "--sax1"))) {
    	    sax1++;
    	    options |= XML_PARSE_SAX1;
    	}
    #endif /* LIBXML_SAX1_ENABLED */
    	else if ((!strcmp(argv[i], "-sax")) ||
    	         (!strcmp(argv[i], "--sax"))) {
    	    sax++;
    	}
    	else if ((!strcmp(argv[i], "-chkregister")) ||
    	         (!strcmp(argv[i], "--chkregister"))) {
    	    chkregister++;
    #ifdef LIBXML_SCHEMAS_ENABLED
    	} else if ((!strcmp(argv[i], "-relaxng")) ||
    	         (!strcmp(argv[i], "--relaxng"))) {
    	    i++;
    	    relaxng = argv[i];
    	    noent++;
    	    options |= XML_PARSE_NOENT;
    	} else if ((!strcmp(argv[i], "-schema")) ||
    	         (!strcmp(argv[i], "--schema"))) {
    	    i++;
    	    schema = argv[i];
    	    noent++;
    #endif
    #ifdef LIBXML_SCHEMATRON_ENABLED
    	} else if ((!strcmp(argv[i], "-schematron")) ||
    	         (!strcmp(argv[i], "--schematron"))) {
    	    i++;
    	    schematron = argv[i];
    	    noent++;
    #endif
            } else if ((!strcmp(argv[i], "-nonet")) ||
                       (!strcmp(argv[i], "--nonet"))) {
    	    options |= XML_PARSE_NONET;
    	    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
            } else if ((!strcmp(argv[i], "-nocompact")) ||
                       (!strcmp(argv[i], "--nocompact"))) {
    	    options &= ~XML_PARSE_COMPACT;
    	} else if ((!strcmp(argv[i], "-load-trace")) ||
    	           (!strcmp(argv[i], "--load-trace"))) {
    	    load_trace++;
            } else if ((!strcmp(argv[i], "-path")) ||
                       (!strcmp(argv[i], "--path"))) {
    	    i++;
    	    parsePath(BAD_CAST argv[i]);
    #ifdef LIBXML_PATTERN_ENABLED
            } else if ((!strcmp(argv[i], "-pattern")) ||
                       (!strcmp(argv[i], "--pattern"))) {
    	    i++;
    	    pattern = argv[i];
    #endif
    #ifdef LIBXML_XPATH_ENABLED
            } else if ((!strcmp(argv[i], "-xpath")) ||
                       (!strcmp(argv[i], "--xpath"))) {
    	    i++;
    	    noout++;
    	    xpathquery = argv[i];
    #endif
    	} else if ((!strcmp(argv[i], "-oldxml10")) ||
    	           (!strcmp(argv[i], "--oldxml10"))) {
    	    oldxml10++;
    	    options |= XML_PARSE_OLD10;
    	} else {
    	    fprintf(stderr, "Unknown option %s\n", argv[i]);
    	    usage(argv[0]);
    	    return(1);
    	}
        }
    
    #ifdef LIBXML_CATALOG_ENABLED
        if (nocatalogs == 0) {
    	if (catalogs) {
    	    const char *catal;
    
    	    catal = getenv("SGML_CATALOG_FILES");
    	    if (catal != NULL) {
    		xmlLoadCatalogs(catal);
    	    } else {
    		fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
    	    }
    	}
        }
    #endif
    
    #ifdef LIBXML_SAX1_ENABLED
        if (sax1)
            xmlSAXDefaultVersion(1);
        else
            xmlSAXDefaultVersion(2);
    #endif /* LIBXML_SAX1_ENABLED */
    
        if (chkregister) {
    	xmlRegisterNodeDefault(registerNode);
    	xmlDeregisterNodeDefault(deregisterNode);
        }
    
        indent = getenv("XMLLINT_INDENT");
        if(indent != NULL) {
    	xmlTreeIndentString = indent;
        }
    
    
        defaultEntityLoader = xmlGetExternalEntityLoader();
        xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
    
        xmlLineNumbersDefault(1);
        if (loaddtd != 0)
    	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
        if (dtdattrs)
    	xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
        if (noent != 0) xmlSubstituteEntitiesDefault(1);
    #ifdef LIBXML_VALID_ENABLED
        if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
    #endif /* LIBXML_VALID_ENABLED */
        if ((htmlout) && (!nowrap)) {
    	xmlGenericError(xmlGenericErrorContext,
             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
    	xmlGenericError(xmlGenericErrorContext,
    		"\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
    	xmlGenericError(xmlGenericErrorContext,
    	 "<html><head><title>%s output</title></head>\n",
    		argv[0]);
    	xmlGenericError(xmlGenericErrorContext,
    	 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
    		argv[0]);
        }
    
    #ifdef LIBXML_SCHEMATRON_ENABLED
        if ((schematron != NULL) && (sax == 0)
    #ifdef LIBXML_READER_ENABLED
            && (stream == 0)
    #endif /* LIBXML_READER_ENABLED */
    	) {
    	xmlSchematronParserCtxtPtr ctxt;
    
            /* forces loading the DTDs */
            xmlLoadExtDtdDefaultValue |= 1;
    	options |= XML_PARSE_DTDLOAD;
    	if (timing) {
    	    startTimer();
    	}
    	ctxt = xmlSchematronNewParserCtxt(schematron);
    #if 0
    	xmlSchematronSetParserErrors(ctxt,
    		(xmlSchematronValidityErrorFunc) fprintf,
    		(xmlSchematronValidityWarningFunc) fprintf,
    		stderr);
    #endif
    	wxschematron = xmlSchematronParse(ctxt);
    	if (wxschematron == NULL) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "Schematron schema %s failed to compile\n", schematron);
                progresult = XMLLINT_ERR_SCHEMACOMP;
    	    schematron = NULL;
    	}
    	xmlSchematronFreeParserCtxt(ctxt);
    	if (timing) {
    	    endTimer("Compiling the schemas");
    	}
        }
    #endif
    #ifdef LIBXML_SCHEMAS_ENABLED
        if ((relaxng != NULL) && (sax == 0)
    #ifdef LIBXML_READER_ENABLED
            && (stream == 0)
    #endif /* LIBXML_READER_ENABLED */
    	) {
    	xmlRelaxNGParserCtxtPtr ctxt;
    
            /* forces loading the DTDs */
            xmlLoadExtDtdDefaultValue |= 1;
    	options |= XML_PARSE_DTDLOAD;
    	if (timing) {
    	    startTimer();
    	}
    	ctxt = xmlRelaxNGNewParserCtxt(relaxng);
    	xmlRelaxNGSetParserErrors(ctxt,
    		(xmlRelaxNGValidityErrorFunc) fprintf,
    		(xmlRelaxNGValidityWarningFunc) fprintf,
    		stderr);
    	relaxngschemas = xmlRelaxNGParse(ctxt);
    	if (relaxngschemas == NULL) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "Relax-NG schema %s failed to compile\n", relaxng);
                progresult = XMLLINT_ERR_SCHEMACOMP;
    	    relaxng = NULL;
    	}
    	xmlRelaxNGFreeParserCtxt(ctxt);
    	if (timing) {
    	    endTimer("Compiling the schemas");
    	}
        } else if ((schema != NULL)
    #ifdef LIBXML_READER_ENABLED
    		&& (stream == 0)
    #endif
    	) {
    	xmlSchemaParserCtxtPtr ctxt;
    
    	if (timing) {
    	    startTimer();
    	}
    	ctxt = xmlSchemaNewParserCtxt(schema);
    	xmlSchemaSetParserErrors(ctxt,
    		(xmlSchemaValidityErrorFunc) fprintf,
    		(xmlSchemaValidityWarningFunc) fprintf,
    		stderr);
    	wxschemas = xmlSchemaParse(ctxt);
    	if (wxschemas == NULL) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "WXS schema %s failed to compile\n", schema);
                progresult = XMLLINT_ERR_SCHEMACOMP;
    	    schema = NULL;
    	}
    	xmlSchemaFreeParserCtxt(ctxt);
    	if (timing) {
    	    endTimer("Compiling the schemas");
    	}
        }
    #endif /* LIBXML_SCHEMAS_ENABLED */
    #ifdef LIBXML_PATTERN_ENABLED
        if ((pattern != NULL)
    #ifdef LIBXML_READER_ENABLED
            && (walker == 0)
    #endif
    	) {
            patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
    	if (patternc == NULL) {
    	    xmlGenericError(xmlGenericErrorContext,
    		    "Pattern %s failed to compile\n", pattern);
                progresult = XMLLINT_ERR_SCHEMAPAT;
    	    pattern = NULL;
    	}
        }
    #endif /* LIBXML_PATTERN_ENABLED */
        for (i = 1; i < argc ; i++) {
    	if ((!strcmp(argv[i], "-encode")) ||
    	         (!strcmp(argv[i], "--encode"))) {
    	    i++;
    	    continue;
            } else if ((!strcmp(argv[i], "-o")) ||
                       (!strcmp(argv[i], "-output")) ||
                       (!strcmp(argv[i], "--output"))) {
                i++;
    	    continue;
            }
    #ifdef LIBXML_VALID_ENABLED
    	if ((!strcmp(argv[i], "-dtdvalid")) ||
    	         (!strcmp(argv[i], "--dtdvalid"))) {
    	    i++;
    	    continue;
            }
    	if ((!strcmp(argv[i], "-path")) ||
                       (!strcmp(argv[i], "--path"))) {
                i++;
    	    continue;
            }
    	if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
    	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
    	    i++;
    	    continue;
            }
    #endif /* LIBXML_VALID_ENABLED */
    	if ((!strcmp(argv[i], "-relaxng")) ||
    	         (!strcmp(argv[i], "--relaxng"))) {
    	    i++;
    	    continue;
            }
    	if ((!strcmp(argv[i], "-maxmem")) ||
    	         (!strcmp(argv[i], "--maxmem"))) {
    	    i++;
    	    continue;
            }
    	if ((!strcmp(argv[i], "-pretty")) ||
    	         (!strcmp(argv[i], "--pretty"))) {
    	    i++;
    	    continue;
            }
    	if ((!strcmp(argv[i], "-schema")) ||
    	         (!strcmp(argv[i], "--schema"))) {
    	    i++;
    	    continue;
            }
    	if ((!strcmp(argv[i], "-schematron")) ||
    	         (!strcmp(argv[i], "--schematron"))) {
    	    i++;
    	    continue;
            }
    #ifdef LIBXML_PATTERN_ENABLED
            if ((!strcmp(argv[i], "-pattern")) ||
    	    (!strcmp(argv[i], "--pattern"))) {
    	    i++;
    	    continue;
    	}
    #endif
    #ifdef LIBXML_XPATH_ENABLED
            if ((!strcmp(argv[i], "-xpath")) ||
    	    (!strcmp(argv[i], "--xpath"))) {
    	    i++;
    	    continue;
    	}
    #endif
    	if ((timing) && (repeat))
    	    startTimer();
    	/* Remember file names.  "-" means stdin.  <sven@zen.org> */
    	if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
    	    if (repeat) {
    		xmlParserCtxtPtr ctxt = NULL;
    
    		for (acount = 0;acount < repeat;acount++) {
    #ifdef LIBXML_READER_ENABLED
    		    if (stream != 0) {
    			streamFile(argv[i]);
    		    } else {
    #endif /* LIBXML_READER_ENABLED */
                            if (sax) {
    			    testSAX(argv[i]);
    			} else {
    			    if (ctxt == NULL)
    				ctxt = xmlNewParserCtxt();
    			    parseAndPrintFile(argv[i], ctxt);
    			}
    #ifdef LIBXML_READER_ENABLED
    		    }
    #endif /* LIBXML_READER_ENABLED */
    		}
    		if (ctxt != NULL)
    		    xmlFreeParserCtxt(ctxt);
    	    } else {
    		nbregister = 0;
    
    #ifdef LIBXML_READER_ENABLED
    		if (stream != 0)
    		    streamFile(argv[i]);
    		else
    #endif /* LIBXML_READER_ENABLED */
                    if (sax) {
    		    testSAX(argv[i]);
    		} else {
    		    parseAndPrintFile(argv[i], NULL);
    		}
    
                    if ((chkregister) && (nbregister != 0)) {
    		    fprintf(stderr, "Registration count off: %d\n", nbregister);
    		    progresult = XMLLINT_ERR_RDREGIS;
    		}
    	    }
    	    files ++;
    	    if ((timing) && (repeat)) {
    		endTimer("%d iterations", repeat);
    	    }
    	}
        }
        if (generate)
    	parseAndPrintFile(NULL, NULL);
        if ((htmlout) && (!nowrap)) {
    	xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
        }
        if ((files == 0) && (!generate) && (version == 0)) {
    	usage(argv[0]);
        }
    #ifdef LIBXML_SCHEMATRON_ENABLED
        if (wxschematron != NULL)
    	xmlSchematronFree(wxschematron);
    #endif
    #ifdef LIBXML_SCHEMAS_ENABLED
        if (relaxngschemas != NULL)
    	xmlRelaxNGFree(relaxngschemas);
        if (wxschemas != NULL)
    	xmlSchemaFree(wxschemas);
        xmlRelaxNGCleanupTypes();
    #endif
    #ifdef LIBXML_PATTERN_ENABLED
        if (patternc != NULL)
            xmlFreePattern(patternc);
    #endif
        xmlCleanupParser();
        xmlMemoryDump();
    
        return(progresult);
    }