/*
* 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
#endif
#ifdef HAVE_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
#endif
#ifdef HAVE_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/xmlerror.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
{
ftime(&timebuffer);
if (tvp) {
}
return (0);
}
#endif /* HAVE_FTIME */
#endif /* HAVE_SYS_TIME_H */
#endif /* HAVE_SYS_TIMEB_H */
#endif /* !HAVE_GETTIMEOFDAY */
#if defined(HAVE_GETTIMEOFDAY)
/*
* startTimer: call where you want to start timing
*/
static void
startTimer(void)
{
}
/*
* 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
{
long msec;
msec *= 1000;
#ifndef HAVE_STDARG_H
#error "endTimer required stdarg functions"
#endif
}
#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
#endif
static void
startTimer(void)
{
}
static void XMLCDECL
{
long msec;
#ifndef HAVE_STDARG_H
#error "endTimer required stdarg functions"
#endif
}
#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
{
/*
* We cannot do anything because we don't have a timing function
*/
#ifdef HAVE_STDARG_H
#else
/* We don't have gettimeofday, time or stdarg.h, what crazy world is
* this ?!
*/
#endif
}
#endif
/*
* empty SAX block
*/
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 */
};
extern xmlSAXHandlerPtr debugSAXHandler;
/************************************************************************
* *
* Debug Handlers *
* *
************************************************************************/
/**
* isStandaloneDebug:
* @ctxt: An XML parser context
*
* Is this document tagged standalone ?
*
* Returns 1 if true
*/
static int
{
callbacks++;
if (quiet)
return(0);
return(0);
}
/**
* hasInternalSubsetDebug:
* @ctxt: An XML parser context
*
* Does this document has an internal subset
*
* Returns 1 if true
*/
static int
{
callbacks++;
if (quiet)
return(0);
return(0);
}
/**
* hasExternalSubsetDebug:
* @ctxt: An XML parser context
*
* Does this document has an external subset
*
* Returns 1 if true
*/
static int
{
callbacks++;
if (quiet)
return(0);
return(0);
}
/**
* internalSubsetDebug:
* @ctxt: An XML parser context
*
* Does this document has an internal subset
*/
static void
{
callbacks++;
if (quiet)
return;
if (ExternalID == NULL)
else
else
}
/**
* externalSubsetDebug:
* @ctxt: An XML parser context
*
* Does this document has an external subset
*/
static void
{
callbacks++;
if (quiet)
return;
if (ExternalID == NULL)
else
else
}
/**
* 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
{
callbacks++;
if (quiet)
return(NULL);
/* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
else
else
/*********
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
{
callbacks++;
if (quiet)
return(NULL);
return(NULL);
}
/**
* getParameterEntityDebug:
* @ctxt: An XML parser context
* @name: The entity name
*
* Get a parameter entity by name
*
* Returns the xmlParserInputPtr
*/
static xmlEntityPtr
{
callbacks++;
if (quiet)
return(NULL);
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
{
/* not all libraries handle printing null pointers nicely */
callbacks++;
if (quiet)
return;
}
/**
* attributeDeclDebug:
* @ctxt: An XML parser context
* @name: the attribute name
* @type: the attribute type
*
* An attribute definition has been parsed
*/
static void
{
callbacks++;
if (quiet)
return;
if (defaultValue == NULL)
else
}
/**
* 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
{
callbacks++;
if (quiet)
return;
}
/**
* 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
{
callbacks++;
if (quiet)
return;
}
/**
* 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
const xmlChar *notationName)
{
if (notationName == NULL)
callbacks++;
if (quiet)
return;
(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
{
callbacks++;
if (quiet)
return;
}
/**
* startDocumentDebug:
* @ctxt: An XML parser context
*
* called when the document start being processed.
*/
static void
{
callbacks++;
if (quiet)
return;
}
/**
* endDocumentDebug:
* @ctxt: An XML parser context
*
* called when the document end has been detected.
*/
static void
{
callbacks++;
if (quiet)
return;
}
/**
* startElementDebug:
* @ctxt: An XML parser context
* @name: The element name
*
* called when an opening tag has been processed.
*/
static void
{
int i;
callbacks++;
if (quiet)
return;
}
}
}
/**
* endElementDebug:
* @ctxt: An XML parser context
* @name: The element name
*
* called when the end of an element has been detected.
*/
static void
{
callbacks++;
if (quiet)
return;
}
/**
* 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
{
int i;
callbacks++;
if (quiet)
return;
for (i = 0;(i<len) && (i < 30);i++)
output[i] = 0;
}
/**
* referenceDebug:
* @ctxt: An XML parser context
* @name: The entity name
*
* called when an entity reference is detected.
*/
static void
{
callbacks++;
if (quiet)
return;
}
/**
* 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
{
int i;
callbacks++;
if (quiet)
return;
for (i = 0;(i<len) && (i < 30);i++)
output[i] = 0;
}
/**
* 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
{
callbacks++;
if (quiet)
return;
else
(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
{
callbacks++;
if (quiet)
return;
}
/**
* commentDebug:
* @ctxt: An XML parser context
* @value: the comment content
*
* A comment has been parsed.
*/
static void
{
callbacks++;
if (quiet)
return;
}
/**
* warningDebug:
* @ctxt: An XML parser context
* @...: extra parameters for the message display
*
* Display and format a warning messages, gives file, line, position and
* extra parameters.
*/
static void XMLCDECL
{
callbacks++;
if (quiet)
return;
}
/**
* errorDebug:
* @ctxt: An XML parser context
* @...: extra parameters for the message display
*
* Display and format a error messages, gives file, line, position and
* extra parameters.
*/
static void XMLCDECL
{
callbacks++;
if (quiet)
return;
}
/**
* fatalErrorDebug:
* @ctxt: An XML parser context
* @...: extra parameters for the message display
*
* Display and format a fatalError messages, gives file, line, position and
* extra parameters.
*/
static void XMLCDECL
{
callbacks++;
if (quiet)
return;
}
1,
NULL,
NULL,
NULL,
};
/*
* SAX2 specific callbacks
*/
/**
* startElementNsDebug:
* @ctxt: An XML parser context
* @name: The element name
*
* called when an opening tag has been processed.
*/
static void
int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int nb_defaulted,
const xmlChar **attributes)
{
int i;
callbacks++;
if (quiet)
return;
else
else
if (namespaces != NULL) {
for (i = 0;i < nb_namespaces * 2;i++) {
if (namespaces[i] != NULL)
i++;
}
}
if (attributes != NULL) {
else
}
}
}
/**
* endElementDebug:
* @ctxt: An XML parser context
* @name: The element name
*
* called when the end of an element has been detected.
*/
static void
{
callbacks++;
if (quiet)
return;
else
else
}
NULL,
NULL,
NULL,
};
/************************************************************************
* *
* Debug *
* *
************************************************************************/
static void
int res;
#ifdef LIBXML_PUSH_ENABLED
if (push) {
FILE *f;
/*
* Empty callbacks for checking
*/
#else
#endif
if (f != NULL) {
int ret;
if (ret > 0) {
}
}
fclose(f);
} else {
"Cannot read file %s\n", filename);
}
}
/*
* Debug callback
*/
#else
#endif
if (f != NULL) {
int ret;
if (ret > 0) {
if (sax2)
else
}
if (ret != 0) {
"xmlSAXUserParseFile returned error %d\n", ret);
}
}
fclose(f);
}
} else {
#endif /* LIBXML_PUSH_ENABLED */
if (!speed) {
/*
* Empty callbacks for checking
*/
if (res != 0) {
}
}
/*
* Debug callback
*/
callbacks = 0;
if (repeat) {
int i;
for (i = 0;i < 99;i++) {
if (sax2)
filename);
else
filename);
}
}
if (sax2)
else
if (res != 0) {
}
if (quiet)
} else {
/*
* test 100x the SAX parse
*/
int i;
for (i = 0; i<100;i++)
if (res != 0) {
}
}
#ifdef LIBXML_PUSH_ENABLED
}
#endif
}
int i;
int files = 0;
LIBXML_TEST_VERSION /* be safe, plus calls xmlInitParser */
for (i = 1; i < argc ; i++) {
debug++;
copy++;
recovery++;
#ifdef LIBXML_PUSH_ENABLED
push++;
#else
#endif /* LIBXML_PUSH_ENABLED */
speed++;
nonull++;
timing++;
quiet++;
repeat++;
quiet++;
noent++;
quiet++;
sax2++;
nonull++;
}
for (i = 1; i < argc ; i++) {
if (argv[i][0] != '-') {
if (timing) {
startTimer();
}
parseAndPrintFile(argv[i]);
if (timing) {
endTimer("Parsing");
}
files ++;
}
}
return(0);
}
#else
return(0);
}
#endif /* LIBXML_SAX1_ENABLED */