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