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