BRANCH release for 2.5.x critical patches
[baserock-morphs: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
14 #include <assert.h>
15
16 #if defined (_WIN32) && !defined(__CYGWIN__)
17 #ifdef _MSC_VER
18 #include <winsock2.h>
19 #pragma comment(lib, "ws2_32.lib")
20 #define gettimeofday(p1,p2)
21 #include <time.h>
22 #else /* _MSC_VER */
23 #include <sys/time.h>
24 #endif /* _MSC_VER */
25 #else /* _WIN32 */
26 #ifdef HAVE_SYS_TIME_H
27 #include <sys/time.h>
28 #endif
29 #ifdef HAVE_TIME_H
30 #include <time.h>
31 #endif
32 #endif /* _WIN32 */
33
34 #ifdef __MINGW32__
35 #define _WINSOCKAPI_
36 #include <wsockcompat.h>
37 #include <winsock2.h>
38 #undef SOCKLEN_T
39 #define SOCKLEN_T unsigned int
40 #endif
41
42
43 #ifdef HAVE_SYS_TIMEB_H
44 #include <sys/timeb.h>
45 #endif
46
47 #ifdef HAVE_SYS_TYPES_H
48 #include <sys/types.h>
49 #endif
50 #ifdef HAVE_SYS_STAT_H
51 #include <sys/stat.h>
52 #endif
53 #ifdef HAVE_FCNTL_H
54 #include <fcntl.h>
55 #endif
56 #ifdef HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59 #ifdef HAVE_SYS_MMAN_H
60 #include <sys/mman.h>
61 /* seems needed for Solaris */
62 #ifndef MAP_FAILED
63 #define MAP_FAILED ((void *) -1)
64 #endif
65 #endif
66 #ifdef HAVE_STDLIB_H
67 #include <stdlib.h>
68 #endif
69 #ifdef HAVE_LIBREADLINE
70 #include <readline/readline.h>
71 #ifdef HAVE_LIBHISTORY
72 #include <readline/history.h>
73 #endif
74 #endif
75
76 #include <libxml/xmlmemory.h>
77 #include <libxml/parser.h>
78 #include <libxml/parserInternals.h>
79 #include <libxml/HTMLparser.h>
80 #include <libxml/HTMLtree.h>
81 #include <libxml/tree.h>
82 #include <libxml/xpath.h>
83 #include <libxml/debugXML.h>
84 #include <libxml/xmlerror.h>
85 #ifdef LIBXML_XINCLUDE_ENABLED
86 #include <libxml/xinclude.h>
87 #endif
88 #ifdef LIBXML_CATALOG_ENABLED
89 #include <libxml/catalog.h>
90 #endif
91 #ifdef LIBXML_DOCB_ENABLED
92 #include <libxml/DOCBparser.h>
93 #endif
94 #include <libxml/globals.h>
95 #include <libxml/xmlreader.h>
96 #ifdef LIBXML_SCHEMAS_ENABLED
97 #include <libxml/relaxng.h>
98 #include <libxml/xmlschemas.h>
99 #endif
100
101 #ifndef XML_XML_DEFAULT_CATALOG
102 #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
103 #endif
104
105 #ifdef LIBXML_DEBUG_ENABLED
106 static int shell = 0;
107 static int debugent = 0;
108 #endif
109 static int debug = 0;
110 static int copy = 0;
111 static int recovery = 0;
112 static int noent = 0;
113 static int noout = 0;
114 static int nowrap = 0;
115 static int valid = 0;
116 static int postvalid = 0;
117 static char * dtdvalid = NULL;
118 #ifdef LIBXML_SCHEMAS_ENABLED
119 static char * relaxng = NULL;
120 static xmlRelaxNGPtr relaxngschemas = NULL;
121 static char * schema = NULL;
122 static xmlSchemaPtr wxschemas = NULL;
123 #endif
124 static int repeat = 0;
125 static int insert = 0;
126 static int compress = 0;
127 #ifdef LIBXML_DOCB_ENABLED
128 static int sgml = 0;
129 #endif
130 static int html = 0;
131 static int htmlout = 0;
132 static int push = 0;
133 #ifdef HAVE_SYS_MMAN_H
134 static int memory = 0;
135 #endif
136 static int noblanks = 0;
137 static int format = 0;
138 static int testIO = 0;
139 static char *encoding = NULL;
140 #ifdef LIBXML_XINCLUDE_ENABLED
141 static int xinclude = 0;
142 #endif
143 static int dtdattrs = 0;
144 static int loaddtd = 0;
145 static int progresult = 0;
146 static int timing = 0;
147 static int generate = 0;
148 static int dropdtd = 0;
149 #ifdef LIBXML_CATALOG_ENABLED
150 static int catalogs = 0;
151 static int nocatalogs = 0;
152 #endif
153 static int stream = 0;
154 static int chkregister = 0;
155 static const char *output = NULL;
156
157 /*
158  * Internal timing routines to remove the necessity to have unix-specific
159  * function calls
160  */
161
162 #ifndef HAVE_GETTIMEOFDAY 
163 #ifdef HAVE_SYS_TIMEB_H
164 #ifdef HAVE_SYS_TIME_H
165 #ifdef HAVE_FTIME
166
167 static int
168 my_gettimeofday(struct timeval *tvp, void *tzp)
169 {
170         struct timeb timebuffer;
171
172         ftime(&timebuffer);
173         if (tvp) {
174                 tvp->tv_sec = timebuffer.time;
175                 tvp->tv_usec = timebuffer.millitm * 1000L;
176         }
177         return (0);
178 }
179 #define HAVE_GETTIMEOFDAY 1
180 #define gettimeofday my_gettimeofday
181
182 #endif /* HAVE_FTIME */
183 #endif /* HAVE_SYS_TIME_H */
184 #endif /* HAVE_SYS_TIMEB_H */
185 #endif /* !HAVE_GETTIMEOFDAY */
186
187 #if defined(HAVE_GETTIMEOFDAY)
188 static struct timeval begin, end;
189
190 /*
191  * startTimer: call where you want to start timing
192  */
193 static void
194 startTimer(void)
195 {
196     gettimeofday(&begin, NULL);
197 }
198
199 /*
200  * endTimer: call where you want to stop timing and to print out a
201  *           message about the timing performed; format is a printf
202  *           type argument
203  */
204 static void
205 endTimer(const char *fmt, ...)
206 {
207     long msec;
208     va_list ap;
209
210     gettimeofday(&end, NULL);
211     msec = end.tv_sec - begin.tv_sec;
212     msec *= 1000;
213     msec += (end.tv_usec - begin.tv_usec) / 1000;
214
215 #ifndef HAVE_STDARG_H
216 #error "endTimer required stdarg functions"
217 #endif
218     va_start(ap, fmt);
219     vfprintf(stderr, fmt, ap);
220     va_end(ap);
221
222     fprintf(stderr, " took %ld ms\n", msec);
223 }
224 #elif defined(HAVE_TIME_H)
225 /*
226  * No gettimeofday function, so we have to make do with calling clock.
227  * This is obviously less accurate, but there's little we can do about
228  * that.
229  */
230 #ifndef CLOCKS_PER_SEC
231 #define CLOCKS_PER_SEC 100
232 #endif
233
234 static clock_t begin, end;
235 static void
236 startTimer(void)
237 {
238     begin = clock();
239 }
240 static void
241 endTimer(const char *fmt, ...)
242 {
243     long msec;
244     va_list ap;
245
246     end = clock();
247     msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
248
249 #ifndef HAVE_STDARG_H
250 #error "endTimer required stdarg functions"
251 #endif
252     va_start(ap, fmt);
253     vfprintf(stderr, fmt, ap);
254     va_end(ap);
255     fprintf(stderr, " took %ld ms\n", msec);
256 }
257 #else
258
259 /*
260  * We don't have a gettimeofday or time.h, so we just don't do timing
261  */
262 static void
263 startTimer(void)
264 {
265     /*
266      * Do nothing
267      */
268 }
269 static void
270 endTimer(char *format, ...)
271 {
272     /*
273      * We cannot do anything because we don't have a timing function
274      */
275 #ifdef HAVE_STDARG_H
276     va_start(ap, format);
277     vfprintf(stderr, format, ap);
278     va_end(ap);
279     fprintf(stderr, " was not timed\n", msec);
280 #else
281     /* We don't have gettimeofday, time or stdarg.h, what crazy world is
282      * this ?!
283      */
284 #endif
285 }
286 #endif
287 /************************************************************************
288  *                                                                      *
289  *                      HTML ouput                                      *
290  *                                                                      *
291  ************************************************************************/
292 char buffer[50000];
293
294 static void
295 xmlHTMLEncodeSend(void) {
296     char *result;
297
298     result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
299     if (result) {
300         xmlGenericError(xmlGenericErrorContext, "%s", result);
301         xmlFree(result);
302     }
303     buffer[0] = 0;
304 }
305
306 /**
307  * xmlHTMLPrintFileInfo:
308  * @input:  an xmlParserInputPtr input
309  * 
310  * Displays the associated file and line informations for the current input
311  */
312
313 static void
314 xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
315     int len;
316     xmlGenericError(xmlGenericErrorContext, "<p>");
317
318     len = strlen(buffer);
319     if (input != NULL) {
320         if (input->filename) {
321             snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
322                     input->line);
323         } else {
324             snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
325         }
326     }
327     xmlHTMLEncodeSend();
328 }
329
330 /**
331  * xmlHTMLPrintFileContext:
332  * @input:  an xmlParserInputPtr input
333  * 
334  * Displays current context within the input content for error tracking
335  */
336
337 static void
338 xmlHTMLPrintFileContext(xmlParserInputPtr input) {
339     const xmlChar *cur, *base;
340     int len;
341     int n;
342
343     if (input == NULL) return;
344     xmlGenericError(xmlGenericErrorContext, "<pre>\n");
345     cur = input->cur;
346     base = input->base;
347     while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
348         cur--;
349     }
350     n = 0;
351     while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
352         cur--;
353     if ((*cur == '\n') || (*cur == '\r')) cur++;
354     base = cur;
355     n = 0;
356     while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
357         len = strlen(buffer);
358         snprintf(&buffer[len], sizeof(buffer) - len, "%c", 
359                     (unsigned char) *cur++);
360         n++;
361     }
362     len = strlen(buffer);
363     snprintf(&buffer[len], sizeof(buffer) - len, "\n");
364     cur = input->cur;
365     while ((*cur == '\n') || (*cur == '\r'))
366         cur--;
367     n = 0;
368     while ((cur != base) && (n++ < 80)) {
369         len = strlen(buffer);
370         snprintf(&buffer[len], sizeof(buffer) - len, " ");
371         base++;
372     }
373     len = strlen(buffer);
374     snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
375     xmlHTMLEncodeSend();
376     xmlGenericError(xmlGenericErrorContext, "</pre>");
377 }
378
379 /**
380  * xmlHTMLError:
381  * @ctx:  an XML parser context
382  * @msg:  the message to display/transmit
383  * @...:  extra parameters for the message display
384  * 
385  * Display and format an error messages, gives file, line, position and
386  * extra parameters.
387  */
388 static void
389 xmlHTMLError(void *ctx, const char *msg, ...)
390 {
391     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
392     xmlParserInputPtr input;
393     va_list args;
394     int len;
395
396     buffer[0] = 0;
397     input = ctxt->input;
398     if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
399         input = ctxt->inputTab[ctxt->inputNr - 2];
400     }
401         
402     xmlHTMLPrintFileInfo(input);
403
404     xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
405     va_start(args, msg);
406     len = strlen(buffer);
407     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
408     va_end(args);
409     xmlHTMLEncodeSend();
410     xmlGenericError(xmlGenericErrorContext, "</p>\n");
411
412     xmlHTMLPrintFileContext(input);
413     xmlHTMLEncodeSend();
414 }
415
416 /**
417  * xmlHTMLWarning:
418  * @ctx:  an XML parser context
419  * @msg:  the message to display/transmit
420  * @...:  extra parameters for the message display
421  * 
422  * Display and format a warning messages, gives file, line, position and
423  * extra parameters.
424  */
425 static void
426 xmlHTMLWarning(void *ctx, const char *msg, ...)
427 {
428     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
429     xmlParserInputPtr input;
430     va_list args;
431     int len;
432
433     buffer[0] = 0;
434     input = ctxt->input;
435     if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
436         input = ctxt->inputTab[ctxt->inputNr - 2];
437     }
438         
439
440     xmlHTMLPrintFileInfo(input);
441         
442     xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
443     va_start(args, msg);
444     len = strlen(buffer);    
445     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
446     va_end(args);
447     xmlHTMLEncodeSend();
448     xmlGenericError(xmlGenericErrorContext, "</p>\n");
449
450     xmlHTMLPrintFileContext(input);
451     xmlHTMLEncodeSend();
452 }
453
454 /**
455  * xmlHTMLValidityError:
456  * @ctx:  an XML parser context
457  * @msg:  the message to display/transmit
458  * @...:  extra parameters for the message display
459  * 
460  * Display and format an validity error messages, gives file,
461  * line, position and extra parameters.
462  */
463 static void
464 xmlHTMLValidityError(void *ctx, const char *msg, ...)
465 {
466     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
467     xmlParserInputPtr input;
468     va_list args;
469     int len;
470
471     buffer[0] = 0;
472     input = ctxt->input;
473     if ((input->filename == NULL) && (ctxt->inputNr > 1))
474         input = ctxt->inputTab[ctxt->inputNr - 2];
475         
476     xmlHTMLPrintFileInfo(input);
477
478     xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
479     len = strlen(buffer);
480     va_start(args, msg);
481     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
482     va_end(args);
483     xmlHTMLEncodeSend();
484     xmlGenericError(xmlGenericErrorContext, "</p>\n");
485
486     xmlHTMLPrintFileContext(input);
487     xmlHTMLEncodeSend();
488 }
489
490 /**
491  * xmlHTMLValidityWarning:
492  * @ctx:  an XML parser context
493  * @msg:  the message to display/transmit
494  * @...:  extra parameters for the message display
495  * 
496  * Display and format a validity warning messages, gives file, line,
497  * position and extra parameters.
498  */
499 static void
500 xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
501 {
502     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
503     xmlParserInputPtr input;
504     va_list args;
505     int len;
506
507     buffer[0] = 0;
508     input = ctxt->input;
509     if ((input->filename == NULL) && (ctxt->inputNr > 1))
510         input = ctxt->inputTab[ctxt->inputNr - 2];
511
512     xmlHTMLPrintFileInfo(input);
513         
514     xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
515     va_start(args, msg);
516     len = strlen(buffer); 
517     vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
518     va_end(args);
519     xmlHTMLEncodeSend();
520     xmlGenericError(xmlGenericErrorContext, "</p>\n");
521
522     xmlHTMLPrintFileContext(input);
523     xmlHTMLEncodeSend();
524 }
525
526 /************************************************************************
527  *                                                                      *
528  *                      Shell Interface                                 *
529  *                                                                      *
530  ************************************************************************/
531 #ifdef LIBXML_DEBUG_ENABLED
532 /**
533  * xmlShellReadline:
534  * @prompt:  the prompt value
535  *
536  * Read a string
537  * 
538  * Returns a pointer to it or NULL on EOF the caller is expected to
539  *     free the returned string.
540  */
541 static char *
542 xmlShellReadline(char *prompt) {
543 #ifdef HAVE_LIBREADLINE
544     char *line_read;
545
546     /* Get a line from the user. */
547     line_read = readline (prompt);
548
549     /* If the line has any text in it, save it on the history. */
550     if (line_read && *line_read)
551         add_history (line_read);
552
553     return (line_read);
554 #else
555     char line_read[501];
556     char *ret;
557     int len;
558
559     if (prompt != NULL)
560         fprintf(stdout, "%s", prompt);
561     if (!fgets(line_read, 500, stdin))
562         return(NULL);
563     line_read[500] = 0;
564     len = strlen(line_read);
565     ret = (char *) malloc(len + 1);
566     if (ret != NULL) {
567         memcpy (ret, line_read, len + 1);
568     }
569     return(ret);
570 #endif
571 }
572 #endif /* LIBXML_DEBUG_ENABLED */
573
574 /************************************************************************
575  *                                                                      *
576  *                      I/O Interfaces                                  *
577  *                                                                      *
578  ************************************************************************/
579
580 static int myRead(FILE *f, char * buf, int len) {
581     return(fread(buf, 1, len, f));
582 }
583 static void myClose(FILE *f) {
584   if (f != stdin) {
585     fclose(f);
586   }
587 }
588
589 /************************************************************************
590  *                                                                      *
591  *                      Stream Test processing                          *
592  *                                                                      *
593  ************************************************************************/
594 static void processNode(xmlTextReaderPtr reader) {
595     xmlChar *name, *value;
596
597     name = xmlTextReaderName(reader);
598     if (name == NULL)
599         name = xmlStrdup(BAD_CAST "--");
600
601     value = xmlTextReaderValue(reader);
602
603     printf("%d %d %s %d %d", 
604             xmlTextReaderDepth(reader),
605             xmlTextReaderNodeType(reader),
606             name,
607             xmlTextReaderIsEmptyElement(reader),
608             xmlTextReaderHasValue(reader));
609     xmlFree(name);
610     if (value == NULL)
611         printf("\n");
612     else {
613         printf(" %s\n", value);
614         xmlFree(value);
615     }
616 }
617
618 static void streamFile(char *filename) {
619     xmlTextReaderPtr reader;
620     int ret;
621
622     reader = xmlNewTextReaderFilename(filename);
623     if (reader != NULL) {
624         if (valid)
625             xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
626         else
627             xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
628 #ifdef LIBXML_SCHEMAS_ENABLED
629         if (relaxng != NULL) {
630             if (timing) {
631                 startTimer();
632             }
633             ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
634             if (ret < 0) {
635                 xmlGenericError(xmlGenericErrorContext,
636                         "Relax-NG schema %s failed to compile\n", relaxng);
637                 relaxng = NULL;
638             }
639             if (timing) {
640                 endTimer("Compiling the schemas");
641             }
642         }
643 #endif
644
645         /*
646          * Process all nodes in sequence
647          */
648         if (timing) {
649             startTimer();
650         }
651         ret = xmlTextReaderRead(reader);
652         while (ret == 1) {
653             if (debug)
654                 processNode(reader);
655             ret = xmlTextReaderRead(reader);
656         }
657         if (timing) {
658 #ifdef LIBXML_SCHEMAS_ENABLED
659             if ((valid) || (relaxng != NULL))
660 #else
661             if (valid)
662 #endif
663                 endTimer("Parsing and validating");
664             else
665                 endTimer("Parsing");
666         }
667
668         if (valid) {
669             if (xmlTextReaderIsValid(reader) != 1) {
670                 xmlGenericError(xmlGenericErrorContext,
671                         "Document %s does not validate\n", filename);
672                 progresult = 3;
673             }
674         }
675 #ifdef LIBXML_SCHEMAS_ENABLED
676         if (relaxng != NULL) {
677             if (xmlTextReaderIsValid(reader) != 1) {
678                 printf("%s fails to validate\n", filename);
679                 progresult = 3;
680             } else {
681                 printf("%s validates\n", filename);
682             }
683         }
684 #endif
685         /*
686          * Done, cleanup and status
687          */
688         xmlFreeTextReader(reader);
689         if (ret != 0) {
690             printf("%s : failed to parse\n", filename);
691             progresult = 1;
692         }
693     } else {
694         fprintf(stderr, "Unable to open %s\n", filename);
695         progresult = 1;
696     }
697 }
698
699 /************************************************************************
700  *                                                                      *
701  *                      Tree Test processing                            *
702  *                                                                      *
703  ************************************************************************/
704 static void parseAndPrintFile(char *filename) {
705     xmlDocPtr doc = NULL, tmp;
706
707     if ((timing) && (!repeat))
708         startTimer();
709     
710
711     if (filename == NULL) {
712         if (generate) {
713             xmlNodePtr n;
714
715             doc = xmlNewDoc(BAD_CAST "1.0");
716             n = xmlNewNode(NULL, BAD_CAST "info");
717             xmlNodeSetContent(n, BAD_CAST "abc");
718             xmlDocSetRootElement(doc, n);
719         }
720     }
721 #ifdef LIBXML_DOCB_ENABLED
722     /*
723      * build an SGML tree from a string;
724      */
725     else if ((sgml) && (push)) {
726         FILE *f;
727
728         f = fopen(filename, "r");
729         if (f != NULL) {
730             int res, size = 3;
731             char chars[4096];
732             docbParserCtxtPtr ctxt;
733
734             /* if (repeat) */
735                 size = 4096;
736             res = fread(chars, 1, 4, f);
737             if (res > 0) {
738                 ctxt = docbCreatePushParserCtxt(NULL, NULL,
739                             chars, res, filename, XML_CHAR_ENCODING_NONE); 
740                 while ((res = fread(chars, 1, size, f)) > 0) {
741                     docbParseChunk(ctxt, chars, res, 0);
742                 }
743                 docbParseChunk(ctxt, chars, 0, 1);
744                 doc = ctxt->myDoc;
745                 docbFreeParserCtxt(ctxt);
746             }
747             fclose(f);
748         }
749     } else if (sgml) {  
750         doc = docbParseFile(filename, NULL);
751     }
752 #endif
753 #ifdef LIBXML_HTML_ENABLED
754     else if ((html) && (push)) {
755         FILE *f;
756
757         f = fopen(filename, "r");
758         if (f != NULL) {
759             int res, size = 3;
760             char chars[4096];
761             htmlParserCtxtPtr ctxt;
762
763             /* if (repeat) */
764                 size = 4096;
765             res = fread(chars, 1, 4, f);
766             if (res > 0) {
767                 ctxt = htmlCreatePushParserCtxt(NULL, NULL,
768                             chars, res, filename, 0);
769                 while ((res = fread(chars, 1, size, f)) > 0) {
770                     htmlParseChunk(ctxt, chars, res, 0);
771                 }
772                 htmlParseChunk(ctxt, chars, 0, 1);
773                 doc = ctxt->myDoc;
774                 htmlFreeParserCtxt(ctxt);
775             }
776             fclose(f);
777         }
778     }
779     else if (html) {
780         doc = htmlParseFile(filename, NULL);
781     }
782 #endif /* LIBXML_HTML_ENABLED */
783     else {
784         /*
785          * build an XML tree from a string;
786          */
787         if (push) {
788             FILE *f;
789
790             /* '-' Usually means stdin -<sven@zen.org> */
791             if ((filename[0] == '-') && (filename[1] == 0)) {
792               f = stdin;
793             } else {
794               f = fopen(filename, "r");
795             }
796             if (f != NULL) {
797                 int ret;
798                 int res, size = 1024;
799                 char chars[1024];
800                 xmlParserCtxtPtr ctxt;
801
802                 /* if (repeat) size = 1024; */
803                 res = fread(chars, 1, 4, f);
804                 if (res > 0) {
805                     ctxt = xmlCreatePushParserCtxt(NULL, NULL,
806                                 chars, res, filename);
807                     while ((res = fread(chars, 1, size, f)) > 0) {
808                         xmlParseChunk(ctxt, chars, res, 0);
809                     }
810                     xmlParseChunk(ctxt, chars, 0, 1);
811                     doc = ctxt->myDoc;
812                     ret = ctxt->wellFormed;
813                     xmlFreeParserCtxt(ctxt);
814                     if (!ret) {
815                         xmlFreeDoc(doc);
816                         doc = NULL;
817                     }
818                 }
819             }
820         } else if (testIO) {
821             int ret;
822             FILE *f;
823
824             /* '-' Usually means stdin -<sven@zen.org> */
825             if ((filename[0] == '-') && (filename[1] == 0)) {
826               f = stdin;
827             } else {
828               f = fopen(filename, "r");
829             }
830             if (f != NULL) {
831                 xmlParserCtxtPtr ctxt;
832
833                 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
834                             (xmlInputReadCallback) myRead,
835                             (xmlInputCloseCallback) myClose,
836                             f, XML_CHAR_ENCODING_NONE);
837                 xmlParseDocument(ctxt);
838
839                 ret = ctxt->wellFormed;
840                 doc = ctxt->myDoc;
841                 xmlFreeParserCtxt(ctxt);
842                 if (!ret) {
843                     xmlFreeDoc(doc);
844                     doc = NULL;
845                 }
846             }
847         } else if (recovery) {
848             doc = xmlRecoverFile(filename);
849         } else if (htmlout) {
850             int ret;
851             xmlParserCtxtPtr ctxt;
852             xmlSAXHandler silent, *old;
853
854             ctxt = xmlCreateFileParserCtxt(filename);
855
856             if (ctxt == NULL) {       
857               /* If xmlCreateFileParserCtxt() return NULL something
858                  strange happened so we don't want to do anything.  Do
859                  we want to print an error message here?
860                  <sven@zen.org> */
861               doc = NULL;
862             } else {
863               memcpy(&silent, ctxt->sax, sizeof(silent));
864               old = ctxt->sax;
865               silent.error = xmlHTMLError;
866               if (xmlGetWarningsDefaultValue)
867                 silent.warning = xmlHTMLWarning;
868               else 
869                 silent.warning = NULL;
870               silent.fatalError = xmlHTMLError;
871               ctxt->sax = &silent;
872               ctxt->vctxt.error = xmlHTMLValidityError;
873               if (xmlGetWarningsDefaultValue)
874                 ctxt->vctxt.warning = xmlHTMLValidityWarning;
875               else 
876                 ctxt->vctxt.warning = NULL;
877
878               xmlParseDocument(ctxt);
879
880               ret = ctxt->wellFormed;
881               doc = ctxt->myDoc;
882               ctxt->sax = old;
883               xmlFreeParserCtxt(ctxt);
884               if (!ret) {
885                 xmlFreeDoc(doc);
886                 doc = NULL;
887               }
888             }
889 #ifdef HAVE_SYS_MMAN_H
890         } else if (memory) {
891             int fd;
892             struct stat info;
893             const char *base;
894             if (stat(filename, &info) < 0) 
895                 return;
896             if ((fd = open(filename, O_RDONLY)) < 0)
897                 return;
898             base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
899             if (base == (void *) MAP_FAILED)
900                 return;
901
902             doc = xmlParseMemory((char *) base, info.st_size);
903             munmap((char *) base, info.st_size);
904 #endif
905         } else if (valid) {
906             int ret;
907             xmlParserCtxtPtr ctxt;
908
909             ctxt = xmlCreateFileParserCtxt(filename);
910
911             if (ctxt == NULL) {       
912               doc = NULL;
913             } else {
914               xmlParseDocument(ctxt);
915               if (ctxt->valid == 0)
916                   progresult = 4;
917               ret = ctxt->wellFormed;
918               doc = ctxt->myDoc;
919               xmlFreeParserCtxt(ctxt);
920               if (!ret) {
921                 xmlFreeDoc(doc);
922                 doc = NULL;
923               }
924             }
925         } else {
926             doc = xmlParseFile(filename);
927         }
928     }
929
930     /*
931      * If we don't have a document we might as well give up.  Do we
932      * want an error message here?  <sven@zen.org> */
933     if (doc == NULL) {
934         progresult = 1;
935         return;
936     }
937
938     if ((timing) && (!repeat)) {
939         endTimer("Parsing");
940     }
941
942     /*
943      * Remove DOCTYPE nodes
944      */
945     if (dropdtd) {
946         xmlDtdPtr dtd;
947
948         dtd = xmlGetIntSubset(doc);
949         if (dtd != NULL) {
950             xmlUnlinkNode((xmlNodePtr)dtd);
951             xmlFreeDtd(dtd);
952         }
953     }
954
955 #ifdef LIBXML_XINCLUDE_ENABLED
956     if (xinclude) {
957         if ((timing) && (!repeat)) {
958             startTimer();
959         }
960         xmlXIncludeProcess(doc);
961         if ((timing) && (!repeat)) {
962             endTimer("Xinclude processing");
963         }
964     }
965 #endif
966
967 #ifdef LIBXML_DEBUG_ENABLED
968     /*
969      * shell interaction
970      */
971     if (shell)  
972         xmlShell(doc, filename, xmlShellReadline, stdout);
973 #endif
974
975     /*
976      * test intermediate copy if needed.
977      */
978     if (copy) {
979         tmp = doc;
980         doc = xmlCopyDoc(doc, 1);
981         xmlFreeDoc(tmp);
982     }
983
984     if ((insert) && (!html)) {
985         const xmlChar* list[256];
986         int nb, i;
987         xmlNodePtr node;
988
989         if (doc->children != NULL) {
990             node = doc->children;
991             while ((node != NULL) && (node->last == NULL)) node = node->next;
992             if (node != NULL) {
993                 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
994                 if (nb < 0) {
995                     printf("could not get valid list of elements\n");
996                 } else if (nb == 0) {
997                     printf("No element can be inserted under root\n");
998                 } else {
999                     printf("%d element types can be inserted under root:\n",
1000                            nb);
1001                     for (i = 0;i < nb;i++) {
1002                          printf("%s\n", (char *) list[i]);
1003                     }
1004                 }
1005             }
1006         }    
1007     }else if (noout == 0) {
1008         /*
1009          * print it.
1010          */
1011 #ifdef LIBXML_DEBUG_ENABLED
1012         if (!debug) {
1013 #endif
1014             if ((timing) && (!repeat)) {
1015                 startTimer();
1016             }
1017 #ifdef HAVE_SYS_MMAN_H
1018             if (memory) {
1019                 xmlChar *result;
1020                 int len;
1021
1022                 if (encoding != NULL) {
1023                     if ( format ) {
1024                         xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
1025                     } else { 
1026                         xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
1027                     }
1028                 } else {
1029                     if (format)
1030                         xmlDocDumpFormatMemory(doc, &result, &len, 1);
1031                     else
1032                         xmlDocDumpMemory(doc, &result, &len);
1033                 }
1034                 if (result == NULL) {
1035                     fprintf(stderr, "Failed to save\n");
1036                 } else {
1037                     write(1, result, len);
1038                     xmlFree(result);
1039                 }
1040             } else
1041 #endif /* HAVE_SYS_MMAN_H */
1042             if (compress) {
1043                 xmlSaveFile(output ? output : "-", doc);
1044             }
1045             else if (encoding != NULL) {
1046                 if ( format ) {
1047                     xmlSaveFormatFileEnc(output ? output : "-", doc, encoding, 1);
1048                 }
1049                 else {
1050                     xmlSaveFileEnc(output ? output : "-", doc, encoding);
1051                 }
1052             }
1053             else if (format) {
1054                 xmlSaveFormatFile(output ? output : "-", doc, 1);
1055             }
1056             else {
1057                 FILE *out;
1058                 if (output == NULL)
1059                     out = stdout;
1060                 else {
1061                     out = fopen(output,"wb");
1062                 }
1063                 xmlDocDump(out, doc);
1064
1065                 if (output)
1066                     fclose(out);
1067             }
1068             if ((timing) && (!repeat)) {
1069                 endTimer("Saving");
1070             }
1071 #ifdef LIBXML_DEBUG_ENABLED
1072         } else {
1073             FILE *out;
1074             if (output == NULL)
1075                 out = stdout;
1076             else {
1077                 out = fopen(output,"wb");
1078             }
1079             xmlDebugDumpDocument(out, doc);
1080
1081             if (output)
1082                 fclose(out);
1083         }
1084 #endif
1085     }
1086
1087     /*
1088      * A posteriori validation test
1089      */
1090     if (dtdvalid != NULL) {
1091         xmlDtdPtr dtd;
1092
1093         if ((timing) && (!repeat)) {
1094             startTimer();
1095         }
1096         dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid); 
1097         if ((timing) && (!repeat)) {
1098             endTimer("Parsing DTD");
1099         }
1100         if (dtd == NULL) {
1101             xmlGenericError(xmlGenericErrorContext,
1102                     "Could not parse DTD %s\n", dtdvalid);
1103             progresult = 2;
1104         } else {
1105             xmlValidCtxtPtr cvp;
1106
1107             if ((cvp = xmlNewValidCtxt()) == NULL) {
1108                 xmlGenericError(xmlGenericErrorContext,
1109                         "Couldn't allocate validation context\n");
1110                 exit(-1);
1111             }
1112             cvp->userData = (void *) stderr;
1113             cvp->error    = (xmlValidityErrorFunc) fprintf;
1114             cvp->warning  = (xmlValidityWarningFunc) fprintf;
1115
1116             if ((timing) && (!repeat)) {
1117                 startTimer();
1118             }
1119             if (!xmlValidateDtd(cvp, doc, dtd)) {
1120                 xmlGenericError(xmlGenericErrorContext,
1121                         "Document %s does not validate against %s\n",
1122                         filename, dtdvalid);
1123                 progresult = 3;
1124             }
1125             if ((timing) && (!repeat)) {
1126                 endTimer("Validating against DTD");
1127             }
1128             xmlFreeValidCtxt(cvp);
1129             xmlFreeDtd(dtd);
1130         }
1131     } else if (postvalid) {
1132         xmlValidCtxtPtr cvp;
1133
1134         if ((cvp = xmlNewValidCtxt()) == NULL) {
1135             xmlGenericError(xmlGenericErrorContext,
1136                     "Couldn't allocate validation context\n");
1137             exit(-1);
1138         }
1139
1140         if ((timing) && (!repeat)) {
1141             startTimer();
1142         }
1143         cvp->userData = (void *) stderr;
1144         cvp->error    = (xmlValidityErrorFunc) fprintf;
1145         cvp->warning  = (xmlValidityWarningFunc) fprintf;
1146         if (!xmlValidateDocument(cvp, doc)) {
1147             xmlGenericError(xmlGenericErrorContext,
1148                     "Document %s does not validate\n", filename);
1149             progresult = 3;
1150         }
1151         if ((timing) && (!repeat)) {
1152             endTimer("Validating");
1153         }
1154         xmlFreeValidCtxt(cvp);
1155 #ifdef LIBXML_SCHEMAS_ENABLED
1156     } else if (relaxngschemas != NULL) {
1157         xmlRelaxNGValidCtxtPtr ctxt;
1158         int ret;
1159
1160         if ((timing) && (!repeat)) {
1161             startTimer();
1162         }
1163
1164         ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
1165         xmlRelaxNGSetValidErrors(ctxt,
1166                 (xmlRelaxNGValidityErrorFunc) fprintf,
1167                 (xmlRelaxNGValidityWarningFunc) fprintf,
1168                 stderr);
1169         ret = xmlRelaxNGValidateDoc(ctxt, doc);
1170         if (ret == 0) {
1171             printf("%s validates\n", filename);
1172         } else if (ret > 0) {
1173             printf("%s fails to validate\n", filename);
1174         } else {
1175             printf("%s validation generated an internal error\n",
1176                    filename);
1177         }
1178         xmlRelaxNGFreeValidCtxt(ctxt);
1179         if ((timing) && (!repeat)) {
1180             endTimer("Validating");
1181         }
1182     } else if (wxschemas != NULL) {
1183         xmlSchemaValidCtxtPtr ctxt;
1184         int ret;
1185
1186         if ((timing) && (!repeat)) {
1187             startTimer();
1188         }
1189
1190         ctxt = xmlSchemaNewValidCtxt(wxschemas);
1191         xmlSchemaSetValidErrors(ctxt,
1192                 (xmlSchemaValidityErrorFunc) fprintf,
1193                 (xmlSchemaValidityWarningFunc) fprintf,
1194                 stderr);
1195         ret = xmlSchemaValidateDoc(ctxt, doc);
1196         if (ret == 0) {
1197             printf("%s validates\n", filename);
1198         } else if (ret > 0) {
1199             printf("%s fails to validate\n", filename);
1200         } else {
1201             printf("%s validation generated an internal error\n",
1202                    filename);
1203         }
1204         xmlSchemaFreeValidCtxt(ctxt);
1205         if ((timing) && (!repeat)) {
1206             endTimer("Validating");
1207         }
1208 #endif
1209     }
1210
1211 #ifdef LIBXML_DEBUG_ENABLED
1212     if ((debugent) && (!html))
1213         xmlDebugDumpEntities(stderr, doc);
1214 #endif
1215
1216     /*
1217      * free it.
1218      */
1219     if ((timing) && (!repeat)) {
1220         startTimer();
1221     }
1222     xmlFreeDoc(doc);
1223     if ((timing) && (!repeat)) {
1224         endTimer("Freeing");
1225     }
1226 }
1227
1228 /************************************************************************
1229  *                                                                      *
1230  *                      Usage and Main                                  *
1231  *                                                                      *
1232  ************************************************************************/
1233
1234 static void showVersion(const char *name) {
1235     fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
1236     fprintf(stderr, "   compiled with: ");
1237 #ifdef LIBXML_FTP_ENABLED
1238     fprintf(stderr, "FTP ");
1239 #endif
1240 #ifdef LIBXML_HTTP_ENABLED
1241     fprintf(stderr, "HTTP ");
1242 #endif
1243 #ifdef LIBXML_HTML_ENABLED
1244     fprintf(stderr, "HTML ");
1245 #endif
1246 #ifdef LIBXML_C14N_ENABLED
1247     fprintf(stderr, "C14N ");
1248 #endif
1249 #ifdef LIBXML_CATALOG_ENABLED
1250     fprintf(stderr, "Catalog ");
1251 #endif
1252 #ifdef LIBXML_DOCB_ENABLED
1253     fprintf(stderr, "DocBook ");
1254 #endif
1255 #ifdef LIBXML_XPATH_ENABLED
1256     fprintf(stderr, "XPath ");
1257 #endif
1258 #ifdef LIBXML_XPTR_ENABLED
1259     fprintf(stderr, "XPointer ");
1260 #endif
1261 #ifdef LIBXML_XINCLUDE_ENABLED
1262     fprintf(stderr, "XInclude ");
1263 #endif
1264 #ifdef LIBXML_ICONV_ENABLED
1265     fprintf(stderr, "Iconv ");
1266 #endif
1267 #ifdef DEBUG_MEMORY_LOCATION
1268     fprintf(stderr, "MemDebug ");
1269 #endif
1270 #ifdef LIBXML_UNICODE_ENABLED
1271     fprintf(stderr, "Unicode ");
1272 #endif
1273 #ifdef LIBXML_REGEXP_ENABLED
1274     fprintf(stderr, "Regexps ");
1275 #endif
1276 #ifdef LIBXML_AUTOMATA_ENABLED
1277     fprintf(stderr, "Automata ");
1278 #endif
1279 #ifdef LIBXML_SCHEMAS_ENABLED
1280     fprintf(stderr, "Schemas ");
1281 #endif
1282     fprintf(stderr, "\n");
1283 }
1284
1285 static void usage(const char *name) {
1286     printf("Usage : %s [options] XMLfiles ...\n", name);
1287     printf("\tParse the XML files and output the result of the parsing\n");
1288     printf("\t--version : display the version of the XML library used\n");
1289 #ifdef LIBXML_DEBUG_ENABLED
1290     printf("\t--debug : dump a debug tree of the in-memory document\n");
1291     printf("\t--shell : run a navigating shell\n");
1292     printf("\t--debugent : debug the entities defined in the document\n");
1293 #else
1294     printf("\t--debug : dump the nodes content when using --stream\n");
1295 #endif
1296     printf("\t--copy : used to test the internal copy implementation\n");
1297     printf("\t--recover : output what was parsable on broken XML documents\n");
1298     printf("\t--noent : substitute entity references by their value\n");
1299     printf("\t--noout : don't output the result tree\n");
1300     printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
1301     printf("\t--htmlout : output results as HTML\n");
1302     printf("\t--nowrap : do not put HTML doc wrapper\n");
1303     printf("\t--valid : validate the document in addition to std well-formed check\n");
1304     printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
1305     printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
1306     printf("\t--timing : print some timings\n");
1307     printf("\t--output file or -o file: save to a given file\n");
1308     printf("\t--repeat : repeat 100 times, for timing or profiling\n");
1309     printf("\t--insert : ad-hoc test for valid insertions\n");
1310 #ifdef HAVE_ZLIB_H
1311     printf("\t--compress : turn on gzip compression of output\n");
1312 #endif
1313 #ifdef LIBXML_DOCB_ENABLED
1314     printf("\t--sgml : use the DocBook SGML parser\n");
1315 #endif
1316 #ifdef LIBXML_HTML_ENABLED
1317     printf("\t--html : use the HTML parser\n");
1318 #endif
1319     printf("\t--push : use the push mode of the parser\n");
1320 #ifdef HAVE_SYS_MMAN_H
1321     printf("\t--memory : parse from memory\n");
1322 #endif
1323     printf("\t--nowarning : do not emit warnings from parser/validator\n");
1324     printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
1325     printf("\t--format : reformat/reindent the input\n");
1326     printf("\t--testIO : test user I/O support\n");
1327     printf("\t--encode encoding : output in the given encoding\n");
1328 #ifdef LIBXML_CATALOG_ENABLED
1329     printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
1330     printf("\t             otherwise XML Catalogs starting from \n");
1331     printf("\t         " XML_XML_DEFAULT_CATALOG " are activated by default\n");
1332     printf("\t--nocatalogs: deactivate all catalogs\n");
1333 #endif
1334     printf("\t--auto : generate a small doc on the fly\n");
1335 #ifdef LIBXML_XINCLUDE_ENABLED
1336     printf("\t--xinclude : do XInclude processing\n");
1337 #endif
1338     printf("\t--loaddtd : fetch external DTD\n");
1339     printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
1340     printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
1341     printf("\t--stream : use the streaming interface to process very large files\n");
1342     printf("\t--chkregister : verify the node registration code\n");
1343 #ifdef LIBXML_SCHEMAS_ENABLED
1344     printf("\t--relaxng schema : do RelaxNG validation against the schema\n");
1345     printf("\t--schema schema : do validation against the WXS schema\n");
1346 #endif
1347     printf("\nLibxml project home page: http://xmlsoft.org/\n");
1348     printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
1349 }
1350
1351 static void registerNode(xmlNodePtr node)
1352 {
1353     node->_private = malloc(sizeof(long));
1354     *(long*)node->_private = (long) 0x81726354;
1355 }
1356
1357 static void deregisterNode(xmlNodePtr node)
1358 {
1359     assert(node->_private != NULL);
1360     assert(*(long*)node->_private == (long) 0x81726354);
1361     free(node->_private);
1362 }
1363
1364 int
1365 main(int argc, char **argv) {
1366     int i, acount;
1367     int files = 0;
1368     int version = 0;
1369     const char* indent;
1370     
1371     if (argc <= 1) {
1372         usage(argv[0]);
1373         return(1);
1374     }
1375     LIBXML_TEST_VERSION
1376     for (i = 1; i < argc ; i++) {
1377         if (!strcmp(argv[i], "-"))
1378             break;
1379
1380         if (argv[i][0] != '-')
1381             continue;
1382         if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
1383             debug++;
1384         else
1385 #ifdef LIBXML_DEBUG_ENABLED
1386         if ((!strcmp(argv[i], "-shell")) ||
1387                  (!strcmp(argv[i], "--shell"))) {
1388             shell++;
1389             noout = 1;
1390         } else 
1391 #endif
1392         if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
1393             copy++;
1394         else if ((!strcmp(argv[i], "-recover")) ||
1395                  (!strcmp(argv[i], "--recover")))
1396             recovery++;
1397         else if ((!strcmp(argv[i], "-noent")) ||
1398                  (!strcmp(argv[i], "--noent")))
1399             noent++;
1400         else if ((!strcmp(argv[i], "-version")) ||
1401                  (!strcmp(argv[i], "--version"))) {
1402             showVersion(argv[0]);
1403             version = 1;
1404         } else if ((!strcmp(argv[i], "-noout")) ||
1405                  (!strcmp(argv[i], "--noout")))
1406             noout++;
1407         else if ((!strcmp(argv[i], "-o")) ||
1408                  (!strcmp(argv[i], "-output")) ||
1409                  (!strcmp(argv[i], "--output"))) {
1410             i++;
1411             output = argv[i];
1412         }
1413         else if ((!strcmp(argv[i], "-htmlout")) ||
1414                  (!strcmp(argv[i], "--htmlout")))
1415             htmlout++;
1416 #ifdef LIBXML_DOCB_ENABLED
1417         else if ((!strcmp(argv[i], "-sgml")) ||
1418                  (!strcmp(argv[i], "--sgml"))) {
1419             sgml++;
1420         }
1421 #endif
1422 #ifdef LIBXML_HTML_ENABLED
1423         else if ((!strcmp(argv[i], "-html")) ||
1424                  (!strcmp(argv[i], "--html"))) {
1425             html++;
1426         }
1427 #endif /* LIBXML_HTML_ENABLED */
1428         else if ((!strcmp(argv[i], "-nowrap")) ||
1429                  (!strcmp(argv[i], "--nowrap")))
1430             nowrap++;
1431         else if ((!strcmp(argv[i], "-loaddtd")) ||
1432                  (!strcmp(argv[i], "--loaddtd")))
1433             loaddtd++;
1434         else if ((!strcmp(argv[i], "-dtdattr")) ||
1435                  (!strcmp(argv[i], "--dtdattr"))) {
1436             loaddtd++;
1437             dtdattrs++;
1438         } else if ((!strcmp(argv[i], "-valid")) ||
1439                  (!strcmp(argv[i], "--valid")))
1440             valid++;
1441         else if ((!strcmp(argv[i], "-postvalid")) ||
1442                  (!strcmp(argv[i], "--postvalid"))) {
1443             postvalid++;
1444             loaddtd++;
1445         } else if ((!strcmp(argv[i], "-dtdvalid")) ||
1446                  (!strcmp(argv[i], "--dtdvalid"))) {
1447             i++;
1448             dtdvalid = argv[i];
1449             loaddtd++;
1450         }
1451         else if ((!strcmp(argv[i], "-dropdtd")) ||
1452                  (!strcmp(argv[i], "--dropdtd")))
1453             dropdtd++;
1454         else if ((!strcmp(argv[i], "-insert")) ||
1455                  (!strcmp(argv[i], "--insert")))
1456             insert++;
1457         else if ((!strcmp(argv[i], "-timing")) ||
1458                  (!strcmp(argv[i], "--timing")))
1459             timing++;
1460         else if ((!strcmp(argv[i], "-auto")) ||
1461                  (!strcmp(argv[i], "--auto")))
1462             generate++;
1463         else if ((!strcmp(argv[i], "-repeat")) ||
1464                  (!strcmp(argv[i], "--repeat")))
1465             repeat++;
1466         else if ((!strcmp(argv[i], "-push")) ||
1467                  (!strcmp(argv[i], "--push")))
1468             push++;
1469 #ifdef HAVE_SYS_MMAN_H
1470         else if ((!strcmp(argv[i], "-memory")) ||
1471                  (!strcmp(argv[i], "--memory")))
1472             memory++;
1473 #endif
1474         else if ((!strcmp(argv[i], "-testIO")) ||
1475                  (!strcmp(argv[i], "--testIO")))
1476             testIO++;
1477 #ifdef LIBXML_XINCLUDE_ENABLED
1478         else if ((!strcmp(argv[i], "-xinclude")) ||
1479                  (!strcmp(argv[i], "--xinclude")))
1480             xinclude++;
1481 #endif
1482 #ifdef HAVE_ZLIB_H
1483         else if ((!strcmp(argv[i], "-compress")) ||
1484                  (!strcmp(argv[i], "--compress"))) {
1485             compress++;
1486             xmlSetCompressMode(9);
1487         }
1488 #endif
1489         else if ((!strcmp(argv[i], "-nowarning")) ||
1490                  (!strcmp(argv[i], "--nowarning"))) {
1491             xmlGetWarningsDefaultValue = 0;
1492             xmlPedanticParserDefault(0);
1493         }
1494         else if ((!strcmp(argv[i], "-pedantic")) ||
1495                  (!strcmp(argv[i], "--pedantic"))) {
1496             xmlGetWarningsDefaultValue = 1;
1497             xmlPedanticParserDefault(1);
1498         }
1499 #ifdef LIBXML_DEBUG_ENABLED
1500         else if ((!strcmp(argv[i], "-debugent")) ||
1501                  (!strcmp(argv[i], "--debugent"))) {
1502             debugent++;
1503             xmlParserDebugEntities = 1;
1504         } 
1505 #endif
1506 #ifdef LIBXML_CATALOG_ENABLED
1507         else if ((!strcmp(argv[i], "-catalogs")) ||
1508                  (!strcmp(argv[i], "--catalogs"))) {
1509             catalogs++;
1510         } else if ((!strcmp(argv[i], "-nocatalogs")) ||
1511                  (!strcmp(argv[i], "--nocatalogs"))) {
1512             nocatalogs++;
1513         } 
1514 #endif
1515         else if ((!strcmp(argv[i], "-encode")) ||
1516                  (!strcmp(argv[i], "--encode"))) {
1517             i++;
1518             encoding = argv[i];
1519             /*
1520              * OK it's for testing purposes
1521              */
1522             xmlAddEncodingAlias("UTF-8", "DVEnc");
1523         }
1524         else if ((!strcmp(argv[i], "-noblanks")) ||
1525                  (!strcmp(argv[i], "--noblanks"))) {
1526              noblanks++;
1527              xmlKeepBlanksDefault(0);
1528         }
1529         else if ((!strcmp(argv[i], "-format")) ||
1530                  (!strcmp(argv[i], "--format"))) {
1531              noblanks++;
1532              format++;
1533              xmlKeepBlanksDefault(0);
1534         }
1535         else if ((!strcmp(argv[i], "-stream")) ||
1536                  (!strcmp(argv[i], "--stream"))) {
1537              stream++;
1538         }
1539         else if ((!strcmp(argv[i], "-chkregister")) ||
1540                  (!strcmp(argv[i], "--chkregister"))) {
1541              chkregister++;
1542 #ifdef LIBXML_SCHEMAS_ENABLED
1543         } else if ((!strcmp(argv[i], "-relaxng")) ||
1544                  (!strcmp(argv[i], "--relaxng"))) {
1545             i++;
1546             relaxng = argv[i];
1547             noent++;
1548         } else if ((!strcmp(argv[i], "-schema")) ||
1549                  (!strcmp(argv[i], "--schema"))) {
1550             i++;
1551             schema = argv[i];
1552             noent++;
1553 #endif
1554         } else if ((!strcmp(argv[i], "-nonet")) ||
1555                    (!strcmp(argv[i], "--nonet"))) {
1556             xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
1557         } else {
1558             fprintf(stderr, "Unknown option %s\n", argv[i]);
1559             usage(argv[0]);
1560             return(1);
1561         }
1562     }
1563
1564 #ifdef LIBXML_CATALOG_ENABLED
1565     if (nocatalogs == 0) {
1566         if (catalogs) {
1567             const char *catal;
1568
1569             catal = getenv("SGML_CATALOG_FILES");
1570             if (catal != NULL) {
1571                 xmlLoadCatalogs(catal);
1572             } else {
1573                 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
1574             }
1575         }
1576     }
1577 #endif
1578
1579     if (chkregister) {
1580         xmlRegisterNodeDefault(registerNode);
1581         xmlDeregisterNodeDefault(deregisterNode);
1582     }
1583     
1584     indent = getenv("XMLLINT_INDENT");
1585     if(indent != NULL) {
1586         xmlTreeIndentString = indent;
1587     }
1588     
1589
1590     xmlLineNumbersDefault(1);
1591     if (loaddtd != 0)
1592         xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
1593     if (dtdattrs)
1594         xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
1595     if (noent != 0) xmlSubstituteEntitiesDefault(1);
1596     if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1597     if ((htmlout) && (!nowrap)) {
1598         xmlGenericError(xmlGenericErrorContext,
1599          "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
1600         xmlGenericError(xmlGenericErrorContext,
1601                 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
1602         xmlGenericError(xmlGenericErrorContext,
1603          "<html><head><title>%s output</title></head>\n",
1604                 argv[0]);
1605         xmlGenericError(xmlGenericErrorContext, 
1606          "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
1607                 argv[0]);
1608     }
1609
1610 #ifdef LIBXML_SCHEMAS_ENABLED
1611     if ((relaxng != NULL) && (stream == 0)) {
1612         xmlRelaxNGParserCtxtPtr ctxt;
1613
1614         /* forces loading the DTDs */
1615         xmlLoadExtDtdDefaultValue |= 1; 
1616         if (timing) {
1617             startTimer();
1618         }
1619         ctxt = xmlRelaxNGNewParserCtxt(relaxng);
1620         xmlRelaxNGSetParserErrors(ctxt,
1621                 (xmlRelaxNGValidityErrorFunc) fprintf,
1622                 (xmlRelaxNGValidityWarningFunc) fprintf,
1623                 stderr);
1624         relaxngschemas = xmlRelaxNGParse(ctxt);
1625         if (relaxngschemas == NULL) {
1626             xmlGenericError(xmlGenericErrorContext,
1627                     "Relax-NG schema %s failed to compile\n", relaxng);
1628             relaxng = NULL;
1629         }
1630         xmlRelaxNGFreeParserCtxt(ctxt);
1631         if (timing) {
1632             endTimer("Compiling the schemas");
1633         }
1634     } else if ((schema != NULL) && (stream == 0)) {
1635         xmlSchemaParserCtxtPtr ctxt;
1636
1637         if (timing) {
1638             startTimer();
1639         }
1640         ctxt = xmlSchemaNewParserCtxt(schema);
1641         xmlSchemaSetParserErrors(ctxt,
1642                 (xmlSchemaValidityErrorFunc) fprintf,
1643                 (xmlSchemaValidityWarningFunc) fprintf,
1644                 stderr);
1645         wxschemas = xmlSchemaParse(ctxt);
1646         if (wxschemas == NULL) {
1647             xmlGenericError(xmlGenericErrorContext,
1648                     "WXS schema %s failed to compile\n", schema);
1649             schema = NULL;
1650         }
1651         xmlSchemaFreeParserCtxt(ctxt);
1652         if (timing) {
1653             endTimer("Compiling the schemas");
1654         }
1655     }
1656 #endif
1657     for (i = 1; i < argc ; i++) {
1658         if ((!strcmp(argv[i], "-encode")) ||
1659                  (!strcmp(argv[i], "--encode"))) {
1660             i++;
1661             continue;
1662         } else if ((!strcmp(argv[i], "-o")) ||
1663                    (!strcmp(argv[i], "-output")) ||
1664                    (!strcmp(argv[i], "--output"))) {
1665             i++;
1666             continue;
1667         }
1668         if ((!strcmp(argv[i], "-dtdvalid")) ||
1669                  (!strcmp(argv[i], "--dtdvalid"))) {
1670             i++;
1671             continue;
1672         }
1673         if ((!strcmp(argv[i], "-relaxng")) ||
1674                  (!strcmp(argv[i], "--relaxng"))) {
1675             i++;
1676             continue;
1677         }
1678         if ((!strcmp(argv[i], "-schema")) ||
1679                  (!strcmp(argv[i], "--schema"))) {
1680             i++;
1681             continue;
1682         }
1683         if ((timing) && (repeat))
1684             startTimer();
1685         /* Remember file names.  "-" means stdin.  <sven@zen.org> */
1686         if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
1687             if (repeat) {
1688                 for (acount = 0;acount < 100 * repeat;acount++)
1689                     if (stream != 0)
1690                         streamFile(argv[i]);
1691                     else
1692                         parseAndPrintFile(argv[i]);
1693             } else {
1694                 if (stream != 0)
1695                     streamFile(argv[i]);
1696                 else
1697                     parseAndPrintFile(argv[i]);
1698             }
1699             files ++;
1700             if ((timing) && (repeat)) {
1701                 endTimer("100 iterations");
1702             }
1703         }
1704     }
1705     if (generate) 
1706         parseAndPrintFile(NULL);
1707     if ((htmlout) && (!nowrap)) {
1708         xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
1709     }
1710     if ((files == 0) && (!generate) && (version == 0)) {
1711         usage(argv[0]);
1712     }
1713 #ifdef LIBXML_SCHEMAS_ENABLED
1714     if (relaxngschemas != NULL)
1715         xmlRelaxNGFree(relaxngschemas);
1716     if (wxschemas != NULL)
1717         xmlSchemaFree(wxschemas);
1718     xmlRelaxNGCleanupTypes();
1719 #endif
1720     xmlCleanupParser();
1721     xmlMemoryDump();
1722
1723     return(progresult);
1724 }
1725