Reformatted on Windows, then re-committed to CVS
diff --git a/runtest.c b/runtest.c
index b05bfe6..1923dc1 100644
--- a/runtest.c
+++ b/runtest.c
@@ -1,4222 +1,4222 @@
-/*

- * runtest.c: C program to run libxml2 regression tests without

- *            requiring make or Python, and reducing platform dependancies

- *            to a strict minimum.

- *

- * To compile on Unixes:

- * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread

- *

- * See Copyright for the status of this software.

- *

- * daniel@veillard.com

- */

-

-#if !defined(_WIN32) || defined(__CYGWIN__)

-#include <unistd.h>

-#endif

-#include <string.h>

-#include <stdio.h>

-#include <sys/types.h>

-#include <sys/stat.h>

-#include <fcntl.h>

-

-#include <libxml/parser.h>

-#include <libxml/tree.h>

-#include <libxml/uri.h>

-

-#ifdef LIBXML_OUTPUT_ENABLED

-#ifdef LIBXML_READER_ENABLED

-#include <libxml/xmlreader.h>

-#endif

-

-#ifdef LIBXML_XINCLUDE_ENABLED

-#include <libxml/xinclude.h>

-#endif

-

-#ifdef LIBXML_XPATH_ENABLED

-#include <libxml/xpath.h>

-#include <libxml/xpathInternals.h>

-#ifdef LIBXML_XPTR_ENABLED

-#include <libxml/xpointer.h>

-#endif

-#endif

-

-#ifdef LIBXML_SCHEMAS_ENABLED

-#include <libxml/relaxng.h>

-#include <libxml/xmlschemas.h>

-#include <libxml/xmlschemastypes.h>

-#endif

-

-#ifdef LIBXML_PATTERN_ENABLED

-#include <libxml/pattern.h>

-#endif

-

-#ifdef LIBXML_C14N_ENABLED

-#include <libxml/c14n.h>

-#endif

-

-#ifdef LIBXML_HTML_ENABLED

-#include <libxml/HTMLparser.h>

-#include <libxml/HTMLtree.h>

-

-/*

- * pseudo flag for the unification of HTML and XML tests

- */

-#define XML_PARSE_HTML 1 << 24

-#endif

-

-#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)

-#include <libxml/globals.h>

-#include <libxml/threads.h>

-#include <libxml/parser.h>

-#include <libxml/catalog.h>

-#include <string.h>

-#endif

-

-/*

- * O_BINARY is just for Windows compatibility - if it isn't defined

- * on this system, avoid any compilation error

- */

-#ifdef	O_BINARY

-#define RD_FLAGS	O_RDONLY | O_BINARY

-#else

-#define	RD_FLAGS	O_RDONLY

-#endif

-

-typedef int (*functest) (const char *filename, const char *result,

-                         const char *error, int options);

-

-typedef struct testDesc testDesc;

-typedef testDesc *testDescPtr;

-struct testDesc {

-    const char *desc; /* descripton of the test */

-    functest    func; /* function implementing the test */

-    const char *in;   /* glob to path for input files */

-    const char *out;  /* output directory */

-    const char *suffix;/* suffix for output files */

-    const char *err;  /* suffix for error output files */

-    int     options;  /* parser options for the test */

-};

-

-static int checkTestFile(const char *filename);

-

-#if defined(_WIN32) && !defined(__CYGWIN__)

-

-#include <windows.h>

-#include <io.h>

-

-typedef struct

-{

-      size_t gl_pathc;    /* Count of paths matched so far  */

-      char **gl_pathv;    /* List of matched pathnames.  */

-      size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */

-} glob_t;

-

-#define GLOB_DOOFFS 0

-static int glob(const char *pattern, int flags,

-                int errfunc(const char *epath, int eerrno),

-                glob_t *pglob) {

-    glob_t *ret;

-    WIN32_FIND_DATA FindFileData;

-    HANDLE hFind;

-    unsigned int nb_paths = 0;

-    char directory[500];

-    int len;

-

-    if ((pattern == NULL) || (pglob == NULL)) return(-1);

-    

-    strncpy(directory, pattern, 499);

-    for (len = strlen(directory);len >= 0;len--) {

-        if (directory[len] == '/') {

-	    len++;

-	    directory[len] = 0;

-	    break;

-	}

-    }

-    if (len <= 0)

-        len = 0;

-

-    

-    ret = pglob;

-    memset(ret, 0, sizeof(glob_t));

-    

-    hFind = FindFirstFileA(pattern, &FindFileData);

-    if (hFind == INVALID_HANDLE_VALUE) 

-        return(0);

-    nb_paths = 20;

-    ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));

-    if (ret->gl_pathv == NULL) {

-	FindClose(hFind);

-        return(-1);

-    }

-    strncpy(directory + len, FindFileData.cFileName, 499 - len);

-    ret->gl_pathv[ret->gl_pathc] = strdup(directory);

-    if (ret->gl_pathv[ret->gl_pathc] == NULL)

-        goto done;

-    ret->gl_pathc++;

-    while(FindNextFileA(hFind, &FindFileData)) {

-        if (FindFileData.cFileName[0] == '.')

-	    continue;

-        if (ret->gl_pathc + 2 > nb_paths) {

-            char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));

-            if (tmp == NULL)

-                break;

-            ret->gl_pathv = tmp;

-            nb_paths *= 2;

-	}

-	strncpy(directory + len, FindFileData.cFileName, 499 - len);

-	ret->gl_pathv[ret->gl_pathc] = strdup(directory);

-        if (ret->gl_pathv[ret->gl_pathc] == NULL)

-            break;

-        ret->gl_pathc++;

-    }

-    ret->gl_pathv[ret->gl_pathc] = NULL;

-

-done:

-    FindClose(hFind);

-    return(0);

-}

- 

-

-

-static void globfree(glob_t *pglob) {

-    unsigned int i;

-    if (pglob == NULL)

-        return;

-    

-    for (i = 0;i < pglob->gl_pathc;i++) {

-         if (pglob->gl_pathv[i] != NULL)

-             free(pglob->gl_pathv[i]);

-    }

-}

-#define vsnprintf _vsnprintf

-#define snprintf _snprintf

-#else

-#include <glob.h>

-#endif

-

-/************************************************************************

- *									*

- *		Libxml2 specific routines				*

- *									*

- ************************************************************************/

-

-static int nb_tests = 0;

-static int nb_errors = 0;

-static int nb_leaks = 0;

-static long libxmlMemoryAllocatedBase = 0;

-static int extraMemoryFromResolver = 0;

-

-static int

-fatalError(void) {

-    fprintf(stderr, "Exitting tests on fatal error\n");

-    exit(1);

-}

-

-/*

- * We need to trap calls to the resolver to not account memory for the catalog

- * which is shared to the current running test. We also don't want to have

- * network downloads modifying tests.

- */

-static xmlParserInputPtr 

-testExternalEntityLoader(const char *URL, const char *ID,

-			 xmlParserCtxtPtr ctxt) {

-    xmlParserInputPtr ret;

-

-    if (checkTestFile(URL)) {

-	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);

-    } else {

-	int memused = xmlMemUsed();

-	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);

-	extraMemoryFromResolver += xmlMemUsed() - memused;

-    }

-      

-    return(ret);

-}

-

-/*

- * Trapping the error messages at the generic level to grab the equivalent of

- * stderr messages on CLI tools.

- */

-static char testErrors[32769];

-static int testErrorsSize = 0;

-

-static void

-testErrorHandler(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {

-    va_list args;

-    int res;

-

-    if (testErrorsSize >= 32768)

-        return;

-    va_start(args, msg);

-    res = vsnprintf(&testErrors[testErrorsSize],

-                    32768 - testErrorsSize,

-		    msg, args);

-    va_end(args);

-    if (testErrorsSize + res >= 32768) {

-        /* buffer is full */

-	testErrorsSize = 32768;

-	testErrors[testErrorsSize] = 0;

-    } else {

-        testErrorsSize += res;

-    }

-    testErrors[testErrorsSize] = 0;

-}

-

-static void

-channel(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {

-    va_list args;

-    int res;

-

-    if (testErrorsSize >= 32768)

-        return;

-    va_start(args, msg);

-    res = vsnprintf(&testErrors[testErrorsSize],

-                    32768 - testErrorsSize,

-		    msg, args);

-    va_end(args);

-    if (testErrorsSize + res >= 32768) {

-        /* buffer is full */

-	testErrorsSize = 32768;

-	testErrors[testErrorsSize] = 0;

-    } else {

-        testErrorsSize += res;

-    }

-    testErrors[testErrorsSize] = 0;

-}

-

-/**

- * xmlParserPrintFileContext:

- * @input:  an xmlParserInputPtr input

- * 

- * Displays current context within the input content for error tracking

- */

-

-static void

-xmlParserPrintFileContextInternal(xmlParserInputPtr input , 

-		xmlGenericErrorFunc chanl, void *data ) {

-    const xmlChar *cur, *base;

-    unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */

-    xmlChar  content[81]; /* space for 80 chars + line terminator */

-    xmlChar *ctnt;

-

-    if (input == NULL) return;

-    cur = input->cur;

-    base = input->base;

-    /* skip backwards over any end-of-lines */

-    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {

-	cur--;

-    }

-    n = 0;

-    /* search backwards for beginning-of-line (to max buff size) */

-    while ((n++ < (sizeof(content)-1)) && (cur > base) && 

-    	   (*(cur) != '\n') && (*(cur) != '\r'))

-        cur--;

-    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;

-    /* calculate the error position in terms of the current position */

-    col = input->cur - cur;

-    /* search forward for end-of-line (to max buff size) */

-    n = 0;

-    ctnt = content;

-    /* copy selected text to our buffer */

-    while ((*cur != 0) && (*(cur) != '\n') && 

-    	   (*(cur) != '\r') && (n < sizeof(content)-1)) {

-		*ctnt++ = *cur++;

-	n++;

-    }

-    *ctnt = 0;

-    /* print out the selected text */

-    chanl(data ,"%s\n", content);

-    /* create blank line with problem pointer */

-    n = 0;

-    ctnt = content;

-    /* (leave buffer space for pointer + line terminator) */

-    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {

-	if (*(ctnt) != '\t')

-	    *(ctnt) = ' ';

-	ctnt++;

-    }

-    *ctnt++ = '^';

-    *ctnt = 0;

-    chanl(data ,"%s\n", content);

-}

-

-static void

-testStructuredErrorHandler(void *ctx  ATTRIBUTE_UNUSED, xmlErrorPtr err) {

-    char *file = NULL;

-    int line = 0;

-    int code = -1;

-    int domain;

-    void *data = NULL;

-    const char *str;

-    const xmlChar *name = NULL;

-    xmlNodePtr node;

-    xmlErrorLevel level;

-    xmlParserInputPtr input = NULL;

-    xmlParserInputPtr cur = NULL;

-    xmlParserCtxtPtr ctxt = NULL;

-

-    if (err == NULL)

-        return;

-

-    file = err->file;

-    line = err->line;

-    code = err->code;

-    domain = err->domain;

-    level = err->level;

-    node = err->node;

-    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||

-        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||

-	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {

-	ctxt = err->ctxt;

-    }

-    str = err->message;

-

-    if (code == XML_ERR_OK)

-        return;

-

-    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))

-        name = node->name;

-

-    /*

-     * Maintain the compatibility with the legacy error handling

-     */

-    if (ctxt != NULL) {

-        input = ctxt->input;

-        if ((input != NULL) && (input->filename == NULL) &&

-            (ctxt->inputNr > 1)) {

-            cur = input;

-            input = ctxt->inputTab[ctxt->inputNr - 2];

-        }

-        if (input != NULL) {

-            if (input->filename)

-                channel(data, "%s:%d: ", input->filename, input->line);

-            else if ((line != 0) && (domain == XML_FROM_PARSER))

-                channel(data, "Entity: line %d: ", input->line);

-        }

-    } else {

-        if (file != NULL)

-            channel(data, "%s:%d: ", file, line);

-        else if ((line != 0) && (domain == XML_FROM_PARSER))

-            channel(data, "Entity: line %d: ", line);

-    }

-    if (name != NULL) {

-        channel(data, "element %s: ", name);

-    }

-    if (code == XML_ERR_OK)

-        return;

-    switch (domain) {

-        case XML_FROM_PARSER:

-            channel(data, "parser ");

-            break;

-        case XML_FROM_NAMESPACE:

-            channel(data, "namespace ");

-            break;

-        case XML_FROM_DTD:

-        case XML_FROM_VALID:

-            channel(data, "validity ");

-            break;

-        case XML_FROM_HTML:

-            channel(data, "HTML parser ");

-            break;

-        case XML_FROM_MEMORY:

-            channel(data, "memory ");

-            break;

-        case XML_FROM_OUTPUT:

-            channel(data, "output ");

-            break;

-        case XML_FROM_IO:

-            channel(data, "I/O ");

-            break;

-        case XML_FROM_XINCLUDE:

-            channel(data, "XInclude ");

-            break;

-        case XML_FROM_XPATH:

-            channel(data, "XPath ");

-            break;

-        case XML_FROM_XPOINTER:

-            channel(data, "parser ");

-            break;

-        case XML_FROM_REGEXP:

-            channel(data, "regexp ");

-            break;

-        case XML_FROM_MODULE:

-            channel(data, "module ");

-            break;

-        case XML_FROM_SCHEMASV:

-            channel(data, "Schemas validity ");

-            break;

-        case XML_FROM_SCHEMASP:

-            channel(data, "Schemas parser ");

-            break;

-        case XML_FROM_RELAXNGP:

-            channel(data, "Relax-NG parser ");

-            break;

-        case XML_FROM_RELAXNGV:

-            channel(data, "Relax-NG validity ");

-            break;

-        case XML_FROM_CATALOG:

-            channel(data, "Catalog ");

-            break;

-        case XML_FROM_C14N:

-            channel(data, "C14N ");

-            break;

-        case XML_FROM_XSLT:

-            channel(data, "XSLT ");

-            break;

-        default:

-            break;

-    }

-    if (code == XML_ERR_OK)

-        return;

-    switch (level) {

-        case XML_ERR_NONE:

-            channel(data, ": ");

-            break;

-        case XML_ERR_WARNING:

-            channel(data, "warning : ");

-            break;

-        case XML_ERR_ERROR:

-            channel(data, "error : ");

-            break;

-        case XML_ERR_FATAL:

-            channel(data, "error : ");

-            break;

-    }

-    if (code == XML_ERR_OK)

-        return;

-    if (str != NULL) {

-        int len;

-	len = xmlStrlen((const xmlChar *)str);

-	if ((len > 0) && (str[len - 1] != '\n'))

-	    channel(data, "%s\n", str);

-	else

-	    channel(data, "%s", str);

-    } else {

-        channel(data, "%s\n", "out of memory error");

-    }

-    if (code == XML_ERR_OK)

-        return;

-

-    if (ctxt != NULL) {

-        xmlParserPrintFileContextInternal(input, channel, data);

-        if (cur != NULL) {

-            if (cur->filename)

-                channel(data, "%s:%d: \n", cur->filename, cur->line);

-            else if ((line != 0) && (domain == XML_FROM_PARSER))

-                channel(data, "Entity: line %d: \n", cur->line);

-            xmlParserPrintFileContextInternal(cur, channel, data);

-        }

-    }

-    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&

-        (err->int1 < 100) &&

-	(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {

-	xmlChar buf[150];

-	int i;

-

-	channel(data, "%s\n", err->str1);

-	for (i=0;i < err->int1;i++)

-	     buf[i] = ' ';

-	buf[i++] = '^';

-	buf[i] = 0;

-	channel(data, "%s\n", buf);

-    }

-}

-

-static void

-initializeLibxml2(void) {

-    xmlGetWarningsDefaultValue = 0;

-    xmlPedanticParserDefault(0);

-

-    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);

-    xmlInitParser();

-    xmlSetExternalEntityLoader(testExternalEntityLoader);

-    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);

-#ifdef LIBXML_SCHEMAS_ENABLED

-    xmlSchemaInitTypes();

-    xmlRelaxNGInitTypes();

-#endif

-    libxmlMemoryAllocatedBase = xmlMemUsed();

-}

-

-

-/************************************************************************

- *									*

- *		File name and path utilities				*

- *									*

- ************************************************************************/

-

-static const char *baseFilename(const char *filename) {

-    const char *cur;

-    if (filename == NULL)

-        return(NULL);

-    cur = &filename[strlen(filename)];

-    while ((cur > filename) && (*cur != '/'))

-        cur--;

-    if (*cur == '/')

-        return(cur + 1);

-    return(cur);

-}

-

-static char *resultFilename(const char *filename, const char *out,

-                            const char *suffix) {

-    const char *base;

-    char res[500];

-

-/*************

-    if ((filename[0] == 't') && (filename[1] == 'e') &&

-        (filename[2] == 's') && (filename[3] == 't') &&

-	(filename[4] == '/'))

-	filename = &filename[5];

- *************/

-    

-    base = baseFilename(filename);

-    if (suffix == NULL)

-        suffix = ".tmp";

-    if (out == NULL)

-        out = "";

-    snprintf(res, 499, "%s%s%s", out, base, suffix);

-    res[499] = 0;

-    return(strdup(res));

-}

-

-static int checkTestFile(const char *filename) {

-    struct stat buf;

-

-    if (stat(filename, &buf) == -1)

-        return(0);

-

-#if defined(_WIN32) && !defined(__CYGWIN__)

-    if (!(buf.st_mode & _S_IFREG))

-        return(0);

-#else

-    if (!S_ISREG(buf.st_mode))

-        return(0);

-#endif

-

-    return(1);

-}

-

-static int compareFiles(const char *r1, const char *r2) {

-    int res1, res2;

-    int fd1, fd2;

-    char bytes1[4096];

-    char bytes2[4096];

-

-    fd1 = open(r1, RD_FLAGS);

-    if (fd1 < 0)

-        return(-1);

-    fd2 = open(r2, RD_FLAGS);

-    if (fd2 < 0) {

-        close(fd1);

-        return(-1);

-    }

-    while (1) {

-        res1 = read(fd1, bytes1, 4096);

-        res2 = read(fd2, bytes2, 4096);

-	if (res1 != res2) {

-	    close(fd1);

-	    close(fd2);

-	    return(1);

-	}

-	if (res1 == 0)

-	    break;

-	if (memcmp(bytes1, bytes2, res1) != 0) {

-	    close(fd1);

-	    close(fd2);

-	    return(1);

-	}

-    }

-    close(fd1);

-    close(fd2);

-    return(0);

-}

-

-static int compareFileMem(const char *filename, const char *mem, int size) {

-    int res;

-    int fd;

-    char bytes[4096];

-    int idx = 0;

-    struct stat info;

-

-    if (stat(filename, &info) < 0) 

-	return(-1);

-    if (info.st_size != size)

-        return(-1);

-    fd = open(filename, RD_FLAGS);

-    if (fd < 0)

-        return(-1);

-    while (idx < size) {

-        res = read(fd, bytes, 4096);

-	if (res <= 0)

-	    break;

-	if (res + idx > size) 

-	    break;

-	if (memcmp(bytes, &mem[idx], res) != 0) {

-	    int ix;

-	    for (ix=0; ix<res; ix++)

-		if (bytes[ix] != mem[idx+ix])

-			break;

-	    fprintf(stderr,"Compare error at position %d\n", idx+ix);

-	    close(fd);

-	    return(1);

-	}

-	idx += res;

-    }

-    close(fd);

-    return(idx != size);

-}

-

-static int loadMem(const char *filename, const char **mem, int *size) {

-    int fd, res;

-    struct stat info;

-    char *base;

-    int siz = 0;

-    if (stat(filename, &info) < 0) 

-	return(-1);

-    base = malloc(info.st_size + 1);

-    if (base == NULL)

-	return(-1);

-    if ((fd = open(filename, RD_FLAGS)) < 0) {

-        free(base);

-	return(-1);

-    }

-    while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {

-        siz += res;

-    }

-    close(fd);

-#if !defined(_WIN32)

-    if (siz != info.st_size) {

-        free(base);

-	return(-1);

-    }

-#endif

-    base[siz] = 0;

-    *mem = base;

-    *size = siz;

-    return(0);

-}

-

-static int unloadMem(const char *mem) {

-    free((char *)mem);

-    return(0);

-}

-

-/************************************************************************

- *									*

- *		Tests implementations					*

- *									*

- ************************************************************************/

-

-/************************************************************************

- *									*

- *		Parse to SAX based tests				*

- *									*

- ************************************************************************/

-

-FILE *SAXdebug = NULL;

-

-/*

- * 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 */

-};

-

-static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;

-int callbacks = 0;

-int quiet = 0;

-

-/**

- * 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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.internalSubset(%s,", name);

-    if (ExternalID == NULL)

-	fprintf(SAXdebug, " ,");

-    else

-	fprintf(SAXdebug, " %s,", ExternalID);

-    if (SystemID == NULL)

-	fprintf(SAXdebug, " )\n");

-    else

-	fprintf(SAXdebug, " %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(SAXdebug, "SAX.externalSubset(%s,", name);

-    if (ExternalID == NULL)

-	fprintf(SAXdebug, " ,");

-    else

-	fprintf(SAXdebug, " %s,", ExternalID);

-    if (SystemID == NULL)

-	fprintf(SAXdebug, " )\n");

-    else

-	fprintf(SAXdebug, " %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(SAXdebug, "SAX.resolveEntity(");

-    if (publicId != NULL)

-	fprintf(SAXdebug, "%s", (char *)publicId);

-    else

-	fprintf(SAXdebug, " ");

-    if (systemId != NULL)

-	fprintf(SAXdebug, ", %s)\n", (char *)systemId);

-    else

-	fprintf(SAXdebug, ", )\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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",

-                elem, name, type, def);

-    else

-        fprintf(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.startElement(%s", (char *) name);

-    if (atts != NULL) {

-        for (i = 0;(atts[i] != NULL);i++) {

-	    fprintf(SAXdebug, ", %s='", atts[i++]);

-	    if (atts[i] != NULL)

-	        fprintf(SAXdebug, "%s'", atts[i]);

-	}

-    }

-    fprintf(SAXdebug, ")\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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.processingInstruction(%s, %s)\n",

-		(char *) target, (char *) data);

-    else

-	fprintf(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.warning: ");

-    vfprintf(SAXdebug, 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(SAXdebug, "SAX.error: ");

-    vfprintf(SAXdebug, 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(SAXdebug, "SAX.fatalError: ");

-    vfprintf(SAXdebug, 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(SAXdebug, "SAX.startElementNs(%s", (char *) localname);

-    if (prefix == NULL)

-	fprintf(SAXdebug, ", NULL");

-    else

-	fprintf(SAXdebug, ", %s", (char *) prefix);

-    if (URI == NULL)

-	fprintf(SAXdebug, ", NULL");

-    else

-	fprintf(SAXdebug, ", '%s'", (char *) URI);

-    fprintf(SAXdebug, ", %d", nb_namespaces);

-    

-    if (namespaces != NULL) {

-        for (i = 0;i < nb_namespaces * 2;i++) {

-	    fprintf(SAXdebug, ", xmlns");

-	    if (namespaces[i] != NULL)

-	        fprintf(SAXdebug, ":%s", namespaces[i]);

-	    i++;

-	    fprintf(SAXdebug, "='%s'", namespaces[i]);

-	}

-    }

-    fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);

-    if (attributes != NULL) {

-        for (i = 0;i < nb_attributes * 5;i += 5) {

-	    if (attributes[i + 1] != NULL)

-		fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);

-	    else

-		fprintf(SAXdebug, ", %s='", attributes[i]);

-	    fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],

-		    (int)(attributes[i + 4] - attributes[i + 3]));

-	}

-    }

-    fprintf(SAXdebug, ")\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(SAXdebug, "SAX.endElementNs(%s", (char *) localname);

-    if (prefix == NULL)

-	fprintf(SAXdebug, ", NULL");

-    else

-	fprintf(SAXdebug, ", %s", (char *) prefix);

-    if (URI == NULL)

-	fprintf(SAXdebug, ", NULL)\n");

-    else

-	fprintf(SAXdebug, ", '%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;

-

-#ifdef LIBXML_HTML_ENABLED

-/**

- * htmlstartElementDebug:

- * @ctxt:  An XML parser context

- * @name:  The element name

- *

- * called when an opening tag has been processed.

- */

-static void

-htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)

-{

-    int i;

-

-    fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);

-    if (atts != NULL) {

-        for (i = 0;(atts[i] != NULL);i++) {

-	    fprintf(SAXdebug, ", %s", atts[i++]);

-	    if (atts[i] != NULL) {

-		unsigned char output[40];

-		const unsigned char *att = atts[i];

-		int outlen, attlen;

-	        fprintf(SAXdebug, "='");

-		while ((attlen = strlen((char*)att)) > 0) {

-		    outlen = sizeof output - 1;

-		    htmlEncodeEntities(output, &outlen, att, &attlen, '\'');

-		    output[outlen] = 0;

-		    fprintf(SAXdebug, "%s", (char *) output);

-		    att += attlen;

-		}

-		fprintf(SAXdebug, "'");

-	    }

-	}

-    }

-    fprintf(SAXdebug, ")\n");

-}

-

-/**

- * htmlcharactersDebug:

- * @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

-htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)

-{

-    unsigned char output[40];

-    int inlen = len, outlen = 30;

-

-    htmlEncodeEntities(output, &outlen, ch, &inlen, 0);

-    output[outlen] = 0;

-

-    fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);

-}

-

-/**

- * htmlcdataDebug:

- * @ctxt:  An XML parser context

- * @ch:  a xmlChar string

- * @len: the number of xmlChar

- *

- * receiving some cdata chars from the parser.

- * Question: how much at a time ???

- */

-static void

-htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)

-{

-    unsigned char output[40];

-    int inlen = len, outlen = 30;

-

-    htmlEncodeEntities(output, &outlen, ch, &inlen, 0);

-    output[outlen] = 0;

-

-    fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);

-}

-

-xmlSAXHandler debugHTMLSAXHandlerStruct = {

-    internalSubsetDebug,

-    isStandaloneDebug,

-    hasInternalSubsetDebug,

-    hasExternalSubsetDebug,

-    resolveEntityDebug,

-    getEntityDebug,

-    entityDeclDebug,

-    notationDeclDebug,

-    attributeDeclDebug,

-    elementDeclDebug,

-    unparsedEntityDeclDebug,

-    setDocumentLocatorDebug,

-    startDocumentDebug,

-    endDocumentDebug,

-    htmlstartElementDebug,

-    endElementDebug,

-    referenceDebug,

-    htmlcharactersDebug,

-    ignorableWhitespaceDebug,

-    processingInstructionDebug,

-    commentDebug,

-    warningDebug,

-    errorDebug,

-    fatalErrorDebug,

-    getParameterEntityDebug,

-    htmlcdataDebug,

-    externalSubsetDebug,

-    1,

-    NULL,

-    NULL,

-    NULL,

-    NULL

-};

-

-xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;

-#endif /* LIBXML_HTML_ENABLED */

-

-#ifdef LIBXML_SAX1_ENABLED

-/**

- * saxParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file using the SAX API and check for errors.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-saxParseTest(const char *filename, const char *result,

-             const char *err ATTRIBUTE_UNUSED,

-             int options) {

-    int ret;

-    char *temp;

-

-    nb_tests++;

-    temp = resultFilename(filename, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "out of memory\n");

-        fatalError();

-    }

-    SAXdebug = fopen(temp, "wb");

-    if (SAXdebug == NULL) {

-        fprintf(stderr, "Failed to write to %s\n", temp);

-	free(temp);

-	return(-1);

-    }

-

-    /* for SAX we really want the callbacks though the context handlers */

-    xmlSetStructuredErrorFunc(NULL, NULL);

-    xmlSetGenericErrorFunc(NULL, testErrorHandler);

-

-#ifdef LIBXML_HTML_ENABLED

-    if (options & XML_PARSE_HTML) {

-	htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);

-	ret = 0;

-    } else

-#endif

-    ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);

-    if (ret == XML_WAR_UNDECLARED_ENTITY) {

-        fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);

-        ret = 0;

-    }

-    if (ret != 0) {

-        fprintf(stderr, "Failed to parse %s\n", filename);

-	return(1);

-    }

-#ifdef LIBXML_HTML_ENABLED

-    if (options & XML_PARSE_HTML) {

-	htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);

-	ret = 0;

-    } else

-#endif

-    if (options & XML_PARSE_SAX1) {

-	ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);

-    } else {

-	ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);

-    }

-    if (ret == XML_WAR_UNDECLARED_ENTITY) {

-        fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);

-        ret = 0;

-    }

-    fclose(SAXdebug);

-    if (compareFiles(temp, result)) {

-        fprintf(stderr, "Got a difference for %s\n", filename);

-        ret = 1;

-    } else

-    unlink(temp);

-    free(temp);

-    

-    /* switch back to structured error handling */

-    xmlSetGenericErrorFunc(NULL, NULL);

-    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);

-

-    return(ret);

-}

-#endif

-

-/************************************************************************

- *									*

- *		Parse to tree based tests				*

- *									*

- ************************************************************************/

-/**

- * oldParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages: unused

- *

- * Parse a file using the old xmlParseFile API, then serialize back

- * reparse the result and serialize again, then check for deviation

- * in serialization.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-oldParseTest(const char *filename, const char *result,

-             const char *err ATTRIBUTE_UNUSED,

-	     int options ATTRIBUTE_UNUSED) {

-    xmlDocPtr doc;

-    char *temp;

-    int res = 0;

-

-    nb_tests++;

-    /*

-     * base of the test, parse with the old API

-     */

-#ifdef LIBXML_SAX1_ENABLED

-    doc = xmlParseFile(filename);

-#else

-    doc = xmlReadFile(filename, NULL, 0);

-#endif

-    if (doc == NULL)

-        return(1);

-    temp = resultFilename(filename, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "out of memory\n");

-        fatalError();

-    }

-    xmlSaveFile(temp, doc);

-    if (compareFiles(temp, result)) {

-        res = 1;

-    }

-    xmlFreeDoc(doc);

-

-    /*

-     * Parse the saved result to make sure the round trip is okay

-     */

-#ifdef LIBXML_SAX1_ENABLED

-    doc = xmlParseFile(temp);

-#else

-    doc = xmlReadFile(temp, NULL, 0);

-#endif

-    if (doc == NULL)

-        return(1);

-    xmlSaveFile(temp, doc);

-    if (compareFiles(temp, result)) {

-        res = 1;

-    }

-    xmlFreeDoc(doc);

-

-    unlink(temp);

-    free(temp);

-    return(res);

-}

-

-#ifdef LIBXML_PUSH_ENABLED

-/**

- * pushParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages: unused

- *

- * Parse a file using the Push API, then serialize back

- * to check for content.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-pushParseTest(const char *filename, const char *result,

-             const char *err ATTRIBUTE_UNUSED,

-	     int options) {

-    xmlParserCtxtPtr ctxt;

-    xmlDocPtr doc;

-    const char *base;

-    int size, res;

-    int cur = 0;

-

-    nb_tests++;

-    /*

-     * load the document in memory and work from there.

-     */

-    if (loadMem(filename, &base, &size) != 0) {

-        fprintf(stderr, "Failed to load %s\n", filename);

-	return(-1);

-    }

-    

-#ifdef LIBXML_HTML_ENABLED

-    if (options & XML_PARSE_HTML)

-	ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,

-	                                XML_CHAR_ENCODING_NONE);

-    else

-#endif

-    ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);

-    xmlCtxtUseOptions(ctxt, options);

-    cur += 4;

-    while (cur < size) {

-        if (cur + 1024 >= size) {

-#ifdef LIBXML_HTML_ENABLED

-	    if (options & XML_PARSE_HTML)

-		htmlParseChunk(ctxt, base + cur, size - cur, 1);

-	    else

-#endif

-	    xmlParseChunk(ctxt, base + cur, size - cur, 1);

-	    break;

-	} else {

-#ifdef LIBXML_HTML_ENABLED

-	    if (options & XML_PARSE_HTML)

-		htmlParseChunk(ctxt, base + cur, 1024, 0);

-	    else

-#endif

-	    xmlParseChunk(ctxt, base + cur, 1024, 0);

-	    cur += 1024;

-	}

-    }

-    doc = ctxt->myDoc;

-#ifdef LIBXML_HTML_ENABLED

-    if (options & XML_PARSE_HTML)

-        res = 1;

-    else

-#endif

-    res = ctxt->wellFormed;

-    xmlFreeParserCtxt(ctxt);

-    free((char *)base);

-    if (!res) {

-	xmlFreeDoc(doc);

-	fprintf(stderr, "Failed to parse %s\n", filename);

-	return(-1);

-    }

-#ifdef LIBXML_HTML_ENABLED

-    if (options & XML_PARSE_HTML)

-	htmlDocDumpMemory(doc, (xmlChar **) &base, &size);

-    else

-#endif

-    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);

-    xmlFreeDoc(doc);

-    res = compareFileMem(result, base, size);

-    if ((base == NULL) || (res != 0)) {

-	if (base != NULL)

-	    xmlFree((char *)base);

-        fprintf(stderr, "Result for %s failed\n", filename);

-	return(-1);

-    }

-    xmlFree((char *)base);

-    if (err != NULL) {

-	res = compareFileMem(err, testErrors, testErrorsSize);

-	if (res != 0) {

-	    fprintf(stderr, "Error for %s failed\n", filename);

-	    return(-1);

-	}

-    }

-    return(0);

-}

-#endif

-

-/**

- * memParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages: unused

- *

- * Parse a file using the old xmlReadMemory API, then serialize back

- * reparse the result and serialize again, then check for deviation

- * in serialization.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-memParseTest(const char *filename, const char *result,

-             const char *err ATTRIBUTE_UNUSED,

-	     int options ATTRIBUTE_UNUSED) {

-    xmlDocPtr doc;

-    const char *base;

-    int size, res;

-

-    nb_tests++;

-    /*

-     * load and parse the memory

-     */

-    if (loadMem(filename, &base, &size) != 0) {

-        fprintf(stderr, "Failed to load %s\n", filename);

-	return(-1);

-    }

-    

-    doc = xmlReadMemory(base, size, filename, NULL, 0);

-    unloadMem(base);

-    if (doc == NULL) {

-        return(1);

-    }

-    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);

-    xmlFreeDoc(doc);

-    res = compareFileMem(result, base, size);

-    if ((base == NULL) || (res != 0)) {

-	if (base != NULL)

-	    xmlFree((char *)base);

-        fprintf(stderr, "Result for %s failed\n", filename);

-	return(-1);

-    }

-    xmlFree((char *)base);

-    return(0);

-}

-

-/**

- * noentParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages: unused

- *

- * Parse a file with entity resolution, then serialize back

- * reparse the result and serialize again, then check for deviation

- * in serialization.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-noentParseTest(const char *filename, const char *result,

-               const char *err  ATTRIBUTE_UNUSED,

-	       int options) {

-    xmlDocPtr doc;

-    char *temp;

-    int res = 0;

-

-    nb_tests++;

-    /*

-     * base of the test, parse with the old API

-     */

-    doc = xmlReadFile(filename, NULL, options);

-    if (doc == NULL)

-        return(1);

-    temp = resultFilename(filename, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "Out of memory\n");

-        fatalError();

-    }

-    xmlSaveFile(temp, doc);

-    if (compareFiles(temp, result)) {

-        res = 1;

-    }

-    xmlFreeDoc(doc);

-

-    /*

-     * Parse the saved result to make sure the round trip is okay

-     */

-    doc = xmlReadFile(filename, NULL, options);

-    if (doc == NULL)

-        return(1);

-    xmlSaveFile(temp, doc);

-    if (compareFiles(temp, result)) {

-        res = 1;

-    }

-    xmlFreeDoc(doc);

-

-    unlink(temp);

-    free(temp);

-    return(res);

-}

-

-/**

- * errParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file using the xmlReadFile API and check for errors.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-errParseTest(const char *filename, const char *result, const char *err,

-             int options) {

-    xmlDocPtr doc;

-    const char *base = NULL;

-    int size, res = 0;

-

-    nb_tests++;

-#ifdef LIBXML_HTML_ENABLED

-    if (options & XML_PARSE_HTML) {

-        doc = htmlReadFile(filename, NULL, options);

-    } else

-#endif

-#ifdef LIBXML_XINCLUDE_ENABLED

-    if (options & XML_PARSE_XINCLUDE) {

-	doc = xmlReadFile(filename, NULL, options);

-	xmlXIncludeProcessFlags(doc, options);

-    } else

-#endif

-    {

-	xmlGetWarningsDefaultValue = 1;

-	doc = xmlReadFile(filename, NULL, options);

-    }

-    xmlGetWarningsDefaultValue = 0;

-    if (result) {

-	if (doc == NULL) {

-	    base = "";

-	    size = 0;

-	} else {

-#ifdef LIBXML_HTML_ENABLED

-	    if (options & XML_PARSE_HTML) {

-		htmlDocDumpMemory(doc, (xmlChar **) &base, &size);

-	    } else

-#endif

-	    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);

-	}

-	res = compareFileMem(result, base, size);

-    }

-    if (doc != NULL) {

-	if (base != NULL)

-	    xmlFree((char *)base);

-	xmlFreeDoc(doc);

-    }

-    if (res != 0) {

-        fprintf(stderr, "Result for %s failed\n", filename);

-	return(-1);

-    }

-    if (err != NULL) {

-	res = compareFileMem(err, testErrors, testErrorsSize);

-	if (res != 0) {

-	    fprintf(stderr, "Error for %s failed\n", filename);

-	    return(-1);

-	}

-    } else if (options & XML_PARSE_DTDVALID) {

-        if (testErrorsSize != 0)

-	    fprintf(stderr, "Validation for %s failed\n", filename);

-    }

-

-    return(0);

-}

-

-#ifdef LIBXML_READER_ENABLED

-/************************************************************************

- *									*

- *		Reader based tests					*

- *									*

- ************************************************************************/

-

-static void processNode(FILE *out, xmlTextReaderPtr reader) {

-    const xmlChar *name, *value;

-    int type, empty;

-

-    type = xmlTextReaderNodeType(reader);

-    empty = xmlTextReaderIsEmptyElement(reader);

-

-    name = xmlTextReaderConstName(reader);

-    if (name == NULL)

-	name = BAD_CAST "--";

-

-    value = xmlTextReaderConstValue(reader);

-

-    

-    fprintf(out, "%d %d %s %d %d", 

-	    xmlTextReaderDepth(reader),

-	    type,

-	    name,

-	    empty,

-	    xmlTextReaderHasValue(reader));

-    if (value == NULL)

-	fprintf(out, "\n");

-    else {

-	fprintf(out, " %s\n", value);

-    }

-}

-static int

-streamProcessTest(const char *filename, const char *result, const char *err,

-                  xmlTextReaderPtr reader, const char *rng) {

-    int ret;

-    char *temp = NULL;

-    FILE *t = NULL;

-

-    if (reader == NULL)

-        return(-1);

-

-    nb_tests++;

-    if (result != NULL) {

-	temp = resultFilename(filename, "", ".res");

-	if (temp == NULL) {

-	    fprintf(stderr, "Out of memory\n");

-	    fatalError();

-	}

-	t = fopen(temp, "wb");

-	if (t == NULL) {

-	    fprintf(stderr, "Can't open temp file %s\n", temp);

-	    free(temp);

-	    return(-1);

-	}

-    }

-#ifdef LIBXML_SCHEMAS_ENABLED

-    if (rng != NULL) {

-	ret = xmlTextReaderRelaxNGValidate(reader, rng);

-	if (ret < 0) {

-	    testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",

-	                     rng);

-	    fclose(t);

-	    unlink(temp);

-	    free(temp);

-	    return(0);

-	}

-    }

-#endif

-    xmlGetWarningsDefaultValue = 1;

-    ret = xmlTextReaderRead(reader);

-    while (ret == 1) {

-	if ((t != NULL) && (rng == NULL))

-	    processNode(t, reader);

-        ret = xmlTextReaderRead(reader);

-    }

-    if (ret != 0) {

-        testErrorHandler(NULL, "%s : failed to parse\n", filename);

-    }

-    if (rng != NULL) {

-        if (xmlTextReaderIsValid(reader) != 1) {

-	    testErrorHandler(NULL, "%s fails to validate\n", filename);

-	} else {

-	    testErrorHandler(NULL, "%s validates\n", filename);

-	}

-    }

-    xmlGetWarningsDefaultValue = 0;

-    if (t != NULL) {

-        fclose(t);

-	ret = compareFiles(temp, result);

-	unlink(temp);

-	free(temp);

-	if (ret) {

-	    fprintf(stderr, "Result for %s failed\n", filename);

-	    return(-1);

-	}

-    }

-    if (err != NULL) {

-	ret = compareFileMem(err, testErrors, testErrorsSize);

-	if (ret != 0) {

-	    fprintf(stderr, "Error for %s failed\n", filename);

-	    printf("%s", testErrors);

-	    return(-1);

-	}

-    }

-

-    return(0);

-}

-

-/**

- * streamParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file using the reader API and check for errors.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-streamParseTest(const char *filename, const char *result, const char *err,

-                int options) {

-    xmlTextReaderPtr reader;

-    int ret;

-

-    reader = xmlReaderForFile(filename, NULL, options);

-    ret = streamProcessTest(filename, result, err, reader, NULL);

-    xmlFreeTextReader(reader);

-    return(ret);

-}

-

-/**

- * walkerParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file using the walker, i.e. a reader built from a atree.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-walkerParseTest(const char *filename, const char *result, const char *err,

-                int options) {

-    xmlDocPtr doc;

-    xmlTextReaderPtr reader;

-    int ret;

-

-    doc = xmlReadFile(filename, NULL, options);

-    if (doc == NULL) {

-        fprintf(stderr, "Failed to parse %s\n", filename);

-	return(-1);

-    }

-    reader = xmlReaderWalker(doc);

-    ret = streamProcessTest(filename, result, err, reader, NULL);

-    xmlFreeTextReader(reader);

-    xmlFreeDoc(doc);

-    return(ret);

-}

-

-/**

- * streamMemParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file using the reader API from memory and check for errors.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-streamMemParseTest(const char *filename, const char *result, const char *err,

-                   int options) {

-    xmlTextReaderPtr reader;

-    int ret;

-    const char *base;

-    int size;

-

-    /*

-     * load and parse the memory

-     */

-    if (loadMem(filename, &base, &size) != 0) {

-        fprintf(stderr, "Failed to load %s\n", filename);

-	return(-1);

-    }

-    reader = xmlReaderForMemory(base, size, filename, NULL, options);

-    ret = streamProcessTest(filename, result, err, reader, NULL);

-    free((char *)base);

-    xmlFreeTextReader(reader);

-    return(ret);

-}

-#endif

-

-#ifdef LIBXML_XPATH_ENABLED

-#ifdef LIBXML_DEBUG_ENABLED

-/************************************************************************

- *									*

- *		XPath and XPointer based tests				*

- *									*

- ************************************************************************/

-

-FILE *xpathOutput;

-xmlDocPtr xpathDocument;

-

-static void

-testXPath(const char *str, int xptr, int expr) {

-    xmlXPathObjectPtr res;

-    xmlXPathContextPtr ctxt;

-    

-    nb_tests++;

-#if defined(LIBXML_XPTR_ENABLED)

-    if (xptr) {

-	ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);

-	res = xmlXPtrEval(BAD_CAST str, ctxt);

-    } else {

-#endif

-	ctxt = xmlXPathNewContext(xpathDocument);

-	ctxt->node = xmlDocGetRootElement(xpathDocument);

-	if (expr)

-	    res = xmlXPathEvalExpression(BAD_CAST str, ctxt);

-	else {

-	    /* res = xmlXPathEval(BAD_CAST str, ctxt); */

-	    xmlXPathCompExprPtr comp;

-

-	    comp = xmlXPathCompile(BAD_CAST str);

-	    if (comp != NULL) {

-		res = xmlXPathCompiledEval(comp, ctxt);

-		xmlXPathFreeCompExpr(comp);

-	    } else

-		res = NULL;

-	}

-#if defined(LIBXML_XPTR_ENABLED)

-    }

-#endif

-    xmlXPathDebugDumpObject(xpathOutput, res, 0);

-    xmlXPathFreeObject(res);

-    xmlXPathFreeContext(ctxt);

-}

-

-/**

- * xpathExprTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing XPath standalone expressions and evaluate them

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-xpathCommonTest(const char *filename, const char *result,

-                int xptr, int expr) {

-    FILE *input;

-    char expression[5000];

-    int len, ret = 0;

-    char *temp;

-

-    temp = resultFilename(filename, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "Out of memory\n");

-        fatalError();

-    }

-    xpathOutput = fopen(temp, "wb");

-    if (xpathOutput == NULL) {

-	fprintf(stderr, "failed to open output file %s\n", temp);

-        free(temp);

-	return(-1);

-    }

-

-    input = fopen(filename, "rb");

-    if (input == NULL) {

-        xmlGenericError(xmlGenericErrorContext,

-		"Cannot open %s for reading\n", filename);

-        free(temp);

-	return(-1);

-    }

-    while (fgets(expression, 4500, input) != NULL) {

-	len = strlen(expression);

-	len--;

-	while ((len >= 0) && 

-	       ((expression[len] == '\n') || (expression[len] == '\t') ||

-		(expression[len] == '\r') || (expression[len] == ' '))) len--;

-	expression[len + 1] = 0;      

-	if (len >= 0) {

-	    fprintf(xpathOutput,

-	            "\n========================\nExpression: %s\n",

-		    expression) ;

-	    testXPath(expression, xptr, expr);

-	}

-    }

-

-    fclose(input);

-    fclose(xpathOutput);

-    if (result != NULL) {

-	ret = compareFiles(temp, result);

-	if (ret) {

-	    fprintf(stderr, "Result for %s failed\n", filename);

-	}

-    }

-

-    unlink(temp);

-    free(temp);

-    return(ret);

-}

-

-/**

- * xpathExprTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing XPath standalone expressions and evaluate them

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-xpathExprTest(const char *filename, const char *result,

-              const char *err ATTRIBUTE_UNUSED,

-              int options ATTRIBUTE_UNUSED) {

-    return(xpathCommonTest(filename, result, 0, 1));

-}

-

-/**

- * xpathDocTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing XPath expressions and evaluate them against

- * a set of corresponding documents.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-xpathDocTest(const char *filename,

-             const char *resul ATTRIBUTE_UNUSED,

-             const char *err ATTRIBUTE_UNUSED,

-             int options) {

-

-    char pattern[500];

-    char result[500];

-    glob_t globbuf;

-    size_t i;

-    int ret = 0, res;

-

-    xpathDocument = xmlReadFile(filename, NULL,

-                                options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);

-    if (xpathDocument == NULL) {

-        fprintf(stderr, "Failed to load %s\n", filename);

-	return(-1);

-    }

-

-    snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));

-    pattern[499] = 0;

-    globbuf.gl_offs = 0;

-    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);

-    for (i = 0;i < globbuf.gl_pathc;i++) {

-        snprintf(result, 499, "result/XPath/tests/%s",

-	         baseFilename(globbuf.gl_pathv[i]));

-	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);

-	if (res != 0)

-	    ret = res;

-    }

-    globfree(&globbuf);

-

-    xmlFreeDoc(xpathDocument);

-    return(ret);

-}

-

-#ifdef LIBXML_XPTR_ENABLED

-/**

- * xptrDocTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing XPath expressions and evaluate them against

- * a set of corresponding documents.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-xptrDocTest(const char *filename,

-            const char *resul ATTRIBUTE_UNUSED,

-            const char *err ATTRIBUTE_UNUSED,

-            int options) {

-

-    char pattern[500];

-    char result[500];

-    glob_t globbuf;

-    size_t i;

-    int ret = 0, res;

-

-    xpathDocument = xmlReadFile(filename, NULL,

-                                options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);

-    if (xpathDocument == NULL) {

-        fprintf(stderr, "Failed to load %s\n", filename);

-	return(-1);

-    }

-

-    snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));

-    pattern[499] = 0;

-    globbuf.gl_offs = 0;

-    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);

-    for (i = 0;i < globbuf.gl_pathc;i++) {

-        snprintf(result, 499, "result/XPath/xptr/%s",

-	         baseFilename(globbuf.gl_pathv[i]));

-	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);

-	if (res != 0)

-	    ret = res;

-    }

-    globfree(&globbuf);

-

-    xmlFreeDoc(xpathDocument);

-    return(ret);

-}

-#endif /* LIBXML_XPTR_ENABLED */

-

-/**

- * xmlidDocTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing xml:id and check for errors and verify

- * that XPath queries will work on them as expected.

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-xmlidDocTest(const char *filename,

-             const char *result,

-             const char *err,

-             int options) {

-

-    int res = 0;

-    int ret = 0;

-    char *temp;

-

-    xpathDocument = xmlReadFile(filename, NULL,

-                                options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);

-    if (xpathDocument == NULL) {

-        fprintf(stderr, "Failed to load %s\n", filename);

-	return(-1);

-    }

-

-    temp = resultFilename(filename, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "Out of memory\n");

-        fatalError();

-    }

-    xpathOutput = fopen(temp, "wb");

-    if (xpathOutput == NULL) {

-	fprintf(stderr, "failed to open output file %s\n", temp);

-        xmlFreeDoc(xpathDocument);

-        free(temp);

-	return(-1);

-    }

-

-    testXPath("id('bar')", 0, 0);

-

-    fclose(xpathOutput);

-    if (result != NULL) {

-	ret = compareFiles(temp, result);

-	if (ret) {

-	    fprintf(stderr, "Result for %s failed\n", filename);

-	    res = 1;

-	}

-    }

-

-    unlink(temp);

-    free(temp);

-    xmlFreeDoc(xpathDocument);

-

-    if (err != NULL) {

-	ret = compareFileMem(err, testErrors, testErrorsSize);

-	if (ret != 0) {

-	    fprintf(stderr, "Error for %s failed\n", filename);

-	    res = 1;

-	}

-    }

-    return(res);

-}

-

-#endif /* LIBXML_DEBUG_ENABLED */

-#endif /* XPATH */

-/************************************************************************

- *									*

- *			URI based tests					*

- *									*

- ************************************************************************/

-

-static void

-handleURI(const char *str, const char *base, FILE *o) {

-    int ret;

-    xmlURIPtr uri;

-    xmlChar *res = NULL, *parsed = NULL;

-

-    uri = xmlCreateURI();

-

-    if (base == NULL) {

-	ret = xmlParseURIReference(uri, str);

-	if (ret != 0)

-	    fprintf(o, "%s : error %d\n", str, ret);

-	else {

-	    xmlNormalizeURIPath(uri->path);

-	    xmlPrintURI(o, uri);

-	    fprintf(o, "\n");

-	}

-    } else {

-	res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);

-	if (res != NULL) {

-	    fprintf(o, "%s\n", (char *) res);

-	}

-	else

-	    fprintf(o, "::ERROR::\n");

-    }

-    if (res != NULL)

-	xmlFree(res);

-    if (parsed != NULL)

-	xmlFree(parsed);

-    xmlFreeURI(uri);

-}

-

-/**

- * uriCommonTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing URI and check for errors

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-uriCommonTest(const char *filename,

-             const char *result,

-             const char *err,

-             const char *base) {

-    char *temp;

-    FILE *o, *f;

-    char str[1024];

-    int res = 0, i, ret;

-

-    temp = resultFilename(filename, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "Out of memory\n");

-        fatalError();

-    }

-    o = fopen(temp, "wb");

-    if (o == NULL) {

-	fprintf(stderr, "failed to open output file %s\n", temp);

-        free(temp);

-	return(-1);

-    }

-    f = fopen(filename, "rb");

-    if (f == NULL) {

-	fprintf(stderr, "failed to open input file %s\n", filename);

-	fclose(o);

-	unlink(temp);

-        free(temp);

-	return(-1);

-    }

-

-    while (1) {

-	/*

-	 * read one line in string buffer.

-	 */

-	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)

-	   break;

-

-	/*

-	 * remove the ending spaces

-	 */

-	i = strlen(str);

-	while ((i > 0) &&

-	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||

-		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {

-	    i--;

-	    str[i] = 0;

-	}

-	nb_tests++;

-	handleURI(str, base, o);

-    }

-

-    fclose(f);

-    fclose(o);

-

-    if (result != NULL) {

-	ret = compareFiles(temp, result);

-	if (ret) {

-	    fprintf(stderr, "Result for %s failed\n", filename);

-	    res = 1;

-	}

-    }

-    if (err != NULL) {

-	ret = compareFileMem(err, testErrors, testErrorsSize);

-	if (ret != 0) {

-	    fprintf(stderr, "Error for %s failed\n", filename);

-	    res = 1;

-	}

-    }

-

-    unlink(temp);

-    free(temp);

-    return(res);

-}

-

-/**

- * uriParseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing URI and check for errors

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-uriParseTest(const char *filename,

-             const char *result,

-             const char *err,

-             int options ATTRIBUTE_UNUSED) {

-    return(uriCommonTest(filename, result, err, NULL));

-}

-

-/**

- * uriBaseTest:

- * @filename: the file to parse

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing URI, compose them against a fixed base and

- * check for errors

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-uriBaseTest(const char *filename,

-             const char *result,

-             const char *err,

-             int options ATTRIBUTE_UNUSED) {

-    return(uriCommonTest(filename, result, err,

-                         "http://foo.com/path/to/index.html?orig#help"));

-}

-

-#ifdef LIBXML_SCHEMAS_ENABLED

-/************************************************************************

- *									*

- *			Schemas tests					*

- *									*

- ************************************************************************/

-static int

-schemasOneTest(const char *sch,

-               const char *filename,

-               const char *result,

-	       const char *err,

-	       int options,

-	       xmlSchemaPtr schemas) {

-    xmlDocPtr doc;

-    xmlSchemaValidCtxtPtr ctxt;

-    int ret = 0;

-    char *temp;

-    FILE *schemasOutput;

-

-    doc = xmlReadFile(filename, NULL, options);

-    if (doc == NULL) {

-        fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);

-	return(-1);

-    }

-

-    temp = resultFilename(result, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "Out of memory\n");

-        fatalError();

-    }

-    schemasOutput = fopen(temp, "wb");

-    if (schemasOutput == NULL) {

-	fprintf(stderr, "failed to open output file %s\n", temp);

-	xmlFreeDoc(doc);

-        free(temp);

-	return(-1);

-    }

-

-    ctxt = xmlSchemaNewValidCtxt(schemas);

-    xmlSchemaSetValidErrors(ctxt,

-         (xmlSchemaValidityErrorFunc) testErrorHandler,

-         (xmlSchemaValidityWarningFunc) testErrorHandler,

-	 ctxt);

-    ret = xmlSchemaValidateDoc(ctxt, doc);

-    if (ret == 0) {

-	fprintf(schemasOutput, "%s validates\n", filename);

-    } else if (ret > 0) {

-	fprintf(schemasOutput, "%s fails to validate\n", filename);

-    } else {

-	fprintf(schemasOutput, "%s validation generated an internal error\n",

-	       filename);

-    }

-    fclose(schemasOutput);

-    if (result) {

-	if (compareFiles(temp, result)) {

-	    fprintf(stderr, "Result for %s on %s failed\n", filename, sch);

-	    ret = 1;

-	}

-    }

-    unlink(temp);

-    free(temp);

-

-    if (err != NULL) {

-	if (compareFileMem(err, testErrors, testErrorsSize)) {

-	    fprintf(stderr, "Error for %s on %s failed\n", filename, sch);

-	    ret = 1;

-	}

-    }

-

-

-    xmlSchemaFreeValidCtxt(ctxt);

-    xmlFreeDoc(doc);

-    return(ret);

-}

-/**

- * schemasTest:

- * @filename: the schemas file

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a file containing URI, compose them against a fixed base and

- * check for errors

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-schemasTest(const char *filename,

-            const char *resul ATTRIBUTE_UNUSED,

-            const char *errr ATTRIBUTE_UNUSED,

-            int options) {

-    const char *base = baseFilename(filename);

-    const char *base2;

-    const char *instance;

-    xmlSchemaParserCtxtPtr ctxt;

-    xmlSchemaPtr schemas;

-    int res = 0, len, ret;

-    char pattern[500];

-    char prefix[500];

-    char result[500];

-    char err[500];

-    glob_t globbuf;

-    size_t i;

-    char count = 0;

-

-    /* first compile the schemas if possible */

-    ctxt = xmlSchemaNewParserCtxt(filename);

-    xmlSchemaSetParserErrors(ctxt,

-         (xmlSchemaValidityErrorFunc) testErrorHandler,

-         (xmlSchemaValidityWarningFunc) testErrorHandler,

-	 ctxt);

-    schemas = xmlSchemaParse(ctxt);

-    xmlSchemaFreeParserCtxt(ctxt);

-

-    /*

-     * most of the mess is about the output filenames generated by the Makefile

-     */

-    len = strlen(base);

-    if ((len > 499) || (len < 5)) {

-        xmlSchemaFree(schemas);

-	return(-1);

-    }

-    len -= 4; /* remove trailing .xsd */

-    if (base[len - 2] == '_') {

-        len -= 2; /* remove subtest number */

-    }

-    if (base[len - 2] == '_') {

-        len -= 2; /* remove subtest number */

-    }

-    memcpy(prefix, base, len);

-    prefix[len] = 0;

-

-    snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);

-    pattern[499] = 0;

-

-    if (base[len] == '_') {

-        len += 2;

-	memcpy(prefix, base, len);

-	prefix[len] = 0;

-    }

-

-    globbuf.gl_offs = 0;

-    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);

-    for (i = 0;i < globbuf.gl_pathc;i++) {

-        testErrorsSize = 0;

-	testErrors[0] = 0;

-        instance = globbuf.gl_pathv[i];

-	base2 = baseFilename(instance);

-	len = strlen(base2);

-	if ((len > 6) && (base2[len - 6] == '_')) {

-	    count = base2[len - 5];

-	    snprintf(result, 499, "result/schemas/%s_%c",

-		     prefix, count);

-	    result[499] = 0;

-	    snprintf(err, 499, "result/schemas/%s_%c.err",

-		     prefix, count);

-	    err[499] = 0;

-	} else {

-	    fprintf(stderr, "don't know how to process %s\n", instance);

-	    continue;

-	}

-	if (schemas == NULL) {

-	} else {

-	    nb_tests++;

-	    ret = schemasOneTest(filename, instance, result, err,

-	                         options, schemas);

-	    if (res != 0)

-		ret = res;

-	}

-    }

-    globfree(&globbuf);

-    xmlSchemaFree(schemas);

-

-    return(res);

-}

-

-/************************************************************************

- *									*

- *			Schemas tests					*

- *									*

- ************************************************************************/

-static int

-rngOneTest(const char *sch,

-               const char *filename,

-               const char *result,

-	       const char *err,

-	       int options,

-	       xmlRelaxNGPtr schemas) {

-    xmlDocPtr doc;

-    xmlRelaxNGValidCtxtPtr ctxt;

-    int ret = 0;

-    char *temp;

-    FILE *schemasOutput;

-

-    doc = xmlReadFile(filename, NULL, options);

-    if (doc == NULL) {

-        fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);

-	return(-1);

-    }

-

-    temp = resultFilename(result, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "Out of memory\n");

-        fatalError();

-    }

-    schemasOutput = fopen(temp, "wb");

-    if (schemasOutput == NULL) {

-	fprintf(stderr, "failed to open output file %s\n", temp);

-	xmlFreeDoc(doc);

-        free(temp);

-	return(-1);

-    }

-

-    ctxt = xmlRelaxNGNewValidCtxt(schemas);

-    xmlRelaxNGSetValidErrors(ctxt,

-         (xmlRelaxNGValidityErrorFunc) testErrorHandler,

-         (xmlRelaxNGValidityWarningFunc) testErrorHandler,

-	 ctxt);

-    ret = xmlRelaxNGValidateDoc(ctxt, doc);

-    if (ret == 0) {

-	testErrorHandler(NULL, "%s validates\n", filename);

-    } else if (ret > 0) {

-	testErrorHandler(NULL, "%s fails to validate\n", filename);

-    } else {

-	testErrorHandler(NULL, "%s validation generated an internal error\n",

-	       filename);

-    }

-    fclose(schemasOutput);

-    if (result) {

-	if (compareFiles(temp, result)) {

-	    fprintf(stderr, "Result for %s on %s failed\n", filename, sch);

-	    ret = 1;

-	}

-    }

-    unlink(temp);

-    free(temp);

-

-    if (err != NULL) {

-	if (compareFileMem(err, testErrors, testErrorsSize)) {

-	    fprintf(stderr, "Error for %s on %s failed\n", filename, sch);

-	    ret = 1;

-	    printf("%s", testErrors);

-	}

-    }

-

-

-    xmlRelaxNGFreeValidCtxt(ctxt);

-    xmlFreeDoc(doc);

-    return(ret);

-}

-/**

- * rngTest:

- * @filename: the schemas file

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse an RNG schemas and then apply it to the related .xml

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-rngTest(const char *filename,

-            const char *resul ATTRIBUTE_UNUSED,

-            const char *errr ATTRIBUTE_UNUSED,

-            int options) {

-    const char *base = baseFilename(filename);

-    const char *base2;

-    const char *instance;

-    xmlRelaxNGParserCtxtPtr ctxt;

-    xmlRelaxNGPtr schemas;

-    int res = 0, len, ret;

-    char pattern[500];

-    char prefix[500];

-    char result[500];

-    char err[500];

-    glob_t globbuf;

-    size_t i;

-    char count = 0;

-

-    /* first compile the schemas if possible */

-    ctxt = xmlRelaxNGNewParserCtxt(filename);

-    xmlRelaxNGSetParserErrors(ctxt,

-         (xmlRelaxNGValidityErrorFunc) testErrorHandler,

-         (xmlRelaxNGValidityWarningFunc) testErrorHandler,

-	 ctxt);

-    schemas = xmlRelaxNGParse(ctxt);

-    xmlRelaxNGFreeParserCtxt(ctxt);

-

-    /*

-     * most of the mess is about the output filenames generated by the Makefile

-     */

-    len = strlen(base);

-    if ((len > 499) || (len < 5)) {

-        xmlRelaxNGFree(schemas);

-	return(-1);

-    }

-    len -= 4; /* remove trailing .rng */

-    memcpy(prefix, base, len);

-    prefix[len] = 0;

-

-    snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);

-    pattern[499] = 0;

-

-    globbuf.gl_offs = 0;

-    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);

-    for (i = 0;i < globbuf.gl_pathc;i++) {

-        testErrorsSize = 0;

-	testErrors[0] = 0;

-        instance = globbuf.gl_pathv[i];

-	base2 = baseFilename(instance);

-	len = strlen(base2);

-	if ((len > 6) && (base2[len - 6] == '_')) {

-	    count = base2[len - 5];

-	    snprintf(result, 499, "result/relaxng/%s_%c",

-		     prefix, count);

-	    result[499] = 0;

-	    snprintf(err, 499, "result/relaxng/%s_%c.err",

-		     prefix, count);

-	    err[499] = 0;

-	} else {

-	    fprintf(stderr, "don't know how to process %s\n", instance);

-	    continue;

-	}

-	if (schemas == NULL) {

-	} else {

-	    nb_tests++;

-	    ret = rngOneTest(filename, instance, result, err,

-	                         options, schemas);

-	    if (res != 0)

-		ret = res;

-	}

-    }

-    globfree(&globbuf);

-    xmlRelaxNGFree(schemas);

-

-    return(res);

-}

-

-#ifdef LIBXML_READER_ENABLED

-/**

- * rngStreamTest:

- * @filename: the schemas file

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a set of files with streaming, applying an RNG schemas 

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-rngStreamTest(const char *filename,

-            const char *resul ATTRIBUTE_UNUSED,

-            const char *errr ATTRIBUTE_UNUSED,

-            int options) {

-    const char *base = baseFilename(filename);

-    const char *base2;

-    const char *instance;

-    int res = 0, len, ret;

-    char pattern[500];

-    char prefix[500];

-    char result[500];

-    char err[500];

-    glob_t globbuf;

-    size_t i;

-    char count = 0;

-    xmlTextReaderPtr reader;

-    int disable_err = 0;

-

-    /*

-     * most of the mess is about the output filenames generated by the Makefile

-     */

-    len = strlen(base);

-    if ((len > 499) || (len < 5)) {

-	fprintf(stderr, "len(base) == %d !\n", len);

-	return(-1);

-    }

-    len -= 4; /* remove trailing .rng */

-    memcpy(prefix, base, len);

-    prefix[len] = 0;

-

-    /*

-     * strictly unifying the error messages is nearly impossible this

-     * hack is also done in the Makefile

-     */

-    if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||

-        (!strcmp(prefix, "tutor3_2"))) 

-	disable_err = 1;

-

-    snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);

-    pattern[499] = 0;

-

-    globbuf.gl_offs = 0;

-    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);

-    for (i = 0;i < globbuf.gl_pathc;i++) {

-        testErrorsSize = 0;

-	testErrors[0] = 0;

-        instance = globbuf.gl_pathv[i];

-	base2 = baseFilename(instance);

-	len = strlen(base2);

-	if ((len > 6) && (base2[len - 6] == '_')) {

-	    count = base2[len - 5];

-	    snprintf(result, 499, "result/relaxng/%s_%c",

-		     prefix, count);

-	    result[499] = 0;

-	    snprintf(err, 499, "result/relaxng/%s_%c.err",

-		     prefix, count);

-	    err[499] = 0;

-	} else {

-	    fprintf(stderr, "don't know how to process %s\n", instance);

-	    continue;

-	}

-	reader = xmlReaderForFile(instance, NULL, options);

-	if (reader == NULL) {

-	    fprintf(stderr, "Failed to build reder for %s\n", instance);

-	}

-	if (disable_err == 1)

-	    ret = streamProcessTest(instance, result, NULL, reader, filename);

-	else

-	    ret = streamProcessTest(instance, result, err, reader, filename);

-	xmlFreeTextReader(reader);

-	if (ret != 0) {

-	    fprintf(stderr, "instance %s failed\n", instance);

-	    res = ret;

-	}

-    }

-    globfree(&globbuf);

-

-    return(res);

-}

-#endif /* READER */

-

-#endif

-

-#ifdef LIBXML_PATTERN_ENABLED

-#ifdef LIBXML_READER_ENABLED

-/************************************************************************

- *									*

- *			Patterns tests					*

- *									*

- ************************************************************************/

-static void patternNode(FILE *out, xmlTextReaderPtr reader,

-                        const char *pattern, xmlPatternPtr patternc,

-			xmlStreamCtxtPtr patstream) {

-    xmlChar *path = NULL;

-    int match = -1;

-    int type, empty;

-

-    type = xmlTextReaderNodeType(reader);

-    empty = xmlTextReaderIsEmptyElement(reader);

-	

-    if (type == XML_READER_TYPE_ELEMENT) {

-	/* do the check only on element start */

-	match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));

-

-	if (match) {

-	    path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));

-	    fprintf(out, "Node %s matches pattern %s\n", path, pattern);

-	}

-    }

-    if (patstream != NULL) {

-	int ret;

-

-	if (type == XML_READER_TYPE_ELEMENT) {

-	    ret = xmlStreamPush(patstream,

-				xmlTextReaderConstLocalName(reader),

-				xmlTextReaderConstNamespaceUri(reader));

-	    if (ret < 0) {

-		fprintf(out, "xmlStreamPush() failure\n");

-		xmlFreeStreamCtxt(patstream);

-		patstream = NULL;

-	    } else if (ret != match) {

-		if (path == NULL) {

-		    path = xmlGetNodePath(

-				   xmlTextReaderCurrentNode(reader));

-		}

-		fprintf(out,

-			"xmlPatternMatch and xmlStreamPush disagree\n");

-		fprintf(out,

-			"  pattern %s node %s\n",

-			pattern, path);

-	    }

-	    

-

-	} 

-	if ((type == XML_READER_TYPE_END_ELEMENT) ||

-	    ((type == XML_READER_TYPE_ELEMENT) && (empty))) {

-	    ret = xmlStreamPop(patstream);

-	    if (ret < 0) {

-		fprintf(out, "xmlStreamPop() failure\n");

-		xmlFreeStreamCtxt(patstream);

-		patstream = NULL;

-	    }

-	}

-    }

-    if (path != NULL)

-	xmlFree(path);

-}

-

-/**

- * patternTest:

- * @filename: the schemas file

- * @result: the file with expected result

- * @err: the file with error messages

- *

- * Parse a set of files with streaming, applying an RNG schemas 

- *

- * Returns 0 in case of success, an error code otherwise

- */

-static int

-patternTest(const char *filename,

-            const char *resul ATTRIBUTE_UNUSED,

-            const char *err ATTRIBUTE_UNUSED,

-            int options) {

-    xmlPatternPtr patternc = NULL;

-    xmlStreamCtxtPtr patstream = NULL;

-    FILE *o, *f;

-    char str[1024];

-    char xml[500];

-    char result[500];

-    int len, i;

-    int ret = 0, res;

-    char *temp;

-    xmlTextReaderPtr reader;

-    xmlDocPtr doc;

-

-    len = strlen(filename);

-    len -= 4;

-    memcpy(xml, filename, len);

-    xml[len] = 0;

-    snprintf(result, 499, "result/pattern/%s", baseFilename(xml));

-    result[499] = 0;

-    memcpy(xml + len, ".xml", 5);

-

-    if (!checkTestFile(xml)) {

-	fprintf(stderr, "Missing xml file %s\n", xml);

-	return(-1);

-    }

-    if (!checkTestFile(result)) {

-	fprintf(stderr, "Missing result file %s\n", result);

-	return(-1);

-    }

-    f = fopen(filename, "rb");

-    if (f == NULL) {

-        fprintf(stderr, "Failed to open %s\n", filename);

-	return(-1);

-    }

-    temp = resultFilename(filename, "", ".res");

-    if (temp == NULL) {

-        fprintf(stderr, "Out of memory\n");

-        fatalError();

-    }

-    o = fopen(temp, "wb");

-    if (o == NULL) {

-	fprintf(stderr, "failed to open output file %s\n", temp);

-	fclose(f);

-        free(temp);

-	return(-1);

-    }

-    while (1) {

-	/*

-	 * read one line in string buffer.

-	 */

-	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)

-	   break;

-

-	/*

-	 * remove the ending spaces

-	 */

-	i = strlen(str);

-	while ((i > 0) &&

-	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||

-		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {

-	    i--;

-	    str[i] = 0;

-	}

-	doc = xmlReadFile(xml, NULL, options);

-	if (doc == NULL) {

-	    fprintf(stderr, "Failed to parse %s\n", xml);

-	    ret = 1;

-	} else {

-	    xmlNodePtr root;

-	    const xmlChar *namespaces[22];

-	    int j;

-	    xmlNsPtr ns;

-

-	    root = xmlDocGetRootElement(doc);

-	    for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {

-		namespaces[j++] = ns->href;

-		namespaces[j++] = ns->prefix;

-	    }

-	    namespaces[j++] = NULL;

-	    namespaces[j++] = NULL;

-

-	    patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,

-					 0, &namespaces[0]);

-	    if (patternc == NULL) {

-		testErrorHandler(NULL,

-			"Pattern %s failed to compile\n", str);

-		xmlFreeDoc(doc);

-		ret = 1;

-		continue;

-	    }

-	    patstream = xmlPatternGetStreamCtxt(patternc);

-	    if (patstream != NULL) {

-		ret = xmlStreamPush(patstream, NULL, NULL);

-		if (ret < 0) {

-		    fprintf(stderr, "xmlStreamPush() failure\n");

-		    xmlFreeStreamCtxt(patstream);

-		    patstream = NULL;

-		}

-	    }

-	    nb_tests++;

-

-	    reader = xmlReaderWalker(doc);

-	    res = xmlTextReaderRead(reader);

-	    while (res == 1) {

-		patternNode(o, reader, str, patternc, patstream);

-		res = xmlTextReaderRead(reader);

-	    }

-	    if (res != 0) {

-		fprintf(o, "%s : failed to parse\n", filename);

-	    }

-	    xmlFreeTextReader(reader);

-	    xmlFreeDoc(doc);

-	    xmlFreeStreamCtxt(patstream);

-	    patstream = NULL;

-	    xmlFreePattern(patternc);

-

-	}

-    }

-

-    fclose(f);

-    fclose(o);

-

-    ret = compareFiles(temp, result);

-    if (ret) {

-	fprintf(stderr, "Result for %s failed\n", filename);

-	ret = 1;

-    }

-    unlink(temp);

-    free(temp);

-    return(ret);

-}

-#endif /* READER */

-#endif /* PATTERN */

-#ifdef LIBXML_C14N_ENABLED

-/************************************************************************

- *									*

- *			Canonicalization tests				*

- *									*

- ************************************************************************/

-static xmlXPathObjectPtr

-load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {

-    xmlXPathObjectPtr xpath; 

-    xmlDocPtr doc;

-    xmlChar *expr;

-    xmlXPathContextPtr ctx; 

-    xmlNodePtr node;

-    xmlNsPtr ns;

-    

-    /*

-     * load XPath expr as a file

-     */

-    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;

-    xmlSubstituteEntitiesDefault(1);

-

-    doc = xmlParseFile(filename);

-    if (doc == NULL) {

-	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);

-	return(NULL);

-    }

-    

-    /*

-     * Check the document is of the right kind

-     */    

-    if(xmlDocGetRootElement(doc) == NULL) {

-        fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);

-	xmlFreeDoc(doc);

-	return(NULL);

-    }

-

-    node = doc->children;

-    while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {

-	node = node->next;

-    }

-    

-    if(node == NULL) {   

-        fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);

-	xmlFreeDoc(doc);

-	return(NULL);

-    }

-

-    expr = xmlNodeGetContent(node);

-    if(expr == NULL) {

-        fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);

-	xmlFreeDoc(doc);

-	return(NULL);

-    }

-

-    ctx = xmlXPathNewContext(parent_doc);

-    if(ctx == NULL) {

-        fprintf(stderr,"Error: unable to create new context\n");

-        xmlFree(expr); 

-        xmlFreeDoc(doc); 

-        return(NULL);

-    }

-

-    /*

-     * Register namespaces

-     */

-    ns = node->nsDef;

-    while(ns != NULL) {

-	if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {

-	    fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);

-    	    xmlFree(expr); 

-	    xmlXPathFreeContext(ctx); 

-	    xmlFreeDoc(doc); 

-	    return(NULL);

-	}

-	ns = ns->next;

-    }

-

-    /*  

-     * Evaluate xpath

-     */

-    xpath = xmlXPathEvalExpression(expr, ctx);

-    if(xpath == NULL) {

-        fprintf(stderr,"Error: unable to evaluate xpath expression\n");

-    	xmlFree(expr); 

-        xmlXPathFreeContext(ctx); 

-        xmlFreeDoc(doc); 

-        return(NULL);

-    }

-

-    /* print_xpath_nodes(xpath->nodesetval); */

-

-    xmlFree(expr); 

-    xmlXPathFreeContext(ctx); 

-    xmlFreeDoc(doc); 

-    return(xpath);

-}

-

-/*

- * Macro used to grow the current buffer.

- */

-#define xxx_growBufferReentrant() {						\

-    buffer_size *= 2;							\

-    buffer = (xmlChar **)						\

-    		xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));	\

-    if (buffer == NULL) {						\

-	perror("realloc failed");					\

-	return(NULL);							\

-    }									\

-}

-

-static xmlChar **

-parse_list(xmlChar *str) {

-    xmlChar **buffer;

-    xmlChar **out = NULL;

-    int buffer_size = 0;

-    int len;

-

-    if(str == NULL) {

-	return(NULL);

-    }

-

-    len = xmlStrlen(str);

-    if((str[0] == '\'') && (str[len - 1] == '\'')) {

-	str[len - 1] = '\0';

-	str++;

-	len -= 2;

-    }

-    /*

-     * allocate an translation buffer.

-     */

-    buffer_size = 1000;

-    buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));

-    if (buffer == NULL) {

-	perror("malloc failed");

-	return(NULL);

-    }

-    out = buffer;

-    

-    while(*str != '\0') {

-	if (out - buffer > buffer_size - 10) {

-	    int indx = out - buffer;

-

-	    xxx_growBufferReentrant();

-	    out = &buffer[indx];

-	}

-	(*out++) = str;

-	while(*str != ',' && *str != '\0') ++str;

-	if(*str == ',') *(str++) = '\0';

-    }

-    (*out) = NULL;

-    return buffer;

-}

-

-static int 

-c14nRunTest(const char* xml_filename, int with_comments, int exclusive,

-	    const char* xpath_filename, const char *ns_filename,

-	    const char* result_file) {

-    xmlDocPtr doc;

-    xmlXPathObjectPtr xpath = NULL; 

-    xmlChar *result = NULL;

-    int ret;

-    xmlChar **inclusive_namespaces = NULL;

-    const char *nslist = NULL;

-    int nssize;

-

-

-    /*

-     * build an XML tree from a the file; we need to add default

-     * attributes and resolve all character and entities references

-     */

-    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;

-    xmlSubstituteEntitiesDefault(1);

-

-    doc = xmlParseFile(xml_filename);

-    if (doc == NULL) {

-	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);

-	return(-1);

-    }

-    

-    /*

-     * Check the document is of the right kind

-     */    

-    if(xmlDocGetRootElement(doc) == NULL) {

-        fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);

-	xmlFreeDoc(doc);

-	return(-1);

-    }

-

-    /* 

-     * load xpath file if specified 

-     */

-    if(xpath_filename) {

-	xpath = load_xpath_expr(doc, xpath_filename);

-	if(xpath == NULL) {

-	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");

-	    xmlFreeDoc(doc); 

-	    return(-1);

-	}

-    }

-

-    if (ns_filename != NULL) {

-        if (loadMem(ns_filename, &nslist, &nssize)) {

-	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");

-	    if(xpath != NULL) xmlXPathFreeObject(xpath);

-	    xmlFreeDoc(doc); 

-	    return(-1);

-	}

-        inclusive_namespaces = parse_list((xmlChar *) nslist);

-    }

-

-    /*

-     * Canonical form

-     */      

-    /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */

-    ret = xmlC14NDocDumpMemory(doc, 

-	    (xpath) ? xpath->nodesetval : NULL, 

-	    exclusive, inclusive_namespaces,

-	    with_comments, &result);

-    if (ret >= 0) {

-	if(result != NULL) {

-	    if (compareFileMem(result_file, (const char *) result, ret)) {

-		fprintf(stderr, "Result mismatch for %s\n", xml_filename);

-	        ret = -1;

-	    }

-	}

-    } else {

-	fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);

-	ret = -1;

-    }

-        

-    /*

-     * Cleanup

-     */ 

-    if (result != NULL) xmlFree(result);

-    if(xpath != NULL) xmlXPathFreeObject(xpath);

-    if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);

-    if (nslist != NULL) free((char *) nslist);

-    xmlFreeDoc(doc);    

-

-    return(ret);

-}

-

-static int

-c14nCommonTest(const char *filename, int with_comments, int exclusive,

-               const char *subdir) {

-    char buf[500];

-    char prefix[500];

-    const char *base;

-    int len;

-    char *result = NULL;

-    char *xpath = NULL;

-    char *ns = NULL;

-    int ret = 0;

-

-    base = baseFilename(filename);

-    len = strlen(base);

-    len -= 4;

-    memcpy(prefix, base, len);

-    prefix[len] = 0;

-

-    snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);

-    if (!checkTestFile(buf)) {

-        fprintf(stderr, "Missing result file %s", buf);

-	return(-1);

-    }

-    result = strdup(buf);

-    snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);

-    if (checkTestFile(buf)) {

-	xpath = strdup(buf);

-    }

-    snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);

-    if (checkTestFile(buf)) {

-	ns = strdup(buf);

-    }

-

-    nb_tests++;

-    if (c14nRunTest(filename, with_comments, exclusive,

-                    xpath, ns, result) < 0)

-        ret = 1;

-

-    if (result != NULL) free(result);

-    if (xpath != NULL) free(xpath);

-    if (ns != NULL) free(ns);

-    return(ret);

-}

-

-static int

-c14nWithCommentTest(const char *filename,

-                    const char *resul ATTRIBUTE_UNUSED,

-		    const char *err ATTRIBUTE_UNUSED,

-		    int options ATTRIBUTE_UNUSED) {

-    return(c14nCommonTest(filename, 1, 0, "with-comments"));

-}

-static int

-c14nWithoutCommentTest(const char *filename,

-                    const char *resul ATTRIBUTE_UNUSED,

-		    const char *err ATTRIBUTE_UNUSED,

-		    int options ATTRIBUTE_UNUSED) {

-    return(c14nCommonTest(filename, 0, 0, "without-comments"));

-}

-static int

-c14nExcWithoutCommentTest(const char *filename,

-                    const char *resul ATTRIBUTE_UNUSED,

-		    const char *err ATTRIBUTE_UNUSED,

-		    int options ATTRIBUTE_UNUSED) {

-    return(c14nCommonTest(filename, 0, 1, "exc-without-comments"));

-}

-#endif

-#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)

-/************************************************************************

- *									*

- *			Catalog and threads test			*

- *									*

- ************************************************************************/

-

-/*

- * mostly a cut and paste from testThreads.c

- */

-#define	MAX_ARGC	20

-

-static const char *catalog = "test/threads/complex.xml";

-static const char *testfiles[] = {

-    "test/threads/abc.xml",

-    "test/threads/acb.xml",

-    "test/threads/bac.xml",

-    "test/threads/bca.xml",

-    "test/threads/cab.xml",

-    "test/threads/cba.xml",

-    "test/threads/invalid.xml",

-};

-

-const char *Okay = "OK";

-const char *Failed = "Failed";

-

-#ifndef xmlDoValidityCheckingDefaultValue

-#error xmlDoValidityCheckingDefaultValue is not a macro

-#endif

-#ifndef xmlGenericErrorContext

-#error xmlGenericErrorContext is not a macro

-#endif

-

-static void *

-thread_specific_data(void *private_data)

-{

-    xmlDocPtr myDoc;

-    const char *filename = (const char *) private_data;

-    int okay = 1;

-

-    if (!strcmp(filename, "test/threads/invalid.xml")) {

-        xmlDoValidityCheckingDefaultValue = 0;

-        xmlGenericErrorContext = stdout;

-    } else {

-        xmlDoValidityCheckingDefaultValue = 1;

-        xmlGenericErrorContext = stderr;

-    }

-    myDoc = xmlParseFile(filename);

-    if (myDoc) {

-        xmlFreeDoc(myDoc);

-    } else {

-        printf("parse failed\n");

-        okay = 0;

-    }

-    if (!strcmp(filename, "test/threads/invalid.xml")) {

-        if (xmlDoValidityCheckingDefaultValue != 0) {

-            printf("ValidityCheckingDefaultValue override failed\n");

-            okay = 0;

-        }

-        if (xmlGenericErrorContext != stdout) {

-            printf("xmlGenericErrorContext override failed\n");

-            okay = 0;

-        }

-    } else {

-        if (xmlDoValidityCheckingDefaultValue != 1) {

-            printf("ValidityCheckingDefaultValue override failed\n");

-            okay = 0;

-        }

-        if (xmlGenericErrorContext != stderr) {

-            printf("xmlGenericErrorContext override failed\n");

-            okay = 0;

-        }

-    }

-    if (okay == 0)

-        return ((void *) Failed);

-    return ((void *) Okay);

-}

-

-#if defined(linux) || defined(solaris)

-

-#include <pthread.h>

-

-static pthread_t tid[MAX_ARGC];

-

-static int

-testThread(void)

-{

-    unsigned int i, repeat;

-    unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);

-    void *results[MAX_ARGC];

-    int ret;

-    int res = 0;

-    

-    xmlInitParser();

-

-    for (repeat = 0; repeat < 500; repeat++) {

-        xmlLoadCatalog(catalog);

-        nb_tests++;

-

-        for (i = 0; i < num_threads; i++) {

-            results[i] = NULL;

-            tid[i] = (pthread_t) - 1;

-        }

-

-        for (i = 0; i < num_threads; i++) {

-            ret = pthread_create(&tid[i], 0, thread_specific_data,

-                                 (void *) testfiles[i]);

-            if (ret != 0) {

-                fprintf(stderr, "pthread_create failed\n");

-                return (1);

-            }

-        }

-        for (i = 0; i < num_threads; i++) {

-            ret = pthread_join(tid[i], &results[i]);

-            if (ret != 0) {

-                fprintf(stderr, "pthread_join failed\n");

-                return (1);

-            }

-        }

-

-        xmlCatalogCleanup();

-        for (i = 0; i < num_threads; i++)

-            if (results[i] != (void *) Okay) {

-                fprintf(stderr, "Thread %d handling %s failed\n",

-                        i, testfiles[i]);

-                res = 1;

-            }

-    }

-    return (res);

-}

-

-#elif defined WIN32

-#include <windows.h>

-#include <string.h>

-

-#define TEST_REPEAT_COUNT 500

-

-static HANDLE tid[MAX_ARGC];

-

-static DWORD WINAPI

-win32_thread_specific_data(void *private_data)

-{

-    return((DWORD) thread_specific_data(private_data));

-}

-

-static int

-testThread(void)

-{

-    unsigned int i, repeat;

-    unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);

-    DWORD results[MAX_ARGC];

-    BOOL ret;

-    int res = 0;

-

-    xmlInitParser();

-    for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {

-        xmlLoadCatalog(catalog);

-        nb_tests++;

-

-        for (i = 0; i < num_threads; i++) {

-            results[i] = 0;

-            tid[i] = (HANDLE) - 1;

-        }

-

-        for (i = 0; i < num_threads; i++) {

-            DWORD useless;

-

-            tid[i] = CreateThread(NULL, 0,

-                                  win32_thread_specific_data, 

-				  (void *) testfiles[i], 0,

-                                  &useless);

-            if (tid[i] == NULL) {

-                fprintf(stderr, "CreateThread failed\n");

-                return(1);

-            }

-        }

-

-        if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==

-            WAIT_FAILED) {

-            fprintf(stderr, "WaitForMultipleObjects failed\n");

-	    return(1);

-	}

-

-        for (i = 0; i < num_threads; i++) {

-            ret = GetExitCodeThread(tid[i], &results[i]);

-            if (ret == 0) {

-                fprintf(stderr, "GetExitCodeThread failed\n");

-                return(1);

-            }

-            CloseHandle(tid[i]);

-        }

-

-        xmlCatalogCleanup();

-        for (i = 0; i < num_threads; i++) {

-            if (results[i] != (DWORD) Okay) {

-                fprintf(stderr, "Thread %d handling %s failed\n",

-		        i, testfiles[i]);

-	        res = 1;

-	    }

-        }

-    }

-

-    return (res);

-}

-

-#elif defined __BEOS__

-#include <OS.h>

-

-static thread_id tid[MAX_ARGC];

-

-static int

-testThread(void)

-{

-    unsigned int i, repeat;

-    unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);

-    void *results[MAX_ARGC];

-    status_t ret;

-    int res = 0;

-

-    xmlInitParser();

-    for (repeat = 0; repeat < 500; repeat++) {

-        xmlLoadCatalog(catalog);

-        for (i = 0; i < num_threads; i++) {

-            results[i] = NULL;

-            tid[i] = (thread_id) - 1;

-        }

-        for (i = 0; i < num_threads; i++) {

-            tid[i] =

-                spawn_thread(thread_specific_data, "xmlTestThread",

-                             B_NORMAL_PRIORITY, (void *) testfiles[i]);

-            if (tid[i] < B_OK) {

-                fprintf(stderr, "beos_thread_create failed\n");

-                return (1);

-            }

-            printf("beos_thread_create %d -> %d\n", i, tid[i]);

-        }

-        for (i = 0; i < num_threads; i++) {

-            ret = wait_for_thread(tid[i], &results[i]);

-            printf("beos_thread_wait %d -> %d\n", i, ret);

-            if (ret != B_OK) {

-                fprintf(stderr, "beos_thread_wait failed\n");

-                return (1);

-            }

-        }

-

-        xmlCatalogCleanup();

-        ret = B_OK;

-        for (i = 0; i < num_threads; i++)

-            if (results[i] != (void *) Okay) {

-                printf("Thread %d handling %s failed\n", i, testfiles[i]);

-                ret = B_ERROR;

-            }

-    }

-    if (ret != B_OK)

-        return(1);

-    return (0);

-}

-#else

-static int

-testThread(void)

-{

-    fprintf(stderr,

-            "Specific platform thread support not detected\n");

-    return (-1);

-}

-#endif

-static int 

-threadsTest(const char *filename ATTRIBUTE_UNUSED,

-	    const char *resul ATTRIBUTE_UNUSED,

-	    const char *err ATTRIBUTE_UNUSED,

-	    int options ATTRIBUTE_UNUSED) {

-    return(testThread());

-}

-#endif

-/************************************************************************

- *									*

- *			Tests Descriptions				*

- *									*

- ************************************************************************/

-

-static

-testDesc testDescriptions[] = {

-    { "XML regression tests" ,

-      oldParseTest, "./test/*", "result/", "", NULL,

-      0 },

-    { "XML regression tests on memory" ,

-      memParseTest, "./test/*", "result/", "", NULL,

-      0 },

-    { "XML entity subst regression tests" ,

-      noentParseTest, "./test/*", "result/noent/", "", NULL,

-      XML_PARSE_NOENT },

-    { "XML Namespaces regression tests",

-      errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",

-      0 },

-    { "Error cases regression tests",

-      errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",

-      0 },

-#ifdef LIBXML_READER_ENABLED

-    { "Error cases stream regression tests",

-      streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",

-      0 },

-    { "Reader regression tests",

-      streamParseTest, "./test/*", "result/", ".rdr", NULL,

-      0 },

-    { "Reader entities substitution regression tests",

-      streamParseTest, "./test/*", "result/", ".rde", NULL,

-      XML_PARSE_NOENT },

-    { "Reader on memory regression tests",

-      streamMemParseTest, "./test/*", "result/", ".rdr", NULL,

-      0 },

-    { "Walker regression tests",

-      walkerParseTest, "./test/*", "result/", ".rdr", NULL,

-      0 },

-#endif

-#ifdef LIBXML_SAX1_ENABLED

-    { "SAX1 callbacks regression tests" ,

-      saxParseTest, "./test/*", "result/", ".sax", NULL,

-      XML_PARSE_SAX1 },

-    { "SAX2 callbacks regression tests" ,

-      saxParseTest, "./test/*", "result/", ".sax2", NULL,

-      0 },

-#endif

-#ifdef LIBXML_PUSH_ENABLED

-    { "XML push regression tests" ,

-      pushParseTest, "./test/*", "result/", "", NULL,

-      0 },

-#endif

-#ifdef LIBXML_HTML_ENABLED

-    { "HTML regression tests" ,

-      errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",

-      XML_PARSE_HTML },

-#ifdef LIBXML_PUSH_ENABLED

-    { "Push HTML regression tests" ,

-      pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",

-      XML_PARSE_HTML },

-#endif

-#ifdef LIBXML_SAX1_ENABLED

-    { "HTML SAX regression tests" ,

-      saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,

-      XML_PARSE_HTML },

-#endif

-#endif

-#ifdef LIBXML_VALID_ENABLED

-    { "Valid documents regression tests" ,

-      errParseTest, "./test/VCM/*", NULL, NULL, NULL,

-      XML_PARSE_DTDVALID },

-    { "Validity checking regression tests" ,

-      errParseTest, "./test/VC/*", "result/VC/", NULL, "",

-      XML_PARSE_DTDVALID },

-    { "General documents valid regression tests" ,

-      errParseTest, "./test/valid/*", "result/valid/", "", ".err",

-      XML_PARSE_DTDVALID },

-#endif

-#ifdef LIBXML_XINCLUDE_ENABLED

-    { "XInclude regression tests" ,

-      errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,

-      /* Ignore errors at this point ".err", */

-      XML_PARSE_XINCLUDE },

-    { "XInclude xmlReader regression tests",

-      streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",

-      /* Ignore errors at this point ".err", */

-      NULL, XML_PARSE_XINCLUDE },

-    { "XInclude regression tests stripping include nodes" ,

-      errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,

-      /* Ignore errors at this point ".err", */

-      XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },

-    { "XInclude xmlReader regression tests stripping include nodes",

-      streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",

-      /* Ignore errors at this point ".err", */

-      NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },

-#endif

-#ifdef LIBXML_XPATH_ENABLED

-#ifdef LIBXML_DEBUG_ENABLED

-    { "XPath expressions regression tests" ,

-      xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,

-      0 },

-    { "XPath document queries regression tests" ,

-      xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,

-      0 },

-#ifdef LIBXML_XPTR_ENABLED

-    { "XPointer document queries regression tests" ,

-      xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,

-      0 },

-#endif

-    { "xml:id regression tests" ,

-      xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",

-      0 },

-#endif

-#endif

-    { "URI parsing tests" ,

-      uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,

-      0 },

-    { "URI base composition tests" ,

-      uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,

-      0 },

-#ifdef LIBXML_SCHEMAS_ENABLED

-    { "Schemas regression tests" ,

-      schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,

-      0 },

-    { "Relax-NG regression tests" ,

-      rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,

-      XML_PARSE_DTDATTR | XML_PARSE_NOENT },

-#ifdef LIBXML_READER_ENABLED

-    { "Relax-NG streaming regression tests" ,

-      rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,

-      XML_PARSE_DTDATTR | XML_PARSE_NOENT },

-#endif

-#endif

-#ifdef LIBXML_PATTERN_ENABLED

-#ifdef LIBXML_READER_ENABLED

-    { "Pattern regression tests" ,

-      patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,

-      0 },

-#endif

-#endif

-#ifdef LIBXML_C14N_ENABLED

-    { "C14N with comments regression tests" ,

-      c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,

-      0 },

-    { "C14N without comments regression tests" ,

-      c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,

-      0 },

-    { "C14N exclusive without comments regression tests" ,

-      c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,

-      0 },

-#endif

-#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)

-    { "Catalog and Threads regression tests" ,

-      threadsTest, NULL, NULL, NULL, NULL,

-      0 },

-#endif

-    {NULL, NULL, NULL, NULL, NULL, NULL, 0}

-};

-

-/************************************************************************

- *									*

- *		The main code driving the tests				*

- *									*

- ************************************************************************/

-

-static int

-launchTests(testDescPtr tst) {

-    int res = 0, err = 0;

-    size_t i;

-    char *result;

-    char *error;

-    int mem;

-

-    if (tst == NULL) return(-1);

-    if (tst->in != NULL) {

-	glob_t globbuf;

-

-	globbuf.gl_offs = 0;

-	glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);

-	for (i = 0;i < globbuf.gl_pathc;i++) {

-	    if (!checkTestFile(globbuf.gl_pathv[i]))

-	        continue;

-	    if (tst->suffix != NULL) {

-		result = resultFilename(globbuf.gl_pathv[i], tst->out,

-					tst->suffix);

-		if (result == NULL) {

-		    fprintf(stderr, "Out of memory !\n");

-		    fatalError();

-		}

-	    } else {

-	        result = NULL;

-	    }

-	    if (tst->err != NULL) {

-		error = resultFilename(globbuf.gl_pathv[i], tst->out,

-		                        tst->err);

-		if (error == NULL) {

-		    fprintf(stderr, "Out of memory !\n");

-		    fatalError();

-		}

-	    } else {

-	        error = NULL;

-	    }

-	    if ((result) &&(!checkTestFile(result))) {

-	        fprintf(stderr, "Missing result file %s\n", result);

-	    } else if ((error) &&(!checkTestFile(error))) {

-	        fprintf(stderr, "Missing error file %s\n", error);

-	    } else {

-		mem = xmlMemUsed();

-		extraMemoryFromResolver = 0;

-		testErrorsSize = 0;

-		testErrors[0] = 0;

-		res = tst->func(globbuf.gl_pathv[i], result, error,

-		                tst->options);

-		xmlResetLastError();

-		if (res != 0) {

-		    fprintf(stderr, "File %s generated an error\n",

-		            globbuf.gl_pathv[i]);

-		    nb_errors++;

-		    err++;

-		}

-		else if (xmlMemUsed() != mem) {

-		    if ((xmlMemUsed() != mem) &&

-		        (extraMemoryFromResolver == 0)) {

-			fprintf(stderr, "File %s leaked %d bytes\n",

-				globbuf.gl_pathv[i], xmlMemUsed() - mem);

-			nb_leaks++;

-			err++;

-		    }

-		}

-		testErrorsSize = 0;

-	    }

-	    if (result)

-		free(result);

-	    if (error)

-		free(error);

-	}

-	globfree(&globbuf);

-    } else {

-        testErrorsSize = 0;

-	testErrors[0] = 0;

-	extraMemoryFromResolver = 0;

-        res = tst->func(NULL, NULL, NULL, tst->options);

-	if (res != 0) {

-	    nb_errors++;

-	    err++;

-	}

-    }

-    return(err);

-}

-

-int

-main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {

-    int i = 0, res, ret = 0;

-    int verbose = 0;

-    int old_errors, old_tests, old_leaks;

-

-    initializeLibxml2();

-

-    if ((argc >= 2) && (!strcmp(argv[1], "-v")))

-        verbose = 1;

-    for (i = 0; testDescriptions[i].func != NULL; i++) {

-        old_errors = nb_errors;

-        old_tests = nb_tests;

-        old_leaks = nb_leaks;

-        if (testDescriptions[i].desc != NULL)

-	    printf("## %s\n", testDescriptions[i].desc);

-	res = launchTests(&testDescriptions[i]);

-	if (res != 0)

-	    ret++;

-	if (verbose) {

-	    if ((nb_errors == old_errors) && (nb_leaks == old_leaks))

-	        printf("Ran %d tests, no errors\n", nb_tests - old_tests);

-	    else

-	        printf("Ran %d tests, %d errors, %d leaks\n",

-		       nb_tests - old_tests,

-		       nb_errors - old_errors,

-		       nb_leaks - old_leaks);

-	}

-    }

-    if ((nb_errors == 0) && (nb_leaks == 0)) {

-        ret = 0;

-	printf("Total %d tests, no errors\n",

-	       nb_tests);

-    } else {

-        ret = 1;

-	printf("Total %d tests, %d errors, %d leaks\n",

-	       nb_tests, nb_errors, nb_leaks);

-    }

-    xmlCleanupParser();

-    xmlMemoryDump();

-

-    return(ret);

-}

-

-#else /* ! LIBXML_OUTPUT_ENABLED */

-int

-main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {

-    fprintf(stderr, "runtest requires output to be enabled in libxml2\n");

-    return(1);

-}

-#endif

+/*
+ * runtest.c: C program to run libxml2 regression tests without
+ *            requiring make or Python, and reducing platform dependancies
+ *            to a strict minimum.
+ *
+ * To compile on Unixes:
+ * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/uri.h>
+
+#ifdef LIBXML_OUTPUT_ENABLED
+#ifdef LIBXML_READER_ENABLED
+#include <libxml/xmlreader.h>
+#endif
+
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+
+#ifdef LIBXML_XPATH_ENABLED
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#ifdef LIBXML_XPTR_ENABLED
+#include <libxml/xpointer.h>
+#endif
+#endif
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xmlschemastypes.h>
+#endif
+
+#ifdef LIBXML_PATTERN_ENABLED
+#include <libxml/pattern.h>
+#endif
+
+#ifdef LIBXML_C14N_ENABLED
+#include <libxml/c14n.h>
+#endif
+
+#ifdef LIBXML_HTML_ENABLED
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+
+/*
+ * pseudo flag for the unification of HTML and XML tests
+ */
+#define XML_PARSE_HTML 1 << 24
+#endif
+
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+#include <libxml/globals.h>
+#include <libxml/threads.h>
+#include <libxml/parser.h>
+#include <libxml/catalog.h>
+#include <string.h>
+#endif
+
+/*
+ * O_BINARY is just for Windows compatibility - if it isn't defined
+ * on this system, avoid any compilation error
+ */
+#ifdef	O_BINARY
+#define RD_FLAGS	O_RDONLY | O_BINARY
+#else
+#define	RD_FLAGS	O_RDONLY
+#endif
+
+typedef int (*functest) (const char *filename, const char *result,
+                         const char *error, int options);
+
+typedef struct testDesc testDesc;
+typedef testDesc *testDescPtr;
+struct testDesc {
+    const char *desc; /* descripton of the test */
+    functest    func; /* function implementing the test */
+    const char *in;   /* glob to path for input files */
+    const char *out;  /* output directory */
+    const char *suffix;/* suffix for output files */
+    const char *err;  /* suffix for error output files */
+    int     options;  /* parser options for the test */
+};
+
+static int checkTestFile(const char *filename);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
+#include <windows.h>
+#include <io.h>
+
+typedef struct
+{
+      size_t gl_pathc;    /* Count of paths matched so far  */
+      char **gl_pathv;    /* List of matched pathnames.  */
+      size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */
+} glob_t;
+
+#define GLOB_DOOFFS 0
+static int glob(const char *pattern, int flags,
+                int errfunc(const char *epath, int eerrno),
+                glob_t *pglob) {
+    glob_t *ret;
+    WIN32_FIND_DATA FindFileData;
+    HANDLE hFind;
+    unsigned int nb_paths = 0;
+    char directory[500];
+    int len;
+
+    if ((pattern == NULL) || (pglob == NULL)) return(-1);
+    
+    strncpy(directory, pattern, 499);
+    for (len = strlen(directory);len >= 0;len--) {
+        if (directory[len] == '/') {
+	    len++;
+	    directory[len] = 0;
+	    break;
+	}
+    }
+    if (len <= 0)
+        len = 0;
+
+    
+    ret = pglob;
+    memset(ret, 0, sizeof(glob_t));
+    
+    hFind = FindFirstFileA(pattern, &FindFileData);
+    if (hFind == INVALID_HANDLE_VALUE) 
+        return(0);
+    nb_paths = 20;
+    ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
+    if (ret->gl_pathv == NULL) {
+	FindClose(hFind);
+        return(-1);
+    }
+    strncpy(directory + len, FindFileData.cFileName, 499 - len);
+    ret->gl_pathv[ret->gl_pathc] = strdup(directory);
+    if (ret->gl_pathv[ret->gl_pathc] == NULL)
+        goto done;
+    ret->gl_pathc++;
+    while(FindNextFileA(hFind, &FindFileData)) {
+        if (FindFileData.cFileName[0] == '.')
+	    continue;
+        if (ret->gl_pathc + 2 > nb_paths) {
+            char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
+            if (tmp == NULL)
+                break;
+            ret->gl_pathv = tmp;
+            nb_paths *= 2;
+	}
+	strncpy(directory + len, FindFileData.cFileName, 499 - len);
+	ret->gl_pathv[ret->gl_pathc] = strdup(directory);
+        if (ret->gl_pathv[ret->gl_pathc] == NULL)
+            break;
+        ret->gl_pathc++;
+    }
+    ret->gl_pathv[ret->gl_pathc] = NULL;
+
+done:
+    FindClose(hFind);
+    return(0);
+}
+ 
+
+
+static void globfree(glob_t *pglob) {
+    unsigned int i;
+    if (pglob == NULL)
+        return;
+    
+    for (i = 0;i < pglob->gl_pathc;i++) {
+         if (pglob->gl_pathv[i] != NULL)
+             free(pglob->gl_pathv[i]);
+    }
+}
+#define vsnprintf _vsnprintf
+#define snprintf _snprintf
+#else
+#include <glob.h>
+#endif
+
+/************************************************************************
+ *									*
+ *		Libxml2 specific routines				*
+ *									*
+ ************************************************************************/
+
+static int nb_tests = 0;
+static int nb_errors = 0;
+static int nb_leaks = 0;
+static long libxmlMemoryAllocatedBase = 0;
+static int extraMemoryFromResolver = 0;
+
+static int
+fatalError(void) {
+    fprintf(stderr, "Exitting tests on fatal error\n");
+    exit(1);
+}
+
+/*
+ * We need to trap calls to the resolver to not account memory for the catalog
+ * which is shared to the current running test. We also don't want to have
+ * network downloads modifying tests.
+ */
+static xmlParserInputPtr 
+testExternalEntityLoader(const char *URL, const char *ID,
+			 xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr ret;
+
+    if (checkTestFile(URL)) {
+	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+    } else {
+	int memused = xmlMemUsed();
+	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+	extraMemoryFromResolver += xmlMemUsed() - memused;
+    }
+      
+    return(ret);
+}
+
+/*
+ * Trapping the error messages at the generic level to grab the equivalent of
+ * stderr messages on CLI tools.
+ */
+static char testErrors[32769];
+static int testErrorsSize = 0;
+
+static void
+testErrorHandler(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
+    va_list args;
+    int res;
+
+    if (testErrorsSize >= 32768)
+        return;
+    va_start(args, msg);
+    res = vsnprintf(&testErrors[testErrorsSize],
+                    32768 - testErrorsSize,
+		    msg, args);
+    va_end(args);
+    if (testErrorsSize + res >= 32768) {
+        /* buffer is full */
+	testErrorsSize = 32768;
+	testErrors[testErrorsSize] = 0;
+    } else {
+        testErrorsSize += res;
+    }
+    testErrors[testErrorsSize] = 0;
+}
+
+static void
+channel(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
+    va_list args;
+    int res;
+
+    if (testErrorsSize >= 32768)
+        return;
+    va_start(args, msg);
+    res = vsnprintf(&testErrors[testErrorsSize],
+                    32768 - testErrorsSize,
+		    msg, args);
+    va_end(args);
+    if (testErrorsSize + res >= 32768) {
+        /* buffer is full */
+	testErrorsSize = 32768;
+	testErrors[testErrorsSize] = 0;
+    } else {
+        testErrorsSize += res;
+    }
+    testErrors[testErrorsSize] = 0;
+}
+
+/**
+ * xmlParserPrintFileContext:
+ * @input:  an xmlParserInputPtr input
+ * 
+ * Displays current context within the input content for error tracking
+ */
+
+static void
+xmlParserPrintFileContextInternal(xmlParserInputPtr input , 
+		xmlGenericErrorFunc chanl, void *data ) {
+    const xmlChar *cur, *base;
+    unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */
+    xmlChar  content[81]; /* space for 80 chars + line terminator */
+    xmlChar *ctnt;
+
+    if (input == NULL) return;
+    cur = input->cur;
+    base = input->base;
+    /* skip backwards over any end-of-lines */
+    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
+	cur--;
+    }
+    n = 0;
+    /* search backwards for beginning-of-line (to max buff size) */
+    while ((n++ < (sizeof(content)-1)) && (cur > base) && 
+    	   (*(cur) != '\n') && (*(cur) != '\r'))
+        cur--;
+    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
+    /* calculate the error position in terms of the current position */
+    col = input->cur - cur;
+    /* search forward for end-of-line (to max buff size) */
+    n = 0;
+    ctnt = content;
+    /* copy selected text to our buffer */
+    while ((*cur != 0) && (*(cur) != '\n') && 
+    	   (*(cur) != '\r') && (n < sizeof(content)-1)) {
+		*ctnt++ = *cur++;
+	n++;
+    }
+    *ctnt = 0;
+    /* print out the selected text */
+    chanl(data ,"%s\n", content);
+    /* create blank line with problem pointer */
+    n = 0;
+    ctnt = content;
+    /* (leave buffer space for pointer + line terminator) */
+    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
+	if (*(ctnt) != '\t')
+	    *(ctnt) = ' ';
+	ctnt++;
+    }
+    *ctnt++ = '^';
+    *ctnt = 0;
+    chanl(data ,"%s\n", content);
+}
+
+static void
+testStructuredErrorHandler(void *ctx  ATTRIBUTE_UNUSED, xmlErrorPtr err) {
+    char *file = NULL;
+    int line = 0;
+    int code = -1;
+    int domain;
+    void *data = NULL;
+    const char *str;
+    const xmlChar *name = NULL;
+    xmlNodePtr node;
+    xmlErrorLevel level;
+    xmlParserInputPtr input = NULL;
+    xmlParserInputPtr cur = NULL;
+    xmlParserCtxtPtr ctxt = NULL;
+
+    if (err == NULL)
+        return;
+
+    file = err->file;
+    line = err->line;
+    code = err->code;
+    domain = err->domain;
+    level = err->level;
+    node = err->node;
+    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
+        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
+	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
+	ctxt = err->ctxt;
+    }
+    str = err->message;
+
+    if (code == XML_ERR_OK)
+        return;
+
+    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
+        name = node->name;
+
+    /*
+     * Maintain the compatibility with the legacy error handling
+     */
+    if (ctxt != NULL) {
+        input = ctxt->input;
+        if ((input != NULL) && (input->filename == NULL) &&
+            (ctxt->inputNr > 1)) {
+            cur = input;
+            input = ctxt->inputTab[ctxt->inputNr - 2];
+        }
+        if (input != NULL) {
+            if (input->filename)
+                channel(data, "%s:%d: ", input->filename, input->line);
+            else if ((line != 0) && (domain == XML_FROM_PARSER))
+                channel(data, "Entity: line %d: ", input->line);
+        }
+    } else {
+        if (file != NULL)
+            channel(data, "%s:%d: ", file, line);
+        else if ((line != 0) && (domain == XML_FROM_PARSER))
+            channel(data, "Entity: line %d: ", line);
+    }
+    if (name != NULL) {
+        channel(data, "element %s: ", name);
+    }
+    if (code == XML_ERR_OK)
+        return;
+    switch (domain) {
+        case XML_FROM_PARSER:
+            channel(data, "parser ");
+            break;
+        case XML_FROM_NAMESPACE:
+            channel(data, "namespace ");
+            break;
+        case XML_FROM_DTD:
+        case XML_FROM_VALID:
+            channel(data, "validity ");
+            break;
+        case XML_FROM_HTML:
+            channel(data, "HTML parser ");
+            break;
+        case XML_FROM_MEMORY:
+            channel(data, "memory ");
+            break;
+        case XML_FROM_OUTPUT:
+            channel(data, "output ");
+            break;
+        case XML_FROM_IO:
+            channel(data, "I/O ");
+            break;
+        case XML_FROM_XINCLUDE:
+            channel(data, "XInclude ");
+            break;
+        case XML_FROM_XPATH:
+            channel(data, "XPath ");
+            break;
+        case XML_FROM_XPOINTER:
+            channel(data, "parser ");
+            break;
+        case XML_FROM_REGEXP:
+            channel(data, "regexp ");
+            break;
+        case XML_FROM_MODULE:
+            channel(data, "module ");
+            break;
+        case XML_FROM_SCHEMASV:
+            channel(data, "Schemas validity ");
+            break;
+        case XML_FROM_SCHEMASP:
+            channel(data, "Schemas parser ");
+            break;
+        case XML_FROM_RELAXNGP:
+            channel(data, "Relax-NG parser ");
+            break;
+        case XML_FROM_RELAXNGV:
+            channel(data, "Relax-NG validity ");
+            break;
+        case XML_FROM_CATALOG:
+            channel(data, "Catalog ");
+            break;
+        case XML_FROM_C14N:
+            channel(data, "C14N ");
+            break;
+        case XML_FROM_XSLT:
+            channel(data, "XSLT ");
+            break;
+        default:
+            break;
+    }
+    if (code == XML_ERR_OK)
+        return;
+    switch (level) {
+        case XML_ERR_NONE:
+            channel(data, ": ");
+            break;
+        case XML_ERR_WARNING:
+            channel(data, "warning : ");
+            break;
+        case XML_ERR_ERROR:
+            channel(data, "error : ");
+            break;
+        case XML_ERR_FATAL:
+            channel(data, "error : ");
+            break;
+    }
+    if (code == XML_ERR_OK)
+        return;
+    if (str != NULL) {
+        int len;
+	len = xmlStrlen((const xmlChar *)str);
+	if ((len > 0) && (str[len - 1] != '\n'))
+	    channel(data, "%s\n", str);
+	else
+	    channel(data, "%s", str);
+    } else {
+        channel(data, "%s\n", "out of memory error");
+    }
+    if (code == XML_ERR_OK)
+        return;
+
+    if (ctxt != NULL) {
+        xmlParserPrintFileContextInternal(input, channel, data);
+        if (cur != NULL) {
+            if (cur->filename)
+                channel(data, "%s:%d: \n", cur->filename, cur->line);
+            else if ((line != 0) && (domain == XML_FROM_PARSER))
+                channel(data, "Entity: line %d: \n", cur->line);
+            xmlParserPrintFileContextInternal(cur, channel, data);
+        }
+    }
+    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
+        (err->int1 < 100) &&
+	(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
+	xmlChar buf[150];
+	int i;
+
+	channel(data, "%s\n", err->str1);
+	for (i=0;i < err->int1;i++)
+	     buf[i] = ' ';
+	buf[i++] = '^';
+	buf[i] = 0;
+	channel(data, "%s\n", buf);
+    }
+}
+
+static void
+initializeLibxml2(void) {
+    xmlGetWarningsDefaultValue = 0;
+    xmlPedanticParserDefault(0);
+
+    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
+    xmlInitParser();
+    xmlSetExternalEntityLoader(testExternalEntityLoader);
+    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
+#ifdef LIBXML_SCHEMAS_ENABLED
+    xmlSchemaInitTypes();
+    xmlRelaxNGInitTypes();
+#endif
+    libxmlMemoryAllocatedBase = xmlMemUsed();
+}
+
+
+/************************************************************************
+ *									*
+ *		File name and path utilities				*
+ *									*
+ ************************************************************************/
+
+static const char *baseFilename(const char *filename) {
+    const char *cur;
+    if (filename == NULL)
+        return(NULL);
+    cur = &filename[strlen(filename)];
+    while ((cur > filename) && (*cur != '/'))
+        cur--;
+    if (*cur == '/')
+        return(cur + 1);
+    return(cur);
+}
+
+static char *resultFilename(const char *filename, const char *out,
+                            const char *suffix) {
+    const char *base;
+    char res[500];
+
+/*************
+    if ((filename[0] == 't') && (filename[1] == 'e') &&
+        (filename[2] == 's') && (filename[3] == 't') &&
+	(filename[4] == '/'))
+	filename = &filename[5];
+ *************/
+    
+    base = baseFilename(filename);
+    if (suffix == NULL)
+        suffix = ".tmp";
+    if (out == NULL)
+        out = "";
+    snprintf(res, 499, "%s%s%s", out, base, suffix);
+    res[499] = 0;
+    return(strdup(res));
+}
+
+static int checkTestFile(const char *filename) {
+    struct stat buf;
+
+    if (stat(filename, &buf) == -1)
+        return(0);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+    if (!(buf.st_mode & _S_IFREG))
+        return(0);
+#else
+    if (!S_ISREG(buf.st_mode))
+        return(0);
+#endif
+
+    return(1);
+}
+
+static int compareFiles(const char *r1, const char *r2) {
+    int res1, res2;
+    int fd1, fd2;
+    char bytes1[4096];
+    char bytes2[4096];
+
+    fd1 = open(r1, RD_FLAGS);
+    if (fd1 < 0)
+        return(-1);
+    fd2 = open(r2, RD_FLAGS);
+    if (fd2 < 0) {
+        close(fd1);
+        return(-1);
+    }
+    while (1) {
+        res1 = read(fd1, bytes1, 4096);
+        res2 = read(fd2, bytes2, 4096);
+	if (res1 != res2) {
+	    close(fd1);
+	    close(fd2);
+	    return(1);
+	}
+	if (res1 == 0)
+	    break;
+	if (memcmp(bytes1, bytes2, res1) != 0) {
+	    close(fd1);
+	    close(fd2);
+	    return(1);
+	}
+    }
+    close(fd1);
+    close(fd2);
+    return(0);
+}
+
+static int compareFileMem(const char *filename, const char *mem, int size) {
+    int res;
+    int fd;
+    char bytes[4096];
+    int idx = 0;
+    struct stat info;
+
+    if (stat(filename, &info) < 0) 
+	return(-1);
+    if (info.st_size != size)
+        return(-1);
+    fd = open(filename, RD_FLAGS);
+    if (fd < 0)
+        return(-1);
+    while (idx < size) {
+        res = read(fd, bytes, 4096);
+	if (res <= 0)
+	    break;
+	if (res + idx > size) 
+	    break;
+	if (memcmp(bytes, &mem[idx], res) != 0) {
+	    int ix;
+	    for (ix=0; ix<res; ix++)
+		if (bytes[ix] != mem[idx+ix])
+			break;
+	    fprintf(stderr,"Compare error at position %d\n", idx+ix);
+	    close(fd);
+	    return(1);
+	}
+	idx += res;
+    }
+    close(fd);
+    return(idx != size);
+}
+
+static int loadMem(const char *filename, const char **mem, int *size) {
+    int fd, res;
+    struct stat info;
+    char *base;
+    int siz = 0;
+    if (stat(filename, &info) < 0) 
+	return(-1);
+    base = malloc(info.st_size + 1);
+    if (base == NULL)
+	return(-1);
+    if ((fd = open(filename, RD_FLAGS)) < 0) {
+        free(base);
+	return(-1);
+    }
+    while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
+        siz += res;
+    }
+    close(fd);
+#if !defined(_WIN32)
+    if (siz != info.st_size) {
+        free(base);
+	return(-1);
+    }
+#endif
+    base[siz] = 0;
+    *mem = base;
+    *size = siz;
+    return(0);
+}
+
+static int unloadMem(const char *mem) {
+    free((char *)mem);
+    return(0);
+}
+
+/************************************************************************
+ *									*
+ *		Tests implementations					*
+ *									*
+ ************************************************************************/
+
+/************************************************************************
+ *									*
+ *		Parse to SAX based tests				*
+ *									*
+ ************************************************************************/
+
+FILE *SAXdebug = NULL;
+
+/*
+ * 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 */
+};
+
+static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
+int callbacks = 0;
+int quiet = 0;
+
+/**
+ * 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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.internalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(SAXdebug, " ,");
+    else
+	fprintf(SAXdebug, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(SAXdebug, " )\n");
+    else
+	fprintf(SAXdebug, " %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(SAXdebug, "SAX.externalSubset(%s,", name);
+    if (ExternalID == NULL)
+	fprintf(SAXdebug, " ,");
+    else
+	fprintf(SAXdebug, " %s,", ExternalID);
+    if (SystemID == NULL)
+	fprintf(SAXdebug, " )\n");
+    else
+	fprintf(SAXdebug, " %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(SAXdebug, "SAX.resolveEntity(");
+    if (publicId != NULL)
+	fprintf(SAXdebug, "%s", (char *)publicId);
+    else
+	fprintf(SAXdebug, " ");
+    if (systemId != NULL)
+	fprintf(SAXdebug, ", %s)\n", (char *)systemId);
+    else
+	fprintf(SAXdebug, ", )\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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
+                elem, name, type, def);
+    else
+        fprintf(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.startElement(%s", (char *) name);
+    if (atts != NULL) {
+        for (i = 0;(atts[i] != NULL);i++) {
+	    fprintf(SAXdebug, ", %s='", atts[i++]);
+	    if (atts[i] != NULL)
+	        fprintf(SAXdebug, "%s'", atts[i]);
+	}
+    }
+    fprintf(SAXdebug, ")\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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
+		(char *) target, (char *) data);
+    else
+	fprintf(SAXdebug, "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(SAXdebug, "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(SAXdebug, "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(SAXdebug, "SAX.warning: ");
+    vfprintf(SAXdebug, 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(SAXdebug, "SAX.error: ");
+    vfprintf(SAXdebug, 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(SAXdebug, "SAX.fatalError: ");
+    vfprintf(SAXdebug, 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(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(SAXdebug, ", NULL");
+    else
+	fprintf(SAXdebug, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(SAXdebug, ", NULL");
+    else
+	fprintf(SAXdebug, ", '%s'", (char *) URI);
+    fprintf(SAXdebug, ", %d", nb_namespaces);
+    
+    if (namespaces != NULL) {
+        for (i = 0;i < nb_namespaces * 2;i++) {
+	    fprintf(SAXdebug, ", xmlns");
+	    if (namespaces[i] != NULL)
+	        fprintf(SAXdebug, ":%s", namespaces[i]);
+	    i++;
+	    fprintf(SAXdebug, "='%s'", namespaces[i]);
+	}
+    }
+    fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
+    if (attributes != NULL) {
+        for (i = 0;i < nb_attributes * 5;i += 5) {
+	    if (attributes[i + 1] != NULL)
+		fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
+	    else
+		fprintf(SAXdebug, ", %s='", attributes[i]);
+	    fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
+		    (int)(attributes[i + 4] - attributes[i + 3]));
+	}
+    }
+    fprintf(SAXdebug, ")\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(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
+    if (prefix == NULL)
+	fprintf(SAXdebug, ", NULL");
+    else
+	fprintf(SAXdebug, ", %s", (char *) prefix);
+    if (URI == NULL)
+	fprintf(SAXdebug, ", NULL)\n");
+    else
+	fprintf(SAXdebug, ", '%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;
+
+#ifdef LIBXML_HTML_ENABLED
+/**
+ * htmlstartElementDebug:
+ * @ctxt:  An XML parser context
+ * @name:  The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
+{
+    int i;
+
+    fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
+    if (atts != NULL) {
+        for (i = 0;(atts[i] != NULL);i++) {
+	    fprintf(SAXdebug, ", %s", atts[i++]);
+	    if (atts[i] != NULL) {
+		unsigned char output[40];
+		const unsigned char *att = atts[i];
+		int outlen, attlen;
+	        fprintf(SAXdebug, "='");
+		while ((attlen = strlen((char*)att)) > 0) {
+		    outlen = sizeof output - 1;
+		    htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
+		    output[outlen] = 0;
+		    fprintf(SAXdebug, "%s", (char *) output);
+		    att += attlen;
+		}
+		fprintf(SAXdebug, "'");
+	    }
+	}
+    }
+    fprintf(SAXdebug, ")\n");
+}
+
+/**
+ * htmlcharactersDebug:
+ * @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
+htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+    unsigned char output[40];
+    int inlen = len, outlen = 30;
+
+    htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
+    output[outlen] = 0;
+
+    fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
+}
+
+/**
+ * htmlcdataDebug:
+ * @ctxt:  An XML parser context
+ * @ch:  a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some cdata chars from the parser.
+ * Question: how much at a time ???
+ */
+static void
+htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+    unsigned char output[40];
+    int inlen = len, outlen = 30;
+
+    htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
+    output[outlen] = 0;
+
+    fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
+}
+
+xmlSAXHandler debugHTMLSAXHandlerStruct = {
+    internalSubsetDebug,
+    isStandaloneDebug,
+    hasInternalSubsetDebug,
+    hasExternalSubsetDebug,
+    resolveEntityDebug,
+    getEntityDebug,
+    entityDeclDebug,
+    notationDeclDebug,
+    attributeDeclDebug,
+    elementDeclDebug,
+    unparsedEntityDeclDebug,
+    setDocumentLocatorDebug,
+    startDocumentDebug,
+    endDocumentDebug,
+    htmlstartElementDebug,
+    endElementDebug,
+    referenceDebug,
+    htmlcharactersDebug,
+    ignorableWhitespaceDebug,
+    processingInstructionDebug,
+    commentDebug,
+    warningDebug,
+    errorDebug,
+    fatalErrorDebug,
+    getParameterEntityDebug,
+    htmlcdataDebug,
+    externalSubsetDebug,
+    1,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
+#endif /* LIBXML_HTML_ENABLED */
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * saxParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the SAX API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+saxParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+             int options) {
+    int ret;
+    char *temp;
+
+    nb_tests++;
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "out of memory\n");
+        fatalError();
+    }
+    SAXdebug = fopen(temp, "wb");
+    if (SAXdebug == NULL) {
+        fprintf(stderr, "Failed to write to %s\n", temp);
+	free(temp);
+	return(-1);
+    }
+
+    /* for SAX we really want the callbacks though the context handlers */
+    xmlSetStructuredErrorFunc(NULL, NULL);
+    xmlSetGenericErrorFunc(NULL, testErrorHandler);
+
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+	htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
+	ret = 0;
+    } else
+#endif
+    ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
+    if (ret == XML_WAR_UNDECLARED_ENTITY) {
+        fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
+        ret = 0;
+    }
+    if (ret != 0) {
+        fprintf(stderr, "Failed to parse %s\n", filename);
+	return(1);
+    }
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+	htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
+	ret = 0;
+    } else
+#endif
+    if (options & XML_PARSE_SAX1) {
+	ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
+    } else {
+	ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
+    }
+    if (ret == XML_WAR_UNDECLARED_ENTITY) {
+        fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
+        ret = 0;
+    }
+    fclose(SAXdebug);
+    if (compareFiles(temp, result)) {
+        fprintf(stderr, "Got a difference for %s\n", filename);
+        ret = 1;
+    } else
+    unlink(temp);
+    free(temp);
+    
+    /* switch back to structured error handling */
+    xmlSetGenericErrorFunc(NULL, NULL);
+    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
+
+    return(ret);
+}
+#endif
+
+/************************************************************************
+ *									*
+ *		Parse to tree based tests				*
+ *									*
+ ************************************************************************/
+/**
+ * oldParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the old xmlParseFile API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+oldParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+	     int options ATTRIBUTE_UNUSED) {
+    xmlDocPtr doc;
+    char *temp;
+    int res = 0;
+
+    nb_tests++;
+    /*
+     * base of the test, parse with the old API
+     */
+#ifdef LIBXML_SAX1_ENABLED
+    doc = xmlParseFile(filename);
+#else
+    doc = xmlReadFile(filename, NULL, 0);
+#endif
+    if (doc == NULL)
+        return(1);
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "out of memory\n");
+        fatalError();
+    }
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    /*
+     * Parse the saved result to make sure the round trip is okay
+     */
+#ifdef LIBXML_SAX1_ENABLED
+    doc = xmlParseFile(temp);
+#else
+    doc = xmlReadFile(temp, NULL, 0);
+#endif
+    if (doc == NULL)
+        return(1);
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    unlink(temp);
+    free(temp);
+    return(res);
+}
+
+#ifdef LIBXML_PUSH_ENABLED
+/**
+ * pushParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the Push API, then serialize back
+ * to check for content.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+pushParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+	     int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    const char *base;
+    int size, res;
+    int cur = 0;
+
+    nb_tests++;
+    /*
+     * load the document in memory and work from there.
+     */
+    if (loadMem(filename, &base, &size) != 0) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+    
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+	ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
+	                                XML_CHAR_ENCODING_NONE);
+    else
+#endif
+    ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
+    xmlCtxtUseOptions(ctxt, options);
+    cur += 4;
+    while (cur < size) {
+        if (cur + 1024 >= size) {
+#ifdef LIBXML_HTML_ENABLED
+	    if (options & XML_PARSE_HTML)
+		htmlParseChunk(ctxt, base + cur, size - cur, 1);
+	    else
+#endif
+	    xmlParseChunk(ctxt, base + cur, size - cur, 1);
+	    break;
+	} else {
+#ifdef LIBXML_HTML_ENABLED
+	    if (options & XML_PARSE_HTML)
+		htmlParseChunk(ctxt, base + cur, 1024, 0);
+	    else
+#endif
+	    xmlParseChunk(ctxt, base + cur, 1024, 0);
+	    cur += 1024;
+	}
+    }
+    doc = ctxt->myDoc;
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+        res = 1;
+    else
+#endif
+    res = ctxt->wellFormed;
+    xmlFreeParserCtxt(ctxt);
+    free((char *)base);
+    if (!res) {
+	xmlFreeDoc(doc);
+	fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML)
+	htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    else
+#endif
+    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    xmlFreeDoc(doc);
+    res = compareFileMem(result, base, size);
+    if ((base == NULL) || (res != 0)) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+        fprintf(stderr, "Result for %s failed\n", filename);
+	return(-1);
+    }
+    xmlFree((char *)base);
+    if (err != NULL) {
+	res = compareFileMem(err, testErrors, testErrorsSize);
+	if (res != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    return(-1);
+	}
+    }
+    return(0);
+}
+#endif
+
+/**
+ * memParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the old xmlReadMemory API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+memParseTest(const char *filename, const char *result,
+             const char *err ATTRIBUTE_UNUSED,
+	     int options ATTRIBUTE_UNUSED) {
+    xmlDocPtr doc;
+    const char *base;
+    int size, res;
+
+    nb_tests++;
+    /*
+     * load and parse the memory
+     */
+    if (loadMem(filename, &base, &size) != 0) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+    
+    doc = xmlReadMemory(base, size, filename, NULL, 0);
+    unloadMem(base);
+    if (doc == NULL) {
+        return(1);
+    }
+    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+    xmlFreeDoc(doc);
+    res = compareFileMem(result, base, size);
+    if ((base == NULL) || (res != 0)) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+        fprintf(stderr, "Result for %s failed\n", filename);
+	return(-1);
+    }
+    xmlFree((char *)base);
+    return(0);
+}
+
+/**
+ * noentParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file with entity resolution, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+noentParseTest(const char *filename, const char *result,
+               const char *err  ATTRIBUTE_UNUSED,
+	       int options) {
+    xmlDocPtr doc;
+    char *temp;
+    int res = 0;
+
+    nb_tests++;
+    /*
+     * base of the test, parse with the old API
+     */
+    doc = xmlReadFile(filename, NULL, options);
+    if (doc == NULL)
+        return(1);
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    /*
+     * Parse the saved result to make sure the round trip is okay
+     */
+    doc = xmlReadFile(filename, NULL, options);
+    if (doc == NULL)
+        return(1);
+    xmlSaveFile(temp, doc);
+    if (compareFiles(temp, result)) {
+        res = 1;
+    }
+    xmlFreeDoc(doc);
+
+    unlink(temp);
+    free(temp);
+    return(res);
+}
+
+/**
+ * errParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the xmlReadFile API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+errParseTest(const char *filename, const char *result, const char *err,
+             int options) {
+    xmlDocPtr doc;
+    const char *base = NULL;
+    int size, res = 0;
+
+    nb_tests++;
+#ifdef LIBXML_HTML_ENABLED
+    if (options & XML_PARSE_HTML) {
+        doc = htmlReadFile(filename, NULL, options);
+    } else
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+    if (options & XML_PARSE_XINCLUDE) {
+	doc = xmlReadFile(filename, NULL, options);
+	xmlXIncludeProcessFlags(doc, options);
+    } else
+#endif
+    {
+	xmlGetWarningsDefaultValue = 1;
+	doc = xmlReadFile(filename, NULL, options);
+    }
+    xmlGetWarningsDefaultValue = 0;
+    if (result) {
+	if (doc == NULL) {
+	    base = "";
+	    size = 0;
+	} else {
+#ifdef LIBXML_HTML_ENABLED
+	    if (options & XML_PARSE_HTML) {
+		htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+	    } else
+#endif
+	    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+	}
+	res = compareFileMem(result, base, size);
+    }
+    if (doc != NULL) {
+	if (base != NULL)
+	    xmlFree((char *)base);
+	xmlFreeDoc(doc);
+    }
+    if (res != 0) {
+        fprintf(stderr, "Result for %s failed\n", filename);
+	return(-1);
+    }
+    if (err != NULL) {
+	res = compareFileMem(err, testErrors, testErrorsSize);
+	if (res != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    return(-1);
+	}
+    } else if (options & XML_PARSE_DTDVALID) {
+        if (testErrorsSize != 0)
+	    fprintf(stderr, "Validation for %s failed\n", filename);
+    }
+
+    return(0);
+}
+
+#ifdef LIBXML_READER_ENABLED
+/************************************************************************
+ *									*
+ *		Reader based tests					*
+ *									*
+ ************************************************************************/
+
+static void processNode(FILE *out, xmlTextReaderPtr reader) {
+    const xmlChar *name, *value;
+    int type, empty;
+
+    type = xmlTextReaderNodeType(reader);
+    empty = xmlTextReaderIsEmptyElement(reader);
+
+    name = xmlTextReaderConstName(reader);
+    if (name == NULL)
+	name = BAD_CAST "--";
+
+    value = xmlTextReaderConstValue(reader);
+
+    
+    fprintf(out, "%d %d %s %d %d", 
+	    xmlTextReaderDepth(reader),
+	    type,
+	    name,
+	    empty,
+	    xmlTextReaderHasValue(reader));
+    if (value == NULL)
+	fprintf(out, "\n");
+    else {
+	fprintf(out, " %s\n", value);
+    }
+}
+static int
+streamProcessTest(const char *filename, const char *result, const char *err,
+                  xmlTextReaderPtr reader, const char *rng) {
+    int ret;
+    char *temp = NULL;
+    FILE *t = NULL;
+
+    if (reader == NULL)
+        return(-1);
+
+    nb_tests++;
+    if (result != NULL) {
+	temp = resultFilename(filename, "", ".res");
+	if (temp == NULL) {
+	    fprintf(stderr, "Out of memory\n");
+	    fatalError();
+	}
+	t = fopen(temp, "wb");
+	if (t == NULL) {
+	    fprintf(stderr, "Can't open temp file %s\n", temp);
+	    free(temp);
+	    return(-1);
+	}
+    }
+#ifdef LIBXML_SCHEMAS_ENABLED
+    if (rng != NULL) {
+	ret = xmlTextReaderRelaxNGValidate(reader, rng);
+	if (ret < 0) {
+	    testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
+	                     rng);
+	    fclose(t);
+	    unlink(temp);
+	    free(temp);
+	    return(0);
+	}
+    }
+#endif
+    xmlGetWarningsDefaultValue = 1;
+    ret = xmlTextReaderRead(reader);
+    while (ret == 1) {
+	if ((t != NULL) && (rng == NULL))
+	    processNode(t, reader);
+        ret = xmlTextReaderRead(reader);
+    }
+    if (ret != 0) {
+        testErrorHandler(NULL, "%s : failed to parse\n", filename);
+    }
+    if (rng != NULL) {
+        if (xmlTextReaderIsValid(reader) != 1) {
+	    testErrorHandler(NULL, "%s fails to validate\n", filename);
+	} else {
+	    testErrorHandler(NULL, "%s validates\n", filename);
+	}
+    }
+    xmlGetWarningsDefaultValue = 0;
+    if (t != NULL) {
+        fclose(t);
+	ret = compareFiles(temp, result);
+	unlink(temp);
+	free(temp);
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed\n", filename);
+	    return(-1);
+	}
+    }
+    if (err != NULL) {
+	ret = compareFileMem(err, testErrors, testErrorsSize);
+	if (ret != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    printf("%s", testErrors);
+	    return(-1);
+	}
+    }
+
+    return(0);
+}
+
+/**
+ * streamParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the reader API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+streamParseTest(const char *filename, const char *result, const char *err,
+                int options) {
+    xmlTextReaderPtr reader;
+    int ret;
+
+    reader = xmlReaderForFile(filename, NULL, options);
+    ret = streamProcessTest(filename, result, err, reader, NULL);
+    xmlFreeTextReader(reader);
+    return(ret);
+}
+
+/**
+ * walkerParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the walker, i.e. a reader built from a atree.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+walkerParseTest(const char *filename, const char *result, const char *err,
+                int options) {
+    xmlDocPtr doc;
+    xmlTextReaderPtr reader;
+    int ret;
+
+    doc = xmlReadFile(filename, NULL, options);
+    if (doc == NULL) {
+        fprintf(stderr, "Failed to parse %s\n", filename);
+	return(-1);
+    }
+    reader = xmlReaderWalker(doc);
+    ret = streamProcessTest(filename, result, err, reader, NULL);
+    xmlFreeTextReader(reader);
+    xmlFreeDoc(doc);
+    return(ret);
+}
+
+/**
+ * streamMemParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the reader API from memory and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+streamMemParseTest(const char *filename, const char *result, const char *err,
+                   int options) {
+    xmlTextReaderPtr reader;
+    int ret;
+    const char *base;
+    int size;
+
+    /*
+     * load and parse the memory
+     */
+    if (loadMem(filename, &base, &size) != 0) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+    reader = xmlReaderForMemory(base, size, filename, NULL, options);
+    ret = streamProcessTest(filename, result, err, reader, NULL);
+    free((char *)base);
+    xmlFreeTextReader(reader);
+    return(ret);
+}
+#endif
+
+#ifdef LIBXML_XPATH_ENABLED
+#ifdef LIBXML_DEBUG_ENABLED
+/************************************************************************
+ *									*
+ *		XPath and XPointer based tests				*
+ *									*
+ ************************************************************************/
+
+FILE *xpathOutput;
+xmlDocPtr xpathDocument;
+
+static void
+testXPath(const char *str, int xptr, int expr) {
+    xmlXPathObjectPtr res;
+    xmlXPathContextPtr ctxt;
+    
+    nb_tests++;
+#if defined(LIBXML_XPTR_ENABLED)
+    if (xptr) {
+	ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
+	res = xmlXPtrEval(BAD_CAST str, ctxt);
+    } else {
+#endif
+	ctxt = xmlXPathNewContext(xpathDocument);
+	ctxt->node = xmlDocGetRootElement(xpathDocument);
+	if (expr)
+	    res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
+	else {
+	    /* res = xmlXPathEval(BAD_CAST str, ctxt); */
+	    xmlXPathCompExprPtr comp;
+
+	    comp = xmlXPathCompile(BAD_CAST str);
+	    if (comp != NULL) {
+		res = xmlXPathCompiledEval(comp, ctxt);
+		xmlXPathFreeCompExpr(comp);
+	    } else
+		res = NULL;
+	}
+#if defined(LIBXML_XPTR_ENABLED)
+    }
+#endif
+    xmlXPathDebugDumpObject(xpathOutput, res, 0);
+    xmlXPathFreeObject(res);
+    xmlXPathFreeContext(ctxt);
+}
+
+/**
+ * xpathExprTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath standalone expressions and evaluate them
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathCommonTest(const char *filename, const char *result,
+                int xptr, int expr) {
+    FILE *input;
+    char expression[5000];
+    int len, ret = 0;
+    char *temp;
+
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    xpathOutput = fopen(temp, "wb");
+    if (xpathOutput == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        free(temp);
+	return(-1);
+    }
+
+    input = fopen(filename, "rb");
+    if (input == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+		"Cannot open %s for reading\n", filename);
+        free(temp);
+	return(-1);
+    }
+    while (fgets(expression, 4500, input) != NULL) {
+	len = strlen(expression);
+	len--;
+	while ((len >= 0) && 
+	       ((expression[len] == '\n') || (expression[len] == '\t') ||
+		(expression[len] == '\r') || (expression[len] == ' '))) len--;
+	expression[len + 1] = 0;      
+	if (len >= 0) {
+	    fprintf(xpathOutput,
+	            "\n========================\nExpression: %s\n",
+		    expression) ;
+	    testXPath(expression, xptr, expr);
+	}
+    }
+
+    fclose(input);
+    fclose(xpathOutput);
+    if (result != NULL) {
+	ret = compareFiles(temp, result);
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed\n", filename);
+	}
+    }
+
+    unlink(temp);
+    free(temp);
+    return(ret);
+}
+
+/**
+ * xpathExprTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath standalone expressions and evaluate them
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathExprTest(const char *filename, const char *result,
+              const char *err ATTRIBUTE_UNUSED,
+              int options ATTRIBUTE_UNUSED) {
+    return(xpathCommonTest(filename, result, 0, 1));
+}
+
+/**
+ * xpathDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath expressions and evaluate them against
+ * a set of corresponding documents.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathDocTest(const char *filename,
+             const char *resul ATTRIBUTE_UNUSED,
+             const char *err ATTRIBUTE_UNUSED,
+             int options) {
+
+    char pattern[500];
+    char result[500];
+    glob_t globbuf;
+    size_t i;
+    int ret = 0, res;
+
+    xpathDocument = xmlReadFile(filename, NULL,
+                                options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+    if (xpathDocument == NULL) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
+    pattern[499] = 0;
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        snprintf(result, 499, "result/XPath/tests/%s",
+	         baseFilename(globbuf.gl_pathv[i]));
+	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
+	if (res != 0)
+	    ret = res;
+    }
+    globfree(&globbuf);
+
+    xmlFreeDoc(xpathDocument);
+    return(ret);
+}
+
+#ifdef LIBXML_XPTR_ENABLED
+/**
+ * xptrDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath expressions and evaluate them against
+ * a set of corresponding documents.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xptrDocTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *err ATTRIBUTE_UNUSED,
+            int options) {
+
+    char pattern[500];
+    char result[500];
+    glob_t globbuf;
+    size_t i;
+    int ret = 0, res;
+
+    xpathDocument = xmlReadFile(filename, NULL,
+                                options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+    if (xpathDocument == NULL) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
+    pattern[499] = 0;
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        snprintf(result, 499, "result/XPath/xptr/%s",
+	         baseFilename(globbuf.gl_pathv[i]));
+	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
+	if (res != 0)
+	    ret = res;
+    }
+    globfree(&globbuf);
+
+    xmlFreeDoc(xpathDocument);
+    return(ret);
+}
+#endif /* LIBXML_XPTR_ENABLED */
+
+/**
+ * xmlidDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing xml:id and check for errors and verify
+ * that XPath queries will work on them as expected.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xmlidDocTest(const char *filename,
+             const char *result,
+             const char *err,
+             int options) {
+
+    int res = 0;
+    int ret = 0;
+    char *temp;
+
+    xpathDocument = xmlReadFile(filename, NULL,
+                                options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+    if (xpathDocument == NULL) {
+        fprintf(stderr, "Failed to load %s\n", filename);
+	return(-1);
+    }
+
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    xpathOutput = fopen(temp, "wb");
+    if (xpathOutput == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        xmlFreeDoc(xpathDocument);
+        free(temp);
+	return(-1);
+    }
+
+    testXPath("id('bar')", 0, 0);
+
+    fclose(xpathOutput);
+    if (result != NULL) {
+	ret = compareFiles(temp, result);
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed\n", filename);
+	    res = 1;
+	}
+    }
+
+    unlink(temp);
+    free(temp);
+    xmlFreeDoc(xpathDocument);
+
+    if (err != NULL) {
+	ret = compareFileMem(err, testErrors, testErrorsSize);
+	if (ret != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    res = 1;
+	}
+    }
+    return(res);
+}
+
+#endif /* LIBXML_DEBUG_ENABLED */
+#endif /* XPATH */
+/************************************************************************
+ *									*
+ *			URI based tests					*
+ *									*
+ ************************************************************************/
+
+static void
+handleURI(const char *str, const char *base, FILE *o) {
+    int ret;
+    xmlURIPtr uri;
+    xmlChar *res = NULL, *parsed = NULL;
+
+    uri = xmlCreateURI();
+
+    if (base == NULL) {
+	ret = xmlParseURIReference(uri, str);
+	if (ret != 0)
+	    fprintf(o, "%s : error %d\n", str, ret);
+	else {
+	    xmlNormalizeURIPath(uri->path);
+	    xmlPrintURI(o, uri);
+	    fprintf(o, "\n");
+	}
+    } else {
+	res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
+	if (res != NULL) {
+	    fprintf(o, "%s\n", (char *) res);
+	}
+	else
+	    fprintf(o, "::ERROR::\n");
+    }
+    if (res != NULL)
+	xmlFree(res);
+    if (parsed != NULL)
+	xmlFree(parsed);
+    xmlFreeURI(uri);
+}
+
+/**
+ * uriCommonTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI and check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriCommonTest(const char *filename,
+             const char *result,
+             const char *err,
+             const char *base) {
+    char *temp;
+    FILE *o, *f;
+    char str[1024];
+    int res = 0, i, ret;
+
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    o = fopen(temp, "wb");
+    if (o == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+        free(temp);
+	return(-1);
+    }
+    f = fopen(filename, "rb");
+    if (f == NULL) {
+	fprintf(stderr, "failed to open input file %s\n", filename);
+	fclose(o);
+	unlink(temp);
+        free(temp);
+	return(-1);
+    }
+
+    while (1) {
+	/*
+	 * read one line in string buffer.
+	 */
+	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
+	   break;
+
+	/*
+	 * remove the ending spaces
+	 */
+	i = strlen(str);
+	while ((i > 0) &&
+	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
+		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
+	    i--;
+	    str[i] = 0;
+	}
+	nb_tests++;
+	handleURI(str, base, o);
+    }
+
+    fclose(f);
+    fclose(o);
+
+    if (result != NULL) {
+	ret = compareFiles(temp, result);
+	if (ret) {
+	    fprintf(stderr, "Result for %s failed\n", filename);
+	    res = 1;
+	}
+    }
+    if (err != NULL) {
+	ret = compareFileMem(err, testErrors, testErrorsSize);
+	if (ret != 0) {
+	    fprintf(stderr, "Error for %s failed\n", filename);
+	    res = 1;
+	}
+    }
+
+    unlink(temp);
+    free(temp);
+    return(res);
+}
+
+/**
+ * uriParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI and check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriParseTest(const char *filename,
+             const char *result,
+             const char *err,
+             int options ATTRIBUTE_UNUSED) {
+    return(uriCommonTest(filename, result, err, NULL));
+}
+
+/**
+ * uriBaseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI, compose them against a fixed base and
+ * check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriBaseTest(const char *filename,
+             const char *result,
+             const char *err,
+             int options ATTRIBUTE_UNUSED) {
+    return(uriCommonTest(filename, result, err,
+                         "http://foo.com/path/to/index.html?orig#help"));
+}
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+/************************************************************************
+ *									*
+ *			Schemas tests					*
+ *									*
+ ************************************************************************/
+static int
+schemasOneTest(const char *sch,
+               const char *filename,
+               const char *result,
+	       const char *err,
+	       int options,
+	       xmlSchemaPtr schemas) {
+    xmlDocPtr doc;
+    xmlSchemaValidCtxtPtr ctxt;
+    int ret = 0;
+    char *temp;
+    FILE *schemasOutput;
+
+    doc = xmlReadFile(filename, NULL, options);
+    if (doc == NULL) {
+        fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
+	return(-1);
+    }
+
+    temp = resultFilename(result, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    schemasOutput = fopen(temp, "wb");
+    if (schemasOutput == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+	xmlFreeDoc(doc);
+        free(temp);
+	return(-1);
+    }
+
+    ctxt = xmlSchemaNewValidCtxt(schemas);
+    xmlSchemaSetValidErrors(ctxt,
+         (xmlSchemaValidityErrorFunc) testErrorHandler,
+         (xmlSchemaValidityWarningFunc) testErrorHandler,
+	 ctxt);
+    ret = xmlSchemaValidateDoc(ctxt, doc);
+    if (ret == 0) {
+	fprintf(schemasOutput, "%s validates\n", filename);
+    } else if (ret > 0) {
+	fprintf(schemasOutput, "%s fails to validate\n", filename);
+    } else {
+	fprintf(schemasOutput, "%s validation generated an internal error\n",
+	       filename);
+    }
+    fclose(schemasOutput);
+    if (result) {
+	if (compareFiles(temp, result)) {
+	    fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
+	    ret = 1;
+	}
+    }
+    unlink(temp);
+    free(temp);
+
+    if (err != NULL) {
+	if (compareFileMem(err, testErrors, testErrorsSize)) {
+	    fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
+	    ret = 1;
+	}
+    }
+
+
+    xmlSchemaFreeValidCtxt(ctxt);
+    xmlFreeDoc(doc);
+    return(ret);
+}
+/**
+ * schemasTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI, compose them against a fixed base and
+ * check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+schemasTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *errr ATTRIBUTE_UNUSED,
+            int options) {
+    const char *base = baseFilename(filename);
+    const char *base2;
+    const char *instance;
+    xmlSchemaParserCtxtPtr ctxt;
+    xmlSchemaPtr schemas;
+    int res = 0, len, ret;
+    char pattern[500];
+    char prefix[500];
+    char result[500];
+    char err[500];
+    glob_t globbuf;
+    size_t i;
+    char count = 0;
+
+    /* first compile the schemas if possible */
+    ctxt = xmlSchemaNewParserCtxt(filename);
+    xmlSchemaSetParserErrors(ctxt,
+         (xmlSchemaValidityErrorFunc) testErrorHandler,
+         (xmlSchemaValidityWarningFunc) testErrorHandler,
+	 ctxt);
+    schemas = xmlSchemaParse(ctxt);
+    xmlSchemaFreeParserCtxt(ctxt);
+
+    /*
+     * most of the mess is about the output filenames generated by the Makefile
+     */
+    len = strlen(base);
+    if ((len > 499) || (len < 5)) {
+        xmlSchemaFree(schemas);
+	return(-1);
+    }
+    len -= 4; /* remove trailing .xsd */
+    if (base[len - 2] == '_') {
+        len -= 2; /* remove subtest number */
+    }
+    if (base[len - 2] == '_') {
+        len -= 2; /* remove subtest number */
+    }
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
+    pattern[499] = 0;
+
+    if (base[len] == '_') {
+        len += 2;
+	memcpy(prefix, base, len);
+	prefix[len] = 0;
+    }
+
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        testErrorsSize = 0;
+	testErrors[0] = 0;
+        instance = globbuf.gl_pathv[i];
+	base2 = baseFilename(instance);
+	len = strlen(base2);
+	if ((len > 6) && (base2[len - 6] == '_')) {
+	    count = base2[len - 5];
+	    snprintf(result, 499, "result/schemas/%s_%c",
+		     prefix, count);
+	    result[499] = 0;
+	    snprintf(err, 499, "result/schemas/%s_%c.err",
+		     prefix, count);
+	    err[499] = 0;
+	} else {
+	    fprintf(stderr, "don't know how to process %s\n", instance);
+	    continue;
+	}
+	if (schemas == NULL) {
+	} else {
+	    nb_tests++;
+	    ret = schemasOneTest(filename, instance, result, err,
+	                         options, schemas);
+	    if (res != 0)
+		ret = res;
+	}
+    }
+    globfree(&globbuf);
+    xmlSchemaFree(schemas);
+
+    return(res);
+}
+
+/************************************************************************
+ *									*
+ *			Schemas tests					*
+ *									*
+ ************************************************************************/
+static int
+rngOneTest(const char *sch,
+               const char *filename,
+               const char *result,
+	       const char *err,
+	       int options,
+	       xmlRelaxNGPtr schemas) {
+    xmlDocPtr doc;
+    xmlRelaxNGValidCtxtPtr ctxt;
+    int ret = 0;
+    char *temp;
+    FILE *schemasOutput;
+
+    doc = xmlReadFile(filename, NULL, options);
+    if (doc == NULL) {
+        fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
+	return(-1);
+    }
+
+    temp = resultFilename(result, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    schemasOutput = fopen(temp, "wb");
+    if (schemasOutput == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+	xmlFreeDoc(doc);
+        free(temp);
+	return(-1);
+    }
+
+    ctxt = xmlRelaxNGNewValidCtxt(schemas);
+    xmlRelaxNGSetValidErrors(ctxt,
+         (xmlRelaxNGValidityErrorFunc) testErrorHandler,
+         (xmlRelaxNGValidityWarningFunc) testErrorHandler,
+	 ctxt);
+    ret = xmlRelaxNGValidateDoc(ctxt, doc);
+    if (ret == 0) {
+	testErrorHandler(NULL, "%s validates\n", filename);
+    } else if (ret > 0) {
+	testErrorHandler(NULL, "%s fails to validate\n", filename);
+    } else {
+	testErrorHandler(NULL, "%s validation generated an internal error\n",
+	       filename);
+    }
+    fclose(schemasOutput);
+    if (result) {
+	if (compareFiles(temp, result)) {
+	    fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
+	    ret = 1;
+	}
+    }
+    unlink(temp);
+    free(temp);
+
+    if (err != NULL) {
+	if (compareFileMem(err, testErrors, testErrorsSize)) {
+	    fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
+	    ret = 1;
+	    printf("%s", testErrors);
+	}
+    }
+
+
+    xmlRelaxNGFreeValidCtxt(ctxt);
+    xmlFreeDoc(doc);
+    return(ret);
+}
+/**
+ * rngTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse an RNG schemas and then apply it to the related .xml
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+rngTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *errr ATTRIBUTE_UNUSED,
+            int options) {
+    const char *base = baseFilename(filename);
+    const char *base2;
+    const char *instance;
+    xmlRelaxNGParserCtxtPtr ctxt;
+    xmlRelaxNGPtr schemas;
+    int res = 0, len, ret;
+    char pattern[500];
+    char prefix[500];
+    char result[500];
+    char err[500];
+    glob_t globbuf;
+    size_t i;
+    char count = 0;
+
+    /* first compile the schemas if possible */
+    ctxt = xmlRelaxNGNewParserCtxt(filename);
+    xmlRelaxNGSetParserErrors(ctxt,
+         (xmlRelaxNGValidityErrorFunc) testErrorHandler,
+         (xmlRelaxNGValidityWarningFunc) testErrorHandler,
+	 ctxt);
+    schemas = xmlRelaxNGParse(ctxt);
+    xmlRelaxNGFreeParserCtxt(ctxt);
+
+    /*
+     * most of the mess is about the output filenames generated by the Makefile
+     */
+    len = strlen(base);
+    if ((len > 499) || (len < 5)) {
+        xmlRelaxNGFree(schemas);
+	return(-1);
+    }
+    len -= 4; /* remove trailing .rng */
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
+    pattern[499] = 0;
+
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        testErrorsSize = 0;
+	testErrors[0] = 0;
+        instance = globbuf.gl_pathv[i];
+	base2 = baseFilename(instance);
+	len = strlen(base2);
+	if ((len > 6) && (base2[len - 6] == '_')) {
+	    count = base2[len - 5];
+	    snprintf(result, 499, "result/relaxng/%s_%c",
+		     prefix, count);
+	    result[499] = 0;
+	    snprintf(err, 499, "result/relaxng/%s_%c.err",
+		     prefix, count);
+	    err[499] = 0;
+	} else {
+	    fprintf(stderr, "don't know how to process %s\n", instance);
+	    continue;
+	}
+	if (schemas == NULL) {
+	} else {
+	    nb_tests++;
+	    ret = rngOneTest(filename, instance, result, err,
+	                         options, schemas);
+	    if (res != 0)
+		ret = res;
+	}
+    }
+    globfree(&globbuf);
+    xmlRelaxNGFree(schemas);
+
+    return(res);
+}
+
+#ifdef LIBXML_READER_ENABLED
+/**
+ * rngStreamTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a set of files with streaming, applying an RNG schemas 
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+rngStreamTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *errr ATTRIBUTE_UNUSED,
+            int options) {
+    const char *base = baseFilename(filename);
+    const char *base2;
+    const char *instance;
+    int res = 0, len, ret;
+    char pattern[500];
+    char prefix[500];
+    char result[500];
+    char err[500];
+    glob_t globbuf;
+    size_t i;
+    char count = 0;
+    xmlTextReaderPtr reader;
+    int disable_err = 0;
+
+    /*
+     * most of the mess is about the output filenames generated by the Makefile
+     */
+    len = strlen(base);
+    if ((len > 499) || (len < 5)) {
+	fprintf(stderr, "len(base) == %d !\n", len);
+	return(-1);
+    }
+    len -= 4; /* remove trailing .rng */
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    /*
+     * strictly unifying the error messages is nearly impossible this
+     * hack is also done in the Makefile
+     */
+    if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
+        (!strcmp(prefix, "tutor3_2"))) 
+	disable_err = 1;
+
+    snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
+    pattern[499] = 0;
+
+    globbuf.gl_offs = 0;
+    glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+    for (i = 0;i < globbuf.gl_pathc;i++) {
+        testErrorsSize = 0;
+	testErrors[0] = 0;
+        instance = globbuf.gl_pathv[i];
+	base2 = baseFilename(instance);
+	len = strlen(base2);
+	if ((len > 6) && (base2[len - 6] == '_')) {
+	    count = base2[len - 5];
+	    snprintf(result, 499, "result/relaxng/%s_%c",
+		     prefix, count);
+	    result[499] = 0;
+	    snprintf(err, 499, "result/relaxng/%s_%c.err",
+		     prefix, count);
+	    err[499] = 0;
+	} else {
+	    fprintf(stderr, "don't know how to process %s\n", instance);
+	    continue;
+	}
+	reader = xmlReaderForFile(instance, NULL, options);
+	if (reader == NULL) {
+	    fprintf(stderr, "Failed to build reder for %s\n", instance);
+	}
+	if (disable_err == 1)
+	    ret = streamProcessTest(instance, result, NULL, reader, filename);
+	else
+	    ret = streamProcessTest(instance, result, err, reader, filename);
+	xmlFreeTextReader(reader);
+	if (ret != 0) {
+	    fprintf(stderr, "instance %s failed\n", instance);
+	    res = ret;
+	}
+    }
+    globfree(&globbuf);
+
+    return(res);
+}
+#endif /* READER */
+
+#endif
+
+#ifdef LIBXML_PATTERN_ENABLED
+#ifdef LIBXML_READER_ENABLED
+/************************************************************************
+ *									*
+ *			Patterns tests					*
+ *									*
+ ************************************************************************/
+static void patternNode(FILE *out, xmlTextReaderPtr reader,
+                        const char *pattern, xmlPatternPtr patternc,
+			xmlStreamCtxtPtr patstream) {
+    xmlChar *path = NULL;
+    int match = -1;
+    int type, empty;
+
+    type = xmlTextReaderNodeType(reader);
+    empty = xmlTextReaderIsEmptyElement(reader);
+	
+    if (type == XML_READER_TYPE_ELEMENT) {
+	/* do the check only on element start */
+	match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
+
+	if (match) {
+	    path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
+	    fprintf(out, "Node %s matches pattern %s\n", path, pattern);
+	}
+    }
+    if (patstream != NULL) {
+	int ret;
+
+	if (type == XML_READER_TYPE_ELEMENT) {
+	    ret = xmlStreamPush(patstream,
+				xmlTextReaderConstLocalName(reader),
+				xmlTextReaderConstNamespaceUri(reader));
+	    if (ret < 0) {
+		fprintf(out, "xmlStreamPush() failure\n");
+		xmlFreeStreamCtxt(patstream);
+		patstream = NULL;
+	    } else if (ret != match) {
+		if (path == NULL) {
+		    path = xmlGetNodePath(
+				   xmlTextReaderCurrentNode(reader));
+		}
+		fprintf(out,
+			"xmlPatternMatch and xmlStreamPush disagree\n");
+		fprintf(out,
+			"  pattern %s node %s\n",
+			pattern, path);
+	    }
+	    
+
+	} 
+	if ((type == XML_READER_TYPE_END_ELEMENT) ||
+	    ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
+	    ret = xmlStreamPop(patstream);
+	    if (ret < 0) {
+		fprintf(out, "xmlStreamPop() failure\n");
+		xmlFreeStreamCtxt(patstream);
+		patstream = NULL;
+	    }
+	}
+    }
+    if (path != NULL)
+	xmlFree(path);
+}
+
+/**
+ * patternTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a set of files with streaming, applying an RNG schemas 
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+patternTest(const char *filename,
+            const char *resul ATTRIBUTE_UNUSED,
+            const char *err ATTRIBUTE_UNUSED,
+            int options) {
+    xmlPatternPtr patternc = NULL;
+    xmlStreamCtxtPtr patstream = NULL;
+    FILE *o, *f;
+    char str[1024];
+    char xml[500];
+    char result[500];
+    int len, i;
+    int ret = 0, res;
+    char *temp;
+    xmlTextReaderPtr reader;
+    xmlDocPtr doc;
+
+    len = strlen(filename);
+    len -= 4;
+    memcpy(xml, filename, len);
+    xml[len] = 0;
+    snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
+    result[499] = 0;
+    memcpy(xml + len, ".xml", 5);
+
+    if (!checkTestFile(xml)) {
+	fprintf(stderr, "Missing xml file %s\n", xml);
+	return(-1);
+    }
+    if (!checkTestFile(result)) {
+	fprintf(stderr, "Missing result file %s\n", result);
+	return(-1);
+    }
+    f = fopen(filename, "rb");
+    if (f == NULL) {
+        fprintf(stderr, "Failed to open %s\n", filename);
+	return(-1);
+    }
+    temp = resultFilename(filename, "", ".res");
+    if (temp == NULL) {
+        fprintf(stderr, "Out of memory\n");
+        fatalError();
+    }
+    o = fopen(temp, "wb");
+    if (o == NULL) {
+	fprintf(stderr, "failed to open output file %s\n", temp);
+	fclose(f);
+        free(temp);
+	return(-1);
+    }
+    while (1) {
+	/*
+	 * read one line in string buffer.
+	 */
+	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
+	   break;
+
+	/*
+	 * remove the ending spaces
+	 */
+	i = strlen(str);
+	while ((i > 0) &&
+	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
+		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
+	    i--;
+	    str[i] = 0;
+	}
+	doc = xmlReadFile(xml, NULL, options);
+	if (doc == NULL) {
+	    fprintf(stderr, "Failed to parse %s\n", xml);
+	    ret = 1;
+	} else {
+	    xmlNodePtr root;
+	    const xmlChar *namespaces[22];
+	    int j;
+	    xmlNsPtr ns;
+
+	    root = xmlDocGetRootElement(doc);
+	    for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
+		namespaces[j++] = ns->href;
+		namespaces[j++] = ns->prefix;
+	    }
+	    namespaces[j++] = NULL;
+	    namespaces[j++] = NULL;
+
+	    patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
+					 0, &namespaces[0]);
+	    if (patternc == NULL) {
+		testErrorHandler(NULL,
+			"Pattern %s failed to compile\n", str);
+		xmlFreeDoc(doc);
+		ret = 1;
+		continue;
+	    }
+	    patstream = xmlPatternGetStreamCtxt(patternc);
+	    if (patstream != NULL) {
+		ret = xmlStreamPush(patstream, NULL, NULL);
+		if (ret < 0) {
+		    fprintf(stderr, "xmlStreamPush() failure\n");
+		    xmlFreeStreamCtxt(patstream);
+		    patstream = NULL;
+		}
+	    }
+	    nb_tests++;
+
+	    reader = xmlReaderWalker(doc);
+	    res = xmlTextReaderRead(reader);
+	    while (res == 1) {
+		patternNode(o, reader, str, patternc, patstream);
+		res = xmlTextReaderRead(reader);
+	    }
+	    if (res != 0) {
+		fprintf(o, "%s : failed to parse\n", filename);
+	    }
+	    xmlFreeTextReader(reader);
+	    xmlFreeDoc(doc);
+	    xmlFreeStreamCtxt(patstream);
+	    patstream = NULL;
+	    xmlFreePattern(patternc);
+
+	}
+    }
+
+    fclose(f);
+    fclose(o);
+
+    ret = compareFiles(temp, result);
+    if (ret) {
+	fprintf(stderr, "Result for %s failed\n", filename);
+	ret = 1;
+    }
+    unlink(temp);
+    free(temp);
+    return(ret);
+}
+#endif /* READER */
+#endif /* PATTERN */
+#ifdef LIBXML_C14N_ENABLED
+/************************************************************************
+ *									*
+ *			Canonicalization tests				*
+ *									*
+ ************************************************************************/
+static xmlXPathObjectPtr
+load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
+    xmlXPathObjectPtr xpath; 
+    xmlDocPtr doc;
+    xmlChar *expr;
+    xmlXPathContextPtr ctx; 
+    xmlNodePtr node;
+    xmlNsPtr ns;
+    
+    /*
+     * load XPath expr as a file
+     */
+    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+    xmlSubstituteEntitiesDefault(1);
+
+    doc = xmlParseFile(filename);
+    if (doc == NULL) {
+	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
+	return(NULL);
+    }
+    
+    /*
+     * Check the document is of the right kind
+     */    
+    if(xmlDocGetRootElement(doc) == NULL) {
+        fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
+	xmlFreeDoc(doc);
+	return(NULL);
+    }
+
+    node = doc->children;
+    while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
+	node = node->next;
+    }
+    
+    if(node == NULL) {   
+        fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);
+	xmlFreeDoc(doc);
+	return(NULL);
+    }
+
+    expr = xmlNodeGetContent(node);
+    if(expr == NULL) {
+        fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
+	xmlFreeDoc(doc);
+	return(NULL);
+    }
+
+    ctx = xmlXPathNewContext(parent_doc);
+    if(ctx == NULL) {
+        fprintf(stderr,"Error: unable to create new context\n");
+        xmlFree(expr); 
+        xmlFreeDoc(doc); 
+        return(NULL);
+    }
+
+    /*
+     * Register namespaces
+     */
+    ns = node->nsDef;
+    while(ns != NULL) {
+	if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
+	    fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
+    	    xmlFree(expr); 
+	    xmlXPathFreeContext(ctx); 
+	    xmlFreeDoc(doc); 
+	    return(NULL);
+	}
+	ns = ns->next;
+    }
+
+    /*  
+     * Evaluate xpath
+     */
+    xpath = xmlXPathEvalExpression(expr, ctx);
+    if(xpath == NULL) {
+        fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+    	xmlFree(expr); 
+        xmlXPathFreeContext(ctx); 
+        xmlFreeDoc(doc); 
+        return(NULL);
+    }
+
+    /* print_xpath_nodes(xpath->nodesetval); */
+
+    xmlFree(expr); 
+    xmlXPathFreeContext(ctx); 
+    xmlFreeDoc(doc); 
+    return(xpath);
+}
+
+/*
+ * Macro used to grow the current buffer.
+ */
+#define xxx_growBufferReentrant() {						\
+    buffer_size *= 2;							\
+    buffer = (xmlChar **)						\
+    		xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));	\
+    if (buffer == NULL) {						\
+	perror("realloc failed");					\
+	return(NULL);							\
+    }									\
+}
+
+static xmlChar **
+parse_list(xmlChar *str) {
+    xmlChar **buffer;
+    xmlChar **out = NULL;
+    int buffer_size = 0;
+    int len;
+
+    if(str == NULL) {
+	return(NULL);
+    }
+
+    len = xmlStrlen(str);
+    if((str[0] == '\'') && (str[len - 1] == '\'')) {
+	str[len - 1] = '\0';
+	str++;
+	len -= 2;
+    }
+    /*
+     * allocate an translation buffer.
+     */
+    buffer_size = 1000;
+    buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
+    if (buffer == NULL) {
+	perror("malloc failed");
+	return(NULL);
+    }
+    out = buffer;
+    
+    while(*str != '\0') {
+	if (out - buffer > buffer_size - 10) {
+	    int indx = out - buffer;
+
+	    xxx_growBufferReentrant();
+	    out = &buffer[indx];
+	}
+	(*out++) = str;
+	while(*str != ',' && *str != '\0') ++str;
+	if(*str == ',') *(str++) = '\0';
+    }
+    (*out) = NULL;
+    return buffer;
+}
+
+static int 
+c14nRunTest(const char* xml_filename, int with_comments, int exclusive,
+	    const char* xpath_filename, const char *ns_filename,
+	    const char* result_file) {
+    xmlDocPtr doc;
+    xmlXPathObjectPtr xpath = NULL; 
+    xmlChar *result = NULL;
+    int ret;
+    xmlChar **inclusive_namespaces = NULL;
+    const char *nslist = NULL;
+    int nssize;
+
+
+    /*
+     * build an XML tree from a the file; we need to add default
+     * attributes and resolve all character and entities references
+     */
+    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+    xmlSubstituteEntitiesDefault(1);
+
+    doc = xmlParseFile(xml_filename);
+    if (doc == NULL) {
+	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
+	return(-1);
+    }
+    
+    /*
+     * Check the document is of the right kind
+     */    
+    if(xmlDocGetRootElement(doc) == NULL) {
+        fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
+	xmlFreeDoc(doc);
+	return(-1);
+    }
+
+    /* 
+     * load xpath file if specified 
+     */
+    if(xpath_filename) {
+	xpath = load_xpath_expr(doc, xpath_filename);
+	if(xpath == NULL) {
+	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+	    xmlFreeDoc(doc); 
+	    return(-1);
+	}
+    }
+
+    if (ns_filename != NULL) {
+        if (loadMem(ns_filename, &nslist, &nssize)) {
+	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+	    if(xpath != NULL) xmlXPathFreeObject(xpath);
+	    xmlFreeDoc(doc); 
+	    return(-1);
+	}
+        inclusive_namespaces = parse_list((xmlChar *) nslist);
+    }
+
+    /*
+     * Canonical form
+     */      
+    /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
+    ret = xmlC14NDocDumpMemory(doc, 
+	    (xpath) ? xpath->nodesetval : NULL, 
+	    exclusive, inclusive_namespaces,
+	    with_comments, &result);
+    if (ret >= 0) {
+	if(result != NULL) {
+	    if (compareFileMem(result_file, (const char *) result, ret)) {
+		fprintf(stderr, "Result mismatch for %s\n", xml_filename);
+	        ret = -1;
+	    }
+	}
+    } else {
+	fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
+	ret = -1;
+    }
+        
+    /*
+     * Cleanup
+     */ 
+    if (result != NULL) xmlFree(result);
+    if(xpath != NULL) xmlXPathFreeObject(xpath);
+    if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
+    if (nslist != NULL) free((char *) nslist);
+    xmlFreeDoc(doc);    
+
+    return(ret);
+}
+
+static int
+c14nCommonTest(const char *filename, int with_comments, int exclusive,
+               const char *subdir) {
+    char buf[500];
+    char prefix[500];
+    const char *base;
+    int len;
+    char *result = NULL;
+    char *xpath = NULL;
+    char *ns = NULL;
+    int ret = 0;
+
+    base = baseFilename(filename);
+    len = strlen(base);
+    len -= 4;
+    memcpy(prefix, base, len);
+    prefix[len] = 0;
+
+    snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
+    if (!checkTestFile(buf)) {
+        fprintf(stderr, "Missing result file %s", buf);
+	return(-1);
+    }
+    result = strdup(buf);
+    snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
+    if (checkTestFile(buf)) {
+	xpath = strdup(buf);
+    }
+    snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
+    if (checkTestFile(buf)) {
+	ns = strdup(buf);
+    }
+
+    nb_tests++;
+    if (c14nRunTest(filename, with_comments, exclusive,
+                    xpath, ns, result) < 0)
+        ret = 1;
+
+    if (result != NULL) free(result);
+    if (xpath != NULL) free(xpath);
+    if (ns != NULL) free(ns);
+    return(ret);
+}
+
+static int
+c14nWithCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+		    const char *err ATTRIBUTE_UNUSED,
+		    int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 1, 0, "with-comments"));
+}
+static int
+c14nWithoutCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+		    const char *err ATTRIBUTE_UNUSED,
+		    int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 0, 0, "without-comments"));
+}
+static int
+c14nExcWithoutCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+		    const char *err ATTRIBUTE_UNUSED,
+		    int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 0, 1, "exc-without-comments"));
+}
+#endif
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+/************************************************************************
+ *									*
+ *			Catalog and threads test			*
+ *									*
+ ************************************************************************/
+
+/*
+ * mostly a cut and paste from testThreads.c
+ */
+#define	MAX_ARGC	20
+
+static const char *catalog = "test/threads/complex.xml";
+static const char *testfiles[] = {
+    "test/threads/abc.xml",
+    "test/threads/acb.xml",
+    "test/threads/bac.xml",
+    "test/threads/bca.xml",
+    "test/threads/cab.xml",
+    "test/threads/cba.xml",
+    "test/threads/invalid.xml",
+};
+
+const char *Okay = "OK";
+const char *Failed = "Failed";
+
+#ifndef xmlDoValidityCheckingDefaultValue
+#error xmlDoValidityCheckingDefaultValue is not a macro
+#endif
+#ifndef xmlGenericErrorContext
+#error xmlGenericErrorContext is not a macro
+#endif
+
+static void *
+thread_specific_data(void *private_data)
+{
+    xmlDocPtr myDoc;
+    const char *filename = (const char *) private_data;
+    int okay = 1;
+
+    if (!strcmp(filename, "test/threads/invalid.xml")) {
+        xmlDoValidityCheckingDefaultValue = 0;
+        xmlGenericErrorContext = stdout;
+    } else {
+        xmlDoValidityCheckingDefaultValue = 1;
+        xmlGenericErrorContext = stderr;
+    }
+    myDoc = xmlParseFile(filename);
+    if (myDoc) {
+        xmlFreeDoc(myDoc);
+    } else {
+        printf("parse failed\n");
+        okay = 0;
+    }
+    if (!strcmp(filename, "test/threads/invalid.xml")) {
+        if (xmlDoValidityCheckingDefaultValue != 0) {
+            printf("ValidityCheckingDefaultValue override failed\n");
+            okay = 0;
+        }
+        if (xmlGenericErrorContext != stdout) {
+            printf("xmlGenericErrorContext override failed\n");
+            okay = 0;
+        }
+    } else {
+        if (xmlDoValidityCheckingDefaultValue != 1) {
+            printf("ValidityCheckingDefaultValue override failed\n");
+            okay = 0;
+        }
+        if (xmlGenericErrorContext != stderr) {
+            printf("xmlGenericErrorContext override failed\n");
+            okay = 0;
+        }
+    }
+    if (okay == 0)
+        return ((void *) Failed);
+    return ((void *) Okay);
+}
+
+#if defined(linux) || defined(solaris)
+
+#include <pthread.h>
+
+static pthread_t tid[MAX_ARGC];
+
+static int
+testThread(void)
+{
+    unsigned int i, repeat;
+    unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
+    void *results[MAX_ARGC];
+    int ret;
+    int res = 0;
+    
+    xmlInitParser();
+
+    for (repeat = 0; repeat < 500; repeat++) {
+        xmlLoadCatalog(catalog);
+        nb_tests++;
+
+        for (i = 0; i < num_threads; i++) {
+            results[i] = NULL;
+            tid[i] = (pthread_t) - 1;
+        }
+
+        for (i = 0; i < num_threads; i++) {
+            ret = pthread_create(&tid[i], 0, thread_specific_data,
+                                 (void *) testfiles[i]);
+            if (ret != 0) {
+                fprintf(stderr, "pthread_create failed\n");
+                return (1);
+            }
+        }
+        for (i = 0; i < num_threads; i++) {
+            ret = pthread_join(tid[i], &results[i]);
+            if (ret != 0) {
+                fprintf(stderr, "pthread_join failed\n");
+                return (1);
+            }
+        }
+
+        xmlCatalogCleanup();
+        for (i = 0; i < num_threads; i++)
+            if (results[i] != (void *) Okay) {
+                fprintf(stderr, "Thread %d handling %s failed\n",
+                        i, testfiles[i]);
+                res = 1;
+            }
+    }
+    return (res);
+}
+
+#elif defined WIN32
+#include <windows.h>
+#include <string.h>
+
+#define TEST_REPEAT_COUNT 500
+
+static HANDLE tid[MAX_ARGC];
+
+static DWORD WINAPI
+win32_thread_specific_data(void *private_data)
+{
+    return((DWORD) thread_specific_data(private_data));
+}
+
+static int
+testThread(void)
+{
+    unsigned int i, repeat;
+    unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
+    DWORD results[MAX_ARGC];
+    BOOL ret;
+    int res = 0;
+
+    xmlInitParser();
+    for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
+        xmlLoadCatalog(catalog);
+        nb_tests++;
+
+        for (i = 0; i < num_threads; i++) {
+            results[i] = 0;
+            tid[i] = (HANDLE) - 1;
+        }
+
+        for (i = 0; i < num_threads; i++) {
+            DWORD useless;
+
+            tid[i] = CreateThread(NULL, 0,
+                                  win32_thread_specific_data, 
+				  (void *) testfiles[i], 0,
+                                  &useless);
+            if (tid[i] == NULL) {
+                fprintf(stderr, "CreateThread failed\n");
+                return(1);
+            }
+        }
+
+        if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
+            WAIT_FAILED) {
+            fprintf(stderr, "WaitForMultipleObjects failed\n");
+	    return(1);
+	}
+
+        for (i = 0; i < num_threads; i++) {
+            ret = GetExitCodeThread(tid[i], &results[i]);
+            if (ret == 0) {
+                fprintf(stderr, "GetExitCodeThread failed\n");
+                return(1);
+            }
+            CloseHandle(tid[i]);
+        }
+
+        xmlCatalogCleanup();
+        for (i = 0; i < num_threads; i++) {
+            if (results[i] != (DWORD) Okay) {
+                fprintf(stderr, "Thread %d handling %s failed\n",
+		        i, testfiles[i]);
+	        res = 1;
+	    }
+        }
+    }
+
+    return (res);
+}
+
+#elif defined __BEOS__
+#include <OS.h>
+
+static thread_id tid[MAX_ARGC];
+
+static int
+testThread(void)
+{
+    unsigned int i, repeat;
+    unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
+    void *results[MAX_ARGC];
+    status_t ret;
+    int res = 0;
+
+    xmlInitParser();
+    for (repeat = 0; repeat < 500; repeat++) {
+        xmlLoadCatalog(catalog);
+        for (i = 0; i < num_threads; i++) {
+            results[i] = NULL;
+            tid[i] = (thread_id) - 1;
+        }
+        for (i = 0; i < num_threads; i++) {
+            tid[i] =
+                spawn_thread(thread_specific_data, "xmlTestThread",
+                             B_NORMAL_PRIORITY, (void *) testfiles[i]);
+            if (tid[i] < B_OK) {
+                fprintf(stderr, "beos_thread_create failed\n");
+                return (1);
+            }
+            printf("beos_thread_create %d -> %d\n", i, tid[i]);
+        }
+        for (i = 0; i < num_threads; i++) {
+            ret = wait_for_thread(tid[i], &results[i]);
+            printf("beos_thread_wait %d -> %d\n", i, ret);
+            if (ret != B_OK) {
+                fprintf(stderr, "beos_thread_wait failed\n");
+                return (1);
+            }
+        }
+
+        xmlCatalogCleanup();
+        ret = B_OK;
+        for (i = 0; i < num_threads; i++)
+            if (results[i] != (void *) Okay) {
+                printf("Thread %d handling %s failed\n", i, testfiles[i]);
+                ret = B_ERROR;
+            }
+    }
+    if (ret != B_OK)
+        return(1);
+    return (0);
+}
+#else
+static int
+testThread(void)
+{
+    fprintf(stderr,
+            "Specific platform thread support not detected\n");
+    return (-1);
+}
+#endif
+static int 
+threadsTest(const char *filename ATTRIBUTE_UNUSED,
+	    const char *resul ATTRIBUTE_UNUSED,
+	    const char *err ATTRIBUTE_UNUSED,
+	    int options ATTRIBUTE_UNUSED) {
+    return(testThread());
+}
+#endif
+/************************************************************************
+ *									*
+ *			Tests Descriptions				*
+ *									*
+ ************************************************************************/
+
+static
+testDesc testDescriptions[] = {
+    { "XML regression tests" ,
+      oldParseTest, "./test/*", "result/", "", NULL,
+      0 },
+    { "XML regression tests on memory" ,
+      memParseTest, "./test/*", "result/", "", NULL,
+      0 },
+    { "XML entity subst regression tests" ,
+      noentParseTest, "./test/*", "result/noent/", "", NULL,
+      XML_PARSE_NOENT },
+    { "XML Namespaces regression tests",
+      errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
+      0 },
+    { "Error cases regression tests",
+      errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
+      0 },
+#ifdef LIBXML_READER_ENABLED
+    { "Error cases stream regression tests",
+      streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
+      0 },
+    { "Reader regression tests",
+      streamParseTest, "./test/*", "result/", ".rdr", NULL,
+      0 },
+    { "Reader entities substitution regression tests",
+      streamParseTest, "./test/*", "result/", ".rde", NULL,
+      XML_PARSE_NOENT },
+    { "Reader on memory regression tests",
+      streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
+      0 },
+    { "Walker regression tests",
+      walkerParseTest, "./test/*", "result/", ".rdr", NULL,
+      0 },
+#endif
+#ifdef LIBXML_SAX1_ENABLED
+    { "SAX1 callbacks regression tests" ,
+      saxParseTest, "./test/*", "result/", ".sax", NULL,
+      XML_PARSE_SAX1 },
+    { "SAX2 callbacks regression tests" ,
+      saxParseTest, "./test/*", "result/", ".sax2", NULL,
+      0 },
+#endif
+#ifdef LIBXML_PUSH_ENABLED
+    { "XML push regression tests" ,
+      pushParseTest, "./test/*", "result/", "", NULL,
+      0 },
+#endif
+#ifdef LIBXML_HTML_ENABLED
+    { "HTML regression tests" ,
+      errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
+      XML_PARSE_HTML },
+#ifdef LIBXML_PUSH_ENABLED
+    { "Push HTML regression tests" ,
+      pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
+      XML_PARSE_HTML },
+#endif
+#ifdef LIBXML_SAX1_ENABLED
+    { "HTML SAX regression tests" ,
+      saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
+      XML_PARSE_HTML },
+#endif
+#endif
+#ifdef LIBXML_VALID_ENABLED
+    { "Valid documents regression tests" ,
+      errParseTest, "./test/VCM/*", NULL, NULL, NULL,
+      XML_PARSE_DTDVALID },
+    { "Validity checking regression tests" ,
+      errParseTest, "./test/VC/*", "result/VC/", NULL, "",
+      XML_PARSE_DTDVALID },
+    { "General documents valid regression tests" ,
+      errParseTest, "./test/valid/*", "result/valid/", "", ".err",
+      XML_PARSE_DTDVALID },
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+    { "XInclude regression tests" ,
+      errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
+      /* Ignore errors at this point ".err", */
+      XML_PARSE_XINCLUDE },
+    { "XInclude xmlReader regression tests",
+      streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
+      /* Ignore errors at this point ".err", */
+      NULL, XML_PARSE_XINCLUDE },
+    { "XInclude regression tests stripping include nodes" ,
+      errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
+      /* Ignore errors at this point ".err", */
+      XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
+    { "XInclude xmlReader regression tests stripping include nodes",
+      streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
+      /* Ignore errors at this point ".err", */
+      NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
+#endif
+#ifdef LIBXML_XPATH_ENABLED
+#ifdef LIBXML_DEBUG_ENABLED
+    { "XPath expressions regression tests" ,
+      xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
+      0 },
+    { "XPath document queries regression tests" ,
+      xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
+      0 },
+#ifdef LIBXML_XPTR_ENABLED
+    { "XPointer document queries regression tests" ,
+      xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
+      0 },
+#endif
+    { "xml:id regression tests" ,
+      xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
+      0 },
+#endif
+#endif
+    { "URI parsing tests" ,
+      uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
+      0 },
+    { "URI base composition tests" ,
+      uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
+      0 },
+#ifdef LIBXML_SCHEMAS_ENABLED
+    { "Schemas regression tests" ,
+      schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
+      0 },
+    { "Relax-NG regression tests" ,
+      rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+      XML_PARSE_DTDATTR | XML_PARSE_NOENT },
+#ifdef LIBXML_READER_ENABLED
+    { "Relax-NG streaming regression tests" ,
+      rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+      XML_PARSE_DTDATTR | XML_PARSE_NOENT },
+#endif
+#endif
+#ifdef LIBXML_PATTERN_ENABLED
+#ifdef LIBXML_READER_ENABLED
+    { "Pattern regression tests" ,
+      patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
+      0 },
+#endif
+#endif
+#ifdef LIBXML_C14N_ENABLED
+    { "C14N with comments regression tests" ,
+      c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
+      0 },
+    { "C14N without comments regression tests" ,
+      c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
+      0 },
+    { "C14N exclusive without comments regression tests" ,
+      c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
+      0 },
+#endif
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+    { "Catalog and Threads regression tests" ,
+      threadsTest, NULL, NULL, NULL, NULL,
+      0 },
+#endif
+    {NULL, NULL, NULL, NULL, NULL, NULL, 0}
+};
+
+/************************************************************************
+ *									*
+ *		The main code driving the tests				*
+ *									*
+ ************************************************************************/
+
+static int
+launchTests(testDescPtr tst) {
+    int res = 0, err = 0;
+    size_t i;
+    char *result;
+    char *error;
+    int mem;
+
+    if (tst == NULL) return(-1);
+    if (tst->in != NULL) {
+	glob_t globbuf;
+
+	globbuf.gl_offs = 0;
+	glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
+	for (i = 0;i < globbuf.gl_pathc;i++) {
+	    if (!checkTestFile(globbuf.gl_pathv[i]))
+	        continue;
+	    if (tst->suffix != NULL) {
+		result = resultFilename(globbuf.gl_pathv[i], tst->out,
+					tst->suffix);
+		if (result == NULL) {
+		    fprintf(stderr, "Out of memory !\n");
+		    fatalError();
+		}
+	    } else {
+	        result = NULL;
+	    }
+	    if (tst->err != NULL) {
+		error = resultFilename(globbuf.gl_pathv[i], tst->out,
+		                        tst->err);
+		if (error == NULL) {
+		    fprintf(stderr, "Out of memory !\n");
+		    fatalError();
+		}
+	    } else {
+	        error = NULL;
+	    }
+	    if ((result) &&(!checkTestFile(result))) {
+	        fprintf(stderr, "Missing result file %s\n", result);
+	    } else if ((error) &&(!checkTestFile(error))) {
+	        fprintf(stderr, "Missing error file %s\n", error);
+	    } else {
+		mem = xmlMemUsed();
+		extraMemoryFromResolver = 0;
+		testErrorsSize = 0;
+		testErrors[0] = 0;
+		res = tst->func(globbuf.gl_pathv[i], result, error,
+		                tst->options);
+		xmlResetLastError();
+		if (res != 0) {
+		    fprintf(stderr, "File %s generated an error\n",
+		            globbuf.gl_pathv[i]);
+		    nb_errors++;
+		    err++;
+		}
+		else if (xmlMemUsed() != mem) {
+		    if ((xmlMemUsed() != mem) &&
+		        (extraMemoryFromResolver == 0)) {
+			fprintf(stderr, "File %s leaked %d bytes\n",
+				globbuf.gl_pathv[i], xmlMemUsed() - mem);
+			nb_leaks++;
+			err++;
+		    }
+		}
+		testErrorsSize = 0;
+	    }
+	    if (result)
+		free(result);
+	    if (error)
+		free(error);
+	}
+	globfree(&globbuf);
+    } else {
+        testErrorsSize = 0;
+	testErrors[0] = 0;
+	extraMemoryFromResolver = 0;
+        res = tst->func(NULL, NULL, NULL, tst->options);
+	if (res != 0) {
+	    nb_errors++;
+	    err++;
+	}
+    }
+    return(err);
+}
+
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    int i = 0, res, ret = 0;
+    int verbose = 0;
+    int old_errors, old_tests, old_leaks;
+
+    initializeLibxml2();
+
+    if ((argc >= 2) && (!strcmp(argv[1], "-v")))
+        verbose = 1;
+    for (i = 0; testDescriptions[i].func != NULL; i++) {
+        old_errors = nb_errors;
+        old_tests = nb_tests;
+        old_leaks = nb_leaks;
+        if (testDescriptions[i].desc != NULL)
+	    printf("## %s\n", testDescriptions[i].desc);
+	res = launchTests(&testDescriptions[i]);
+	if (res != 0)
+	    ret++;
+	if (verbose) {
+	    if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+	        printf("Ran %d tests, no errors\n", nb_tests - old_tests);
+	    else
+	        printf("Ran %d tests, %d errors, %d leaks\n",
+		       nb_tests - old_tests,
+		       nb_errors - old_errors,
+		       nb_leaks - old_leaks);
+	}
+    }
+    if ((nb_errors == 0) && (nb_leaks == 0)) {
+        ret = 0;
+	printf("Total %d tests, no errors\n",
+	       nb_tests);
+    } else {
+        ret = 1;
+	printf("Total %d tests, %d errors, %d leaks\n",
+	       nb_tests, nb_errors, nb_leaks);
+    }
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return(ret);
+}
+
+#else /* ! LIBXML_OUTPUT_ENABLED */
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    fprintf(stderr, "runtest requires output to be enabled in libxml2\n");
+    return(1);
+}
+#endif