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