summaryrefslogtreecommitdiffstats
path: root/libxml2/testSAX.c
diff options
context:
space:
mode:
Diffstat (limited to 'libxml2/testSAX.c')
-rw-r--r--libxml2/testSAX.c1198
1 files changed, 1198 insertions, 0 deletions
diff --git a/libxml2/testSAX.c b/libxml2/testSAX.c
new file mode 100644
index 0000000..81c4b93
--- /dev/null
+++ b/libxml2/testSAX.c
@@ -0,0 +1,1198 @@
+/*
+ * 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 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_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
+ */
+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; */
+ 1,
+ NULL,
+ NULL, /* startElementNs */
+ NULL, /* endElementNs */
+ NULL /* xmlStructuredErrorFunc */
+};
+
+static 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 XMLCDECL
+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 XMLCDECL
+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 XMLCDECL
+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);
+}
+
+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 (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);
+}
+
+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;
+
+/************************************************************************
+ * *
+ * 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 */