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