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