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