1/*
2 * xmllint.c : a small tester program for XML input.
3 *
4 * See Copyright for the status of this software.
5 *
6 * daniel@veillard.com
7 */
8
9#include "libxml.h"
10
11#include <string.h>
12#include <stdarg.h>
13#include <assert.h>
14
15#if defined (_WIN32) && !defined(__CYGWIN__)
16#if defined (_MSC_VER) || defined(__BORLANDC__)
17#include <winsock2.h>
18#pragma comment(lib, "ws2_32.lib")
19#define gettimeofday(p1,p2)
20#endif /* _MSC_VER */
21#endif /* _WIN32 */
22
23#ifdef HAVE_SYS_TIME_H
24#include <sys/time.h>
25#endif
26#ifdef HAVE_TIME_H
27#include <time.h>
28#endif
29
30#ifdef __MINGW32__
31#define _WINSOCKAPI_
32#include <wsockcompat.h>
33#include <winsock2.h>
34#undef XML_SOCKLEN_T
35#define XML_SOCKLEN_T unsigned int
36#endif
37
38#ifdef HAVE_SYS_TIMEB_H
39#include <sys/timeb.h>
40#endif
41
42#ifdef HAVE_SYS_TYPES_H
43#include <sys/types.h>
44#endif
45#ifdef HAVE_SYS_STAT_H
46#include <sys/stat.h>
47#endif
48#ifdef HAVE_FCNTL_H
49#include <fcntl.h>
50#endif
51#ifdef HAVE_UNISTD_H
52#include <unistd.h>
53#endif
54#ifdef HAVE_SYS_MMAN_H
55#include <sys/mman.h>
56/* seems needed for Solaris */
57#ifndef MAP_FAILED
58#define MAP_FAILED ((void *) -1)
59#endif
60#endif
61#ifdef HAVE_STDLIB_H
62#include <stdlib.h>
63#endif
64#ifdef HAVE_LIBREADLINE
65#include <readline/readline.h>
66#ifdef HAVE_LIBHISTORY
67#include <readline/history.h>
68#endif
69#endif
70
71#include <libxml/xmlmemory.h>
72#include <libxml/parser.h>
73#include <libxml/parserInternals.h>
74#include <libxml/HTMLparser.h>
75#include <libxml/HTMLtree.h>
76#include <libxml/tree.h>
77#include <libxml/xpath.h>
78#include <libxml/debugXML.h>
79#include <libxml/xmlerror.h>
80#ifdef LIBXML_XINCLUDE_ENABLED
81#include <libxml/xinclude.h>
82#endif
83#ifdef LIBXML_CATALOG_ENABLED
84#include <libxml/catalog.h>
85#endif
86#include <libxml/globals.h>
87#include <libxml/xmlreader.h>
88#ifdef LIBXML_SCHEMATRON_ENABLED
89#include <libxml/schematron.h>
90#endif
91#ifdef LIBXML_SCHEMAS_ENABLED
92#include <libxml/relaxng.h>
93#include <libxml/xmlschemas.h>
94#endif
95#ifdef LIBXML_PATTERN_ENABLED
96#include <libxml/pattern.h>
97#endif
98#ifdef LIBXML_C14N_ENABLED
99#include <libxml/c14n.h>
100#endif
101#ifdef LIBXML_OUTPUT_ENABLED
102#include <libxml/xmlsave.h>
103#endif
104
105#ifndef XML_XML_DEFAULT_CATALOG
106#define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
107#endif
108
109typedef enum {
110    XMLLINT_RETURN_OK = 0,	/* No error */
111    XMLLINT_ERR_UNCLASS = 1,	/* Unclassified */
112    XMLLINT_ERR_DTD = 2,	/* Error in DTD */
113    XMLLINT_ERR_VALID = 3,	/* Validation error */
114    XMLLINT_ERR_RDFILE = 4,	/* CtxtReadFile error */
115    XMLLINT_ERR_SCHEMACOMP = 5,	/* Schema compilation */
116    XMLLINT_ERR_OUT = 6,	/* Error writing output */
117    XMLLINT_ERR_SCHEMAPAT = 7,	/* Error in schema pattern */
118    XMLLINT_ERR_RDREGIS = 8,	/* Error in Reader registration */
119    XMLLINT_ERR_MEM = 9,	/* Out of memory error */
120    XMLLINT_ERR_XPATH = 10	/* XPath evaluation error */
121} xmllintReturnCode;
122#ifdef LIBXML_DEBUG_ENABLED
123static int shell = 0;
124static int debugent = 0;
125#endif
126static int debug = 0;
127static int maxmem = 0;
128#ifdef LIBXML_TREE_ENABLED
129static int copy = 0;
130#endif /* LIBXML_TREE_ENABLED */
131static int recovery = 0;
132static int noent = 0;
133static int noenc = 0;
134static int noblanks = 0;
135static int noout = 0;
136static int nowrap = 0;
137#ifdef LIBXML_OUTPUT_ENABLED
138static int format = 0;
139static const char *output = NULL;
140static int compress = 0;
141static int oldout = 0;
142#endif /* LIBXML_OUTPUT_ENABLED */
143#ifdef LIBXML_VALID_ENABLED
144static int valid = 0;
145static int postvalid = 0;
146static char * dtdvalid = NULL;
147static char * dtdvalidfpi = NULL;
148#endif
149#ifdef LIBXML_SCHEMAS_ENABLED
150static char * relaxng = NULL;
151static xmlRelaxNGPtr relaxngschemas = NULL;
152static char * schema = NULL;
153static xmlSchemaPtr wxschemas = NULL;
154#endif
155#ifdef LIBXML_SCHEMATRON_ENABLED
156static char * schematron = NULL;
157static xmlSchematronPtr wxschematron = NULL;
158#endif
159static int repeat = 0;
160static int insert = 0;
161#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
162static int html = 0;
163static int xmlout = 0;
164#endif
165static int htmlout = 0;
166#if defined(LIBXML_HTML_ENABLED)
167static int nodefdtd = 0;
168#endif
169#ifdef LIBXML_PUSH_ENABLED
170static int push = 0;
171static int pushsize = 4096;
172#endif /* LIBXML_PUSH_ENABLED */
173#ifdef HAVE_MMAP
174static int memory = 0;
175#endif
176static int testIO = 0;
177static char *encoding = NULL;
178#ifdef LIBXML_XINCLUDE_ENABLED
179static int xinclude = 0;
180#endif
181static int dtdattrs = 0;
182static int loaddtd = 0;
183static xmllintReturnCode progresult = XMLLINT_RETURN_OK;
184static int timing = 0;
185static int generate = 0;
186static int dropdtd = 0;
187#ifdef LIBXML_CATALOG_ENABLED
188static int catalogs = 0;
189static int nocatalogs = 0;
190#endif
191#ifdef LIBXML_C14N_ENABLED
192static int canonical = 0;
193static int canonical_11 = 0;
194static int exc_canonical = 0;
195#endif
196#ifdef LIBXML_READER_ENABLED
197static int stream = 0;
198static int walker = 0;
199#endif /* LIBXML_READER_ENABLED */
200static int chkregister = 0;
201static int nbregister = 0;
202#ifdef LIBXML_SAX1_ENABLED
203static int sax1 = 0;
204#endif /* LIBXML_SAX1_ENABLED */
205#ifdef LIBXML_PATTERN_ENABLED
206static const char *pattern = NULL;
207static xmlPatternPtr patternc = NULL;
208static xmlStreamCtxtPtr patstream = NULL;
209#endif
210#ifdef LIBXML_XPATH_ENABLED
211static const char *xpathquery = NULL;
212#endif
213static int options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
214static int sax = 0;
215static int oldxml10 = 0;
216
217/************************************************************************
218 *									*
219 *		 Entity loading control and customization.		*
220 *									*
221 ************************************************************************/
222#define MAX_PATHS 64
223#ifdef _WIN32
224# define PATH_SEPARATOR ';'
225#else
226# define PATH_SEPARATOR ':'
227#endif
228static xmlChar *paths[MAX_PATHS + 1];
229static int nbpaths = 0;
230static int load_trace = 0;
231
232static
233void parsePath(const xmlChar *path) {
234    const xmlChar *cur;
235
236    if (path == NULL)
237	return;
238    while (*path != 0) {
239	if (nbpaths >= MAX_PATHS) {
240	    fprintf(stderr, "MAX_PATHS reached: too many paths\n");
241	    return;
242	}
243	cur = path;
244	while ((*cur == ' ') || (*cur == PATH_SEPARATOR))
245	    cur++;
246	path = cur;
247	while ((*cur != 0) && (*cur != ' ') && (*cur != PATH_SEPARATOR))
248	    cur++;
249	if (cur != path) {
250	    paths[nbpaths] = xmlStrndup(path, cur - path);
251	    if (paths[nbpaths] != NULL)
252		nbpaths++;
253	    path = cur;
254	}
255    }
256}
257
258static xmlExternalEntityLoader defaultEntityLoader = NULL;
259
260static xmlParserInputPtr
261xmllintExternalEntityLoader(const char *URL, const char *ID,
262			     xmlParserCtxtPtr ctxt) {
263    xmlParserInputPtr ret;
264    warningSAXFunc warning = NULL;
265    errorSAXFunc err = NULL;
266
267    int i;
268    const char *lastsegment = URL;
269    const char *iter = URL;
270
271    if ((nbpaths > 0) && (iter != NULL)) {
272	while (*iter != 0) {
273	    if (*iter == '/')
274		lastsegment = iter + 1;
275	    iter++;
276	}
277    }
278
279    if ((ctxt != NULL) && (ctxt->sax != NULL)) {
280	warning = ctxt->sax->warning;
281	err = ctxt->sax->error;
282	ctxt->sax->warning = NULL;
283	ctxt->sax->error = NULL;
284    }
285
286    if (defaultEntityLoader != NULL) {
287	ret = defaultEntityLoader(URL, ID, ctxt);
288	if (ret != NULL) {
289	    if (warning != NULL)
290		ctxt->sax->warning = warning;
291	    if (err != NULL)
292		ctxt->sax->error = err;
293	    if (load_trace) {
294		fprintf \
295			(stderr,
296			 "Loaded URL=\"%s\" ID=\"%s\"\n",
297			 URL ? URL : "(null)",
298			 ID ? ID : "(null)");
299	    }
300	    return(ret);
301	}
302    }
303    for (i = 0;i < nbpaths;i++) {
304	xmlChar *newURL;
305
306	newURL = xmlStrdup((const xmlChar *) paths[i]);
307	newURL = xmlStrcat(newURL, (const xmlChar *) "/");
308	newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
309	if (newURL != NULL) {
310	    ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
311	    if (ret != NULL) {
312		if (warning != NULL)
313		    ctxt->sax->warning = warning;
314		if (err != NULL)
315		    ctxt->sax->error = err;
316		if (load_trace) {
317		    fprintf \
318			(stderr,
319			 "Loaded URL=\"%s\" ID=\"%s\"\n",
320			 newURL,
321			 ID ? ID : "(null)");
322		}
323		xmlFree(newURL);
324		return(ret);
325	    }
326	    xmlFree(newURL);
327	}
328    }
329    if (err != NULL)
330        ctxt->sax->error = err;
331    if (warning != NULL) {
332	ctxt->sax->warning = warning;
333	if (URL != NULL)
334	    warning(ctxt, "failed to load external entity \"%s\"\n", URL);
335	else if (ID != NULL)
336	    warning(ctxt, "failed to load external entity \"%s\"\n", ID);
337    }
338    return(NULL);
339}
340/************************************************************************
341 *									*
342 * Memory allocation consumption debugging				*
343 *									*
344 ************************************************************************/
345
346static void
347OOM(void)
348{
349    fprintf(stderr, "Ran out of memory needs > %d bytes\n", maxmem);
350    progresult = XMLLINT_ERR_MEM;
351}
352
353static void
354myFreeFunc(void *mem)
355{
356    xmlMemFree(mem);
357}
358static void *
359myMallocFunc(size_t size)
360{
361    void *ret;
362
363    ret = xmlMemMalloc(size);
364    if (ret != NULL) {
365        if (xmlMemUsed() > maxmem) {
366            OOM();
367            xmlMemFree(ret);
368            return (NULL);
369        }
370    }
371    return (ret);
372}
373static void *
374myReallocFunc(void *mem, size_t size)
375{
376    void *ret;
377
378    ret = xmlMemRealloc(mem, size);
379    if (ret != NULL) {
380        if (xmlMemUsed() > maxmem) {
381            OOM();
382            xmlMemFree(ret);
383            return (NULL);
384        }
385    }
386    return (ret);
387}
388static char *
389myStrdupFunc(const char *str)
390{
391    char *ret;
392
393    ret = xmlMemoryStrdup(str);
394    if (ret != NULL) {
395        if (xmlMemUsed() > maxmem) {
396            OOM();
397            xmlFree(ret);
398            return (NULL);
399        }
400    }
401    return (ret);
402}
403/************************************************************************
404 *									*
405 * Internal timing routines to remove the necessity to have		*
406 * unix-specific function calls.					*
407 *									*
408 ************************************************************************/
409
410#ifndef HAVE_GETTIMEOFDAY
411#ifdef HAVE_SYS_TIMEB_H
412#ifdef HAVE_SYS_TIME_H
413#ifdef HAVE_FTIME
414
415static int
416my_gettimeofday(struct timeval *tvp, void *tzp)
417{
418	struct timeb timebuffer;
419
420	ftime(&timebuffer);
421	if (tvp) {
422		tvp->tv_sec = timebuffer.time;
423		tvp->tv_usec = timebuffer.millitm * 1000L;
424	}
425	return (0);
426}
427#define HAVE_GETTIMEOFDAY 1
428#define gettimeofday my_gettimeofday
429
430#endif /* HAVE_FTIME */
431#endif /* HAVE_SYS_TIME_H */
432#endif /* HAVE_SYS_TIMEB_H */
433#endif /* !HAVE_GETTIMEOFDAY */
434
435#if defined(HAVE_GETTIMEOFDAY)
436static struct timeval begin, end;
437
438/*
439 * startTimer: call where you want to start timing
440 */
441static void
442startTimer(void)
443{
444    gettimeofday(&begin, NULL);
445}
446
447/*
448 * endTimer: call where you want to stop timing and to print out a
449 *           message about the timing performed; format is a printf
450 *           type argument
451 */
452static void XMLCDECL LIBXML_ATTR_FORMAT(1,2)
453endTimer(const char *fmt, ...)
454{
455    long msec;
456    va_list ap;
457
458    gettimeofday(&end, NULL);
459    msec = end.tv_sec - begin.tv_sec;
460    msec *= 1000;
461    msec += (end.tv_usec - begin.tv_usec) / 1000;
462
463#ifndef HAVE_STDARG_H
464#error "endTimer required stdarg functions"
465#endif
466    va_start(ap, fmt);
467    vfprintf(stderr, fmt, ap);
468    va_end(ap);
469
470    fprintf(stderr, " took %ld ms\n", msec);
471}
472#elif defined(HAVE_TIME_H)
473/*
474 * No gettimeofday function, so we have to make do with calling clock.
475 * This is obviously less accurate, but there's little we can do about
476 * that.
477 */
478#ifndef CLOCKS_PER_SEC
479#define CLOCKS_PER_SEC 100
480#endif
481
482static clock_t begin, end;
483static void
484startTimer(void)
485{
486    begin = clock();
487}
488static void XMLCDECL LIBXML_ATTR_FORMAT(1,2)
489endTimer(const char *fmt, ...)
490{
491    long msec;
492    va_list ap;
493
494    end = clock();
495    msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
496
497#ifndef HAVE_STDARG_H
498#error "endTimer required stdarg functions"
499#endif
500    va_start(ap, fmt);
501    vfprintf(stderr, fmt, ap);
502    va_end(ap);
503    fprintf(stderr, " took %ld ms\n", msec);
504}
505#else
506
507/*
508 * We don't have a gettimeofday or time.h, so we just don't do timing
509 */
510static void
511startTimer(void)
512{
513    /*
514     * Do nothing
515     */
516}
517static void XMLCDECL LIBXML_ATTR_FORMAT(1,2)
518endTimer(char *format, ...)
519{
520    /*
521     * We cannot do anything because we don't have a timing function
522     */
523#ifdef HAVE_STDARG_H
524    va_list ap;
525    va_start(ap, format);
526    vfprintf(stderr, format, ap);
527    va_end(ap);
528    fprintf(stderr, " was not timed\n");
529#else
530    /* We don't have gettimeofday, time or stdarg.h, what crazy world is
531     * this ?!
532     */
533#endif
534}
535#endif
536/************************************************************************
537 *									*
538 *			HTML ouput					*
539 *									*
540 ************************************************************************/
541static char buffer[50000];
542
543static void
544xmlHTMLEncodeSend(void) {
545    char *result;
546
547    result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
548    if (result) {
549	xmlGenericError(xmlGenericErrorContext, "%s", result);
550	xmlFree(result);
551    }
552    buffer[0] = 0;
553}
554
555/**
556 * xmlHTMLPrintFileInfo:
557 * @input:  an xmlParserInputPtr input
558 *
559 * Displays the associated file and line informations for the current input
560 */
561
562static void
563xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
564    int len;
565    xmlGenericError(xmlGenericErrorContext, "<p>");
566
567    len = strlen(buffer);
568    if (input != NULL) {
569	if (input->filename) {
570	    snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
571		    input->line);
572	} else {
573	    snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
574	}
575    }
576    xmlHTMLEncodeSend();
577}
578
579/**
580 * xmlHTMLPrintFileContext:
581 * @input:  an xmlParserInputPtr input
582 *
583 * Displays current context within the input content for error tracking
584 */
585
586static void
587xmlHTMLPrintFileContext(xmlParserInputPtr input) {
588    const xmlChar *cur, *base;
589    int len;
590    int n;
591
592    if (input == NULL) return;
593    xmlGenericError(xmlGenericErrorContext, "<pre>\n");
594    cur = input->cur;
595    base = input->base;
596    while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
597	cur--;
598    }
599    n = 0;
600    while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
601        cur--;
602    if ((*cur == '\n') || (*cur == '\r')) cur++;
603    base = cur;
604    n = 0;
605    while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
606	len = strlen(buffer);
607        snprintf(&buffer[len], sizeof(buffer) - len, "%c",
608		    (unsigned char) *cur++);
609	n++;
610    }
611    len = strlen(buffer);
612    snprintf(&buffer[len], sizeof(buffer) - len, "\n");
613    cur = input->cur;
614    while ((*cur == '\n') || (*cur == '\r'))
615	cur--;
616    n = 0;
617    while ((cur != base) && (n++ < 80)) {
618	len = strlen(buffer);
619        snprintf(&buffer[len], sizeof(buffer) - len, " ");
620        base++;
621    }
622    len = strlen(buffer);
623    snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
624    xmlHTMLEncodeSend();
625    xmlGenericError(xmlGenericErrorContext, "</pre>");
626}
627
628/**
629 * xmlHTMLError:
630 * @ctx:  an XML parser context
631 * @msg:  the message to display/transmit
632 * @...:  extra parameters for the message display
633 *
634 * Display and format an error messages, gives file, line, position and
635 * extra parameters.
636 */
637static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
638xmlHTMLError(void *ctx, const char *msg, ...)
639{
640    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
641    xmlParserInputPtr input;
642    va_list args;
643    int len;
644
645    buffer[0] = 0;
646    input = ctxt->input;
647    if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
648        input = ctxt->inputTab[ctxt->inputNr - 2];
649    }
650
651    xmlHTMLPrintFileInfo(input);
652
653    xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
654    va_start(args, msg);
655    len = strlen(buffer);
656    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
657    va_end(args);
658    xmlHTMLEncodeSend();
659    xmlGenericError(xmlGenericErrorContext, "</p>\n");
660
661    xmlHTMLPrintFileContext(input);
662    xmlHTMLEncodeSend();
663}
664
665/**
666 * xmlHTMLWarning:
667 * @ctx:  an XML parser context
668 * @msg:  the message to display/transmit
669 * @...:  extra parameters for the message display
670 *
671 * Display and format a warning messages, gives file, line, position and
672 * extra parameters.
673 */
674static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
675xmlHTMLWarning(void *ctx, const char *msg, ...)
676{
677    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
678    xmlParserInputPtr input;
679    va_list args;
680    int len;
681
682    buffer[0] = 0;
683    input = ctxt->input;
684    if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
685        input = ctxt->inputTab[ctxt->inputNr - 2];
686    }
687
688
689    xmlHTMLPrintFileInfo(input);
690
691    xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
692    va_start(args, msg);
693    len = strlen(buffer);
694    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
695    va_end(args);
696    xmlHTMLEncodeSend();
697    xmlGenericError(xmlGenericErrorContext, "</p>\n");
698
699    xmlHTMLPrintFileContext(input);
700    xmlHTMLEncodeSend();
701}
702
703/**
704 * xmlHTMLValidityError:
705 * @ctx:  an XML parser context
706 * @msg:  the message to display/transmit
707 * @...:  extra parameters for the message display
708 *
709 * Display and format an validity error messages, gives file,
710 * line, position and extra parameters.
711 */
712static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
713xmlHTMLValidityError(void *ctx, const char *msg, ...)
714{
715    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
716    xmlParserInputPtr input;
717    va_list args;
718    int len;
719
720    buffer[0] = 0;
721    input = ctxt->input;
722    if ((input->filename == NULL) && (ctxt->inputNr > 1))
723        input = ctxt->inputTab[ctxt->inputNr - 2];
724
725    xmlHTMLPrintFileInfo(input);
726
727    xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
728    len = strlen(buffer);
729    va_start(args, msg);
730    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
731    va_end(args);
732    xmlHTMLEncodeSend();
733    xmlGenericError(xmlGenericErrorContext, "</p>\n");
734
735    xmlHTMLPrintFileContext(input);
736    xmlHTMLEncodeSend();
737    progresult = XMLLINT_ERR_VALID;
738}
739
740/**
741 * xmlHTMLValidityWarning:
742 * @ctx:  an XML parser context
743 * @msg:  the message to display/transmit
744 * @...:  extra parameters for the message display
745 *
746 * Display and format a validity warning messages, gives file, line,
747 * position and extra parameters.
748 */
749static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
750xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
751{
752    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
753    xmlParserInputPtr input;
754    va_list args;
755    int len;
756
757    buffer[0] = 0;
758    input = ctxt->input;
759    if ((input->filename == NULL) && (ctxt->inputNr > 1))
760        input = ctxt->inputTab[ctxt->inputNr - 2];
761
762    xmlHTMLPrintFileInfo(input);
763
764    xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
765    va_start(args, msg);
766    len = strlen(buffer);
767    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
768    va_end(args);
769    xmlHTMLEncodeSend();
770    xmlGenericError(xmlGenericErrorContext, "</p>\n");
771
772    xmlHTMLPrintFileContext(input);
773    xmlHTMLEncodeSend();
774}
775
776/************************************************************************
777 *									*
778 *			Shell Interface					*
779 *									*
780 ************************************************************************/
781#ifdef LIBXML_DEBUG_ENABLED
782#ifdef LIBXML_XPATH_ENABLED
783/**
784 * xmlShellReadline:
785 * @prompt:  the prompt value
786 *
787 * Read a string
788 *
789 * Returns a pointer to it or NULL on EOF the caller is expected to
790 *     free the returned string.
791 */
792static char *
793xmlShellReadline(char *prompt) {
794#ifdef HAVE_LIBREADLINE
795    char *line_read;
796
797    /* Get a line from the user. */
798    line_read = readline (prompt);
799
800    /* If the line has any text in it, save it on the history. */
801    if (line_read && *line_read)
802	add_history (line_read);
803
804    return (line_read);
805#else
806    char line_read[501];
807    char *ret;
808    int len;
809
810    if (prompt != NULL)
811	fprintf(stdout, "%s", prompt);
812    fflush(stdout);
813    if (!fgets(line_read, 500, stdin))
814        return(NULL);
815    line_read[500] = 0;
816    len = strlen(line_read);
817    ret = (char *) malloc(len + 1);
818    if (ret != NULL) {
819	memcpy (ret, line_read, len + 1);
820    }
821    return(ret);
822#endif
823}
824#endif /* LIBXML_XPATH_ENABLED */
825#endif /* LIBXML_DEBUG_ENABLED */
826
827/************************************************************************
828 *									*
829 *			I/O Interfaces					*
830 *									*
831 ************************************************************************/
832
833static int myRead(FILE *f, char * buf, int len) {
834    return(fread(buf, 1, len, f));
835}
836static void myClose(FILE *f) {
837  if (f != stdin) {
838    fclose(f);
839  }
840}
841
842/************************************************************************
843 *									*
844 *			SAX based tests					*
845 *									*
846 ************************************************************************/
847
848/*
849 * empty SAX block
850 */
851static xmlSAXHandler emptySAXHandlerStruct = {
852    NULL, /* internalSubset */
853    NULL, /* isStandalone */
854    NULL, /* hasInternalSubset */
855    NULL, /* hasExternalSubset */
856    NULL, /* resolveEntity */
857    NULL, /* getEntity */
858    NULL, /* entityDecl */
859    NULL, /* notationDecl */
860    NULL, /* attributeDecl */
861    NULL, /* elementDecl */
862    NULL, /* unparsedEntityDecl */
863    NULL, /* setDocumentLocator */
864    NULL, /* startDocument */
865    NULL, /* endDocument */
866    NULL, /* startElement */
867    NULL, /* endElement */
868    NULL, /* reference */
869    NULL, /* characters */
870    NULL, /* ignorableWhitespace */
871    NULL, /* processingInstruction */
872    NULL, /* comment */
873    NULL, /* xmlParserWarning */
874    NULL, /* xmlParserError */
875    NULL, /* xmlParserError */
876    NULL, /* getParameterEntity */
877    NULL, /* cdataBlock; */
878    NULL, /* externalSubset; */
879    XML_SAX2_MAGIC,
880    NULL,
881    NULL, /* startElementNs */
882    NULL, /* endElementNs */
883    NULL  /* xmlStructuredErrorFunc */
884};
885
886static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
887extern xmlSAXHandlerPtr debugSAXHandler;
888static int callbacks;
889
890/**
891 * isStandaloneDebug:
892 * @ctxt:  An XML parser context
893 *
894 * Is this document tagged standalone ?
895 *
896 * Returns 1 if true
897 */
898static int
899isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
900{
901    callbacks++;
902    if (noout)
903	return(0);
904    fprintf(stdout, "SAX.isStandalone()\n");
905    return(0);
906}
907
908/**
909 * hasInternalSubsetDebug:
910 * @ctxt:  An XML parser context
911 *
912 * Does this document has an internal subset
913 *
914 * Returns 1 if true
915 */
916static int
917hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
918{
919    callbacks++;
920    if (noout)
921	return(0);
922    fprintf(stdout, "SAX.hasInternalSubset()\n");
923    return(0);
924}
925
926/**
927 * hasExternalSubsetDebug:
928 * @ctxt:  An XML parser context
929 *
930 * Does this document has an external subset
931 *
932 * Returns 1 if true
933 */
934static int
935hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
936{
937    callbacks++;
938    if (noout)
939	return(0);
940    fprintf(stdout, "SAX.hasExternalSubset()\n");
941    return(0);
942}
943
944/**
945 * internalSubsetDebug:
946 * @ctxt:  An XML parser context
947 *
948 * Does this document has an internal subset
949 */
950static void
951internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
952	       const xmlChar *ExternalID, const xmlChar *SystemID)
953{
954    callbacks++;
955    if (noout)
956	return;
957    fprintf(stdout, "SAX.internalSubset(%s,", name);
958    if (ExternalID == NULL)
959	fprintf(stdout, " ,");
960    else
961	fprintf(stdout, " %s,", ExternalID);
962    if (SystemID == NULL)
963	fprintf(stdout, " )\n");
964    else
965	fprintf(stdout, " %s)\n", SystemID);
966}
967
968/**
969 * externalSubsetDebug:
970 * @ctxt:  An XML parser context
971 *
972 * Does this document has an external subset
973 */
974static void
975externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
976	       const xmlChar *ExternalID, const xmlChar *SystemID)
977{
978    callbacks++;
979    if (noout)
980	return;
981    fprintf(stdout, "SAX.externalSubset(%s,", name);
982    if (ExternalID == NULL)
983	fprintf(stdout, " ,");
984    else
985	fprintf(stdout, " %s,", ExternalID);
986    if (SystemID == NULL)
987	fprintf(stdout, " )\n");
988    else
989	fprintf(stdout, " %s)\n", SystemID);
990}
991
992/**
993 * resolveEntityDebug:
994 * @ctxt:  An XML parser context
995 * @publicId: The public ID of the entity
996 * @systemId: The system ID of the entity
997 *
998 * Special entity resolver, better left to the parser, it has
999 * more context than the application layer.
1000 * The default behaviour is to NOT resolve the entities, in that case
1001 * the ENTITY_REF nodes are built in the structure (and the parameter
1002 * values).
1003 *
1004 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
1005 */
1006static xmlParserInputPtr
1007resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
1008{
1009    callbacks++;
1010    if (noout)
1011	return(NULL);
1012    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1013
1014
1015    fprintf(stdout, "SAX.resolveEntity(");
1016    if (publicId != NULL)
1017	fprintf(stdout, "%s", (char *)publicId);
1018    else
1019	fprintf(stdout, " ");
1020    if (systemId != NULL)
1021	fprintf(stdout, ", %s)\n", (char *)systemId);
1022    else
1023	fprintf(stdout, ", )\n");
1024    return(NULL);
1025}
1026
1027/**
1028 * getEntityDebug:
1029 * @ctxt:  An XML parser context
1030 * @name: The entity name
1031 *
1032 * Get an entity by name
1033 *
1034 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
1035 */
1036static xmlEntityPtr
1037getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1038{
1039    callbacks++;
1040    if (noout)
1041	return(NULL);
1042    fprintf(stdout, "SAX.getEntity(%s)\n", name);
1043    return(NULL);
1044}
1045
1046/**
1047 * getParameterEntityDebug:
1048 * @ctxt:  An XML parser context
1049 * @name: The entity name
1050 *
1051 * Get a parameter entity by name
1052 *
1053 * Returns the xmlParserInputPtr
1054 */
1055static xmlEntityPtr
1056getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1057{
1058    callbacks++;
1059    if (noout)
1060	return(NULL);
1061    fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
1062    return(NULL);
1063}
1064
1065
1066/**
1067 * entityDeclDebug:
1068 * @ctxt:  An XML parser context
1069 * @name:  the entity name
1070 * @type:  the entity type
1071 * @publicId: The public ID of the entity
1072 * @systemId: The system ID of the entity
1073 * @content: the entity value (without processing).
1074 *
1075 * An entity definition has been parsed
1076 */
1077static void
1078entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1079          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
1080{
1081const xmlChar *nullstr = BAD_CAST "(null)";
1082    /* not all libraries handle printing null pointers nicely */
1083    if (publicId == NULL)
1084        publicId = nullstr;
1085    if (systemId == NULL)
1086        systemId = nullstr;
1087    if (content == NULL)
1088        content = (xmlChar *)nullstr;
1089    callbacks++;
1090    if (noout)
1091	return;
1092    fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
1093            name, type, publicId, systemId, content);
1094}
1095
1096/**
1097 * attributeDeclDebug:
1098 * @ctxt:  An XML parser context
1099 * @name:  the attribute name
1100 * @type:  the attribute type
1101 *
1102 * An attribute definition has been parsed
1103 */
1104static void
1105attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
1106                   const xmlChar * name, int type, int def,
1107                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
1108{
1109    callbacks++;
1110    if (noout)
1111        return;
1112    if (defaultValue == NULL)
1113        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1114                elem, name, type, def);
1115    else
1116        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1117                elem, name, type, def, defaultValue);
1118    xmlFreeEnumeration(tree);
1119}
1120
1121/**
1122 * elementDeclDebug:
1123 * @ctxt:  An XML parser context
1124 * @name:  the element name
1125 * @type:  the element type
1126 * @content: the element value (without processing).
1127 *
1128 * An element definition has been parsed
1129 */
1130static void
1131elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1132	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
1133{
1134    callbacks++;
1135    if (noout)
1136	return;
1137    fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
1138            name, type);
1139}
1140
1141/**
1142 * notationDeclDebug:
1143 * @ctxt:  An XML parser context
1144 * @name: The name of the notation
1145 * @publicId: The public ID of the entity
1146 * @systemId: The system ID of the entity
1147 *
1148 * What to do when a notation declaration has been parsed.
1149 */
1150static void
1151notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1152	     const xmlChar *publicId, const xmlChar *systemId)
1153{
1154    callbacks++;
1155    if (noout)
1156	return;
1157    fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
1158            (char *) name, (char *) publicId, (char *) systemId);
1159}
1160
1161/**
1162 * unparsedEntityDeclDebug:
1163 * @ctxt:  An XML parser context
1164 * @name: The name of the entity
1165 * @publicId: The public ID of the entity
1166 * @systemId: The system ID of the entity
1167 * @notationName: the name of the notation
1168 *
1169 * What to do when an unparsed entity declaration is parsed
1170 */
1171static void
1172unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1173		   const xmlChar *publicId, const xmlChar *systemId,
1174		   const xmlChar *notationName)
1175{
1176const xmlChar *nullstr = BAD_CAST "(null)";
1177
1178    if (publicId == NULL)
1179        publicId = nullstr;
1180    if (systemId == NULL)
1181        systemId = nullstr;
1182    if (notationName == NULL)
1183        notationName = nullstr;
1184    callbacks++;
1185    if (noout)
1186	return;
1187    fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1188            (char *) name, (char *) publicId, (char *) systemId,
1189	    (char *) notationName);
1190}
1191
1192/**
1193 * setDocumentLocatorDebug:
1194 * @ctxt:  An XML parser context
1195 * @loc: A SAX Locator
1196 *
1197 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1198 * Everything is available on the context, so this is useless in our case.
1199 */
1200static void
1201setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1202{
1203    callbacks++;
1204    if (noout)
1205	return;
1206    fprintf(stdout, "SAX.setDocumentLocator()\n");
1207}
1208
1209/**
1210 * startDocumentDebug:
1211 * @ctxt:  An XML parser context
1212 *
1213 * called when the document start being processed.
1214 */
1215static void
1216startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1217{
1218    callbacks++;
1219    if (noout)
1220	return;
1221    fprintf(stdout, "SAX.startDocument()\n");
1222}
1223
1224/**
1225 * endDocumentDebug:
1226 * @ctxt:  An XML parser context
1227 *
1228 * called when the document end has been detected.
1229 */
1230static void
1231endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1232{
1233    callbacks++;
1234    if (noout)
1235	return;
1236    fprintf(stdout, "SAX.endDocument()\n");
1237}
1238
1239/**
1240 * startElementDebug:
1241 * @ctxt:  An XML parser context
1242 * @name:  The element name
1243 *
1244 * called when an opening tag has been processed.
1245 */
1246static void
1247startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1248{
1249    int i;
1250
1251    callbacks++;
1252    if (noout)
1253	return;
1254    fprintf(stdout, "SAX.startElement(%s", (char *) name);
1255    if (atts != NULL) {
1256        for (i = 0;(atts[i] != NULL);i++) {
1257	    fprintf(stdout, ", %s='", atts[i++]);
1258	    if (atts[i] != NULL)
1259	        fprintf(stdout, "%s'", atts[i]);
1260	}
1261    }
1262    fprintf(stdout, ")\n");
1263}
1264
1265/**
1266 * endElementDebug:
1267 * @ctxt:  An XML parser context
1268 * @name:  The element name
1269 *
1270 * called when the end of an element has been detected.
1271 */
1272static void
1273endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1274{
1275    callbacks++;
1276    if (noout)
1277	return;
1278    fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
1279}
1280
1281/**
1282 * charactersDebug:
1283 * @ctxt:  An XML parser context
1284 * @ch:  a xmlChar string
1285 * @len: the number of xmlChar
1286 *
1287 * receiving some chars from the parser.
1288 * Question: how much at a time ???
1289 */
1290static void
1291charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1292{
1293    char out[40];
1294    int i;
1295
1296    callbacks++;
1297    if (noout)
1298	return;
1299    for (i = 0;(i<len) && (i < 30);i++)
1300	out[i] = ch[i];
1301    out[i] = 0;
1302
1303    fprintf(stdout, "SAX.characters(%s, %d)\n", out, len);
1304}
1305
1306/**
1307 * referenceDebug:
1308 * @ctxt:  An XML parser context
1309 * @name:  The entity name
1310 *
1311 * called when an entity reference is detected.
1312 */
1313static void
1314referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1315{
1316    callbacks++;
1317    if (noout)
1318	return;
1319    fprintf(stdout, "SAX.reference(%s)\n", name);
1320}
1321
1322/**
1323 * ignorableWhitespaceDebug:
1324 * @ctxt:  An XML parser context
1325 * @ch:  a xmlChar string
1326 * @start: the first char in the string
1327 * @len: the number of xmlChar
1328 *
1329 * receiving some ignorable whitespaces from the parser.
1330 * Question: how much at a time ???
1331 */
1332static void
1333ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1334{
1335    char out[40];
1336    int i;
1337
1338    callbacks++;
1339    if (noout)
1340	return;
1341    for (i = 0;(i<len) && (i < 30);i++)
1342	out[i] = ch[i];
1343    out[i] = 0;
1344    fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", out, len);
1345}
1346
1347/**
1348 * processingInstructionDebug:
1349 * @ctxt:  An XML parser context
1350 * @target:  the target name
1351 * @data: the PI data's
1352 * @len: the number of xmlChar
1353 *
1354 * A processing instruction has been parsed.
1355 */
1356static void
1357processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1358                      const xmlChar *data)
1359{
1360    callbacks++;
1361    if (noout)
1362	return;
1363    if (data != NULL)
1364	fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
1365		(char *) target, (char *) data);
1366    else
1367	fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
1368		(char *) target);
1369}
1370
1371/**
1372 * cdataBlockDebug:
1373 * @ctx: the user data (XML parser context)
1374 * @value:  The pcdata content
1375 * @len:  the block length
1376 *
1377 * called when a pcdata block has been parsed
1378 */
1379static void
1380cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1381{
1382    callbacks++;
1383    if (noout)
1384	return;
1385    fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
1386	    (char *) value, len);
1387}
1388
1389/**
1390 * commentDebug:
1391 * @ctxt:  An XML parser context
1392 * @value:  the comment content
1393 *
1394 * A comment has been parsed.
1395 */
1396static void
1397commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1398{
1399    callbacks++;
1400    if (noout)
1401	return;
1402    fprintf(stdout, "SAX.comment(%s)\n", value);
1403}
1404
1405/**
1406 * warningDebug:
1407 * @ctxt:  An XML parser context
1408 * @msg:  the message to display/transmit
1409 * @...:  extra parameters for the message display
1410 *
1411 * Display and format a warning messages, gives file, line, position and
1412 * extra parameters.
1413 */
1414static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
1415warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1416{
1417    va_list args;
1418
1419    callbacks++;
1420    if (noout)
1421	return;
1422    va_start(args, msg);
1423    fprintf(stdout, "SAX.warning: ");
1424    vfprintf(stdout, msg, args);
1425    va_end(args);
1426}
1427
1428/**
1429 * errorDebug:
1430 * @ctxt:  An XML parser context
1431 * @msg:  the message to display/transmit
1432 * @...:  extra parameters for the message display
1433 *
1434 * Display and format a error messages, gives file, line, position and
1435 * extra parameters.
1436 */
1437static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
1438errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1439{
1440    va_list args;
1441
1442    callbacks++;
1443    if (noout)
1444	return;
1445    va_start(args, msg);
1446    fprintf(stdout, "SAX.error: ");
1447    vfprintf(stdout, msg, args);
1448    va_end(args);
1449}
1450
1451/**
1452 * fatalErrorDebug:
1453 * @ctxt:  An XML parser context
1454 * @msg:  the message to display/transmit
1455 * @...:  extra parameters for the message display
1456 *
1457 * Display and format a fatalError messages, gives file, line, position and
1458 * extra parameters.
1459 */
1460static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
1461fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1462{
1463    va_list args;
1464
1465    callbacks++;
1466    if (noout)
1467	return;
1468    va_start(args, msg);
1469    fprintf(stdout, "SAX.fatalError: ");
1470    vfprintf(stdout, msg, args);
1471    va_end(args);
1472}
1473
1474static xmlSAXHandler debugSAXHandlerStruct = {
1475    internalSubsetDebug,
1476    isStandaloneDebug,
1477    hasInternalSubsetDebug,
1478    hasExternalSubsetDebug,
1479    resolveEntityDebug,
1480    getEntityDebug,
1481    entityDeclDebug,
1482    notationDeclDebug,
1483    attributeDeclDebug,
1484    elementDeclDebug,
1485    unparsedEntityDeclDebug,
1486    setDocumentLocatorDebug,
1487    startDocumentDebug,
1488    endDocumentDebug,
1489    startElementDebug,
1490    endElementDebug,
1491    referenceDebug,
1492    charactersDebug,
1493    ignorableWhitespaceDebug,
1494    processingInstructionDebug,
1495    commentDebug,
1496    warningDebug,
1497    errorDebug,
1498    fatalErrorDebug,
1499    getParameterEntityDebug,
1500    cdataBlockDebug,
1501    externalSubsetDebug,
1502    1,
1503    NULL,
1504    NULL,
1505    NULL,
1506    NULL
1507};
1508
1509xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1510
1511/*
1512 * SAX2 specific callbacks
1513 */
1514/**
1515 * startElementNsDebug:
1516 * @ctxt:  An XML parser context
1517 * @name:  The element name
1518 *
1519 * called when an opening tag has been processed.
1520 */
1521static void
1522startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1523                    const xmlChar *localname,
1524                    const xmlChar *prefix,
1525                    const xmlChar *URI,
1526		    int nb_namespaces,
1527		    const xmlChar **namespaces,
1528		    int nb_attributes,
1529		    int nb_defaulted,
1530		    const xmlChar **attributes)
1531{
1532    int i;
1533
1534    callbacks++;
1535    if (noout)
1536	return;
1537    fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
1538    if (prefix == NULL)
1539	fprintf(stdout, ", NULL");
1540    else
1541	fprintf(stdout, ", %s", (char *) prefix);
1542    if (URI == NULL)
1543	fprintf(stdout, ", NULL");
1544    else
1545	fprintf(stdout, ", '%s'", (char *) URI);
1546    fprintf(stdout, ", %d", nb_namespaces);
1547
1548    if (namespaces != NULL) {
1549        for (i = 0;i < nb_namespaces * 2;i++) {
1550	    fprintf(stdout, ", xmlns");
1551	    if (namespaces[i] != NULL)
1552	        fprintf(stdout, ":%s", namespaces[i]);
1553	    i++;
1554	    fprintf(stdout, "='%s'", namespaces[i]);
1555	}
1556    }
1557    fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
1558    if (attributes != NULL) {
1559        for (i = 0;i < nb_attributes * 5;i += 5) {
1560	    if (attributes[i + 1] != NULL)
1561		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
1562	    else
1563		fprintf(stdout, ", %s='", attributes[i]);
1564	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
1565		    (int)(attributes[i + 4] - attributes[i + 3]));
1566	}
1567    }
1568    fprintf(stdout, ")\n");
1569}
1570
1571/**
1572 * endElementDebug:
1573 * @ctxt:  An XML parser context
1574 * @name:  The element name
1575 *
1576 * called when the end of an element has been detected.
1577 */
1578static void
1579endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1580                  const xmlChar *localname,
1581                  const xmlChar *prefix,
1582                  const xmlChar *URI)
1583{
1584    callbacks++;
1585    if (noout)
1586	return;
1587    fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
1588    if (prefix == NULL)
1589	fprintf(stdout, ", NULL");
1590    else
1591	fprintf(stdout, ", %s", (char *) prefix);
1592    if (URI == NULL)
1593	fprintf(stdout, ", NULL)\n");
1594    else
1595	fprintf(stdout, ", '%s')\n", (char *) URI);
1596}
1597
1598static xmlSAXHandler debugSAX2HandlerStruct = {
1599    internalSubsetDebug,
1600    isStandaloneDebug,
1601    hasInternalSubsetDebug,
1602    hasExternalSubsetDebug,
1603    resolveEntityDebug,
1604    getEntityDebug,
1605    entityDeclDebug,
1606    notationDeclDebug,
1607    attributeDeclDebug,
1608    elementDeclDebug,
1609    unparsedEntityDeclDebug,
1610    setDocumentLocatorDebug,
1611    startDocumentDebug,
1612    endDocumentDebug,
1613    NULL,
1614    NULL,
1615    referenceDebug,
1616    charactersDebug,
1617    ignorableWhitespaceDebug,
1618    processingInstructionDebug,
1619    commentDebug,
1620    warningDebug,
1621    errorDebug,
1622    fatalErrorDebug,
1623    getParameterEntityDebug,
1624    cdataBlockDebug,
1625    externalSubsetDebug,
1626    XML_SAX2_MAGIC,
1627    NULL,
1628    startElementNsDebug,
1629    endElementNsDebug,
1630    NULL
1631};
1632
1633static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1634
1635static void
1636testSAX(const char *filename) {
1637    xmlSAXHandlerPtr handler;
1638    const char *user_data = "user_data"; /* mostly for debugging */
1639    xmlParserInputBufferPtr buf = NULL;
1640    xmlParserInputPtr inputStream;
1641    xmlParserCtxtPtr ctxt = NULL;
1642    xmlSAXHandlerPtr old_sax = NULL;
1643
1644    callbacks = 0;
1645
1646    if (noout) {
1647        handler = emptySAXHandler;
1648#ifdef LIBXML_SAX1_ENABLED
1649    } else if (sax1) {
1650        handler = debugSAXHandler;
1651#endif
1652    } else {
1653        handler = debugSAX2Handler;
1654    }
1655
1656    /*
1657     * it's not the simplest code but the most generic in term of I/O
1658     */
1659    buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1660    if (buf == NULL) {
1661        goto error;
1662    }
1663
1664#ifdef LIBXML_SCHEMAS_ENABLED
1665    if (wxschemas != NULL) {
1666        int ret;
1667	xmlSchemaValidCtxtPtr vctxt;
1668
1669	vctxt = xmlSchemaNewValidCtxt(wxschemas);
1670	xmlSchemaSetValidErrors(vctxt,
1671		(xmlSchemaValidityErrorFunc) fprintf,
1672		(xmlSchemaValidityWarningFunc) fprintf,
1673		stderr);
1674	xmlSchemaValidateSetFilename(vctxt, filename);
1675
1676	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
1677	                              (void *)user_data);
1678	if (repeat == 0) {
1679	    if (ret == 0) {
1680		fprintf(stderr, "%s validates\n", filename);
1681	    } else if (ret > 0) {
1682		fprintf(stderr, "%s fails to validate\n", filename);
1683		progresult = XMLLINT_ERR_VALID;
1684	    } else {
1685		fprintf(stderr, "%s validation generated an internal error\n",
1686		       filename);
1687		progresult = XMLLINT_ERR_VALID;
1688	    }
1689	}
1690	xmlSchemaFreeValidCtxt(vctxt);
1691    } else
1692#endif
1693    {
1694	/*
1695	 * Create the parser context amd hook the input
1696	 */
1697	ctxt = xmlNewParserCtxt();
1698	if (ctxt == NULL) {
1699	    xmlFreeParserInputBuffer(buf);
1700	    goto error;
1701	}
1702	old_sax = ctxt->sax;
1703	ctxt->sax = handler;
1704	ctxt->userData = (void *) user_data;
1705	inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
1706	if (inputStream == NULL) {
1707	    xmlFreeParserInputBuffer(buf);
1708	    goto error;
1709	}
1710	inputPush(ctxt, inputStream);
1711
1712	/* do the parsing */
1713	xmlParseDocument(ctxt);
1714
1715	if (ctxt->myDoc != NULL) {
1716	    fprintf(stderr, "SAX generated a doc !\n");
1717	    xmlFreeDoc(ctxt->myDoc);
1718	    ctxt->myDoc = NULL;
1719	}
1720    }
1721
1722error:
1723    if (ctxt != NULL) {
1724        ctxt->sax = old_sax;
1725        xmlFreeParserCtxt(ctxt);
1726    }
1727}
1728
1729/************************************************************************
1730 *									*
1731 *			Stream Test processing				*
1732 *									*
1733 ************************************************************************/
1734#ifdef LIBXML_READER_ENABLED
1735static void processNode(xmlTextReaderPtr reader) {
1736    const xmlChar *name, *value;
1737    int type, empty;
1738
1739    type = xmlTextReaderNodeType(reader);
1740    empty = xmlTextReaderIsEmptyElement(reader);
1741
1742    if (debug) {
1743	name = xmlTextReaderConstName(reader);
1744	if (name == NULL)
1745	    name = BAD_CAST "--";
1746
1747	value = xmlTextReaderConstValue(reader);
1748
1749
1750	printf("%d %d %s %d %d",
1751		xmlTextReaderDepth(reader),
1752		type,
1753		name,
1754		empty,
1755		xmlTextReaderHasValue(reader));
1756	if (value == NULL)
1757	    printf("\n");
1758	else {
1759	    printf(" %s\n", value);
1760	}
1761    }
1762#ifdef LIBXML_PATTERN_ENABLED
1763    if (patternc) {
1764        xmlChar *path = NULL;
1765        int match = -1;
1766
1767	if (type == XML_READER_TYPE_ELEMENT) {
1768	    /* do the check only on element start */
1769	    match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
1770
1771	    if (match) {
1772#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
1773		path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
1774		printf("Node %s matches pattern %s\n", path, pattern);
1775#else
1776                printf("Node %s matches pattern %s\n",
1777                       xmlTextReaderConstName(reader), pattern);
1778#endif
1779	    }
1780	}
1781	if (patstream != NULL) {
1782	    int ret;
1783
1784	    if (type == XML_READER_TYPE_ELEMENT) {
1785		ret = xmlStreamPush(patstream,
1786		                    xmlTextReaderConstLocalName(reader),
1787				    xmlTextReaderConstNamespaceUri(reader));
1788		if (ret < 0) {
1789		    fprintf(stderr, "xmlStreamPush() failure\n");
1790                    xmlFreeStreamCtxt(patstream);
1791		    patstream = NULL;
1792		} else if (ret != match) {
1793#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
1794		    if (path == NULL) {
1795		        path = xmlGetNodePath(
1796		                       xmlTextReaderCurrentNode(reader));
1797		    }
1798#endif
1799		    fprintf(stderr,
1800		            "xmlPatternMatch and xmlStreamPush disagree\n");
1801                    if (path != NULL)
1802                        fprintf(stderr, "  pattern %s node %s\n",
1803                                pattern, path);
1804                    else
1805		        fprintf(stderr, "  pattern %s node %s\n",
1806			    pattern, xmlTextReaderConstName(reader));
1807		}
1808
1809	    }
1810	    if ((type == XML_READER_TYPE_END_ELEMENT) ||
1811	        ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
1812	        ret = xmlStreamPop(patstream);
1813		if (ret < 0) {
1814		    fprintf(stderr, "xmlStreamPop() failure\n");
1815                    xmlFreeStreamCtxt(patstream);
1816		    patstream = NULL;
1817		}
1818	    }
1819	}
1820	if (path != NULL)
1821	    xmlFree(path);
1822    }
1823#endif
1824}
1825
1826static void streamFile(char *filename) {
1827    xmlTextReaderPtr reader;
1828    int ret;
1829#ifdef HAVE_MMAP
1830    int fd = -1;
1831    struct stat info;
1832    const char *base = NULL;
1833    xmlParserInputBufferPtr input = NULL;
1834
1835    if (memory) {
1836	if (stat(filename, &info) < 0)
1837	    return;
1838	if ((fd = open(filename, O_RDONLY)) < 0)
1839	    return;
1840	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
1841	if (base == (void *) MAP_FAILED) {
1842	    close(fd);
1843	    fprintf(stderr, "mmap failure for file %s\n", filename);
1844	    progresult = XMLLINT_ERR_RDFILE;
1845	    return;
1846	}
1847
1848	reader = xmlReaderForMemory(base, info.st_size, filename,
1849	                            NULL, options);
1850    } else
1851#endif
1852	reader = xmlReaderForFile(filename, NULL, options);
1853#ifdef LIBXML_PATTERN_ENABLED
1854    if (pattern != NULL) {
1855        patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
1856	if (patternc == NULL) {
1857	    xmlGenericError(xmlGenericErrorContext,
1858		    "Pattern %s failed to compile\n", pattern);
1859            progresult = XMLLINT_ERR_SCHEMAPAT;
1860	    pattern = NULL;
1861	}
1862    }
1863    if (patternc != NULL) {
1864        patstream = xmlPatternGetStreamCtxt(patternc);
1865	if (patstream != NULL) {
1866	    ret = xmlStreamPush(patstream, NULL, NULL);
1867	    if (ret < 0) {
1868		fprintf(stderr, "xmlStreamPush() failure\n");
1869		xmlFreeStreamCtxt(patstream);
1870		patstream = NULL;
1871            }
1872	}
1873    }
1874#endif
1875
1876
1877    if (reader != NULL) {
1878#ifdef LIBXML_VALID_ENABLED
1879	if (valid)
1880	    xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
1881	else
1882#endif /* LIBXML_VALID_ENABLED */
1883	    if (loaddtd)
1884		xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
1885#ifdef LIBXML_SCHEMAS_ENABLED
1886	if (relaxng != NULL) {
1887	    if ((timing) && (!repeat)) {
1888		startTimer();
1889	    }
1890	    ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
1891	    if (ret < 0) {
1892		xmlGenericError(xmlGenericErrorContext,
1893			"Relax-NG schema %s failed to compile\n", relaxng);
1894		progresult = XMLLINT_ERR_SCHEMACOMP;
1895		relaxng = NULL;
1896	    }
1897	    if ((timing) && (!repeat)) {
1898		endTimer("Compiling the schemas");
1899	    }
1900	}
1901	if (schema != NULL) {
1902	    if ((timing) && (!repeat)) {
1903		startTimer();
1904	    }
1905	    ret = xmlTextReaderSchemaValidate(reader, schema);
1906	    if (ret < 0) {
1907		xmlGenericError(xmlGenericErrorContext,
1908			"XSD schema %s failed to compile\n", schema);
1909		progresult = XMLLINT_ERR_SCHEMACOMP;
1910		schema = NULL;
1911	    }
1912	    if ((timing) && (!repeat)) {
1913		endTimer("Compiling the schemas");
1914	    }
1915	}
1916#endif
1917
1918	/*
1919	 * Process all nodes in sequence
1920	 */
1921	if ((timing) && (!repeat)) {
1922	    startTimer();
1923	}
1924	ret = xmlTextReaderRead(reader);
1925	while (ret == 1) {
1926	    if ((debug)
1927#ifdef LIBXML_PATTERN_ENABLED
1928	        || (patternc)
1929#endif
1930	       )
1931		processNode(reader);
1932	    ret = xmlTextReaderRead(reader);
1933	}
1934	if ((timing) && (!repeat)) {
1935#ifdef LIBXML_SCHEMAS_ENABLED
1936	    if (relaxng != NULL)
1937		endTimer("Parsing and validating");
1938	    else
1939#endif
1940#ifdef LIBXML_VALID_ENABLED
1941	    if (valid)
1942		endTimer("Parsing and validating");
1943	    else
1944#endif
1945	    endTimer("Parsing");
1946	}
1947
1948#ifdef LIBXML_VALID_ENABLED
1949	if (valid) {
1950	    if (xmlTextReaderIsValid(reader) != 1) {
1951		xmlGenericError(xmlGenericErrorContext,
1952			"Document %s does not validate\n", filename);
1953		progresult = XMLLINT_ERR_VALID;
1954	    }
1955	}
1956#endif /* LIBXML_VALID_ENABLED */
1957#ifdef LIBXML_SCHEMAS_ENABLED
1958	if ((relaxng != NULL) || (schema != NULL)) {
1959	    if (xmlTextReaderIsValid(reader) != 1) {
1960		fprintf(stderr, "%s fails to validate\n", filename);
1961		progresult = XMLLINT_ERR_VALID;
1962	    } else {
1963		fprintf(stderr, "%s validates\n", filename);
1964	    }
1965	}
1966#endif
1967	/*
1968	 * Done, cleanup and status
1969	 */
1970	xmlFreeTextReader(reader);
1971	if (ret != 0) {
1972	    fprintf(stderr, "%s : failed to parse\n", filename);
1973	    progresult = XMLLINT_ERR_UNCLASS;
1974	}
1975    } else {
1976	fprintf(stderr, "Unable to open %s\n", filename);
1977	progresult = XMLLINT_ERR_UNCLASS;
1978    }
1979#ifdef LIBXML_PATTERN_ENABLED
1980    if (patstream != NULL) {
1981	xmlFreeStreamCtxt(patstream);
1982	patstream = NULL;
1983    }
1984#endif
1985#ifdef HAVE_MMAP
1986    if (memory) {
1987        xmlFreeParserInputBuffer(input);
1988	munmap((char *) base, info.st_size);
1989	close(fd);
1990    }
1991#endif
1992}
1993
1994static void walkDoc(xmlDocPtr doc) {
1995    xmlTextReaderPtr reader;
1996    int ret;
1997
1998#ifdef LIBXML_PATTERN_ENABLED
1999    xmlNodePtr root;
2000    const xmlChar *namespaces[22];
2001    int i;
2002    xmlNsPtr ns;
2003
2004    root = xmlDocGetRootElement(doc);
2005    if (root == NULL ) {
2006        xmlGenericError(xmlGenericErrorContext,
2007                "Document does not have a root element");
2008        progresult = XMLLINT_ERR_UNCLASS;
2009        return;
2010    }
2011    for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
2012        namespaces[i++] = ns->href;
2013        namespaces[i++] = ns->prefix;
2014    }
2015    namespaces[i++] = NULL;
2016    namespaces[i] = NULL;
2017
2018    if (pattern != NULL) {
2019        patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict,
2020	                             0, &namespaces[0]);
2021	if (patternc == NULL) {
2022	    xmlGenericError(xmlGenericErrorContext,
2023		    "Pattern %s failed to compile\n", pattern);
2024            progresult = XMLLINT_ERR_SCHEMAPAT;
2025	    pattern = NULL;
2026	}
2027    }
2028    if (patternc != NULL) {
2029        patstream = xmlPatternGetStreamCtxt(patternc);
2030	if (patstream != NULL) {
2031	    ret = xmlStreamPush(patstream, NULL, NULL);
2032	    if (ret < 0) {
2033		fprintf(stderr, "xmlStreamPush() failure\n");
2034		xmlFreeStreamCtxt(patstream);
2035		patstream = NULL;
2036            }
2037	}
2038    }
2039#endif /* LIBXML_PATTERN_ENABLED */
2040    reader = xmlReaderWalker(doc);
2041    if (reader != NULL) {
2042	if ((timing) && (!repeat)) {
2043	    startTimer();
2044	}
2045	ret = xmlTextReaderRead(reader);
2046	while (ret == 1) {
2047	    if ((debug)
2048#ifdef LIBXML_PATTERN_ENABLED
2049	        || (patternc)
2050#endif
2051	       )
2052		processNode(reader);
2053	    ret = xmlTextReaderRead(reader);
2054	}
2055	if ((timing) && (!repeat)) {
2056	    endTimer("walking through the doc");
2057	}
2058	xmlFreeTextReader(reader);
2059	if (ret != 0) {
2060	    fprintf(stderr, "failed to walk through the doc\n");
2061	    progresult = XMLLINT_ERR_UNCLASS;
2062	}
2063    } else {
2064	fprintf(stderr, "Failed to crate a reader from the document\n");
2065	progresult = XMLLINT_ERR_UNCLASS;
2066    }
2067#ifdef LIBXML_PATTERN_ENABLED
2068    if (patstream != NULL) {
2069	xmlFreeStreamCtxt(patstream);
2070	patstream = NULL;
2071    }
2072#endif
2073}
2074#endif /* LIBXML_READER_ENABLED */
2075
2076#ifdef LIBXML_XPATH_ENABLED
2077/************************************************************************
2078 *									*
2079 *			XPath Query                                     *
2080 *									*
2081 ************************************************************************/
2082
2083static void doXPathDump(xmlXPathObjectPtr cur) {
2084    switch(cur->type) {
2085        case XPATH_NODESET: {
2086            int i;
2087            xmlNodePtr node;
2088#ifdef LIBXML_OUTPUT_ENABLED
2089            xmlSaveCtxtPtr ctxt;
2090
2091            if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) {
2092                fprintf(stderr, "XPath set is empty\n");
2093                progresult = XMLLINT_ERR_XPATH;
2094                break;
2095            }
2096            ctxt = xmlSaveToFd(1, NULL, 0);
2097            if (ctxt == NULL) {
2098                fprintf(stderr, "Out of memory for XPath\n");
2099                progresult = XMLLINT_ERR_MEM;
2100                return;
2101            }
2102            for (i = 0;i < cur->nodesetval->nodeNr;i++) {
2103                node = cur->nodesetval->nodeTab[i];
2104                xmlSaveTree(ctxt, node);
2105            }
2106            xmlSaveClose(ctxt);
2107#else
2108            printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
2109#endif
2110	    break;
2111        }
2112        case XPATH_BOOLEAN:
2113	    if (cur->boolval) printf("true");
2114	    else printf("false");
2115	    break;
2116        case XPATH_NUMBER:
2117	    switch (xmlXPathIsInf(cur->floatval)) {
2118	    case 1:
2119		printf("Infinity");
2120		break;
2121	    case -1:
2122		printf("-Infinity");
2123		break;
2124	    default:
2125		if (xmlXPathIsNaN(cur->floatval)) {
2126		    printf("NaN");
2127		} else {
2128		    printf("%0g", cur->floatval);
2129		}
2130	    }
2131	    break;
2132        case XPATH_STRING:
2133	    printf("%s", (const char *) cur->stringval);
2134	    break;
2135        case XPATH_UNDEFINED:
2136	    fprintf(stderr, "XPath Object is uninitialized\n");
2137            progresult = XMLLINT_ERR_XPATH;
2138	    break;
2139	default:
2140	    fprintf(stderr, "XPath object of unexpected type\n");
2141            progresult = XMLLINT_ERR_XPATH;
2142	    break;
2143    }
2144}
2145
2146static void doXPathQuery(xmlDocPtr doc, const char *query) {
2147    xmlXPathContextPtr ctxt;
2148    xmlXPathObjectPtr res;
2149
2150    ctxt = xmlXPathNewContext(doc);
2151    if (ctxt == NULL) {
2152        fprintf(stderr, "Out of memory for XPath\n");
2153        progresult = XMLLINT_ERR_MEM;
2154        return;
2155    }
2156    ctxt->node = (xmlNodePtr) doc;
2157    res = xmlXPathEval(BAD_CAST query, ctxt);
2158    xmlXPathFreeContext(ctxt);
2159
2160    if (res == NULL) {
2161        fprintf(stderr, "XPath evaluation failure\n");
2162        progresult = XMLLINT_ERR_XPATH;
2163        return;
2164    }
2165    doXPathDump(res);
2166    xmlXPathFreeObject(res);
2167}
2168#endif /* LIBXML_XPATH_ENABLED */
2169
2170/************************************************************************
2171 *									*
2172 *			Tree Test processing				*
2173 *									*
2174 ************************************************************************/
2175static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
2176    xmlDocPtr doc = NULL;
2177#ifdef LIBXML_TREE_ENABLED
2178    xmlDocPtr tmp;
2179#endif /* LIBXML_TREE_ENABLED */
2180
2181    if ((timing) && (!repeat))
2182	startTimer();
2183
2184
2185#ifdef LIBXML_TREE_ENABLED
2186    if (filename == NULL) {
2187	if (generate) {
2188	    xmlNodePtr n;
2189
2190	    doc = xmlNewDoc(BAD_CAST "1.0");
2191	    n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
2192	    xmlNodeSetContent(n, BAD_CAST "abc");
2193	    xmlDocSetRootElement(doc, n);
2194	}
2195    }
2196#endif /* LIBXML_TREE_ENABLED */
2197#ifdef LIBXML_HTML_ENABLED
2198#ifdef LIBXML_PUSH_ENABLED
2199    else if ((html) && (push)) {
2200        FILE *f;
2201
2202#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2203	f = fopen(filename, "rb");
2204#elif defined(__OS400__)
2205	f = fopen(filename, "rb");
2206#else
2207	f = fopen(filename, "r");
2208#endif
2209        if (f != NULL) {
2210            int res;
2211            char chars[4096];
2212            htmlParserCtxtPtr ctxt;
2213
2214            res = fread(chars, 1, 4, f);
2215            if (res > 0) {
2216                ctxt = htmlCreatePushParserCtxt(NULL, NULL,
2217                            chars, res, filename, XML_CHAR_ENCODING_NONE);
2218                xmlCtxtUseOptions(ctxt, options);
2219                while ((res = fread(chars, 1, pushsize, f)) > 0) {
2220                    htmlParseChunk(ctxt, chars, res, 0);
2221                }
2222                htmlParseChunk(ctxt, chars, 0, 1);
2223                doc = ctxt->myDoc;
2224                htmlFreeParserCtxt(ctxt);
2225            }
2226            fclose(f);
2227        }
2228    }
2229#endif /* LIBXML_PUSH_ENABLED */
2230#ifdef HAVE_MMAP
2231    else if ((html) && (memory)) {
2232	int fd;
2233	struct stat info;
2234	const char *base;
2235	if (stat(filename, &info) < 0)
2236	    return;
2237	if ((fd = open(filename, O_RDONLY)) < 0)
2238	    return;
2239	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2240	if (base == (void *) MAP_FAILED) {
2241	    close(fd);
2242	    fprintf(stderr, "mmap failure for file %s\n", filename);
2243	    progresult = XMLLINT_ERR_RDFILE;
2244	    return;
2245	}
2246
2247	doc = htmlReadMemory((char *) base, info.st_size, filename,
2248	                     NULL, options);
2249
2250	munmap((char *) base, info.st_size);
2251	close(fd);
2252    }
2253#endif
2254    else if (html) {
2255	doc = htmlReadFile(filename, NULL, options);
2256    }
2257#endif /* LIBXML_HTML_ENABLED */
2258    else {
2259#ifdef LIBXML_PUSH_ENABLED
2260	/*
2261	 * build an XML tree from a string;
2262	 */
2263	if (push) {
2264	    FILE *f;
2265
2266	    /* '-' Usually means stdin -<sven@zen.org> */
2267	    if ((filename[0] == '-') && (filename[1] == 0)) {
2268	      f = stdin;
2269	    } else {
2270#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2271		f = fopen(filename, "rb");
2272#elif defined(__OS400__)
2273		f = fopen(filename, "rb");
2274#else
2275		f = fopen(filename, "r");
2276#endif
2277	    }
2278	    if (f != NULL) {
2279		int ret;
2280	        int res, size = 1024;
2281	        char chars[1024];
2282                xmlParserCtxtPtr ctxt;
2283
2284		/* if (repeat) size = 1024; */
2285		res = fread(chars, 1, 4, f);
2286		if (res > 0) {
2287		    ctxt = xmlCreatePushParserCtxt(NULL, NULL,
2288		                chars, res, filename);
2289		    xmlCtxtUseOptions(ctxt, options);
2290		    while ((res = fread(chars, 1, size, f)) > 0) {
2291			xmlParseChunk(ctxt, chars, res, 0);
2292		    }
2293		    xmlParseChunk(ctxt, chars, 0, 1);
2294		    doc = ctxt->myDoc;
2295		    ret = ctxt->wellFormed;
2296		    xmlFreeParserCtxt(ctxt);
2297		    if (!ret) {
2298			xmlFreeDoc(doc);
2299			doc = NULL;
2300		    }
2301	        }
2302                if (f != stdin)
2303                    fclose(f);
2304	    }
2305	} else
2306#endif /* LIBXML_PUSH_ENABLED */
2307        if (testIO) {
2308	    if ((filename[0] == '-') && (filename[1] == 0)) {
2309	        doc = xmlReadFd(0, NULL, NULL, options);
2310	    } else {
2311	        FILE *f;
2312
2313#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2314		f = fopen(filename, "rb");
2315#elif defined(__OS400__)
2316		f = fopen(filename, "rb");
2317#else
2318		f = fopen(filename, "r");
2319#endif
2320		if (f != NULL) {
2321		    if (rectxt == NULL)
2322			doc = xmlReadIO((xmlInputReadCallback) myRead,
2323					(xmlInputCloseCallback) myClose, f,
2324					filename, NULL, options);
2325		    else
2326			doc = xmlCtxtReadIO(rectxt,
2327			                (xmlInputReadCallback) myRead,
2328					(xmlInputCloseCallback) myClose, f,
2329					filename, NULL, options);
2330		} else
2331		    doc = NULL;
2332	    }
2333	} else if (htmlout) {
2334	    xmlParserCtxtPtr ctxt;
2335
2336	    if (rectxt == NULL)
2337		ctxt = xmlNewParserCtxt();
2338	    else
2339	        ctxt = rectxt;
2340	    if (ctxt == NULL) {
2341	        doc = NULL;
2342	    } else {
2343	        ctxt->sax->error = xmlHTMLError;
2344	        ctxt->sax->warning = xmlHTMLWarning;
2345	        ctxt->vctxt.error = xmlHTMLValidityError;
2346	        ctxt->vctxt.warning = xmlHTMLValidityWarning;
2347
2348		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2349
2350		if (rectxt == NULL)
2351		    xmlFreeParserCtxt(ctxt);
2352	    }
2353#ifdef HAVE_MMAP
2354	} else if (memory) {
2355	    int fd;
2356	    struct stat info;
2357	    const char *base;
2358	    if (stat(filename, &info) < 0)
2359		return;
2360	    if ((fd = open(filename, O_RDONLY)) < 0)
2361		return;
2362	    base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2363	    if (base == (void *) MAP_FAILED) {
2364	        close(fd);
2365	        fprintf(stderr, "mmap failure for file %s\n", filename);
2366		progresult = XMLLINT_ERR_RDFILE;
2367	        return;
2368	    }
2369
2370	    if (rectxt == NULL)
2371		doc = xmlReadMemory((char *) base, info.st_size,
2372		                    filename, NULL, options);
2373	    else
2374		doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
2375			                filename, NULL, options);
2376
2377	    munmap((char *) base, info.st_size);
2378	    close(fd);
2379#endif
2380#ifdef LIBXML_VALID_ENABLED
2381	} else if (valid) {
2382	    xmlParserCtxtPtr ctxt = NULL;
2383
2384	    if (rectxt == NULL)
2385		ctxt = xmlNewParserCtxt();
2386	    else
2387	        ctxt = rectxt;
2388	    if (ctxt == NULL) {
2389	        doc = NULL;
2390	    } else {
2391		doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2392
2393		if (ctxt->valid == 0)
2394		    progresult = XMLLINT_ERR_RDFILE;
2395		if (rectxt == NULL)
2396		    xmlFreeParserCtxt(ctxt);
2397	    }
2398#endif /* LIBXML_VALID_ENABLED */
2399	} else {
2400	    if (rectxt != NULL)
2401	        doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
2402	    else {
2403#ifdef LIBXML_SAX1_ENABLED
2404                if (sax1)
2405		    doc = xmlParseFile(filename);
2406		else
2407#endif /* LIBXML_SAX1_ENABLED */
2408		doc = xmlReadFile(filename, NULL, options);
2409	    }
2410	}
2411    }
2412
2413    /*
2414     * If we don't have a document we might as well give up.  Do we
2415     * want an error message here?  <sven@zen.org> */
2416    if (doc == NULL) {
2417	progresult = XMLLINT_ERR_UNCLASS;
2418	return;
2419    }
2420
2421    if ((timing) && (!repeat)) {
2422	endTimer("Parsing");
2423    }
2424
2425    /*
2426     * Remove DOCTYPE nodes
2427     */
2428    if (dropdtd) {
2429	xmlDtdPtr dtd;
2430
2431	dtd = xmlGetIntSubset(doc);
2432	if (dtd != NULL) {
2433	    xmlUnlinkNode((xmlNodePtr)dtd);
2434	    xmlFreeDtd(dtd);
2435	}
2436    }
2437
2438#ifdef LIBXML_XINCLUDE_ENABLED
2439    if (xinclude) {
2440	if ((timing) && (!repeat)) {
2441	    startTimer();
2442	}
2443	if (xmlXIncludeProcessFlags(doc, options) < 0)
2444	    progresult = XMLLINT_ERR_UNCLASS;
2445	if ((timing) && (!repeat)) {
2446	    endTimer("Xinclude processing");
2447	}
2448    }
2449#endif
2450
2451#ifdef LIBXML_XPATH_ENABLED
2452    if (xpathquery != NULL) {
2453        doXPathQuery(doc, xpathquery);
2454    }
2455#endif
2456
2457#ifdef LIBXML_DEBUG_ENABLED
2458#ifdef LIBXML_XPATH_ENABLED
2459    /*
2460     * shell interaction
2461     */
2462    if (shell) {
2463        xmlXPathOrderDocElems(doc);
2464        xmlShell(doc, filename, xmlShellReadline, stdout);
2465    }
2466#endif
2467#endif
2468
2469#ifdef LIBXML_TREE_ENABLED
2470    /*
2471     * test intermediate copy if needed.
2472     */
2473    if (copy) {
2474        tmp = doc;
2475	if (timing) {
2476	    startTimer();
2477	}
2478	doc = xmlCopyDoc(doc, 1);
2479	if (timing) {
2480	    endTimer("Copying");
2481	}
2482	if (timing) {
2483	    startTimer();
2484	}
2485	xmlFreeDoc(tmp);
2486	if (timing) {
2487	    endTimer("Freeing original");
2488	}
2489    }
2490#endif /* LIBXML_TREE_ENABLED */
2491
2492#ifdef LIBXML_VALID_ENABLED
2493    if ((insert) && (!html)) {
2494        const xmlChar* list[256];
2495	int nb, i;
2496	xmlNodePtr node;
2497
2498	if (doc->children != NULL) {
2499	    node = doc->children;
2500	    while ((node != NULL) && (node->last == NULL)) node = node->next;
2501	    if (node != NULL) {
2502		nb = xmlValidGetValidElements(node->last, NULL, list, 256);
2503		if (nb < 0) {
2504		    fprintf(stderr, "could not get valid list of elements\n");
2505		} else if (nb == 0) {
2506		    fprintf(stderr, "No element can be inserted under root\n");
2507		} else {
2508		    fprintf(stderr, "%d element types can be inserted under root:\n",
2509		           nb);
2510		    for (i = 0;i < nb;i++) {
2511			 fprintf(stderr, "%s\n", (char *) list[i]);
2512		    }
2513		}
2514	    }
2515	}
2516    }else
2517#endif /* LIBXML_VALID_ENABLED */
2518#ifdef LIBXML_READER_ENABLED
2519    if (walker) {
2520        walkDoc(doc);
2521    }
2522#endif /* LIBXML_READER_ENABLED */
2523#ifdef LIBXML_OUTPUT_ENABLED
2524    if (noout == 0) {
2525        int ret;
2526
2527	/*
2528	 * print it.
2529	 */
2530#ifdef LIBXML_DEBUG_ENABLED
2531	if (!debug) {
2532#endif
2533	    if ((timing) && (!repeat)) {
2534		startTimer();
2535	    }
2536#ifdef LIBXML_HTML_ENABLED
2537            if ((html) && (!xmlout)) {
2538		if (compress) {
2539		    htmlSaveFile(output ? output : "-", doc);
2540		}
2541		else if (encoding != NULL) {
2542		    if (format == 1) {
2543			htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
2544		    }
2545		    else {
2546			htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
2547		    }
2548		}
2549		else if (format == 1) {
2550		    htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
2551		}
2552		else {
2553		    FILE *out;
2554		    if (output == NULL)
2555			out = stdout;
2556		    else {
2557			out = fopen(output,"wb");
2558		    }
2559		    if (out != NULL) {
2560			if (htmlDocDump(out, doc) < 0)
2561			    progresult = XMLLINT_ERR_OUT;
2562
2563			if (output != NULL)
2564			    fclose(out);
2565		    } else {
2566			fprintf(stderr, "failed to open %s\n", output);
2567			progresult = XMLLINT_ERR_OUT;
2568		    }
2569		}
2570		if ((timing) && (!repeat)) {
2571		    endTimer("Saving");
2572		}
2573	    } else
2574#endif
2575#ifdef LIBXML_C14N_ENABLED
2576            if (canonical) {
2577	        xmlChar *result = NULL;
2578		int size;
2579
2580		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
2581		if (size >= 0) {
2582		    if (write(1, result, size) == -1) {
2583		        fprintf(stderr, "Can't write data\n");
2584		    }
2585		    xmlFree(result);
2586		} else {
2587		    fprintf(stderr, "Failed to canonicalize\n");
2588		    progresult = XMLLINT_ERR_OUT;
2589		}
2590	    } else if (canonical_11) {
2591	        xmlChar *result = NULL;
2592		int size;
2593
2594		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
2595		if (size >= 0) {
2596		    if (write(1, result, size) == -1) {
2597		        fprintf(stderr, "Can't write data\n");
2598		    }
2599		    xmlFree(result);
2600		} else {
2601		    fprintf(stderr, "Failed to canonicalize\n");
2602		    progresult = XMLLINT_ERR_OUT;
2603		}
2604	    } else
2605            if (exc_canonical) {
2606	        xmlChar *result = NULL;
2607		int size;
2608
2609		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
2610		if (size >= 0) {
2611		    if (write(1, result, size) == -1) {
2612		        fprintf(stderr, "Can't write data\n");
2613		    }
2614		    xmlFree(result);
2615		} else {
2616		    fprintf(stderr, "Failed to canonicalize\n");
2617		    progresult = XMLLINT_ERR_OUT;
2618		}
2619	    } else
2620#endif
2621#ifdef HAVE_MMAP
2622	    if (memory) {
2623		xmlChar *result;
2624		int len;
2625
2626		if (encoding != NULL) {
2627		    if (format == 1) {
2628		        xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
2629		    } else {
2630			xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
2631		    }
2632		} else {
2633		    if (format == 1)
2634			xmlDocDumpFormatMemory(doc, &result, &len, 1);
2635		    else
2636			xmlDocDumpMemory(doc, &result, &len);
2637		}
2638		if (result == NULL) {
2639		    fprintf(stderr, "Failed to save\n");
2640		    progresult = XMLLINT_ERR_OUT;
2641		} else {
2642		    if (write(1, result, len) == -1) {
2643		        fprintf(stderr, "Can't write data\n");
2644		    }
2645		    xmlFree(result);
2646		}
2647
2648	    } else
2649#endif /* HAVE_MMAP */
2650	    if (compress) {
2651		xmlSaveFile(output ? output : "-", doc);
2652	    } else if (oldout) {
2653	        if (encoding != NULL) {
2654		    if (format == 1) {
2655			ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
2656						   encoding, 1);
2657		    }
2658		    else {
2659			ret = xmlSaveFileEnc(output ? output : "-", doc,
2660			                     encoding);
2661		    }
2662		    if (ret < 0) {
2663			fprintf(stderr, "failed save to %s\n",
2664				output ? output : "-");
2665			progresult = XMLLINT_ERR_OUT;
2666		    }
2667		} else if (format == 1) {
2668		    ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
2669		    if (ret < 0) {
2670			fprintf(stderr, "failed save to %s\n",
2671				output ? output : "-");
2672			progresult = XMLLINT_ERR_OUT;
2673		    }
2674		} else {
2675		    FILE *out;
2676		    if (output == NULL)
2677			out = stdout;
2678		    else {
2679			out = fopen(output,"wb");
2680		    }
2681		    if (out != NULL) {
2682			if (xmlDocDump(out, doc) < 0)
2683			    progresult = XMLLINT_ERR_OUT;
2684
2685			if (output != NULL)
2686			    fclose(out);
2687		    } else {
2688			fprintf(stderr, "failed to open %s\n", output);
2689			progresult = XMLLINT_ERR_OUT;
2690		    }
2691		}
2692	    } else {
2693	        xmlSaveCtxtPtr ctxt;
2694		int saveOpts = 0;
2695
2696                if (format == 1)
2697		    saveOpts |= XML_SAVE_FORMAT;
2698                else if (format == 2)
2699                    saveOpts |= XML_SAVE_WSNONSIG;
2700
2701#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2702                if (xmlout)
2703                    saveOpts |= XML_SAVE_AS_XML;
2704#endif
2705
2706		if (output == NULL)
2707		    ctxt = xmlSaveToFd(1, encoding, saveOpts);
2708		else
2709		    ctxt = xmlSaveToFilename(output, encoding, saveOpts);
2710
2711		if (ctxt != NULL) {
2712		    if (xmlSaveDoc(ctxt, doc) < 0) {
2713			fprintf(stderr, "failed save to %s\n",
2714				output ? output : "-");
2715			progresult = XMLLINT_ERR_OUT;
2716		    }
2717		    xmlSaveClose(ctxt);
2718		} else {
2719		    progresult = XMLLINT_ERR_OUT;
2720		}
2721	    }
2722	    if ((timing) && (!repeat)) {
2723		endTimer("Saving");
2724	    }
2725#ifdef LIBXML_DEBUG_ENABLED
2726	} else {
2727	    FILE *out;
2728	    if (output == NULL)
2729	        out = stdout;
2730	    else {
2731		out = fopen(output,"wb");
2732	    }
2733	    if (out != NULL) {
2734		xmlDebugDumpDocument(out, doc);
2735
2736		if (output != NULL)
2737		    fclose(out);
2738	    } else {
2739		fprintf(stderr, "failed to open %s\n", output);
2740		progresult = XMLLINT_ERR_OUT;
2741	    }
2742	}
2743#endif
2744    }
2745#endif /* LIBXML_OUTPUT_ENABLED */
2746
2747#ifdef LIBXML_VALID_ENABLED
2748    /*
2749     * A posteriori validation test
2750     */
2751    if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
2752	xmlDtdPtr dtd;
2753
2754	if ((timing) && (!repeat)) {
2755	    startTimer();
2756	}
2757	if (dtdvalid != NULL)
2758	    dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
2759	else
2760	    dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
2761	if ((timing) && (!repeat)) {
2762	    endTimer("Parsing DTD");
2763	}
2764	if (dtd == NULL) {
2765	    if (dtdvalid != NULL)
2766		xmlGenericError(xmlGenericErrorContext,
2767			"Could not parse DTD %s\n", dtdvalid);
2768	    else
2769		xmlGenericError(xmlGenericErrorContext,
2770			"Could not parse DTD %s\n", dtdvalidfpi);
2771	    progresult = XMLLINT_ERR_DTD;
2772	} else {
2773	    xmlValidCtxtPtr cvp;
2774
2775	    if ((cvp = xmlNewValidCtxt()) == NULL) {
2776		xmlGenericError(xmlGenericErrorContext,
2777			"Couldn't allocate validation context\n");
2778		exit(-1);
2779	    }
2780	    cvp->userData = (void *) stderr;
2781	    cvp->error    = (xmlValidityErrorFunc) fprintf;
2782	    cvp->warning  = (xmlValidityWarningFunc) fprintf;
2783
2784	    if ((timing) && (!repeat)) {
2785		startTimer();
2786	    }
2787	    if (!xmlValidateDtd(cvp, doc, dtd)) {
2788		if (dtdvalid != NULL)
2789		    xmlGenericError(xmlGenericErrorContext,
2790			    "Document %s does not validate against %s\n",
2791			    filename, dtdvalid);
2792		else
2793		    xmlGenericError(xmlGenericErrorContext,
2794			    "Document %s does not validate against %s\n",
2795			    filename, dtdvalidfpi);
2796		progresult = XMLLINT_ERR_VALID;
2797	    }
2798	    if ((timing) && (!repeat)) {
2799		endTimer("Validating against DTD");
2800	    }
2801	    xmlFreeValidCtxt(cvp);
2802	    xmlFreeDtd(dtd);
2803	}
2804    } else if (postvalid) {
2805	xmlValidCtxtPtr cvp;
2806
2807	if ((cvp = xmlNewValidCtxt()) == NULL) {
2808	    xmlGenericError(xmlGenericErrorContext,
2809		    "Couldn't allocate validation context\n");
2810	    exit(-1);
2811	}
2812
2813	if ((timing) && (!repeat)) {
2814	    startTimer();
2815	}
2816	cvp->userData = (void *) stderr;
2817	cvp->error    = (xmlValidityErrorFunc) fprintf;
2818	cvp->warning  = (xmlValidityWarningFunc) fprintf;
2819	if (!xmlValidateDocument(cvp, doc)) {
2820	    xmlGenericError(xmlGenericErrorContext,
2821		    "Document %s does not validate\n", filename);
2822	    progresult = XMLLINT_ERR_VALID;
2823	}
2824	if ((timing) && (!repeat)) {
2825	    endTimer("Validating");
2826	}
2827	xmlFreeValidCtxt(cvp);
2828    }
2829#endif /* LIBXML_VALID_ENABLED */
2830#ifdef LIBXML_SCHEMATRON_ENABLED
2831    if (wxschematron != NULL) {
2832	xmlSchematronValidCtxtPtr ctxt;
2833	int ret;
2834	int flag;
2835
2836	if ((timing) && (!repeat)) {
2837	    startTimer();
2838	}
2839
2840	if (debug)
2841	    flag = XML_SCHEMATRON_OUT_XML;
2842	else
2843	    flag = XML_SCHEMATRON_OUT_TEXT;
2844	if (noout)
2845	    flag |= XML_SCHEMATRON_OUT_QUIET;
2846	ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
2847#if 0
2848	xmlSchematronSetValidErrors(ctxt,
2849		(xmlSchematronValidityErrorFunc) fprintf,
2850		(xmlSchematronValidityWarningFunc) fprintf,
2851		stderr);
2852#endif
2853	ret = xmlSchematronValidateDoc(ctxt, doc);
2854	if (ret == 0) {
2855	    fprintf(stderr, "%s validates\n", filename);
2856	} else if (ret > 0) {
2857	    fprintf(stderr, "%s fails to validate\n", filename);
2858	    progresult = XMLLINT_ERR_VALID;
2859	} else {
2860	    fprintf(stderr, "%s validation generated an internal error\n",
2861		   filename);
2862	    progresult = XMLLINT_ERR_VALID;
2863	}
2864	xmlSchematronFreeValidCtxt(ctxt);
2865	if ((timing) && (!repeat)) {
2866	    endTimer("Validating");
2867	}
2868    }
2869#endif
2870#ifdef LIBXML_SCHEMAS_ENABLED
2871    if (relaxngschemas != NULL) {
2872	xmlRelaxNGValidCtxtPtr ctxt;
2873	int ret;
2874
2875	if ((timing) && (!repeat)) {
2876	    startTimer();
2877	}
2878
2879	ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2880	xmlRelaxNGSetValidErrors(ctxt,
2881		(xmlRelaxNGValidityErrorFunc) fprintf,
2882		(xmlRelaxNGValidityWarningFunc) fprintf,
2883		stderr);
2884	ret = xmlRelaxNGValidateDoc(ctxt, doc);
2885	if (ret == 0) {
2886	    fprintf(stderr, "%s validates\n", filename);
2887	} else if (ret > 0) {
2888	    fprintf(stderr, "%s fails to validate\n", filename);
2889	    progresult = XMLLINT_ERR_VALID;
2890	} else {
2891	    fprintf(stderr, "%s validation generated an internal error\n",
2892		   filename);
2893	    progresult = XMLLINT_ERR_VALID;
2894	}
2895	xmlRelaxNGFreeValidCtxt(ctxt);
2896	if ((timing) && (!repeat)) {
2897	    endTimer("Validating");
2898	}
2899    } else if (wxschemas != NULL) {
2900	xmlSchemaValidCtxtPtr ctxt;
2901	int ret;
2902
2903	if ((timing) && (!repeat)) {
2904	    startTimer();
2905	}
2906
2907	ctxt = xmlSchemaNewValidCtxt(wxschemas);
2908	xmlSchemaSetValidErrors(ctxt,
2909		(xmlSchemaValidityErrorFunc) fprintf,
2910		(xmlSchemaValidityWarningFunc) fprintf,
2911		stderr);
2912	ret = xmlSchemaValidateDoc(ctxt, doc);
2913	if (ret == 0) {
2914	    fprintf(stderr, "%s validates\n", filename);
2915	} else if (ret > 0) {
2916	    fprintf(stderr, "%s fails to validate\n", filename);
2917	    progresult = XMLLINT_ERR_VALID;
2918	} else {
2919	    fprintf(stderr, "%s validation generated an internal error\n",
2920		   filename);
2921	    progresult = XMLLINT_ERR_VALID;
2922	}
2923	xmlSchemaFreeValidCtxt(ctxt);
2924	if ((timing) && (!repeat)) {
2925	    endTimer("Validating");
2926	}
2927    }
2928#endif
2929
2930#ifdef LIBXML_DEBUG_ENABLED
2931#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2932    if ((debugent) && (!html))
2933	xmlDebugDumpEntities(stderr, doc);
2934#endif
2935#endif
2936
2937    /*
2938     * free it.
2939     */
2940    if ((timing) && (!repeat)) {
2941	startTimer();
2942    }
2943    xmlFreeDoc(doc);
2944    if ((timing) && (!repeat)) {
2945	endTimer("Freeing");
2946    }
2947}
2948
2949/************************************************************************
2950 *									*
2951 *			Usage and Main					*
2952 *									*
2953 ************************************************************************/
2954
2955static void showVersion(const char *name) {
2956    fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
2957    fprintf(stderr, "   compiled with: ");
2958    if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
2959    if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
2960    if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
2961    if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
2962    if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
2963    if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
2964    if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
2965    if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
2966    if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP ");
2967    if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP ");
2968    if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
2969    if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML ");
2970    if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy ");
2971    if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N ");
2972    if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog ");
2973    if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath ");
2974    if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer ");
2975    if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude ");
2976    if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv ");
2977    if (xmlHasFeature(XML_WITH_ICU)) fprintf(stderr, "ICU ");
2978    if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X ");
2979    if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode ");
2980    if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps ");
2981    if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata ");
2982    if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr ");
2983    if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas ");
2984    if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron ");
2985    if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules ");
2986    if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug ");
2987    if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug ");
2988    if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug ");
2989    if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
2990    if (xmlHasFeature(XML_WITH_LZMA)) fprintf(stderr, "Lzma ");
2991    fprintf(stderr, "\n");
2992}
2993
2994static void usage(const char *name) {
2995    printf("Usage : %s [options] XMLfiles ...\n", name);
2996#ifdef LIBXML_OUTPUT_ENABLED
2997    printf("\tParse the XML files and output the result of the parsing\n");
2998#else
2999    printf("\tParse the XML files\n");
3000#endif /* LIBXML_OUTPUT_ENABLED */
3001    printf("\t--version : display the version of the XML library used\n");
3002#ifdef LIBXML_DEBUG_ENABLED
3003    printf("\t--debug : dump a debug tree of the in-memory document\n");
3004    printf("\t--shell : run a navigating shell\n");
3005    printf("\t--debugent : debug the entities defined in the document\n");
3006#else
3007#ifdef LIBXML_READER_ENABLED
3008    printf("\t--debug : dump the nodes content when using --stream\n");
3009#endif /* LIBXML_READER_ENABLED */
3010#endif
3011#ifdef LIBXML_TREE_ENABLED
3012    printf("\t--copy : used to test the internal copy implementation\n");
3013#endif /* LIBXML_TREE_ENABLED */
3014    printf("\t--recover : output what was parsable on broken XML documents\n");
3015    printf("\t--huge : remove any internal arbitrary parser limits\n");
3016    printf("\t--noent : substitute entity references by their value\n");
3017    printf("\t--noenc : ignore any encoding specified inside the document\n");
3018    printf("\t--noout : don't output the result tree\n");
3019    printf("\t--path 'paths': provide a set of paths for resources\n");
3020    printf("\t--load-trace : print trace of all external entities loaded\n");
3021    printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
3022    printf("\t--nocompact : do not generate compact text nodes\n");
3023    printf("\t--htmlout : output results as HTML\n");
3024    printf("\t--nowrap : do not put HTML doc wrapper\n");
3025#ifdef LIBXML_VALID_ENABLED
3026    printf("\t--valid : validate the document in addition to std well-formed check\n");
3027    printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
3028    printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
3029    printf("\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
3030#endif /* LIBXML_VALID_ENABLED */
3031    printf("\t--timing : print some timings\n");
3032    printf("\t--output file or -o file: save to a given file\n");
3033    printf("\t--repeat : repeat 100 times, for timing or profiling\n");
3034    printf("\t--insert : ad-hoc test for valid insertions\n");
3035#ifdef LIBXML_OUTPUT_ENABLED
3036#ifdef HAVE_ZLIB_H
3037    printf("\t--compress : turn on gzip compression of output\n");
3038#endif
3039#endif /* LIBXML_OUTPUT_ENABLED */
3040#ifdef LIBXML_HTML_ENABLED
3041    printf("\t--html : use the HTML parser\n");
3042    printf("\t--xmlout : force to use the XML serializer when using --html\n");
3043    printf("\t--nodefdtd : do not default HTML doctype\n");
3044#endif
3045#ifdef LIBXML_PUSH_ENABLED
3046    printf("\t--push : use the push mode of the parser\n");
3047    printf("\t--pushsmall : use the push mode of the parser using tiny increments\n");
3048#endif /* LIBXML_PUSH_ENABLED */
3049#ifdef HAVE_MMAP
3050    printf("\t--memory : parse from memory\n");
3051#endif
3052    printf("\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
3053    printf("\t--nowarning : do not emit warnings from parser/validator\n");
3054    printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
3055    printf("\t--nocdata : replace cdata section with text nodes\n");
3056#ifdef LIBXML_OUTPUT_ENABLED
3057    printf("\t--format : reformat/reindent the output\n");
3058    printf("\t--encode encoding : output in the given encoding\n");
3059    printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
3060    printf("\t--pretty STYLE : pretty-print in a particular style\n");
3061    printf("\t                 0 Do not pretty print\n");
3062    printf("\t                 1 Format the XML content, as --format\n");
3063    printf("\t                 2 Add whitespace inside tags, preserving content\n");
3064#endif /* LIBXML_OUTPUT_ENABLED */
3065    printf("\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
3066    printf("\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
3067    printf("\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
3068#ifdef LIBXML_C14N_ENABLED
3069#endif /* LIBXML_C14N_ENABLED */
3070    printf("\t--nsclean : remove redundant namespace declarations\n");
3071    printf("\t--testIO : test user I/O support\n");
3072#ifdef LIBXML_CATALOG_ENABLED
3073    printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
3074    printf("\t             otherwise XML Catalogs starting from \n");
3075    printf("\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
3076    printf("\t--nocatalogs: deactivate all catalogs\n");
3077#endif
3078    printf("\t--auto : generate a small doc on the fly\n");
3079#ifdef LIBXML_XINCLUDE_ENABLED
3080    printf("\t--xinclude : do XInclude processing\n");
3081    printf("\t--noxincludenode : same but do not generate XInclude nodes\n");
3082    printf("\t--nofixup-base-uris : do not fixup xml:base uris\n");
3083#endif
3084    printf("\t--loaddtd : fetch external DTD\n");
3085    printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
3086#ifdef LIBXML_READER_ENABLED
3087    printf("\t--stream : use the streaming interface to process very large files\n");
3088    printf("\t--walker : create a reader and walk though the resulting doc\n");
3089#endif /* LIBXML_READER_ENABLED */
3090#ifdef LIBXML_PATTERN_ENABLED
3091    printf("\t--pattern pattern_value : test the pattern support\n");
3092#endif
3093    printf("\t--chkregister : verify the node registration code\n");
3094#ifdef LIBXML_SCHEMAS_ENABLED
3095    printf("\t--relaxng schema : do RelaxNG validation against the schema\n");
3096    printf("\t--schema schema : do validation against the WXS schema\n");
3097#endif
3098#ifdef LIBXML_SCHEMATRON_ENABLED
3099    printf("\t--schematron schema : do validation against a schematron\n");
3100#endif
3101#ifdef LIBXML_SAX1_ENABLED
3102    printf("\t--sax1: use the old SAX1 interfaces for processing\n");
3103#endif
3104    printf("\t--sax: do not build a tree but work just at the SAX level\n");
3105    printf("\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
3106#ifdef LIBXML_XPATH_ENABLED
3107    printf("\t--xpath expr: evaluate the XPath expression, imply --noout\n");
3108#endif
3109
3110    printf("\nLibxml project home page: http://xmlsoft.org/\n");
3111    printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
3112}
3113
3114static void registerNode(xmlNodePtr node)
3115{
3116    node->_private = malloc(sizeof(long));
3117    if (node->_private == NULL) {
3118        fprintf(stderr, "Out of memory in xmllint:registerNode()\n");
3119	exit(XMLLINT_ERR_MEM);
3120    }
3121    *(long*)node->_private = (long) 0x81726354;
3122    nbregister++;
3123}
3124
3125static void deregisterNode(xmlNodePtr node)
3126{
3127    assert(node->_private != NULL);
3128    assert(*(long*)node->_private == (long) 0x81726354);
3129    free(node->_private);
3130    nbregister--;
3131}
3132
3133int
3134main(int argc, char **argv) {
3135    int i, acount;
3136    int files = 0;
3137    int version = 0;
3138    const char* indent;
3139
3140    if (argc <= 1) {
3141	usage(argv[0]);
3142	return(1);
3143    }
3144    LIBXML_TEST_VERSION
3145    for (i = 1; i < argc ; i++) {
3146	if (!strcmp(argv[i], "-"))
3147	    break;
3148
3149	if (argv[i][0] != '-')
3150	    continue;
3151	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
3152	    debug++;
3153	else
3154#ifdef LIBXML_DEBUG_ENABLED
3155	if ((!strcmp(argv[i], "-shell")) ||
3156	         (!strcmp(argv[i], "--shell"))) {
3157	    shell++;
3158            noout = 1;
3159        } else
3160#endif
3161#ifdef LIBXML_TREE_ENABLED
3162	if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
3163	    copy++;
3164	else
3165#endif /* LIBXML_TREE_ENABLED */
3166	if ((!strcmp(argv[i], "-recover")) ||
3167	         (!strcmp(argv[i], "--recover"))) {
3168	    recovery++;
3169	    options |= XML_PARSE_RECOVER;
3170	} else if ((!strcmp(argv[i], "-huge")) ||
3171	         (!strcmp(argv[i], "--huge"))) {
3172	    options |= XML_PARSE_HUGE;
3173	} else if ((!strcmp(argv[i], "-noent")) ||
3174	         (!strcmp(argv[i], "--noent"))) {
3175	    noent++;
3176	    options |= XML_PARSE_NOENT;
3177	} else if ((!strcmp(argv[i], "-noenc")) ||
3178	         (!strcmp(argv[i], "--noenc"))) {
3179	    noenc++;
3180	    options |= XML_PARSE_IGNORE_ENC;
3181	} else if ((!strcmp(argv[i], "-nsclean")) ||
3182	         (!strcmp(argv[i], "--nsclean"))) {
3183	    options |= XML_PARSE_NSCLEAN;
3184	} else if ((!strcmp(argv[i], "-nocdata")) ||
3185	         (!strcmp(argv[i], "--nocdata"))) {
3186	    options |= XML_PARSE_NOCDATA;
3187	} else if ((!strcmp(argv[i], "-nodict")) ||
3188	         (!strcmp(argv[i], "--nodict"))) {
3189	    options |= XML_PARSE_NODICT;
3190	} else if ((!strcmp(argv[i], "-version")) ||
3191	         (!strcmp(argv[i], "--version"))) {
3192	    showVersion(argv[0]);
3193	    version = 1;
3194	} else if ((!strcmp(argv[i], "-noout")) ||
3195	         (!strcmp(argv[i], "--noout")))
3196	    noout++;
3197#ifdef LIBXML_OUTPUT_ENABLED
3198	else if ((!strcmp(argv[i], "-o")) ||
3199	         (!strcmp(argv[i], "-output")) ||
3200	         (!strcmp(argv[i], "--output"))) {
3201	    i++;
3202	    output = argv[i];
3203	}
3204#endif /* LIBXML_OUTPUT_ENABLED */
3205	else if ((!strcmp(argv[i], "-htmlout")) ||
3206	         (!strcmp(argv[i], "--htmlout")))
3207	    htmlout++;
3208	else if ((!strcmp(argv[i], "-nowrap")) ||
3209	         (!strcmp(argv[i], "--nowrap")))
3210	    nowrap++;
3211#ifdef LIBXML_HTML_ENABLED
3212	else if ((!strcmp(argv[i], "-html")) ||
3213	         (!strcmp(argv[i], "--html"))) {
3214	    html++;
3215        }
3216	else if ((!strcmp(argv[i], "-xmlout")) ||
3217	         (!strcmp(argv[i], "--xmlout"))) {
3218	    xmlout++;
3219	} else if ((!strcmp(argv[i], "-nodefdtd")) ||
3220	         (!strcmp(argv[i], "--nodefdtd"))) {
3221            nodefdtd++;
3222	    options |= HTML_PARSE_NODEFDTD;
3223        }
3224#endif /* LIBXML_HTML_ENABLED */
3225	else if ((!strcmp(argv[i], "-loaddtd")) ||
3226	         (!strcmp(argv[i], "--loaddtd"))) {
3227	    loaddtd++;
3228	    options |= XML_PARSE_DTDLOAD;
3229	} else if ((!strcmp(argv[i], "-dtdattr")) ||
3230	         (!strcmp(argv[i], "--dtdattr"))) {
3231	    loaddtd++;
3232	    dtdattrs++;
3233	    options |= XML_PARSE_DTDATTR;
3234	}
3235#ifdef LIBXML_VALID_ENABLED
3236	else if ((!strcmp(argv[i], "-valid")) ||
3237	         (!strcmp(argv[i], "--valid"))) {
3238	    valid++;
3239	    options |= XML_PARSE_DTDVALID;
3240	} else if ((!strcmp(argv[i], "-postvalid")) ||
3241	         (!strcmp(argv[i], "--postvalid"))) {
3242	    postvalid++;
3243	    loaddtd++;
3244	    options |= XML_PARSE_DTDLOAD;
3245	} else if ((!strcmp(argv[i], "-dtdvalid")) ||
3246	         (!strcmp(argv[i], "--dtdvalid"))) {
3247	    i++;
3248	    dtdvalid = argv[i];
3249	    loaddtd++;
3250	    options |= XML_PARSE_DTDLOAD;
3251	} else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3252	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
3253	    i++;
3254	    dtdvalidfpi = argv[i];
3255	    loaddtd++;
3256	    options |= XML_PARSE_DTDLOAD;
3257        }
3258#endif /* LIBXML_VALID_ENABLED */
3259	else if ((!strcmp(argv[i], "-dropdtd")) ||
3260	         (!strcmp(argv[i], "--dropdtd")))
3261	    dropdtd++;
3262	else if ((!strcmp(argv[i], "-insert")) ||
3263	         (!strcmp(argv[i], "--insert")))
3264	    insert++;
3265	else if ((!strcmp(argv[i], "-timing")) ||
3266	         (!strcmp(argv[i], "--timing")))
3267	    timing++;
3268	else if ((!strcmp(argv[i], "-auto")) ||
3269	         (!strcmp(argv[i], "--auto")))
3270	    generate++;
3271	else if ((!strcmp(argv[i], "-repeat")) ||
3272	         (!strcmp(argv[i], "--repeat"))) {
3273	    if (repeat)
3274	        repeat *= 10;
3275	    else
3276	        repeat = 100;
3277	}
3278#ifdef LIBXML_PUSH_ENABLED
3279	else if ((!strcmp(argv[i], "-push")) ||
3280	         (!strcmp(argv[i], "--push")))
3281	    push++;
3282	else if ((!strcmp(argv[i], "-pushsmall")) ||
3283	         (!strcmp(argv[i], "--pushsmall"))) {
3284	    push++;
3285            pushsize = 10;
3286        }
3287#endif /* LIBXML_PUSH_ENABLED */
3288#ifdef HAVE_MMAP
3289	else if ((!strcmp(argv[i], "-memory")) ||
3290	         (!strcmp(argv[i], "--memory")))
3291	    memory++;
3292#endif
3293	else if ((!strcmp(argv[i], "-testIO")) ||
3294	         (!strcmp(argv[i], "--testIO")))
3295	    testIO++;
3296#ifdef LIBXML_XINCLUDE_ENABLED
3297	else if ((!strcmp(argv[i], "-xinclude")) ||
3298	         (!strcmp(argv[i], "--xinclude"))) {
3299	    xinclude++;
3300	    options |= XML_PARSE_XINCLUDE;
3301	}
3302	else if ((!strcmp(argv[i], "-noxincludenode")) ||
3303	         (!strcmp(argv[i], "--noxincludenode"))) {
3304	    xinclude++;
3305	    options |= XML_PARSE_XINCLUDE;
3306	    options |= XML_PARSE_NOXINCNODE;
3307	}
3308	else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
3309	         (!strcmp(argv[i], "--nofixup-base-uris"))) {
3310	    xinclude++;
3311	    options |= XML_PARSE_XINCLUDE;
3312	    options |= XML_PARSE_NOBASEFIX;
3313	}
3314#endif
3315#ifdef LIBXML_OUTPUT_ENABLED
3316#ifdef HAVE_ZLIB_H
3317	else if ((!strcmp(argv[i], "-compress")) ||
3318	         (!strcmp(argv[i], "--compress"))) {
3319	    compress++;
3320	    xmlSetCompressMode(9);
3321        }
3322#endif
3323#endif /* LIBXML_OUTPUT_ENABLED */
3324	else if ((!strcmp(argv[i], "-nowarning")) ||
3325	         (!strcmp(argv[i], "--nowarning"))) {
3326	    xmlGetWarningsDefaultValue = 0;
3327	    xmlPedanticParserDefault(0);
3328	    options |= XML_PARSE_NOWARNING;
3329        }
3330	else if ((!strcmp(argv[i], "-pedantic")) ||
3331	         (!strcmp(argv[i], "--pedantic"))) {
3332	    xmlGetWarningsDefaultValue = 1;
3333	    xmlPedanticParserDefault(1);
3334	    options |= XML_PARSE_PEDANTIC;
3335        }
3336#ifdef LIBXML_DEBUG_ENABLED
3337	else if ((!strcmp(argv[i], "-debugent")) ||
3338		 (!strcmp(argv[i], "--debugent"))) {
3339	    debugent++;
3340	    xmlParserDebugEntities = 1;
3341	}
3342#endif
3343#ifdef LIBXML_C14N_ENABLED
3344	else if ((!strcmp(argv[i], "-c14n")) ||
3345		 (!strcmp(argv[i], "--c14n"))) {
3346	    canonical++;
3347	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3348	}
3349	else if ((!strcmp(argv[i], "-c14n11")) ||
3350		 (!strcmp(argv[i], "--c14n11"))) {
3351	    canonical_11++;
3352	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3353	}
3354	else if ((!strcmp(argv[i], "-exc-c14n")) ||
3355		 (!strcmp(argv[i], "--exc-c14n"))) {
3356	    exc_canonical++;
3357	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3358	}
3359#endif
3360#ifdef LIBXML_CATALOG_ENABLED
3361	else if ((!strcmp(argv[i], "-catalogs")) ||
3362		 (!strcmp(argv[i], "--catalogs"))) {
3363	    catalogs++;
3364	} else if ((!strcmp(argv[i], "-nocatalogs")) ||
3365		 (!strcmp(argv[i], "--nocatalogs"))) {
3366	    nocatalogs++;
3367	}
3368#endif
3369	else if ((!strcmp(argv[i], "-encode")) ||
3370	         (!strcmp(argv[i], "--encode"))) {
3371	    i++;
3372	    encoding = argv[i];
3373	    /*
3374	     * OK it's for testing purposes
3375	     */
3376	    xmlAddEncodingAlias("UTF-8", "DVEnc");
3377        }
3378	else if ((!strcmp(argv[i], "-noblanks")) ||
3379	         (!strcmp(argv[i], "--noblanks"))) {
3380	    noblanks++;
3381	    xmlKeepBlanksDefault(0);
3382	    options |= XML_PARSE_NOBLANKS;
3383        }
3384	else if ((!strcmp(argv[i], "-maxmem")) ||
3385	         (!strcmp(argv[i], "--maxmem"))) {
3386	     i++;
3387	     if (sscanf(argv[i], "%d", &maxmem) == 1) {
3388	         xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc,
3389		             myStrdupFunc);
3390	     } else {
3391	         maxmem = 0;
3392	     }
3393        }
3394	else if ((!strcmp(argv[i], "-format")) ||
3395	         (!strcmp(argv[i], "--format"))) {
3396	     noblanks++;
3397#ifdef LIBXML_OUTPUT_ENABLED
3398	     format = 1;
3399#endif /* LIBXML_OUTPUT_ENABLED */
3400	     xmlKeepBlanksDefault(0);
3401	}
3402	else if ((!strcmp(argv[i], "-pretty")) ||
3403	         (!strcmp(argv[i], "--pretty"))) {
3404	     i++;
3405#ifdef LIBXML_OUTPUT_ENABLED
3406       if (argv[i] != NULL) {
3407	         format = atoi(argv[i]);
3408	         if (format == 1) {
3409	             noblanks++;
3410	             xmlKeepBlanksDefault(0);
3411	         }
3412       }
3413#endif /* LIBXML_OUTPUT_ENABLED */
3414	}
3415#ifdef LIBXML_READER_ENABLED
3416	else if ((!strcmp(argv[i], "-stream")) ||
3417	         (!strcmp(argv[i], "--stream"))) {
3418	     stream++;
3419	}
3420	else if ((!strcmp(argv[i], "-walker")) ||
3421	         (!strcmp(argv[i], "--walker"))) {
3422	     walker++;
3423             noout++;
3424	}
3425#endif /* LIBXML_READER_ENABLED */
3426#ifdef LIBXML_SAX1_ENABLED
3427	else if ((!strcmp(argv[i], "-sax1")) ||
3428	         (!strcmp(argv[i], "--sax1"))) {
3429	    sax1++;
3430	    options |= XML_PARSE_SAX1;
3431	}
3432#endif /* LIBXML_SAX1_ENABLED */
3433	else if ((!strcmp(argv[i], "-sax")) ||
3434	         (!strcmp(argv[i], "--sax"))) {
3435	    sax++;
3436	}
3437	else if ((!strcmp(argv[i], "-chkregister")) ||
3438	         (!strcmp(argv[i], "--chkregister"))) {
3439	    chkregister++;
3440#ifdef LIBXML_SCHEMAS_ENABLED
3441	} else if ((!strcmp(argv[i], "-relaxng")) ||
3442	         (!strcmp(argv[i], "--relaxng"))) {
3443	    i++;
3444	    relaxng = argv[i];
3445	    noent++;
3446	    options |= XML_PARSE_NOENT;
3447	} else if ((!strcmp(argv[i], "-schema")) ||
3448	         (!strcmp(argv[i], "--schema"))) {
3449	    i++;
3450	    schema = argv[i];
3451	    noent++;
3452#endif
3453#ifdef LIBXML_SCHEMATRON_ENABLED
3454	} else if ((!strcmp(argv[i], "-schematron")) ||
3455	         (!strcmp(argv[i], "--schematron"))) {
3456	    i++;
3457	    schematron = argv[i];
3458	    noent++;
3459#endif
3460        } else if ((!strcmp(argv[i], "-nonet")) ||
3461                   (!strcmp(argv[i], "--nonet"))) {
3462	    options |= XML_PARSE_NONET;
3463	    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
3464        } else if ((!strcmp(argv[i], "-nocompact")) ||
3465                   (!strcmp(argv[i], "--nocompact"))) {
3466	    options &= ~XML_PARSE_COMPACT;
3467	} else if ((!strcmp(argv[i], "-load-trace")) ||
3468	           (!strcmp(argv[i], "--load-trace"))) {
3469	    load_trace++;
3470        } else if ((!strcmp(argv[i], "-path")) ||
3471                   (!strcmp(argv[i], "--path"))) {
3472	    i++;
3473	    parsePath(BAD_CAST argv[i]);
3474#ifdef LIBXML_PATTERN_ENABLED
3475        } else if ((!strcmp(argv[i], "-pattern")) ||
3476                   (!strcmp(argv[i], "--pattern"))) {
3477	    i++;
3478	    pattern = argv[i];
3479#endif
3480#ifdef LIBXML_XPATH_ENABLED
3481        } else if ((!strcmp(argv[i], "-xpath")) ||
3482                   (!strcmp(argv[i], "--xpath"))) {
3483	    i++;
3484	    noout++;
3485	    xpathquery = argv[i];
3486#endif
3487	} else if ((!strcmp(argv[i], "-oldxml10")) ||
3488	           (!strcmp(argv[i], "--oldxml10"))) {
3489	    oldxml10++;
3490	    options |= XML_PARSE_OLD10;
3491	} else {
3492	    fprintf(stderr, "Unknown option %s\n", argv[i]);
3493	    usage(argv[0]);
3494	    return(1);
3495	}
3496    }
3497
3498#ifdef LIBXML_CATALOG_ENABLED
3499    if (nocatalogs == 0) {
3500	if (catalogs) {
3501	    const char *catal;
3502
3503	    catal = getenv("SGML_CATALOG_FILES");
3504	    if (catal != NULL) {
3505		xmlLoadCatalogs(catal);
3506	    } else {
3507		fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
3508	    }
3509	}
3510    }
3511#endif
3512
3513#ifdef LIBXML_SAX1_ENABLED
3514    if (sax1)
3515        xmlSAXDefaultVersion(1);
3516    else
3517        xmlSAXDefaultVersion(2);
3518#endif /* LIBXML_SAX1_ENABLED */
3519
3520    if (chkregister) {
3521	xmlRegisterNodeDefault(registerNode);
3522	xmlDeregisterNodeDefault(deregisterNode);
3523    }
3524
3525    indent = getenv("XMLLINT_INDENT");
3526    if(indent != NULL) {
3527	xmlTreeIndentString = indent;
3528    }
3529
3530
3531    defaultEntityLoader = xmlGetExternalEntityLoader();
3532    xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
3533
3534    xmlLineNumbersDefault(1);
3535    if (loaddtd != 0)
3536	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
3537    if (dtdattrs)
3538	xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
3539    if (noent != 0) xmlSubstituteEntitiesDefault(1);
3540#ifdef LIBXML_VALID_ENABLED
3541    if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
3542#endif /* LIBXML_VALID_ENABLED */
3543    if ((htmlout) && (!nowrap)) {
3544	xmlGenericError(xmlGenericErrorContext,
3545         "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
3546	xmlGenericError(xmlGenericErrorContext,
3547		"\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
3548	xmlGenericError(xmlGenericErrorContext,
3549	 "<html><head><title>%s output</title></head>\n",
3550		argv[0]);
3551	xmlGenericError(xmlGenericErrorContext,
3552	 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
3553		argv[0]);
3554    }
3555
3556#ifdef LIBXML_SCHEMATRON_ENABLED
3557    if ((schematron != NULL) && (sax == 0)
3558#ifdef LIBXML_READER_ENABLED
3559        && (stream == 0)
3560#endif /* LIBXML_READER_ENABLED */
3561	) {
3562	xmlSchematronParserCtxtPtr ctxt;
3563
3564        /* forces loading the DTDs */
3565        xmlLoadExtDtdDefaultValue |= 1;
3566	options |= XML_PARSE_DTDLOAD;
3567	if (timing) {
3568	    startTimer();
3569	}
3570	ctxt = xmlSchematronNewParserCtxt(schematron);
3571#if 0
3572	xmlSchematronSetParserErrors(ctxt,
3573		(xmlSchematronValidityErrorFunc) fprintf,
3574		(xmlSchematronValidityWarningFunc) fprintf,
3575		stderr);
3576#endif
3577	wxschematron = xmlSchematronParse(ctxt);
3578	if (wxschematron == NULL) {
3579	    xmlGenericError(xmlGenericErrorContext,
3580		    "Schematron schema %s failed to compile\n", schematron);
3581            progresult = XMLLINT_ERR_SCHEMACOMP;
3582	    schematron = NULL;
3583	}
3584	xmlSchematronFreeParserCtxt(ctxt);
3585	if (timing) {
3586	    endTimer("Compiling the schemas");
3587	}
3588    }
3589#endif
3590#ifdef LIBXML_SCHEMAS_ENABLED
3591    if ((relaxng != NULL) && (sax == 0)
3592#ifdef LIBXML_READER_ENABLED
3593        && (stream == 0)
3594#endif /* LIBXML_READER_ENABLED */
3595	) {
3596	xmlRelaxNGParserCtxtPtr ctxt;
3597
3598        /* forces loading the DTDs */
3599        xmlLoadExtDtdDefaultValue |= 1;
3600	options |= XML_PARSE_DTDLOAD;
3601	if (timing) {
3602	    startTimer();
3603	}
3604	ctxt = xmlRelaxNGNewParserCtxt(relaxng);
3605	xmlRelaxNGSetParserErrors(ctxt,
3606		(xmlRelaxNGValidityErrorFunc) fprintf,
3607		(xmlRelaxNGValidityWarningFunc) fprintf,
3608		stderr);
3609	relaxngschemas = xmlRelaxNGParse(ctxt);
3610	if (relaxngschemas == NULL) {
3611	    xmlGenericError(xmlGenericErrorContext,
3612		    "Relax-NG schema %s failed to compile\n", relaxng);
3613            progresult = XMLLINT_ERR_SCHEMACOMP;
3614	    relaxng = NULL;
3615	}
3616	xmlRelaxNGFreeParserCtxt(ctxt);
3617	if (timing) {
3618	    endTimer("Compiling the schemas");
3619	}
3620    } else if ((schema != NULL)
3621#ifdef LIBXML_READER_ENABLED
3622		&& (stream == 0)
3623#endif
3624	) {
3625	xmlSchemaParserCtxtPtr ctxt;
3626
3627	if (timing) {
3628	    startTimer();
3629	}
3630	ctxt = xmlSchemaNewParserCtxt(schema);
3631	xmlSchemaSetParserErrors(ctxt,
3632		(xmlSchemaValidityErrorFunc) fprintf,
3633		(xmlSchemaValidityWarningFunc) fprintf,
3634		stderr);
3635	wxschemas = xmlSchemaParse(ctxt);
3636	if (wxschemas == NULL) {
3637	    xmlGenericError(xmlGenericErrorContext,
3638		    "WXS schema %s failed to compile\n", schema);
3639            progresult = XMLLINT_ERR_SCHEMACOMP;
3640	    schema = NULL;
3641	}
3642	xmlSchemaFreeParserCtxt(ctxt);
3643	if (timing) {
3644	    endTimer("Compiling the schemas");
3645	}
3646    }
3647#endif /* LIBXML_SCHEMAS_ENABLED */
3648#ifdef LIBXML_PATTERN_ENABLED
3649    if ((pattern != NULL)
3650#ifdef LIBXML_READER_ENABLED
3651        && (walker == 0)
3652#endif
3653	) {
3654        patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
3655	if (patternc == NULL) {
3656	    xmlGenericError(xmlGenericErrorContext,
3657		    "Pattern %s failed to compile\n", pattern);
3658            progresult = XMLLINT_ERR_SCHEMAPAT;
3659	    pattern = NULL;
3660	}
3661    }
3662#endif /* LIBXML_PATTERN_ENABLED */
3663    for (i = 1; i < argc ; i++) {
3664	if ((!strcmp(argv[i], "-encode")) ||
3665	         (!strcmp(argv[i], "--encode"))) {
3666	    i++;
3667	    continue;
3668        } else if ((!strcmp(argv[i], "-o")) ||
3669                   (!strcmp(argv[i], "-output")) ||
3670                   (!strcmp(argv[i], "--output"))) {
3671            i++;
3672	    continue;
3673        }
3674#ifdef LIBXML_VALID_ENABLED
3675	if ((!strcmp(argv[i], "-dtdvalid")) ||
3676	         (!strcmp(argv[i], "--dtdvalid"))) {
3677	    i++;
3678	    continue;
3679        }
3680	if ((!strcmp(argv[i], "-path")) ||
3681                   (!strcmp(argv[i], "--path"))) {
3682            i++;
3683	    continue;
3684        }
3685	if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3686	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
3687	    i++;
3688	    continue;
3689        }
3690#endif /* LIBXML_VALID_ENABLED */
3691	if ((!strcmp(argv[i], "-relaxng")) ||
3692	         (!strcmp(argv[i], "--relaxng"))) {
3693	    i++;
3694	    continue;
3695        }
3696	if ((!strcmp(argv[i], "-maxmem")) ||
3697	         (!strcmp(argv[i], "--maxmem"))) {
3698	    i++;
3699	    continue;
3700        }
3701	if ((!strcmp(argv[i], "-pretty")) ||
3702	         (!strcmp(argv[i], "--pretty"))) {
3703	    i++;
3704	    continue;
3705        }
3706	if ((!strcmp(argv[i], "-schema")) ||
3707	         (!strcmp(argv[i], "--schema"))) {
3708	    i++;
3709	    continue;
3710        }
3711	if ((!strcmp(argv[i], "-schematron")) ||
3712	         (!strcmp(argv[i], "--schematron"))) {
3713	    i++;
3714	    continue;
3715        }
3716#ifdef LIBXML_PATTERN_ENABLED
3717        if ((!strcmp(argv[i], "-pattern")) ||
3718	    (!strcmp(argv[i], "--pattern"))) {
3719	    i++;
3720	    continue;
3721	}
3722#endif
3723#ifdef LIBXML_XPATH_ENABLED
3724        if ((!strcmp(argv[i], "-xpath")) ||
3725	    (!strcmp(argv[i], "--xpath"))) {
3726	    i++;
3727	    continue;
3728	}
3729#endif
3730	if ((timing) && (repeat))
3731	    startTimer();
3732	/* Remember file names.  "-" means stdin.  <sven@zen.org> */
3733	if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
3734	    if (repeat) {
3735		xmlParserCtxtPtr ctxt = NULL;
3736
3737		for (acount = 0;acount < repeat;acount++) {
3738#ifdef LIBXML_READER_ENABLED
3739		    if (stream != 0) {
3740			streamFile(argv[i]);
3741		    } else {
3742#endif /* LIBXML_READER_ENABLED */
3743                        if (sax) {
3744			    testSAX(argv[i]);
3745			} else {
3746			    if (ctxt == NULL)
3747				ctxt = xmlNewParserCtxt();
3748			    parseAndPrintFile(argv[i], ctxt);
3749			}
3750#ifdef LIBXML_READER_ENABLED
3751		    }
3752#endif /* LIBXML_READER_ENABLED */
3753		}
3754		if (ctxt != NULL)
3755		    xmlFreeParserCtxt(ctxt);
3756	    } else {
3757		nbregister = 0;
3758
3759#ifdef LIBXML_READER_ENABLED
3760		if (stream != 0)
3761		    streamFile(argv[i]);
3762		else
3763#endif /* LIBXML_READER_ENABLED */
3764                if (sax) {
3765		    testSAX(argv[i]);
3766		} else {
3767		    parseAndPrintFile(argv[i], NULL);
3768		}
3769
3770                if ((chkregister) && (nbregister != 0)) {
3771		    fprintf(stderr, "Registration count off: %d\n", nbregister);
3772		    progresult = XMLLINT_ERR_RDREGIS;
3773		}
3774	    }
3775	    files ++;
3776	    if ((timing) && (repeat)) {
3777		endTimer("%d iterations", repeat);
3778	    }
3779	}
3780    }
3781    if (generate)
3782	parseAndPrintFile(NULL, NULL);
3783    if ((htmlout) && (!nowrap)) {
3784	xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
3785    }
3786    if ((files == 0) && (!generate) && (version == 0)) {
3787	usage(argv[0]);
3788    }
3789#ifdef LIBXML_SCHEMATRON_ENABLED
3790    if (wxschematron != NULL)
3791	xmlSchematronFree(wxschematron);
3792#endif
3793#ifdef LIBXML_SCHEMAS_ENABLED
3794    if (relaxngschemas != NULL)
3795	xmlRelaxNGFree(relaxngschemas);
3796    if (wxschemas != NULL)
3797	xmlSchemaFree(wxschemas);
3798    xmlRelaxNGCleanupTypes();
3799#endif
3800#ifdef LIBXML_PATTERN_ENABLED
3801    if (patternc != NULL)
3802        xmlFreePattern(patternc);
3803#endif
3804    xmlCleanupParser();
3805    xmlMemoryDump();
3806
3807    return(progresult);
3808}
3809
3810