Edit

kc3-lang/libxml2/testSAX.c

Branch :

  • Show log

    Commit

  • Author : William M. Brack
    Date : 2005-01-02 09:53:13
    Hash : 21e4ef20
    Message : Re-examined the problems of configuring a "minimal" library. Synchronized the header files with the library code in order to assure that all the various conditionals (LIBXML_xxxx_ENABLED) were the same in both. Modified the API database content to more accurately reflect the conditionals. Enhanced the generation of that database. Although there was no substantial change to any of the library code's logic, a large number of files were modified to achieve the above, and the configuration script was enhanced to do some automatic enabling of features (e.g. --with-xinclude forces --with-xpath). Additionally, all the format errors discovered by apibuild.py were corrected. * configure.in: enhanced cross-checking of options * doc/apibuild.py, doc/elfgcchack.xsl, doc/libxml2-refs.xml, doc/libxml2-api.xml, gentest.py: changed the usage of the <cond> element in module descriptions * elfgcchack.h, testapi.c: regenerated with proper conditionals * HTMLparser.c, SAX.c, globals.c, tree.c, xmlschemas.c, xpath.c, testSAX.c: cleaned up conditionals * include/libxml/[SAX.h, SAX2.h, debugXML.h, encoding.h, entities.h, hash.h, parser.h, parserInternals.h, schemasInternals.h, tree.h, valid.h, xlink.h, xmlIO.h, xmlautomata.h, xmlreader.h, xpath.h]: synchronized the conditionals with the corresponding module code * doc/examples/tree2.c, doc/examples/xpath1.c, doc/examples/xpath2.c: added additional conditions required for compilation * doc/*.html, doc/html/*.html: rebuilt the docs

  • testSAX.c
  • /*
     * testSAX.c : a small tester program for parsing using the SAX API.
     *
     * See Copyright for the status of this software.
     *
     * daniel@veillard.com
     */
    
    #include "libxml.h"
    
    #ifdef HAVE_SYS_TIME_H
    #include <sys/time.h>
    #endif
    #ifdef HAVE_SYS_TIMEB_H
    #include <sys/timeb.h>
    #endif
    #ifdef HAVE_TIME_H
    #include <time.h>
    #endif
    
    #ifdef LIBXML_SAX1_ENABLED
    #include <string.h>
    #include <stdarg.h>
    
    #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_STDLIB_H
    #include <stdlib.h>
    #endif
    #ifdef HAVE_STRING_H
    #include <string.h>
    #endif
    
    
    #include <libxml/globals.h>
    #include <libxml/xmlerror.h>
    #include <libxml/parser.h>
    #include <libxml/parserInternals.h> /* only for xmlNewInputFromFile() */
    #include <libxml/tree.h>
    #include <libxml/debugXML.h>
    #include <libxml/xmlmemory.h>
    
    static int debug = 0;
    static int copy = 0;
    static int recovery = 0;
    static int push = 0;
    static int speed = 0;
    static int noent = 0;
    static int quiet = 0;
    static int nonull = 0;
    static int sax2 = 0;
    static int repeat = 0;
    static int callbacks = 0;
    static int timing = 0;
    
    /*
     * Timing routines.
     */
    /*
     * 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
    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
    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
    endTimer(char *format, ...)
    {
        /*
         * We cannot do anything because we don't have a timing function
         */
    #ifdef HAVE_STDARG_H
        va_start(ap, format);
        vfprintf(stderr, format, ap);
        va_end(ap);
        fprintf(stderr, " was not timed\n", msec);
    #else
        /* We don't have gettimeofday, time or stdarg.h, what crazy world is
         * this ?!
         */
    #endif
    }
    #endif
    
    /*
     * empty SAX block
     */
    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; */
        1,
        NULL,
        NULL, /* startElementNs */
        NULL, /* endElementNs */
        NULL  /* xmlStructuredErrorFunc */
    };
    
    xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
    extern xmlSAXHandlerPtr debugSAXHandler;
    
    /************************************************************************
     *									*
     *				Debug Handlers				*
     *									*
     ************************************************************************/
    
    /**
     * isStandaloneDebug:
     * @ctxt:  An XML parser context
     *
     * Is this document tagged standalone ?
     *
     * Returns 1 if true
     */
    static int
    isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
    {
        callbacks++;
        if (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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");
    /*********
        if (systemId != NULL) {
            return(xmlNewInputFromFile(ctxt, (char *) systemId));
        }
     *********/
        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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
            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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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 output[40];
        int i;
    
        callbacks++;
        if (quiet)
    	return;
        for (i = 0;(i<len) && (i < 30);i++)
    	output[i] = ch[i];
        output[i] = 0;
    
        fprintf(stdout, "SAX.characters(%s, %d)\n", output, 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 (quiet)
    	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 output[40];
        int i;
    
        callbacks++;
        if (quiet)
    	return;
        for (i = 0;(i<len) && (i < 30);i++)
    	output[i] = ch[i];
        output[i] = 0;
        fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", output, 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 (quiet)
    	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 (quiet)
    	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 (quiet)
    	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
    warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
    {
        va_list args;
    
        callbacks++;
        if (quiet)
    	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
    errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
    {
        va_list args;
    
        callbacks++;
        if (quiet)
    	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
    fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
    {
        va_list args;
    
        callbacks++;
        if (quiet)
    	return;
        va_start(args, msg);
        fprintf(stdout, "SAX.fatalError: ");
        vfprintf(stdout, msg, args);
        va_end(args);
    }
    
    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 (quiet)
    	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 (quiet)
    	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);
    }
    
    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
    };
    
    xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
    
    /************************************************************************
     *									*
     *				Debug					*
     *									*
     ************************************************************************/
    
    static void
    parseAndPrintFile(char *filename) {
        int res;
    
    #ifdef LIBXML_PUSH_ENABLED
        if (push) {
    	FILE *f;
    
            if ((!quiet) && (!nonull)) {
    	    /*
    	     * Empty callbacks for checking
    	     */
    #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
    	    f = fopen(filename, "rb");
    #else
    	    f = fopen(filename, "r");
    #endif
    	    if (f != NULL) {
    		int ret;
    		char chars[10];
    		xmlParserCtxtPtr ctxt;
    
    		ret = fread(chars, 1, 4, f);
    		if (ret > 0) {
    		    ctxt = xmlCreatePushParserCtxt(emptySAXHandler, NULL,
    				chars, ret, filename);
    		    while ((ret = fread(chars, 1, 3, f)) > 0) {
    			xmlParseChunk(ctxt, chars, ret, 0);
    		    }
    		    xmlParseChunk(ctxt, chars, 0, 1);
    		    xmlFreeParserCtxt(ctxt);
    		}
    		fclose(f);
    	    } else {
    		xmlGenericError(xmlGenericErrorContext,
    			"Cannot read file %s\n", filename);
    	    }
    	}
    	/*
    	 * Debug callback
    	 */
    #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
    	f = fopen(filename, "rb");
    #else
    	f = fopen(filename, "r");
    #endif
    	if (f != NULL) {
    	    int ret;
    	    char chars[10];
    	    xmlParserCtxtPtr ctxt;
    
    	    ret = fread(chars, 1, 4, f);
    	    if (ret > 0) {
    	        if (sax2)
    		    ctxt = xmlCreatePushParserCtxt(debugSAX2Handler, NULL,
    				chars, ret, filename);
    		else
    		    ctxt = xmlCreatePushParserCtxt(debugSAXHandler, NULL,
    				chars, ret, filename);
    		while ((ret = fread(chars, 1, 3, f)) > 0) {
    		    xmlParseChunk(ctxt, chars, ret, 0);
    		}
    		ret = xmlParseChunk(ctxt, chars, 0, 1);
    		xmlFreeParserCtxt(ctxt);
    		if (ret != 0) {
    		    fprintf(stdout,
    		            "xmlSAXUserParseFile returned error %d\n", ret);
    		}
    	    }
    	    fclose(f);
    	}
        } else {
    #endif /* LIBXML_PUSH_ENABLED */
    	if (!speed) {
    	    /*
    	     * Empty callbacks for checking
    	     */
    	    if ((!quiet) && (!nonull)) {
    		res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
    		if (res != 0) {
    		    fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
    		}
    	    }
    
    	    /*
    	     * Debug callback
    	     */
    	    callbacks = 0;
    	    if (repeat) {
    	        int i;
    		for (i = 0;i < 99;i++) {
    		    if (sax2)
    			res = xmlSAXUserParseFile(debugSAX2Handler, NULL,
    			                          filename);
    		    else
    			res = xmlSAXUserParseFile(debugSAXHandler, NULL,
    			                          filename);
    		}
    	    }
    	    if (sax2)
    	        res = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
    	    else
    		res = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
    	    if (res != 0) {
    		fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
    	    }
    	    if (quiet)
    		fprintf(stdout, "%d callbacks generated\n", callbacks);
    	} else {
    	    /*
    	     * test 100x the SAX parse
    	     */
    	    int i;
    
    	    for (i = 0; i<100;i++)
    		res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
    	    if (res != 0) {
    		fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
    	    }
    	}
    #ifdef LIBXML_PUSH_ENABLED
        }
    #endif
    }
    
    
    int main(int argc, char **argv) {
        int i;
        int files = 0;
    
        LIBXML_TEST_VERSION	/* be safe, plus calls xmlInitParser */
        
        for (i = 1; i < argc ; i++) {
    	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
    	    debug++;
    	else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
    	    copy++;
    	else if ((!strcmp(argv[i], "-recover")) ||
    	         (!strcmp(argv[i], "--recover")))
    	    recovery++;
    	else if ((!strcmp(argv[i], "-push")) ||
    	         (!strcmp(argv[i], "--push")))
    #ifdef LIBXML_PUSH_ENABLED
    	    push++;
    #else
    	    fprintf(stderr,"'push' not enabled in library - ignoring\n");
    #endif /* LIBXML_PUSH_ENABLED */
    	else if ((!strcmp(argv[i], "-speed")) ||
    	         (!strcmp(argv[i], "--speed")))
    	    speed++;
    	else if ((!strcmp(argv[i], "-timing")) ||
    	         (!strcmp(argv[i], "--timing"))) {
    	    nonull++;
    	    timing++;
    	    quiet++;
    	} else if ((!strcmp(argv[i], "-repeat")) ||
    	         (!strcmp(argv[i], "--repeat"))) {
    	    repeat++;
    	    quiet++;
    	} else if ((!strcmp(argv[i], "-noent")) ||
    	         (!strcmp(argv[i], "--noent")))
    	    noent++;
    	else if ((!strcmp(argv[i], "-quiet")) ||
    	         (!strcmp(argv[i], "--quiet")))
    	    quiet++;
    	else if ((!strcmp(argv[i], "-sax2")) ||
    	         (!strcmp(argv[i], "--sax2")))
    	    sax2++;
    	else if ((!strcmp(argv[i], "-nonull")) ||
    	         (!strcmp(argv[i], "--nonull")))
    	    nonull++;
        }
        if (noent != 0) xmlSubstituteEntitiesDefault(1);
        for (i = 1; i < argc ; i++) {
    	if (argv[i][0] != '-') {
    	    if (timing) {
    		startTimer();
    	    }
    	    parseAndPrintFile(argv[i]);
    	    if (timing) {
    		endTimer("Parsing");
    	    }
    	    files ++;
    	}
        }
        xmlCleanupParser();
        xmlMemoryDump();
    
        return(0);
    }
    #else
    int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
        printf("%s : SAX1 parsing support not compiled in\n", argv[0]);
        return(0);
    }
    #endif /* LIBXML_SAX1_ENABLED */