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