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