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