xref: /reactos/sdk/lib/3rdparty/libxml2/xmllint.c (revision 911153da)
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 <stdlib.h>
14 #include <assert.h>
15 #include <time.h>
16 
17 #ifdef HAVE_SYS_TIME_H
18 #include <sys/time.h>
19 #endif
20 #ifdef HAVE_SYS_TIMEB_H
21 #include <sys/timeb.h>
22 #endif
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 #ifdef HAVE_SYS_STAT_H
27 #include <sys/stat.h>
28 #endif
29 #ifdef HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.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 #ifdef LIBXML_OUTPUT_ENABLED
116 static int format = 0;
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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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     xmlParserInputBufferPtr buf = NULL;
1590     xmlParserInputPtr inputStream;
1591     xmlParserCtxtPtr ctxt = NULL;
1592     xmlSAXHandlerPtr old_sax = NULL;
1593 
1594     callbacks = 0;
1595 
1596     if (noout) {
1597         handler = emptySAXHandler;
1598 #ifdef LIBXML_SAX1_ENABLED
1599     } else if (sax1) {
1600         handler = debugSAXHandler;
1601 #endif
1602     } else {
1603         handler = debugSAX2Handler;
1604     }
1605 
1606     /*
1607      * it's not the simplest code but the most generic in term of I/O
1608      */
1609     buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1610     if (buf == NULL) {
1611         goto error;
1612     }
1613 
1614 #ifdef LIBXML_SCHEMAS_ENABLED
1615     if (wxschemas != NULL) {
1616         int ret;
1617 	xmlSchemaValidCtxtPtr vctxt;
1618 
1619 	vctxt = xmlSchemaNewValidCtxt(wxschemas);
1620         if (vctxt == NULL) {
1621             progresult = XMLLINT_ERR_MEM;
1622             xmlFreeParserInputBuffer(buf);
1623             goto error;
1624         }
1625 	xmlSchemaSetValidErrors(vctxt, xmlGenericError, xmlGenericError, NULL);
1626 	xmlSchemaValidateSetFilename(vctxt, filename);
1627 
1628 	ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
1629 	                              (void *)user_data);
1630 	if (repeat == 0) {
1631 	    if (ret == 0) {
1632 	        if (!quiet) {
1633 	            fprintf(stderr, "%s validates\n", filename);
1634 	        }
1635 	    } else if (ret > 0) {
1636 		fprintf(stderr, "%s fails to validate\n", filename);
1637 		progresult = XMLLINT_ERR_VALID;
1638 	    } else {
1639 		fprintf(stderr, "%s validation generated an internal error\n",
1640 		       filename);
1641 		progresult = XMLLINT_ERR_VALID;
1642 	    }
1643 	}
1644 	xmlSchemaFreeValidCtxt(vctxt);
1645     } else
1646 #endif
1647     {
1648 	/*
1649 	 * Create the parser context amd hook the input
1650 	 */
1651 	ctxt = xmlNewParserCtxt();
1652 	if (ctxt == NULL) {
1653             progresult = XMLLINT_ERR_MEM;
1654 	    xmlFreeParserInputBuffer(buf);
1655 	    goto error;
1656 	}
1657 	old_sax = ctxt->sax;
1658 	ctxt->sax = handler;
1659 	ctxt->userData = (void *) user_data;
1660 	inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
1661 	if (inputStream == NULL) {
1662 	    xmlFreeParserInputBuffer(buf);
1663 	    goto error;
1664 	}
1665 	inputPush(ctxt, inputStream);
1666 
1667 	/* do the parsing */
1668 	xmlParseDocument(ctxt);
1669 
1670 	if (ctxt->myDoc != NULL) {
1671 	    fprintf(stderr, "SAX generated a doc !\n");
1672 	    xmlFreeDoc(ctxt->myDoc);
1673 	    ctxt->myDoc = NULL;
1674 	}
1675     }
1676 
1677 error:
1678     if (ctxt != NULL) {
1679         ctxt->sax = old_sax;
1680         xmlFreeParserCtxt(ctxt);
1681     }
1682 }
1683 
1684 /************************************************************************
1685  *									*
1686  *			Stream Test processing				*
1687  *									*
1688  ************************************************************************/
1689 #ifdef LIBXML_READER_ENABLED
processNode(xmlTextReaderPtr reader)1690 static void processNode(xmlTextReaderPtr reader) {
1691     const xmlChar *name, *value;
1692     int type, empty;
1693 
1694     type = xmlTextReaderNodeType(reader);
1695     empty = xmlTextReaderIsEmptyElement(reader);
1696 
1697     if (debug) {
1698 	name = xmlTextReaderConstName(reader);
1699 	if (name == NULL)
1700 	    name = BAD_CAST "--";
1701 
1702 	value = xmlTextReaderConstValue(reader);
1703 
1704 
1705 	printf("%d %d %s %d %d",
1706 		xmlTextReaderDepth(reader),
1707 		type,
1708 		name,
1709 		empty,
1710 		xmlTextReaderHasValue(reader));
1711 	if (value == NULL)
1712 	    printf("\n");
1713 	else {
1714 	    printf(" %s\n", value);
1715 	}
1716     }
1717 #ifdef LIBXML_PATTERN_ENABLED
1718     if (patternc) {
1719         xmlChar *path = NULL;
1720         int match = -1;
1721 
1722 	if (type == XML_READER_TYPE_ELEMENT) {
1723 	    /* do the check only on element start */
1724 	    match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
1725 
1726 	    if (match) {
1727 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
1728 		path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
1729 		printf("Node %s matches pattern %s\n", path, pattern);
1730 #else
1731                 printf("Node %s matches pattern %s\n",
1732                        xmlTextReaderConstName(reader), pattern);
1733 #endif
1734 	    }
1735 	}
1736 	if (patstream != NULL) {
1737 	    int ret;
1738 
1739 	    if (type == XML_READER_TYPE_ELEMENT) {
1740 		ret = xmlStreamPush(patstream,
1741 		                    xmlTextReaderConstLocalName(reader),
1742 				    xmlTextReaderConstNamespaceUri(reader));
1743 		if (ret < 0) {
1744 		    fprintf(stderr, "xmlStreamPush() failure\n");
1745                     xmlFreeStreamCtxt(patstream);
1746 		    patstream = NULL;
1747 		} else if (ret != match) {
1748 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
1749 		    if (path == NULL) {
1750 		        path = xmlGetNodePath(
1751 		                       xmlTextReaderCurrentNode(reader));
1752 		    }
1753 #endif
1754 		    fprintf(stderr,
1755 		            "xmlPatternMatch and xmlStreamPush disagree\n");
1756                     if (path != NULL)
1757                         fprintf(stderr, "  pattern %s node %s\n",
1758                                 pattern, path);
1759                     else
1760 		        fprintf(stderr, "  pattern %s node %s\n",
1761 			    pattern, xmlTextReaderConstName(reader));
1762 		}
1763 
1764 	    }
1765 	    if ((type == XML_READER_TYPE_END_ELEMENT) ||
1766 	        ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
1767 	        ret = xmlStreamPop(patstream);
1768 		if (ret < 0) {
1769 		    fprintf(stderr, "xmlStreamPop() failure\n");
1770                     xmlFreeStreamCtxt(patstream);
1771 		    patstream = NULL;
1772 		}
1773 	    }
1774 	}
1775 	if (path != NULL)
1776 	    xmlFree(path);
1777     }
1778 #endif
1779 }
1780 
streamFile(char * filename)1781 static void streamFile(char *filename) {
1782     xmlTextReaderPtr reader;
1783     int ret;
1784 #ifdef HAVE_MMAP
1785     int fd = -1;
1786     struct stat info;
1787     const char *base = NULL;
1788     xmlParserInputBufferPtr input = NULL;
1789 
1790     if (memory) {
1791 	if (stat(filename, &info) < 0)
1792 	    return;
1793 	if ((fd = open(filename, O_RDONLY)) < 0)
1794 	    return;
1795 	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
1796 	if (base == (void *) MAP_FAILED) {
1797 	    close(fd);
1798 	    fprintf(stderr, "mmap failure for file %s\n", filename);
1799 	    progresult = XMLLINT_ERR_RDFILE;
1800 	    return;
1801 	}
1802 
1803 	reader = xmlReaderForMemory(base, info.st_size, filename,
1804 	                            NULL, options);
1805     } else
1806 #endif
1807 	reader = xmlReaderForFile(filename, NULL, options);
1808 #ifdef LIBXML_PATTERN_ENABLED
1809     if (pattern != NULL) {
1810         patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
1811 	if (patternc == NULL) {
1812 	    xmlGenericError(xmlGenericErrorContext,
1813 		    "Pattern %s failed to compile\n", pattern);
1814             progresult = XMLLINT_ERR_SCHEMAPAT;
1815 	    pattern = NULL;
1816 	}
1817     }
1818     if (patternc != NULL) {
1819         patstream = xmlPatternGetStreamCtxt(patternc);
1820 	if (patstream != NULL) {
1821 	    ret = xmlStreamPush(patstream, NULL, NULL);
1822 	    if (ret < 0) {
1823 		fprintf(stderr, "xmlStreamPush() failure\n");
1824 		xmlFreeStreamCtxt(patstream);
1825 		patstream = NULL;
1826             }
1827 	}
1828     }
1829 #endif
1830 
1831 
1832     if (reader != NULL) {
1833 #ifdef LIBXML_VALID_ENABLED
1834 	if (valid)
1835 	    xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
1836 	else
1837 #endif /* LIBXML_VALID_ENABLED */
1838 	    if (loaddtd)
1839 		xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
1840 #ifdef LIBXML_SCHEMAS_ENABLED
1841 	if (relaxng != NULL) {
1842 	    if ((timing) && (!repeat)) {
1843 		startTimer();
1844 	    }
1845 	    ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
1846 	    if (ret < 0) {
1847 		xmlGenericError(xmlGenericErrorContext,
1848 			"Relax-NG schema %s failed to compile\n", relaxng);
1849 		progresult = XMLLINT_ERR_SCHEMACOMP;
1850 		relaxng = NULL;
1851 	    }
1852 	    if ((timing) && (!repeat)) {
1853 		endTimer("Compiling the schemas");
1854 	    }
1855 	}
1856 	if (schema != NULL) {
1857 	    if ((timing) && (!repeat)) {
1858 		startTimer();
1859 	    }
1860 	    ret = xmlTextReaderSchemaValidate(reader, schema);
1861 	    if (ret < 0) {
1862 		xmlGenericError(xmlGenericErrorContext,
1863 			"XSD schema %s failed to compile\n", schema);
1864 		progresult = XMLLINT_ERR_SCHEMACOMP;
1865 		schema = NULL;
1866 	    }
1867 	    if ((timing) && (!repeat)) {
1868 		endTimer("Compiling the schemas");
1869 	    }
1870 	}
1871 #endif
1872 
1873 	/*
1874 	 * Process all nodes in sequence
1875 	 */
1876 	if ((timing) && (!repeat)) {
1877 	    startTimer();
1878 	}
1879 	ret = xmlTextReaderRead(reader);
1880 	while (ret == 1) {
1881 	    if ((debug)
1882 #ifdef LIBXML_PATTERN_ENABLED
1883 	        || (patternc)
1884 #endif
1885 	       )
1886 		processNode(reader);
1887 	    ret = xmlTextReaderRead(reader);
1888 	}
1889 	if ((timing) && (!repeat)) {
1890 #ifdef LIBXML_SCHEMAS_ENABLED
1891 	    if (relaxng != NULL)
1892 		endTimer("Parsing and validating");
1893 	    else
1894 #endif
1895 #ifdef LIBXML_VALID_ENABLED
1896 	    if (valid)
1897 		endTimer("Parsing and validating");
1898 	    else
1899 #endif
1900 	    endTimer("Parsing");
1901 	}
1902 
1903 #ifdef LIBXML_VALID_ENABLED
1904 	if (valid) {
1905 	    if (xmlTextReaderIsValid(reader) != 1) {
1906 		xmlGenericError(xmlGenericErrorContext,
1907 			"Document %s does not validate\n", filename);
1908 		progresult = XMLLINT_ERR_VALID;
1909 	    }
1910 	}
1911 #endif /* LIBXML_VALID_ENABLED */
1912 #ifdef LIBXML_SCHEMAS_ENABLED
1913 	if ((relaxng != NULL) || (schema != NULL)) {
1914 	    if (xmlTextReaderIsValid(reader) != 1) {
1915 		fprintf(stderr, "%s fails to validate\n", filename);
1916 		progresult = XMLLINT_ERR_VALID;
1917 	    } else {
1918 	        if (!quiet) {
1919 	            fprintf(stderr, "%s validates\n", filename);
1920 	        }
1921 	    }
1922 	}
1923 #endif
1924 	/*
1925 	 * Done, cleanup and status
1926 	 */
1927 	xmlFreeTextReader(reader);
1928 	if (ret != 0) {
1929 	    fprintf(stderr, "%s : failed to parse\n", filename);
1930 	    progresult = XMLLINT_ERR_UNCLASS;
1931 	}
1932     } else {
1933 	fprintf(stderr, "Unable to open %s\n", filename);
1934 	progresult = XMLLINT_ERR_UNCLASS;
1935     }
1936 #ifdef LIBXML_PATTERN_ENABLED
1937     if (patstream != NULL) {
1938 	xmlFreeStreamCtxt(patstream);
1939 	patstream = NULL;
1940     }
1941 #endif
1942 #ifdef HAVE_MMAP
1943     if (memory) {
1944         xmlFreeParserInputBuffer(input);
1945 	munmap((char *) base, info.st_size);
1946 	close(fd);
1947     }
1948 #endif
1949 }
1950 
walkDoc(xmlDocPtr doc)1951 static void walkDoc(xmlDocPtr doc) {
1952     xmlTextReaderPtr reader;
1953     int ret;
1954 
1955 #ifdef LIBXML_PATTERN_ENABLED
1956     xmlNodePtr root;
1957     const xmlChar *namespaces[22];
1958     int i;
1959     xmlNsPtr ns;
1960 
1961     root = xmlDocGetRootElement(doc);
1962     if (root == NULL ) {
1963         xmlGenericError(xmlGenericErrorContext,
1964                 "Document does not have a root element");
1965         progresult = XMLLINT_ERR_UNCLASS;
1966         return;
1967     }
1968     for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
1969         namespaces[i++] = ns->href;
1970         namespaces[i++] = ns->prefix;
1971     }
1972     namespaces[i++] = NULL;
1973     namespaces[i] = NULL;
1974 
1975     if (pattern != NULL) {
1976         patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict,
1977 	                             0, &namespaces[0]);
1978 	if (patternc == NULL) {
1979 	    xmlGenericError(xmlGenericErrorContext,
1980 		    "Pattern %s failed to compile\n", pattern);
1981             progresult = XMLLINT_ERR_SCHEMAPAT;
1982 	    pattern = NULL;
1983 	}
1984     }
1985     if (patternc != NULL) {
1986         patstream = xmlPatternGetStreamCtxt(patternc);
1987 	if (patstream != NULL) {
1988 	    ret = xmlStreamPush(patstream, NULL, NULL);
1989 	    if (ret < 0) {
1990 		fprintf(stderr, "xmlStreamPush() failure\n");
1991 		xmlFreeStreamCtxt(patstream);
1992 		patstream = NULL;
1993             }
1994 	}
1995     }
1996 #endif /* LIBXML_PATTERN_ENABLED */
1997     reader = xmlReaderWalker(doc);
1998     if (reader != NULL) {
1999 	if ((timing) && (!repeat)) {
2000 	    startTimer();
2001 	}
2002 	ret = xmlTextReaderRead(reader);
2003 	while (ret == 1) {
2004 	    if ((debug)
2005 #ifdef LIBXML_PATTERN_ENABLED
2006 	        || (patternc)
2007 #endif
2008 	       )
2009 		processNode(reader);
2010 	    ret = xmlTextReaderRead(reader);
2011 	}
2012 	if ((timing) && (!repeat)) {
2013 	    endTimer("walking through the doc");
2014 	}
2015 	xmlFreeTextReader(reader);
2016 	if (ret != 0) {
2017 	    fprintf(stderr, "failed to walk through the doc\n");
2018 	    progresult = XMLLINT_ERR_UNCLASS;
2019 	}
2020     } else {
2021 	fprintf(stderr, "Failed to crate a reader from the document\n");
2022 	progresult = XMLLINT_ERR_UNCLASS;
2023     }
2024 #ifdef LIBXML_PATTERN_ENABLED
2025     if (patstream != NULL) {
2026 	xmlFreeStreamCtxt(patstream);
2027 	patstream = NULL;
2028     }
2029 #endif
2030 }
2031 #endif /* LIBXML_READER_ENABLED */
2032 
2033 #ifdef LIBXML_XPATH_ENABLED
2034 /************************************************************************
2035  *									*
2036  *			XPath Query                                     *
2037  *									*
2038  ************************************************************************/
2039 
doXPathDump(xmlXPathObjectPtr cur)2040 static void doXPathDump(xmlXPathObjectPtr cur) {
2041     switch(cur->type) {
2042         case XPATH_NODESET: {
2043             int i;
2044             xmlNodePtr node;
2045 #ifdef LIBXML_OUTPUT_ENABLED
2046             xmlOutputBufferPtr buf;
2047 
2048             if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) {
2049                 fprintf(stderr, "XPath set is empty\n");
2050                 progresult = XMLLINT_ERR_XPATH;
2051                 break;
2052             }
2053             buf = xmlOutputBufferCreateFile(stdout, NULL);
2054             if (buf == NULL) {
2055                 fprintf(stderr, "Out of memory for XPath\n");
2056                 progresult = XMLLINT_ERR_MEM;
2057                 return;
2058             }
2059             for (i = 0;i < cur->nodesetval->nodeNr;i++) {
2060                 node = cur->nodesetval->nodeTab[i];
2061                 xmlNodeDumpOutput(buf, NULL, node, 0, 0, NULL);
2062                 xmlOutputBufferWrite(buf, 1, "\n");
2063             }
2064             xmlOutputBufferClose(buf);
2065 #else
2066             printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
2067 #endif
2068 	    break;
2069         }
2070         case XPATH_BOOLEAN:
2071 	    if (cur->boolval) printf("true\n");
2072 	    else printf("false\n");
2073 	    break;
2074         case XPATH_NUMBER:
2075 	    switch (xmlXPathIsInf(cur->floatval)) {
2076 	    case 1:
2077 		printf("Infinity\n");
2078 		break;
2079 	    case -1:
2080 		printf("-Infinity\n");
2081 		break;
2082 	    default:
2083 		if (xmlXPathIsNaN(cur->floatval)) {
2084 		    printf("NaN\n");
2085 		} else {
2086 		    printf("%0g\n", cur->floatval);
2087 		}
2088 	    }
2089 	    break;
2090         case XPATH_STRING:
2091 	    printf("%s\n", (const char *) cur->stringval);
2092 	    break;
2093         case XPATH_UNDEFINED:
2094 	    fprintf(stderr, "XPath Object is uninitialized\n");
2095             progresult = XMLLINT_ERR_XPATH;
2096 	    break;
2097 	default:
2098 	    fprintf(stderr, "XPath object of unexpected type\n");
2099             progresult = XMLLINT_ERR_XPATH;
2100 	    break;
2101     }
2102 }
2103 
doXPathQuery(xmlDocPtr doc,const char * query)2104 static void doXPathQuery(xmlDocPtr doc, const char *query) {
2105     xmlXPathContextPtr ctxt;
2106     xmlXPathObjectPtr res;
2107 
2108     ctxt = xmlXPathNewContext(doc);
2109     if (ctxt == NULL) {
2110         fprintf(stderr, "Out of memory for XPath\n");
2111         progresult = XMLLINT_ERR_MEM;
2112         return;
2113     }
2114     ctxt->node = (xmlNodePtr) doc;
2115     res = xmlXPathEval(BAD_CAST query, ctxt);
2116     xmlXPathFreeContext(ctxt);
2117 
2118     if (res == NULL) {
2119         fprintf(stderr, "XPath evaluation failure\n");
2120         progresult = XMLLINT_ERR_XPATH;
2121         return;
2122     }
2123     doXPathDump(res);
2124     xmlXPathFreeObject(res);
2125 }
2126 #endif /* LIBXML_XPATH_ENABLED */
2127 
2128 /************************************************************************
2129  *									*
2130  *			Tree Test processing				*
2131  *									*
2132  ************************************************************************/
parseAndPrintFile(char * filename,xmlParserCtxtPtr rectxt)2133 static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
2134     xmlDocPtr doc = NULL;
2135 #ifdef LIBXML_TREE_ENABLED
2136     xmlDocPtr tmp;
2137 #endif /* LIBXML_TREE_ENABLED */
2138 
2139     if ((timing) && (!repeat))
2140 	startTimer();
2141 
2142 
2143 #ifdef LIBXML_TREE_ENABLED
2144     if (filename == NULL) {
2145 	if (generate) {
2146 	    xmlNodePtr n;
2147 
2148 	    doc = xmlNewDoc(BAD_CAST "1.0");
2149 	    n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
2150 	    xmlNodeSetContent(n, BAD_CAST "abc");
2151 	    xmlDocSetRootElement(doc, n);
2152 	}
2153     }
2154 #endif /* LIBXML_TREE_ENABLED */
2155 #ifdef LIBXML_HTML_ENABLED
2156 #ifdef LIBXML_PUSH_ENABLED
2157     else if ((html) && (push)) {
2158         FILE *f;
2159 
2160         if ((filename[0] == '-') && (filename[1] == 0)) {
2161             f = stdin;
2162         } else {
2163 	    f = fopen(filename, "rb");
2164         }
2165         if (f != NULL) {
2166             int res;
2167             char chars[4096];
2168             htmlParserCtxtPtr ctxt;
2169 
2170             res = fread(chars, 1, 4, f);
2171             if (res > 0) {
2172                 ctxt = htmlCreatePushParserCtxt(NULL, NULL,
2173                             chars, res, filename, XML_CHAR_ENCODING_NONE);
2174                 if (ctxt == NULL) {
2175                     progresult = XMLLINT_ERR_MEM;
2176                     if (f != stdin)
2177                         fclose(f);
2178                     return;
2179                 }
2180                 htmlCtxtUseOptions(ctxt, options);
2181                 while ((res = fread(chars, 1, pushsize, f)) > 0) {
2182                     htmlParseChunk(ctxt, chars, res, 0);
2183                 }
2184                 htmlParseChunk(ctxt, chars, 0, 1);
2185                 doc = ctxt->myDoc;
2186                 htmlFreeParserCtxt(ctxt);
2187             }
2188             if (f != stdin)
2189                 fclose(f);
2190         }
2191     }
2192 #endif /* LIBXML_PUSH_ENABLED */
2193 #ifdef HAVE_MMAP
2194     else if ((html) && (memory)) {
2195 	int fd;
2196 	struct stat info;
2197 	const char *base;
2198 	if (stat(filename, &info) < 0)
2199 	    return;
2200 	if ((fd = open(filename, O_RDONLY)) < 0)
2201 	    return;
2202 	base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2203 	if (base == (void *) MAP_FAILED) {
2204 	    close(fd);
2205 	    fprintf(stderr, "mmap failure for file %s\n", filename);
2206 	    progresult = XMLLINT_ERR_RDFILE;
2207 	    return;
2208 	}
2209 
2210 	doc = htmlReadMemory((char *) base, info.st_size, filename,
2211 	                     NULL, options);
2212 
2213 	munmap((char *) base, info.st_size);
2214 	close(fd);
2215     }
2216 #endif
2217     else if (html) {
2218 	doc = htmlReadFile(filename, NULL, options);
2219     }
2220 #endif /* LIBXML_HTML_ENABLED */
2221     else {
2222 #ifdef LIBXML_PUSH_ENABLED
2223 	/*
2224 	 * build an XML tree from a string;
2225 	 */
2226 	if (push) {
2227 	    FILE *f;
2228 
2229 	    /* '-' Usually means stdin -<sven@zen.org> */
2230 	    if ((filename[0] == '-') && (filename[1] == 0)) {
2231 	        f = stdin;
2232 	    } else {
2233 		f = fopen(filename, "rb");
2234 	    }
2235 	    if (f != NULL) {
2236 		int ret;
2237 	        int res, size = 1024;
2238 	        char chars[1024];
2239                 xmlParserCtxtPtr ctxt;
2240 
2241 		/* if (repeat) size = 1024; */
2242 		res = fread(chars, 1, 4, f);
2243 		if (res > 0) {
2244 		    ctxt = xmlCreatePushParserCtxt(NULL, NULL,
2245 		                chars, res, filename);
2246                     if (ctxt == NULL) {
2247                         progresult = XMLLINT_ERR_MEM;
2248                         if (f != stdin)
2249                             fclose(f);
2250                         return;
2251                     }
2252 		    xmlCtxtUseOptions(ctxt, options);
2253 		    while ((res = fread(chars, 1, size, f)) > 0) {
2254 			xmlParseChunk(ctxt, chars, res, 0);
2255 		    }
2256 		    xmlParseChunk(ctxt, chars, 0, 1);
2257 		    doc = ctxt->myDoc;
2258 		    ret = ctxt->wellFormed;
2259 		    xmlFreeParserCtxt(ctxt);
2260 		    if ((!ret) && (!recovery)) {
2261 			xmlFreeDoc(doc);
2262 			doc = NULL;
2263 		    }
2264 	        }
2265                 if (f != stdin)
2266                     fclose(f);
2267 	    }
2268 	} else
2269 #endif /* LIBXML_PUSH_ENABLED */
2270         if (testIO) {
2271 	    if ((filename[0] == '-') && (filename[1] == 0)) {
2272 	        doc = xmlReadFd(0, NULL, NULL, options);
2273 	    } else {
2274 	        FILE *f;
2275 
2276 		f = fopen(filename, "rb");
2277 		if (f != NULL) {
2278 		    if (rectxt == NULL)
2279 			doc = xmlReadIO(myRead, myClose, f, filename, NULL,
2280                                         options);
2281 		    else
2282 			doc = xmlCtxtReadIO(rectxt, myRead, myClose, f,
2283 					    filename, NULL, options);
2284 		} else
2285 		    doc = NULL;
2286 	    }
2287 	} else if (htmlout) {
2288 	    xmlParserCtxtPtr ctxt;
2289 
2290 	    if (rectxt == NULL) {
2291 		ctxt = xmlNewParserCtxt();
2292                 if (ctxt == NULL) {
2293                     progresult = XMLLINT_ERR_MEM;
2294                     return;
2295                 }
2296             } else {
2297                 ctxt = rectxt;
2298             }
2299 
2300             ctxt->sax->error = xmlHTMLError;
2301             ctxt->sax->warning = xmlHTMLWarning;
2302             ctxt->vctxt.error = xmlHTMLValidityError;
2303             ctxt->vctxt.warning = xmlHTMLValidityWarning;
2304 
2305             doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2306 
2307             if (rectxt == NULL)
2308                 xmlFreeParserCtxt(ctxt);
2309 #ifdef HAVE_MMAP
2310 	} else if (memory) {
2311 	    int fd;
2312 	    struct stat info;
2313 	    const char *base;
2314 	    if (stat(filename, &info) < 0)
2315 		return;
2316 	    if ((fd = open(filename, O_RDONLY)) < 0)
2317 		return;
2318 	    base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2319 	    if (base == (void *) MAP_FAILED) {
2320 	        close(fd);
2321 	        fprintf(stderr, "mmap failure for file %s\n", filename);
2322 		progresult = XMLLINT_ERR_RDFILE;
2323 	        return;
2324 	    }
2325 
2326 	    if (rectxt == NULL)
2327 		doc = xmlReadMemory((char *) base, info.st_size,
2328 		                    filename, NULL, options);
2329 	    else
2330 		doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
2331 			                filename, NULL, options);
2332 
2333 	    munmap((char *) base, info.st_size);
2334 	    close(fd);
2335 #endif
2336 #ifdef LIBXML_VALID_ENABLED
2337 	} else if (valid) {
2338 	    xmlParserCtxtPtr ctxt = NULL;
2339 
2340 	    if (rectxt == NULL) {
2341 		ctxt = xmlNewParserCtxt();
2342                 if (ctxt == NULL) {
2343                     progresult = XMLLINT_ERR_MEM;
2344                     return;
2345                 }
2346             } else {
2347 	        ctxt = rectxt;
2348             }
2349 
2350             doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2351 
2352             if (ctxt->valid == 0)
2353                 progresult = XMLLINT_ERR_RDFILE;
2354             if (rectxt == NULL)
2355                 xmlFreeParserCtxt(ctxt);
2356 #endif /* LIBXML_VALID_ENABLED */
2357 	} else {
2358 	    if (rectxt != NULL)
2359 	        doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
2360 	    else {
2361 #ifdef LIBXML_SAX1_ENABLED
2362                 if (sax1)
2363 		    doc = xmlParseFile(filename);
2364 		else
2365 #endif /* LIBXML_SAX1_ENABLED */
2366 		doc = xmlReadFile(filename, NULL, options);
2367 	    }
2368 	}
2369     }
2370 
2371     /*
2372      * If we don't have a document we might as well give up.  Do we
2373      * want an error message here?  <sven@zen.org> */
2374     if (doc == NULL) {
2375 	progresult = XMLLINT_ERR_UNCLASS;
2376 	return;
2377     }
2378 
2379     if ((timing) && (!repeat)) {
2380 	endTimer("Parsing");
2381     }
2382 
2383     /*
2384      * Remove DOCTYPE nodes
2385      */
2386     if (dropdtd) {
2387 	xmlDtdPtr dtd;
2388 
2389 	dtd = xmlGetIntSubset(doc);
2390 	if (dtd != NULL) {
2391 	    xmlUnlinkNode((xmlNodePtr)dtd);
2392             doc->intSubset = NULL;
2393 	    xmlFreeDtd(dtd);
2394 	}
2395     }
2396 
2397 #ifdef LIBXML_XINCLUDE_ENABLED
2398     if (xinclude) {
2399 	if ((timing) && (!repeat)) {
2400 	    startTimer();
2401 	}
2402 	if (xmlXIncludeProcessFlags(doc, options) < 0)
2403 	    progresult = XMLLINT_ERR_UNCLASS;
2404 	if ((timing) && (!repeat)) {
2405 	    endTimer("Xinclude processing");
2406 	}
2407     }
2408 #endif
2409 
2410 #ifdef LIBXML_XPATH_ENABLED
2411     if (xpathquery != NULL) {
2412         doXPathQuery(doc, xpathquery);
2413     }
2414 #endif
2415 
2416 #ifdef LIBXML_DEBUG_ENABLED
2417 #ifdef LIBXML_XPATH_ENABLED
2418     /*
2419      * shell interaction
2420      */
2421     if (shell) {
2422         xmlXPathOrderDocElems(doc);
2423         xmlShell(doc, filename, xmlShellReadline, stdout);
2424     }
2425 #endif
2426 #endif
2427 
2428 #ifdef LIBXML_TREE_ENABLED
2429     /*
2430      * test intermediate copy if needed.
2431      */
2432     if (copy) {
2433         tmp = doc;
2434 	if (timing) {
2435 	    startTimer();
2436 	}
2437 	doc = xmlCopyDoc(doc, 1);
2438 	if (timing) {
2439 	    endTimer("Copying");
2440 	}
2441 	if (timing) {
2442 	    startTimer();
2443 	}
2444 	xmlFreeDoc(tmp);
2445 	if (timing) {
2446 	    endTimer("Freeing original");
2447 	}
2448     }
2449 #endif /* LIBXML_TREE_ENABLED */
2450 
2451 #ifdef LIBXML_VALID_ENABLED
2452     if ((insert) && (!html)) {
2453         const xmlChar* list[256];
2454 	int nb, i;
2455 	xmlNodePtr node;
2456 
2457 	if (doc->children != NULL) {
2458 	    node = doc->children;
2459 	    while ((node != NULL) && (node->last == NULL)) node = node->next;
2460 	    if (node != NULL) {
2461 		nb = xmlValidGetValidElements(node->last, NULL, list, 256);
2462 		if (nb < 0) {
2463 		    fprintf(stderr, "could not get valid list of elements\n");
2464 		} else if (nb == 0) {
2465 		    fprintf(stderr, "No element can be inserted under root\n");
2466 		} else {
2467 		    fprintf(stderr, "%d element types can be inserted under root:\n",
2468 		           nb);
2469 		    for (i = 0;i < nb;i++) {
2470 			 fprintf(stderr, "%s\n", (char *) list[i]);
2471 		    }
2472 		}
2473 	    }
2474 	}
2475     }else
2476 #endif /* LIBXML_VALID_ENABLED */
2477 #ifdef LIBXML_READER_ENABLED
2478     if (walker) {
2479         walkDoc(doc);
2480     }
2481 #endif /* LIBXML_READER_ENABLED */
2482 #ifdef LIBXML_OUTPUT_ENABLED
2483     if (noout == 0) {
2484         int ret;
2485 
2486 	/*
2487 	 * print it.
2488 	 */
2489 #ifdef LIBXML_DEBUG_ENABLED
2490 	if (!debug) {
2491 #endif
2492 	    if ((timing) && (!repeat)) {
2493 		startTimer();
2494 	    }
2495 #ifdef LIBXML_HTML_ENABLED
2496             if ((html) && (!xmlout)) {
2497 		if (compress) {
2498 		    htmlSaveFile(output ? output : "-", doc);
2499 		}
2500 		else if (encoding != NULL) {
2501 		    if (format == 1) {
2502 			htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
2503 		    }
2504 		    else {
2505 			htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
2506 		    }
2507 		}
2508 		else if (format == 1) {
2509 		    htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
2510 		}
2511 		else {
2512 		    FILE *out;
2513 		    if (output == NULL)
2514 			out = stdout;
2515 		    else {
2516 			out = fopen(output,"wb");
2517 		    }
2518 		    if (out != NULL) {
2519 			if (htmlDocDump(out, doc) < 0)
2520 			    progresult = XMLLINT_ERR_OUT;
2521 
2522 			if (output != NULL)
2523 			    fclose(out);
2524 		    } else {
2525 			fprintf(stderr, "failed to open %s\n", output);
2526 			progresult = XMLLINT_ERR_OUT;
2527 		    }
2528 		}
2529 		if ((timing) && (!repeat)) {
2530 		    endTimer("Saving");
2531 		}
2532 	    } else
2533 #endif
2534 #ifdef LIBXML_C14N_ENABLED
2535             if (canonical) {
2536 	        xmlChar *result = NULL;
2537 		int size;
2538 
2539 		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
2540 		if (size >= 0) {
2541 		    if (write(1, result, size) == -1) {
2542 		        fprintf(stderr, "Can't write data\n");
2543 		    }
2544 		    xmlFree(result);
2545 		} else {
2546 		    fprintf(stderr, "Failed to canonicalize\n");
2547 		    progresult = XMLLINT_ERR_OUT;
2548 		}
2549 	    } else if (canonical_11) {
2550 	        xmlChar *result = NULL;
2551 		int size;
2552 
2553 		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
2554 		if (size >= 0) {
2555 		    if (write(1, result, size) == -1) {
2556 		        fprintf(stderr, "Can't write data\n");
2557 		    }
2558 		    xmlFree(result);
2559 		} else {
2560 		    fprintf(stderr, "Failed to canonicalize\n");
2561 		    progresult = XMLLINT_ERR_OUT;
2562 		}
2563 	    } else
2564             if (exc_canonical) {
2565 	        xmlChar *result = NULL;
2566 		int size;
2567 
2568 		size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
2569 		if (size >= 0) {
2570 		    if (write(1, result, size) == -1) {
2571 		        fprintf(stderr, "Can't write data\n");
2572 		    }
2573 		    xmlFree(result);
2574 		} else {
2575 		    fprintf(stderr, "Failed to canonicalize\n");
2576 		    progresult = XMLLINT_ERR_OUT;
2577 		}
2578 	    } else
2579 #endif
2580 #ifdef HAVE_MMAP
2581 	    if (memory) {
2582 		xmlChar *result;
2583 		int len;
2584 
2585 		if (encoding != NULL) {
2586 		    if (format == 1) {
2587 		        xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
2588 		    } else {
2589 			xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
2590 		    }
2591 		} else {
2592 		    if (format == 1)
2593 			xmlDocDumpFormatMemory(doc, &result, &len, 1);
2594 		    else
2595 			xmlDocDumpMemory(doc, &result, &len);
2596 		}
2597 		if (result == NULL) {
2598 		    fprintf(stderr, "Failed to save\n");
2599 		    progresult = XMLLINT_ERR_OUT;
2600 		} else {
2601 		    if (write(1, result, len) == -1) {
2602 		        fprintf(stderr, "Can't write data\n");
2603 		    }
2604 		    xmlFree(result);
2605 		}
2606 
2607 	    } else
2608 #endif /* HAVE_MMAP */
2609 	    if (compress) {
2610 		xmlSaveFile(output ? output : "-", doc);
2611 	    } else if (oldout) {
2612 	        if (encoding != NULL) {
2613 		    if (format == 1) {
2614 			ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
2615 						   encoding, 1);
2616 		    }
2617 		    else {
2618 			ret = xmlSaveFileEnc(output ? output : "-", doc,
2619 			                     encoding);
2620 		    }
2621 		    if (ret < 0) {
2622 			fprintf(stderr, "failed save to %s\n",
2623 				output ? output : "-");
2624 			progresult = XMLLINT_ERR_OUT;
2625 		    }
2626 		} else if (format == 1) {
2627 		    ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
2628 		    if (ret < 0) {
2629 			fprintf(stderr, "failed save to %s\n",
2630 				output ? output : "-");
2631 			progresult = XMLLINT_ERR_OUT;
2632 		    }
2633 		} else {
2634 		    FILE *out;
2635 		    if (output == NULL)
2636 			out = stdout;
2637 		    else {
2638 			out = fopen(output,"wb");
2639 		    }
2640 		    if (out != NULL) {
2641 			if (xmlDocDump(out, doc) < 0)
2642 			    progresult = XMLLINT_ERR_OUT;
2643 
2644 			if (output != NULL)
2645 			    fclose(out);
2646 		    } else {
2647 			fprintf(stderr, "failed to open %s\n", output);
2648 			progresult = XMLLINT_ERR_OUT;
2649 		    }
2650 		}
2651 	    } else {
2652 	        xmlSaveCtxtPtr ctxt;
2653 		int saveOpts = 0;
2654 
2655                 if (format == 1)
2656 		    saveOpts |= XML_SAVE_FORMAT;
2657                 else if (format == 2)
2658                     saveOpts |= XML_SAVE_WSNONSIG;
2659 
2660 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2661                 if (xmlout)
2662                     saveOpts |= XML_SAVE_AS_XML;
2663 #endif
2664 
2665 		if (output == NULL)
2666 		    ctxt = xmlSaveToFd(1, encoding, saveOpts);
2667 		else
2668 		    ctxt = xmlSaveToFilename(output, encoding, saveOpts);
2669 
2670 		if (ctxt != NULL) {
2671 		    if (xmlSaveDoc(ctxt, doc) < 0) {
2672 			fprintf(stderr, "failed save to %s\n",
2673 				output ? output : "-");
2674 			progresult = XMLLINT_ERR_OUT;
2675 		    }
2676 		    xmlSaveClose(ctxt);
2677 		} else {
2678 		    progresult = XMLLINT_ERR_OUT;
2679 		}
2680 	    }
2681 	    if ((timing) && (!repeat)) {
2682 		endTimer("Saving");
2683 	    }
2684 #ifdef LIBXML_DEBUG_ENABLED
2685 	} else {
2686 	    FILE *out;
2687 	    if (output == NULL)
2688 	        out = stdout;
2689 	    else {
2690 		out = fopen(output,"wb");
2691 	    }
2692 	    if (out != NULL) {
2693 		xmlDebugDumpDocument(out, doc);
2694 
2695 		if (output != NULL)
2696 		    fclose(out);
2697 	    } else {
2698 		fprintf(stderr, "failed to open %s\n", output);
2699 		progresult = XMLLINT_ERR_OUT;
2700 	    }
2701 	}
2702 #endif
2703     }
2704 #endif /* LIBXML_OUTPUT_ENABLED */
2705 
2706 #ifdef LIBXML_VALID_ENABLED
2707     /*
2708      * A posteriori validation test
2709      */
2710     if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
2711 	xmlDtdPtr dtd;
2712 
2713 	if ((timing) && (!repeat)) {
2714 	    startTimer();
2715 	}
2716 	if (dtdvalid != NULL)
2717 	    dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
2718 	else
2719 	    dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
2720 	if ((timing) && (!repeat)) {
2721 	    endTimer("Parsing DTD");
2722 	}
2723 	if (dtd == NULL) {
2724 	    if (dtdvalid != NULL)
2725 		xmlGenericError(xmlGenericErrorContext,
2726 			"Could not parse DTD %s\n", dtdvalid);
2727 	    else
2728 		xmlGenericError(xmlGenericErrorContext,
2729 			"Could not parse DTD %s\n", dtdvalidfpi);
2730 	    progresult = XMLLINT_ERR_DTD;
2731 	} else {
2732 	    xmlValidCtxtPtr cvp;
2733 
2734 	    if ((cvp = xmlNewValidCtxt()) == NULL) {
2735 		xmlGenericError(xmlGenericErrorContext,
2736 			"Couldn't allocate validation context\n");
2737                 progresult = XMLLINT_ERR_MEM;
2738                 xmlFreeDtd(dtd);
2739                 return;
2740 	    }
2741 	    cvp->userData = NULL;
2742 	    cvp->error    = xmlGenericError;
2743 	    cvp->warning  = xmlGenericError;
2744 
2745 	    if ((timing) && (!repeat)) {
2746 		startTimer();
2747 	    }
2748 	    if (!xmlValidateDtd(cvp, doc, dtd)) {
2749 		if (dtdvalid != NULL)
2750 		    xmlGenericError(xmlGenericErrorContext,
2751 			    "Document %s does not validate against %s\n",
2752 			    filename, dtdvalid);
2753 		else
2754 		    xmlGenericError(xmlGenericErrorContext,
2755 			    "Document %s does not validate against %s\n",
2756 			    filename, dtdvalidfpi);
2757 		progresult = XMLLINT_ERR_VALID;
2758 	    }
2759 	    if ((timing) && (!repeat)) {
2760 		endTimer("Validating against DTD");
2761 	    }
2762 	    xmlFreeValidCtxt(cvp);
2763 	    xmlFreeDtd(dtd);
2764 	}
2765     } else if (postvalid) {
2766 	xmlValidCtxtPtr cvp;
2767 
2768 	if ((cvp = xmlNewValidCtxt()) == NULL) {
2769 	    xmlGenericError(xmlGenericErrorContext,
2770 		    "Couldn't allocate validation context\n");
2771             progresult = XMLLINT_ERR_MEM;
2772             xmlFreeDoc(doc);
2773             return;
2774 	}
2775 
2776 	if ((timing) && (!repeat)) {
2777 	    startTimer();
2778 	}
2779 	cvp->userData = NULL;
2780 	cvp->error    = xmlGenericError;
2781 	cvp->warning  = xmlGenericError;
2782 	if (!xmlValidateDocument(cvp, doc)) {
2783 	    xmlGenericError(xmlGenericErrorContext,
2784 		    "Document %s does not validate\n", filename);
2785 	    progresult = XMLLINT_ERR_VALID;
2786 	}
2787 	if ((timing) && (!repeat)) {
2788 	    endTimer("Validating");
2789 	}
2790 	xmlFreeValidCtxt(cvp);
2791     }
2792 #endif /* LIBXML_VALID_ENABLED */
2793 #ifdef LIBXML_SCHEMATRON_ENABLED
2794     if (wxschematron != NULL) {
2795 	xmlSchematronValidCtxtPtr ctxt;
2796 	int ret;
2797 	int flag;
2798 
2799 	if ((timing) && (!repeat)) {
2800 	    startTimer();
2801 	}
2802 
2803 	if (debug)
2804 	    flag = XML_SCHEMATRON_OUT_XML;
2805 	else
2806 	    flag = XML_SCHEMATRON_OUT_TEXT;
2807 	if (noout)
2808 	    flag |= XML_SCHEMATRON_OUT_QUIET;
2809 	ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
2810         if (ctxt == NULL) {
2811             progresult = XMLLINT_ERR_MEM;
2812             xmlFreeDoc(doc);
2813             return;
2814         }
2815 #if 0
2816 	xmlSchematronSetValidErrors(ctxt, xmlGenericError, xmlGenericError,
2817                 NULL);
2818 #endif
2819 	ret = xmlSchematronValidateDoc(ctxt, doc);
2820 	if (ret == 0) {
2821 	    if (!quiet) {
2822 	        fprintf(stderr, "%s validates\n", filename);
2823 	    }
2824 	} else if (ret > 0) {
2825 	    fprintf(stderr, "%s fails to validate\n", filename);
2826 	    progresult = XMLLINT_ERR_VALID;
2827 	} else {
2828 	    fprintf(stderr, "%s validation generated an internal error\n",
2829 		   filename);
2830 	    progresult = XMLLINT_ERR_VALID;
2831 	}
2832 	xmlSchematronFreeValidCtxt(ctxt);
2833 	if ((timing) && (!repeat)) {
2834 	    endTimer("Validating");
2835 	}
2836     }
2837 #endif
2838 #ifdef LIBXML_SCHEMAS_ENABLED
2839     if (relaxngschemas != NULL) {
2840 	xmlRelaxNGValidCtxtPtr ctxt;
2841 	int ret;
2842 
2843 	if ((timing) && (!repeat)) {
2844 	    startTimer();
2845 	}
2846 
2847 	ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2848         if (ctxt == NULL) {
2849             progresult = XMLLINT_ERR_MEM;
2850             xmlFreeDoc(doc);
2851             return;
2852         }
2853 	xmlRelaxNGSetValidErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
2854 	ret = xmlRelaxNGValidateDoc(ctxt, doc);
2855 	if (ret == 0) {
2856 	    if (!quiet) {
2857 	        fprintf(stderr, "%s validates\n", filename);
2858 	    }
2859 	} else if (ret > 0) {
2860 	    fprintf(stderr, "%s fails to validate\n", filename);
2861 	    progresult = XMLLINT_ERR_VALID;
2862 	} else {
2863 	    fprintf(stderr, "%s validation generated an internal error\n",
2864 		   filename);
2865 	    progresult = XMLLINT_ERR_VALID;
2866 	}
2867 	xmlRelaxNGFreeValidCtxt(ctxt);
2868 	if ((timing) && (!repeat)) {
2869 	    endTimer("Validating");
2870 	}
2871     } else if (wxschemas != NULL) {
2872 	xmlSchemaValidCtxtPtr ctxt;
2873 	int ret;
2874 
2875 	if ((timing) && (!repeat)) {
2876 	    startTimer();
2877 	}
2878 
2879 	ctxt = xmlSchemaNewValidCtxt(wxschemas);
2880         if (ctxt == NULL) {
2881             progresult = XMLLINT_ERR_MEM;
2882             xmlFreeDoc(doc);
2883             return;
2884         }
2885 	xmlSchemaSetValidErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
2886 	ret = xmlSchemaValidateDoc(ctxt, doc);
2887 	if (ret == 0) {
2888 	    if (!quiet) {
2889 	        fprintf(stderr, "%s validates\n", filename);
2890 	    }
2891 	} else if (ret > 0) {
2892 	    fprintf(stderr, "%s fails to validate\n", filename);
2893 	    progresult = XMLLINT_ERR_VALID;
2894 	} else {
2895 	    fprintf(stderr, "%s validation generated an internal error\n",
2896 		   filename);
2897 	    progresult = XMLLINT_ERR_VALID;
2898 	}
2899 	xmlSchemaFreeValidCtxt(ctxt);
2900 	if ((timing) && (!repeat)) {
2901 	    endTimer("Validating");
2902 	}
2903     }
2904 #endif
2905 
2906 #ifdef LIBXML_DEBUG_ENABLED
2907 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2908     if ((debugent) && (!html))
2909 	xmlDebugDumpEntities(stderr, doc);
2910 #endif
2911 #endif
2912 
2913     /*
2914      * free it.
2915      */
2916     if ((timing) && (!repeat)) {
2917 	startTimer();
2918     }
2919     xmlFreeDoc(doc);
2920     if ((timing) && (!repeat)) {
2921 	endTimer("Freeing");
2922     }
2923 }
2924 
2925 /************************************************************************
2926  *									*
2927  *			Usage and Main					*
2928  *									*
2929  ************************************************************************/
2930 
showVersion(const char * name)2931 static void showVersion(const char *name) {
2932     fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
2933     fprintf(stderr, "   compiled with: ");
2934     if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
2935     if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
2936     if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
2937     if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
2938     if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
2939     if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
2940     if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
2941     if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
2942     if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP ");
2943     if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP ");
2944     if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
2945     if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML ");
2946     if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy ");
2947     if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N ");
2948     if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog ");
2949     if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath ");
2950     if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer ");
2951     if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude ");
2952     if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv ");
2953     if (xmlHasFeature(XML_WITH_ICU)) fprintf(stderr, "ICU ");
2954     if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X ");
2955     if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode ");
2956     if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps ");
2957     if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata ");
2958     if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr ");
2959     if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas ");
2960     if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron ");
2961     if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules ");
2962     if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug ");
2963     if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug ");
2964     if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug ");
2965     if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
2966     if (xmlHasFeature(XML_WITH_LZMA)) fprintf(stderr, "Lzma ");
2967     fprintf(stderr, "\n");
2968 }
2969 
usage(FILE * f,const char * name)2970 static void usage(FILE *f, const char *name) {
2971     fprintf(f, "Usage : %s [options] XMLfiles ...\n", name);
2972 #ifdef LIBXML_OUTPUT_ENABLED
2973     fprintf(f, "\tParse the XML files and output the result of the parsing\n");
2974 #else
2975     fprintf(f, "\tParse the XML files\n");
2976 #endif /* LIBXML_OUTPUT_ENABLED */
2977     fprintf(f, "\t--version : display the version of the XML library used\n");
2978 #ifdef LIBXML_DEBUG_ENABLED
2979     fprintf(f, "\t--debug : dump a debug tree of the in-memory document\n");
2980     fprintf(f, "\t--shell : run a navigating shell\n");
2981     fprintf(f, "\t--debugent : debug the entities defined in the document\n");
2982 #else
2983 #ifdef LIBXML_READER_ENABLED
2984     fprintf(f, "\t--debug : dump the nodes content when using --stream\n");
2985 #endif /* LIBXML_READER_ENABLED */
2986 #endif
2987 #ifdef LIBXML_TREE_ENABLED
2988     fprintf(f, "\t--copy : used to test the internal copy implementation\n");
2989 #endif /* LIBXML_TREE_ENABLED */
2990     fprintf(f, "\t--recover : output what was parsable on broken XML documents\n");
2991     fprintf(f, "\t--huge : remove any internal arbitrary parser limits\n");
2992     fprintf(f, "\t--noent : substitute entity references by their value\n");
2993     fprintf(f, "\t--noenc : ignore any encoding specified inside the document\n");
2994     fprintf(f, "\t--noout : don't output the result tree\n");
2995     fprintf(f, "\t--path 'paths': provide a set of paths for resources\n");
2996     fprintf(f, "\t--load-trace : print trace of all external entities loaded\n");
2997     fprintf(f, "\t--nonet : refuse to fetch DTDs or entities over network\n");
2998     fprintf(f, "\t--nocompact : do not generate compact text nodes\n");
2999     fprintf(f, "\t--htmlout : output results as HTML\n");
3000     fprintf(f, "\t--nowrap : do not put HTML doc wrapper\n");
3001 #ifdef LIBXML_VALID_ENABLED
3002     fprintf(f, "\t--valid : validate the document in addition to std well-formed check\n");
3003     fprintf(f, "\t--postvalid : do a posteriori validation, i.e after parsing\n");
3004     fprintf(f, "\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
3005     fprintf(f, "\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
3006 #endif /* LIBXML_VALID_ENABLED */
3007     fprintf(f, "\t--quiet : be quiet when succeeded\n");
3008     fprintf(f, "\t--timing : print some timings\n");
3009     fprintf(f, "\t--output file or -o file: save to a given file\n");
3010     fprintf(f, "\t--repeat : repeat 100 times, for timing or profiling\n");
3011     fprintf(f, "\t--insert : ad-hoc test for valid insertions\n");
3012 #ifdef LIBXML_OUTPUT_ENABLED
3013 #ifdef LIBXML_ZLIB_ENABLED
3014     fprintf(f, "\t--compress : turn on gzip compression of output\n");
3015 #endif
3016 #endif /* LIBXML_OUTPUT_ENABLED */
3017 #ifdef LIBXML_HTML_ENABLED
3018     fprintf(f, "\t--html : use the HTML parser\n");
3019     fprintf(f, "\t--xmlout : force to use the XML serializer when using --html\n");
3020     fprintf(f, "\t--nodefdtd : do not default HTML doctype\n");
3021 #endif
3022 #ifdef LIBXML_PUSH_ENABLED
3023     fprintf(f, "\t--push : use the push mode of the parser\n");
3024     fprintf(f, "\t--pushsmall : use the push mode of the parser using tiny increments\n");
3025 #endif /* LIBXML_PUSH_ENABLED */
3026 #ifdef HAVE_MMAP
3027     fprintf(f, "\t--memory : parse from memory\n");
3028 #endif
3029     fprintf(f, "\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
3030     fprintf(f, "\t--nowarning : do not emit warnings from parser/validator\n");
3031     fprintf(f, "\t--noblanks : drop (ignorable?) blanks spaces\n");
3032     fprintf(f, "\t--nocdata : replace cdata section with text nodes\n");
3033 #ifdef LIBXML_OUTPUT_ENABLED
3034     fprintf(f, "\t--format : reformat/reindent the output\n");
3035     fprintf(f, "\t--encode encoding : output in the given encoding\n");
3036     fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n");
3037     fprintf(f, "\t--pretty STYLE : pretty-print in a particular style\n");
3038     fprintf(f, "\t                 0 Do not pretty print\n");
3039     fprintf(f, "\t                 1 Format the XML content, as --format\n");
3040     fprintf(f, "\t                 2 Add whitespace inside tags, preserving content\n");
3041 #endif /* LIBXML_OUTPUT_ENABLED */
3042     fprintf(f, "\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
3043     fprintf(f, "\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
3044     fprintf(f, "\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
3045 #ifdef LIBXML_C14N_ENABLED
3046 #endif /* LIBXML_C14N_ENABLED */
3047     fprintf(f, "\t--nsclean : remove redundant namespace declarations\n");
3048     fprintf(f, "\t--testIO : test user I/O support\n");
3049 #ifdef LIBXML_CATALOG_ENABLED
3050     fprintf(f, "\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
3051     fprintf(f, "\t             otherwise XML Catalogs starting from \n");
3052     fprintf(f, "\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
3053     fprintf(f, "\t--nocatalogs: deactivate all catalogs\n");
3054 #endif
3055     fprintf(f, "\t--auto : generate a small doc on the fly\n");
3056 #ifdef LIBXML_XINCLUDE_ENABLED
3057     fprintf(f, "\t--xinclude : do XInclude processing\n");
3058     fprintf(f, "\t--noxincludenode : same but do not generate XInclude nodes\n");
3059     fprintf(f, "\t--nofixup-base-uris : do not fixup xml:base uris\n");
3060 #endif
3061     fprintf(f, "\t--loaddtd : fetch external DTD\n");
3062     fprintf(f, "\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
3063 #ifdef LIBXML_READER_ENABLED
3064     fprintf(f, "\t--stream : use the streaming interface to process very large files\n");
3065     fprintf(f, "\t--walker : create a reader and walk though the resulting doc\n");
3066 #ifdef LIBXML_PATTERN_ENABLED
3067     fprintf(f, "\t--pattern pattern_value : test the pattern support\n");
3068 #endif
3069 #endif /* LIBXML_READER_ENABLED */
3070     fprintf(f, "\t--chkregister : verify the node registration code\n");
3071 #ifdef LIBXML_SCHEMAS_ENABLED
3072     fprintf(f, "\t--relaxng schema : do RelaxNG validation against the schema\n");
3073     fprintf(f, "\t--schema schema : do validation against the WXS schema\n");
3074 #endif
3075 #ifdef LIBXML_SCHEMATRON_ENABLED
3076     fprintf(f, "\t--schematron schema : do validation against a schematron\n");
3077 #endif
3078 #ifdef LIBXML_SAX1_ENABLED
3079     fprintf(f, "\t--sax1: use the old SAX1 interfaces for processing\n");
3080 #endif
3081     fprintf(f, "\t--sax: do not build a tree but work just at the SAX level\n");
3082     fprintf(f, "\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
3083 #ifdef LIBXML_XPATH_ENABLED
3084     fprintf(f, "\t--xpath expr: evaluate the XPath expression, imply --noout\n");
3085 #endif
3086 
3087     fprintf(f, "\nLibxml project home page: https://gitlab.gnome.org/GNOME/libxml2\n");
3088 }
3089 
registerNode(xmlNodePtr node)3090 static void registerNode(xmlNodePtr node)
3091 {
3092     node->_private = malloc(sizeof(long));
3093     if (node->_private == NULL) {
3094         fprintf(stderr, "Out of memory in xmllint:registerNode()\n");
3095 	exit(XMLLINT_ERR_MEM);
3096     }
3097     *(long*)node->_private = (long) 0x81726354;
3098     nbregister++;
3099 }
3100 
deregisterNode(xmlNodePtr node)3101 static void deregisterNode(xmlNodePtr node)
3102 {
3103     assert(node->_private != NULL);
3104     assert(*(long*)node->_private == (long) 0x81726354);
3105     free(node->_private);
3106     nbregister--;
3107 }
3108 
3109 int
main(int argc,char ** argv)3110 main(int argc, char **argv) {
3111     int i, acount;
3112     int files = 0;
3113     int version = 0;
3114     const char* indent;
3115 
3116     if (argc <= 1) {
3117 	usage(stderr, argv[0]);
3118 	return(XMLLINT_ERR_UNCLASS);
3119     }
3120 
3121     /* xmlMemSetup must be called before initializing the parser. */
3122     for (i = 1; i < argc ; i++) {
3123 	if (argv[i][0] != '-')
3124 	    continue;
3125 
3126 	if ((!strcmp(argv[i], "-maxmem")) ||
3127 	    (!strcmp(argv[i], "--maxmem"))) {
3128 	     i++;
3129 	     if ((i >= argc) || (sscanf(argv[i], "%d", &maxmem) != 1)) {
3130 	         maxmem = 0;
3131 	     }
3132         }
3133     }
3134     if (maxmem != 0)
3135         xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc, myStrdupFunc);
3136 
3137     LIBXML_TEST_VERSION
3138 
3139     for (i = 1; i < argc ; i++) {
3140 	if (argv[i][0] != '-' || argv[i][1] == 0)
3141 	    continue;
3142 
3143 	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
3144 	    debug++;
3145 	else
3146 #ifdef LIBXML_DEBUG_ENABLED
3147 	if ((!strcmp(argv[i], "-shell")) ||
3148 	         (!strcmp(argv[i], "--shell"))) {
3149 	    shell++;
3150             noout = 1;
3151         } else
3152 #endif
3153 #ifdef LIBXML_TREE_ENABLED
3154 	if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
3155 	    copy++;
3156 	else
3157 #endif /* LIBXML_TREE_ENABLED */
3158 	if ((!strcmp(argv[i], "-recover")) ||
3159 	         (!strcmp(argv[i], "--recover"))) {
3160 	    recovery++;
3161 	    options |= XML_PARSE_RECOVER;
3162 	} else if ((!strcmp(argv[i], "-huge")) ||
3163 	         (!strcmp(argv[i], "--huge"))) {
3164 	    options |= XML_PARSE_HUGE;
3165 	} else if ((!strcmp(argv[i], "-noent")) ||
3166 	         (!strcmp(argv[i], "--noent"))) {
3167 	    noent++;
3168 	    options |= XML_PARSE_NOENT;
3169 	} else if ((!strcmp(argv[i], "-noenc")) ||
3170 	         (!strcmp(argv[i], "--noenc"))) {
3171 	    noenc++;
3172 	    options |= XML_PARSE_IGNORE_ENC;
3173 	} else if ((!strcmp(argv[i], "-nsclean")) ||
3174 	         (!strcmp(argv[i], "--nsclean"))) {
3175 	    options |= XML_PARSE_NSCLEAN;
3176 	} else if ((!strcmp(argv[i], "-nocdata")) ||
3177 	         (!strcmp(argv[i], "--nocdata"))) {
3178 	    options |= XML_PARSE_NOCDATA;
3179 	} else if ((!strcmp(argv[i], "-nodict")) ||
3180 	         (!strcmp(argv[i], "--nodict"))) {
3181 	    options |= XML_PARSE_NODICT;
3182 	} else if ((!strcmp(argv[i], "-version")) ||
3183 	         (!strcmp(argv[i], "--version"))) {
3184 	    showVersion(argv[0]);
3185 	    version = 1;
3186 	} else if ((!strcmp(argv[i], "-noout")) ||
3187 	         (!strcmp(argv[i], "--noout")))
3188 	    noout++;
3189 #ifdef LIBXML_OUTPUT_ENABLED
3190 	else if ((!strcmp(argv[i], "-o")) ||
3191 	         (!strcmp(argv[i], "-output")) ||
3192 	         (!strcmp(argv[i], "--output"))) {
3193 	    i++;
3194 	    output = argv[i];
3195 	}
3196 #endif /* LIBXML_OUTPUT_ENABLED */
3197 	else if ((!strcmp(argv[i], "-htmlout")) ||
3198 	         (!strcmp(argv[i], "--htmlout")))
3199 	    htmlout++;
3200 	else if ((!strcmp(argv[i], "-nowrap")) ||
3201 	         (!strcmp(argv[i], "--nowrap")))
3202 	    nowrap++;
3203 #ifdef LIBXML_HTML_ENABLED
3204 	else if ((!strcmp(argv[i], "-html")) ||
3205 	         (!strcmp(argv[i], "--html"))) {
3206 	    html++;
3207         }
3208 	else if ((!strcmp(argv[i], "-xmlout")) ||
3209 	         (!strcmp(argv[i], "--xmlout"))) {
3210 	    xmlout++;
3211 	} else if ((!strcmp(argv[i], "-nodefdtd")) ||
3212 	         (!strcmp(argv[i], "--nodefdtd"))) {
3213             nodefdtd++;
3214 	    options |= HTML_PARSE_NODEFDTD;
3215         }
3216 #endif /* LIBXML_HTML_ENABLED */
3217 	else if ((!strcmp(argv[i], "-loaddtd")) ||
3218 	         (!strcmp(argv[i], "--loaddtd"))) {
3219 	    loaddtd++;
3220 	    options |= XML_PARSE_DTDLOAD;
3221 	} else if ((!strcmp(argv[i], "-dtdattr")) ||
3222 	         (!strcmp(argv[i], "--dtdattr"))) {
3223 	    loaddtd++;
3224 	    dtdattrs++;
3225 	    options |= XML_PARSE_DTDATTR;
3226 	}
3227 #ifdef LIBXML_VALID_ENABLED
3228 	else if ((!strcmp(argv[i], "-valid")) ||
3229 	         (!strcmp(argv[i], "--valid"))) {
3230 	    valid++;
3231 	    options |= XML_PARSE_DTDVALID;
3232 	} else if ((!strcmp(argv[i], "-postvalid")) ||
3233 	         (!strcmp(argv[i], "--postvalid"))) {
3234 	    postvalid++;
3235 	    loaddtd++;
3236 	    options |= XML_PARSE_DTDLOAD;
3237 	} else if ((!strcmp(argv[i], "-dtdvalid")) ||
3238 	         (!strcmp(argv[i], "--dtdvalid"))) {
3239 	    i++;
3240 	    dtdvalid = argv[i];
3241 	    loaddtd++;
3242 	    options |= XML_PARSE_DTDLOAD;
3243 	} else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3244 	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
3245 	    i++;
3246 	    dtdvalidfpi = argv[i];
3247 	    loaddtd++;
3248 	    options |= XML_PARSE_DTDLOAD;
3249         }
3250 #endif /* LIBXML_VALID_ENABLED */
3251 	else if ((!strcmp(argv[i], "-dropdtd")) ||
3252 	         (!strcmp(argv[i], "--dropdtd")))
3253 	    dropdtd++;
3254 	else if ((!strcmp(argv[i], "-insert")) ||
3255 	         (!strcmp(argv[i], "--insert")))
3256 	    insert++;
3257 	else if ((!strcmp(argv[i], "-quiet")) ||
3258 	         (!strcmp(argv[i], "--quiet")))
3259 	    quiet++;
3260 	else if ((!strcmp(argv[i], "-timing")) ||
3261 	         (!strcmp(argv[i], "--timing")))
3262 	    timing++;
3263 	else if ((!strcmp(argv[i], "-auto")) ||
3264 	         (!strcmp(argv[i], "--auto")))
3265 	    generate++;
3266 	else if ((!strcmp(argv[i], "-repeat")) ||
3267 	         (!strcmp(argv[i], "--repeat"))) {
3268 	    if (repeat)
3269 	        repeat *= 10;
3270 	    else
3271 	        repeat = 100;
3272 	}
3273 #ifdef LIBXML_PUSH_ENABLED
3274 	else if ((!strcmp(argv[i], "-push")) ||
3275 	         (!strcmp(argv[i], "--push")))
3276 	    push++;
3277 	else if ((!strcmp(argv[i], "-pushsmall")) ||
3278 	         (!strcmp(argv[i], "--pushsmall"))) {
3279 	    push++;
3280             pushsize = 10;
3281         }
3282 #endif /* LIBXML_PUSH_ENABLED */
3283 #ifdef HAVE_MMAP
3284 	else if ((!strcmp(argv[i], "-memory")) ||
3285 	         (!strcmp(argv[i], "--memory")))
3286 	    memory++;
3287 #endif
3288 	else if ((!strcmp(argv[i], "-testIO")) ||
3289 	         (!strcmp(argv[i], "--testIO")))
3290 	    testIO++;
3291 #ifdef LIBXML_XINCLUDE_ENABLED
3292 	else if ((!strcmp(argv[i], "-xinclude")) ||
3293 	         (!strcmp(argv[i], "--xinclude"))) {
3294 	    xinclude++;
3295 	    options |= XML_PARSE_XINCLUDE;
3296 	}
3297 	else if ((!strcmp(argv[i], "-noxincludenode")) ||
3298 	         (!strcmp(argv[i], "--noxincludenode"))) {
3299 	    xinclude++;
3300 	    options |= XML_PARSE_XINCLUDE;
3301 	    options |= XML_PARSE_NOXINCNODE;
3302 	}
3303 	else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
3304 	         (!strcmp(argv[i], "--nofixup-base-uris"))) {
3305 	    xinclude++;
3306 	    options |= XML_PARSE_XINCLUDE;
3307 	    options |= XML_PARSE_NOBASEFIX;
3308 	}
3309 #endif
3310 #ifdef LIBXML_OUTPUT_ENABLED
3311 #ifdef LIBXML_ZLIB_ENABLED
3312 	else if ((!strcmp(argv[i], "-compress")) ||
3313 	         (!strcmp(argv[i], "--compress"))) {
3314 	    compress++;
3315 	    xmlSetCompressMode(9);
3316         }
3317 #endif
3318 #endif /* LIBXML_OUTPUT_ENABLED */
3319 	else if ((!strcmp(argv[i], "-nowarning")) ||
3320 	         (!strcmp(argv[i], "--nowarning"))) {
3321 	    xmlGetWarningsDefaultValue = 0;
3322 	    xmlPedanticParserDefault(0);
3323 	    options |= XML_PARSE_NOWARNING;
3324         }
3325 	else if ((!strcmp(argv[i], "-pedantic")) ||
3326 	         (!strcmp(argv[i], "--pedantic"))) {
3327 	    xmlGetWarningsDefaultValue = 1;
3328 	    xmlPedanticParserDefault(1);
3329 	    options |= XML_PARSE_PEDANTIC;
3330         }
3331 #ifdef LIBXML_DEBUG_ENABLED
3332 	else if ((!strcmp(argv[i], "-debugent")) ||
3333 		 (!strcmp(argv[i], "--debugent"))) {
3334 	    debugent++;
3335 	    xmlParserDebugEntities = 1;
3336 	}
3337 #endif
3338 #ifdef LIBXML_C14N_ENABLED
3339 	else if ((!strcmp(argv[i], "-c14n")) ||
3340 		 (!strcmp(argv[i], "--c14n"))) {
3341 	    canonical++;
3342 	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3343 	}
3344 	else if ((!strcmp(argv[i], "-c14n11")) ||
3345 		 (!strcmp(argv[i], "--c14n11"))) {
3346 	    canonical_11++;
3347 	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3348 	}
3349 	else if ((!strcmp(argv[i], "-exc-c14n")) ||
3350 		 (!strcmp(argv[i], "--exc-c14n"))) {
3351 	    exc_canonical++;
3352 	    options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3353 	}
3354 #endif
3355 #ifdef LIBXML_CATALOG_ENABLED
3356 	else if ((!strcmp(argv[i], "-catalogs")) ||
3357 		 (!strcmp(argv[i], "--catalogs"))) {
3358 	    catalogs++;
3359 	} else if ((!strcmp(argv[i], "-nocatalogs")) ||
3360 		 (!strcmp(argv[i], "--nocatalogs"))) {
3361 	    nocatalogs++;
3362 	}
3363 #endif
3364 	else if ((!strcmp(argv[i], "-encode")) ||
3365 	         (!strcmp(argv[i], "--encode"))) {
3366 	    i++;
3367 	    encoding = argv[i];
3368 	    /*
3369 	     * OK it's for testing purposes
3370 	     */
3371 	    xmlAddEncodingAlias("UTF-8", "DVEnc");
3372         }
3373 	else if ((!strcmp(argv[i], "-noblanks")) ||
3374 	         (!strcmp(argv[i], "--noblanks"))) {
3375 	    noblanks++;
3376 	    xmlKeepBlanksDefault(0);
3377 	    options |= XML_PARSE_NOBLANKS;
3378         }
3379 	else if ((!strcmp(argv[i], "-maxmem")) ||
3380 	         (!strcmp(argv[i], "--maxmem"))) {
3381 	     i++;
3382         }
3383 	else if ((!strcmp(argv[i], "-format")) ||
3384 	         (!strcmp(argv[i], "--format"))) {
3385 	     noblanks++;
3386 #ifdef LIBXML_OUTPUT_ENABLED
3387 	     format = 1;
3388 #endif /* LIBXML_OUTPUT_ENABLED */
3389 	     xmlKeepBlanksDefault(0);
3390 	}
3391 	else if ((!strcmp(argv[i], "-pretty")) ||
3392 	         (!strcmp(argv[i], "--pretty"))) {
3393 	     i++;
3394 #ifdef LIBXML_OUTPUT_ENABLED
3395        if (argv[i] != NULL) {
3396 	         format = atoi(argv[i]);
3397 	         if (format == 1) {
3398 	             noblanks++;
3399 	             xmlKeepBlanksDefault(0);
3400 	         }
3401        }
3402 #endif /* LIBXML_OUTPUT_ENABLED */
3403 	}
3404 #ifdef LIBXML_READER_ENABLED
3405 	else if ((!strcmp(argv[i], "-stream")) ||
3406 	         (!strcmp(argv[i], "--stream"))) {
3407 	     stream++;
3408 	}
3409 	else if ((!strcmp(argv[i], "-walker")) ||
3410 	         (!strcmp(argv[i], "--walker"))) {
3411 	     walker++;
3412              noout++;
3413 #ifdef LIBXML_PATTERN_ENABLED
3414         } else if ((!strcmp(argv[i], "-pattern")) ||
3415                    (!strcmp(argv[i], "--pattern"))) {
3416 	    i++;
3417 	    pattern = argv[i];
3418 #endif
3419 	}
3420 #endif /* LIBXML_READER_ENABLED */
3421 #ifdef LIBXML_SAX1_ENABLED
3422 	else if ((!strcmp(argv[i], "-sax1")) ||
3423 	         (!strcmp(argv[i], "--sax1"))) {
3424 	    sax1++;
3425 	    options |= XML_PARSE_SAX1;
3426 	}
3427 #endif /* LIBXML_SAX1_ENABLED */
3428 	else if ((!strcmp(argv[i], "-sax")) ||
3429 	         (!strcmp(argv[i], "--sax"))) {
3430 	    sax++;
3431 	}
3432 	else if ((!strcmp(argv[i], "-chkregister")) ||
3433 	         (!strcmp(argv[i], "--chkregister"))) {
3434 	    chkregister++;
3435 #ifdef LIBXML_SCHEMAS_ENABLED
3436 	} else if ((!strcmp(argv[i], "-relaxng")) ||
3437 	         (!strcmp(argv[i], "--relaxng"))) {
3438 	    i++;
3439 	    relaxng = argv[i];
3440 	    noent++;
3441 	    options |= XML_PARSE_NOENT;
3442 	} else if ((!strcmp(argv[i], "-schema")) ||
3443 	         (!strcmp(argv[i], "--schema"))) {
3444 	    i++;
3445 	    schema = argv[i];
3446 	    noent++;
3447 #endif
3448 #ifdef LIBXML_SCHEMATRON_ENABLED
3449 	} else if ((!strcmp(argv[i], "-schematron")) ||
3450 	         (!strcmp(argv[i], "--schematron"))) {
3451 	    i++;
3452 	    schematron = argv[i];
3453 	    noent++;
3454 #endif
3455         } else if ((!strcmp(argv[i], "-nonet")) ||
3456                    (!strcmp(argv[i], "--nonet"))) {
3457 	    options |= XML_PARSE_NONET;
3458 	    xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
3459         } else if ((!strcmp(argv[i], "-nocompact")) ||
3460                    (!strcmp(argv[i], "--nocompact"))) {
3461 	    options &= ~XML_PARSE_COMPACT;
3462 	} else if ((!strcmp(argv[i], "-load-trace")) ||
3463 	           (!strcmp(argv[i], "--load-trace"))) {
3464 	    load_trace++;
3465         } else if ((!strcmp(argv[i], "-path")) ||
3466                    (!strcmp(argv[i], "--path"))) {
3467 	    i++;
3468 	    parsePath(BAD_CAST argv[i]);
3469 #ifdef LIBXML_XPATH_ENABLED
3470         } else if ((!strcmp(argv[i], "-xpath")) ||
3471                    (!strcmp(argv[i], "--xpath"))) {
3472 	    i++;
3473 	    noout++;
3474 	    xpathquery = argv[i];
3475 #endif
3476 	} else if ((!strcmp(argv[i], "-oldxml10")) ||
3477 	           (!strcmp(argv[i], "--oldxml10"))) {
3478 	    oldxml10++;
3479 	    options |= XML_PARSE_OLD10;
3480 	} else {
3481 	    fprintf(stderr, "Unknown option %s\n", argv[i]);
3482 	    usage(stderr, argv[0]);
3483 	    return(XMLLINT_ERR_UNCLASS);
3484 	}
3485     }
3486 
3487 #ifdef LIBXML_CATALOG_ENABLED
3488     if (nocatalogs == 0) {
3489 	if (catalogs) {
3490 	    const char *catal;
3491 
3492 	    catal = getenv("SGML_CATALOG_FILES");
3493 	    if (catal != NULL) {
3494 		xmlLoadCatalogs(catal);
3495 	    } else {
3496 		fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
3497 	    }
3498 	}
3499     }
3500 #endif
3501 
3502 #ifdef LIBXML_SAX1_ENABLED
3503     if (sax1)
3504         xmlSAXDefaultVersion(1);
3505     else
3506         xmlSAXDefaultVersion(2);
3507 #endif /* LIBXML_SAX1_ENABLED */
3508 
3509     if (chkregister) {
3510 	xmlRegisterNodeDefault(registerNode);
3511 	xmlDeregisterNodeDefault(deregisterNode);
3512     }
3513 
3514     indent = getenv("XMLLINT_INDENT");
3515     if(indent != NULL) {
3516 	xmlTreeIndentString = indent;
3517     }
3518 
3519 
3520     defaultEntityLoader = xmlGetExternalEntityLoader();
3521     xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
3522 
3523     xmlLineNumbersDefault(1);
3524     if (loaddtd != 0)
3525 	xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
3526     if (dtdattrs)
3527 	xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
3528     if (noent != 0) xmlSubstituteEntitiesDefault(1);
3529 #ifdef LIBXML_VALID_ENABLED
3530     if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
3531 #endif /* LIBXML_VALID_ENABLED */
3532     if ((htmlout) && (!nowrap)) {
3533 	xmlGenericError(xmlGenericErrorContext,
3534          "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
3535 	xmlGenericError(xmlGenericErrorContext,
3536 		"\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
3537 	xmlGenericError(xmlGenericErrorContext,
3538 	 "<html><head><title>%s output</title></head>\n",
3539 		argv[0]);
3540 	xmlGenericError(xmlGenericErrorContext,
3541 	 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
3542 		argv[0]);
3543     }
3544 
3545 #ifdef LIBXML_SCHEMATRON_ENABLED
3546     if ((schematron != NULL) && (sax == 0)
3547 #ifdef LIBXML_READER_ENABLED
3548         && (stream == 0)
3549 #endif /* LIBXML_READER_ENABLED */
3550 	) {
3551 	xmlSchematronParserCtxtPtr ctxt;
3552 
3553         /* forces loading the DTDs */
3554         xmlLoadExtDtdDefaultValue |= 1;
3555 	options |= XML_PARSE_DTDLOAD;
3556 	if (timing) {
3557 	    startTimer();
3558 	}
3559 	ctxt = xmlSchematronNewParserCtxt(schematron);
3560         if (ctxt == NULL) {
3561             progresult = XMLLINT_ERR_MEM;
3562             goto error;
3563         }
3564 #if 0
3565 	xmlSchematronSetParserErrors(ctxt, xmlGenericError, xmlGenericError,
3566                 NULL);
3567 #endif
3568 	wxschematron = xmlSchematronParse(ctxt);
3569 	if (wxschematron == NULL) {
3570 	    xmlGenericError(xmlGenericErrorContext,
3571 		    "Schematron schema %s failed to compile\n", schematron);
3572             progresult = XMLLINT_ERR_SCHEMACOMP;
3573 	    schematron = NULL;
3574 	}
3575 	xmlSchematronFreeParserCtxt(ctxt);
3576 	if (timing) {
3577 	    endTimer("Compiling the schemas");
3578 	}
3579     }
3580 #endif
3581 #ifdef LIBXML_SCHEMAS_ENABLED
3582     if ((relaxng != NULL) && (sax == 0)
3583 #ifdef LIBXML_READER_ENABLED
3584         && (stream == 0)
3585 #endif /* LIBXML_READER_ENABLED */
3586 	) {
3587 	xmlRelaxNGParserCtxtPtr ctxt;
3588 
3589         /* forces loading the DTDs */
3590         xmlLoadExtDtdDefaultValue |= 1;
3591 	options |= XML_PARSE_DTDLOAD;
3592 	if (timing) {
3593 	    startTimer();
3594 	}
3595 	ctxt = xmlRelaxNGNewParserCtxt(relaxng);
3596         if (ctxt == NULL) {
3597             progresult = XMLLINT_ERR_MEM;
3598             goto error;
3599         }
3600 	xmlRelaxNGSetParserErrors(ctxt, xmlGenericError, xmlGenericError,
3601                 NULL);
3602 	relaxngschemas = xmlRelaxNGParse(ctxt);
3603 	if (relaxngschemas == NULL) {
3604 	    xmlGenericError(xmlGenericErrorContext,
3605 		    "Relax-NG schema %s failed to compile\n", relaxng);
3606             progresult = XMLLINT_ERR_SCHEMACOMP;
3607 	    relaxng = NULL;
3608 	}
3609 	xmlRelaxNGFreeParserCtxt(ctxt);
3610 	if (timing) {
3611 	    endTimer("Compiling the schemas");
3612 	}
3613     } else if ((schema != NULL)
3614 #ifdef LIBXML_READER_ENABLED
3615 		&& (stream == 0)
3616 #endif
3617 	) {
3618 	xmlSchemaParserCtxtPtr ctxt;
3619 
3620 	if (timing) {
3621 	    startTimer();
3622 	}
3623 	ctxt = xmlSchemaNewParserCtxt(schema);
3624         if (ctxt == NULL) {
3625             progresult = XMLLINT_ERR_MEM;
3626             goto error;
3627         }
3628 	xmlSchemaSetParserErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
3629 	wxschemas = xmlSchemaParse(ctxt);
3630 	if (wxschemas == NULL) {
3631 	    xmlGenericError(xmlGenericErrorContext,
3632 		    "WXS schema %s failed to compile\n", schema);
3633             progresult = XMLLINT_ERR_SCHEMACOMP;
3634 	    schema = NULL;
3635 	}
3636 	xmlSchemaFreeParserCtxt(ctxt);
3637 	if (timing) {
3638 	    endTimer("Compiling the schemas");
3639 	}
3640     }
3641 #endif /* LIBXML_SCHEMAS_ENABLED */
3642 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3643     if ((pattern != NULL) && (walker == 0)) {
3644         patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
3645 	if (patternc == NULL) {
3646 	    xmlGenericError(xmlGenericErrorContext,
3647 		    "Pattern %s failed to compile\n", pattern);
3648             progresult = XMLLINT_ERR_SCHEMAPAT;
3649 	    pattern = NULL;
3650 	}
3651     }
3652 #endif /* LIBXML_READER_ENABLED && LIBXML_PATTERN_ENABLED */
3653     for (i = 1; i < argc ; i++) {
3654 	if ((!strcmp(argv[i], "-encode")) ||
3655 	         (!strcmp(argv[i], "--encode"))) {
3656 	    i++;
3657 	    continue;
3658         } else if ((!strcmp(argv[i], "-o")) ||
3659                    (!strcmp(argv[i], "-output")) ||
3660                    (!strcmp(argv[i], "--output"))) {
3661             i++;
3662 	    continue;
3663         }
3664 #ifdef LIBXML_VALID_ENABLED
3665 	if ((!strcmp(argv[i], "-dtdvalid")) ||
3666 	         (!strcmp(argv[i], "--dtdvalid"))) {
3667 	    i++;
3668 	    continue;
3669         }
3670 	if ((!strcmp(argv[i], "-path")) ||
3671                    (!strcmp(argv[i], "--path"))) {
3672             i++;
3673 	    continue;
3674         }
3675 	if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3676 	         (!strcmp(argv[i], "--dtdvalidfpi"))) {
3677 	    i++;
3678 	    continue;
3679         }
3680 #endif /* LIBXML_VALID_ENABLED */
3681 	if ((!strcmp(argv[i], "-relaxng")) ||
3682 	         (!strcmp(argv[i], "--relaxng"))) {
3683 	    i++;
3684 	    continue;
3685         }
3686 	if ((!strcmp(argv[i], "-maxmem")) ||
3687 	         (!strcmp(argv[i], "--maxmem"))) {
3688 	    i++;
3689 	    continue;
3690         }
3691 	if ((!strcmp(argv[i], "-pretty")) ||
3692 	         (!strcmp(argv[i], "--pretty"))) {
3693 	    i++;
3694 	    continue;
3695         }
3696 	if ((!strcmp(argv[i], "-schema")) ||
3697 	         (!strcmp(argv[i], "--schema"))) {
3698 	    i++;
3699 	    continue;
3700         }
3701 	if ((!strcmp(argv[i], "-schematron")) ||
3702 	         (!strcmp(argv[i], "--schematron"))) {
3703 	    i++;
3704 	    continue;
3705         }
3706 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3707         if ((!strcmp(argv[i], "-pattern")) ||
3708 	    (!strcmp(argv[i], "--pattern"))) {
3709 	    i++;
3710 	    continue;
3711 	}
3712 #endif
3713 #ifdef LIBXML_XPATH_ENABLED
3714         if ((!strcmp(argv[i], "-xpath")) ||
3715 	    (!strcmp(argv[i], "--xpath"))) {
3716 	    i++;
3717 	    continue;
3718 	}
3719 #endif
3720 	if ((timing) && (repeat))
3721 	    startTimer();
3722 	/* Remember file names.  "-" means stdin.  <sven@zen.org> */
3723 	if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
3724 	    if (repeat) {
3725 		xmlParserCtxtPtr ctxt = NULL;
3726 
3727 		for (acount = 0;acount < repeat;acount++) {
3728 #ifdef LIBXML_READER_ENABLED
3729 		    if (stream != 0) {
3730 			streamFile(argv[i]);
3731 		    } else {
3732 #endif /* LIBXML_READER_ENABLED */
3733                         if (sax) {
3734 			    testSAX(argv[i]);
3735 			} else {
3736 			    if (ctxt == NULL)
3737 				ctxt = xmlNewParserCtxt();
3738 			    parseAndPrintFile(argv[i], ctxt);
3739 			}
3740 #ifdef LIBXML_READER_ENABLED
3741 		    }
3742 #endif /* LIBXML_READER_ENABLED */
3743 		}
3744 		if (ctxt != NULL)
3745 		    xmlFreeParserCtxt(ctxt);
3746 	    } else {
3747 		nbregister = 0;
3748 
3749 #ifdef LIBXML_READER_ENABLED
3750 		if (stream != 0)
3751 		    streamFile(argv[i]);
3752 		else
3753 #endif /* LIBXML_READER_ENABLED */
3754                 if (sax) {
3755 		    testSAX(argv[i]);
3756 		} else {
3757 		    parseAndPrintFile(argv[i], NULL);
3758 		}
3759 
3760                 if ((chkregister) && (nbregister != 0)) {
3761 		    fprintf(stderr, "Registration count off: %d\n", nbregister);
3762 		    progresult = XMLLINT_ERR_RDREGIS;
3763 		}
3764 	    }
3765 	    files ++;
3766 	    if ((timing) && (repeat)) {
3767 		endTimer("%d iterations", repeat);
3768 	    }
3769 	}
3770     }
3771     if (generate)
3772 	parseAndPrintFile(NULL, NULL);
3773     if ((htmlout) && (!nowrap)) {
3774 	xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
3775     }
3776     if ((files == 0) && (!generate) && (version == 0)) {
3777 	usage(stderr, argv[0]);
3778         progresult = XMLLINT_ERR_UNCLASS;
3779     }
3780 #ifdef LIBXML_SCHEMATRON_ENABLED
3781     if (wxschematron != NULL)
3782 	xmlSchematronFree(wxschematron);
3783 #endif
3784 #ifdef LIBXML_SCHEMAS_ENABLED
3785     if (relaxngschemas != NULL)
3786 	xmlRelaxNGFree(relaxngschemas);
3787     if (wxschemas != NULL)
3788 	xmlSchemaFree(wxschemas);
3789 #endif
3790 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3791     if (patternc != NULL)
3792         xmlFreePattern(patternc);
3793 #endif
3794 
3795     /* Avoid unused label warning if features are disabled. */
3796     goto error;
3797 
3798 error:
3799     xmlCleanupParser();
3800     xmlMemoryDump();
3801 
3802     return(progresult);
3803 }
3804 
3805