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