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