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