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