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