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