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