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