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