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