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 <stdlib.h>
14 #include <assert.h>
15 #include <time.h>
16
17 #ifdef HAVE_SYS_TIME_H
18 #include <sys/time.h>
19 #endif
20 #ifdef HAVE_SYS_TIMEB_H
21 #include <sys/timeb.h>
22 #endif
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 #ifdef HAVE_SYS_STAT_H
27 #include <sys/stat.h>
28 #endif
29 #ifdef HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #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 #ifdef LIBXML_OUTPUT_ENABLED
116 static int format = 0;
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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 XMLCDECL 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 xmlParserInputBufferPtr buf = NULL;
1590 xmlParserInputPtr inputStream;
1591 xmlParserCtxtPtr ctxt = NULL;
1592 xmlSAXHandlerPtr old_sax = NULL;
1593
1594 callbacks = 0;
1595
1596 if (noout) {
1597 handler = emptySAXHandler;
1598 #ifdef LIBXML_SAX1_ENABLED
1599 } else if (sax1) {
1600 handler = debugSAXHandler;
1601 #endif
1602 } else {
1603 handler = debugSAX2Handler;
1604 }
1605
1606 /*
1607 * it's not the simplest code but the most generic in term of I/O
1608 */
1609 buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1610 if (buf == NULL) {
1611 goto error;
1612 }
1613
1614 #ifdef LIBXML_SCHEMAS_ENABLED
1615 if (wxschemas != NULL) {
1616 int ret;
1617 xmlSchemaValidCtxtPtr vctxt;
1618
1619 vctxt = xmlSchemaNewValidCtxt(wxschemas);
1620 if (vctxt == NULL) {
1621 progresult = XMLLINT_ERR_MEM;
1622 xmlFreeParserInputBuffer(buf);
1623 goto error;
1624 }
1625 xmlSchemaSetValidErrors(vctxt, xmlGenericError, xmlGenericError, NULL);
1626 xmlSchemaValidateSetFilename(vctxt, filename);
1627
1628 ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
1629 (void *)user_data);
1630 if (repeat == 0) {
1631 if (ret == 0) {
1632 if (!quiet) {
1633 fprintf(stderr, "%s validates\n", filename);
1634 }
1635 } else if (ret > 0) {
1636 fprintf(stderr, "%s fails to validate\n", filename);
1637 progresult = XMLLINT_ERR_VALID;
1638 } else {
1639 fprintf(stderr, "%s validation generated an internal error\n",
1640 filename);
1641 progresult = XMLLINT_ERR_VALID;
1642 }
1643 }
1644 xmlSchemaFreeValidCtxt(vctxt);
1645 } else
1646 #endif
1647 {
1648 /*
1649 * Create the parser context amd hook the input
1650 */
1651 ctxt = xmlNewParserCtxt();
1652 if (ctxt == NULL) {
1653 progresult = XMLLINT_ERR_MEM;
1654 xmlFreeParserInputBuffer(buf);
1655 goto error;
1656 }
1657 old_sax = ctxt->sax;
1658 ctxt->sax = handler;
1659 ctxt->userData = (void *) user_data;
1660 inputStream = xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE);
1661 if (inputStream == NULL) {
1662 xmlFreeParserInputBuffer(buf);
1663 goto error;
1664 }
1665 inputPush(ctxt, inputStream);
1666
1667 /* do the parsing */
1668 xmlParseDocument(ctxt);
1669
1670 if (ctxt->myDoc != NULL) {
1671 fprintf(stderr, "SAX generated a doc !\n");
1672 xmlFreeDoc(ctxt->myDoc);
1673 ctxt->myDoc = NULL;
1674 }
1675 }
1676
1677 error:
1678 if (ctxt != NULL) {
1679 ctxt->sax = old_sax;
1680 xmlFreeParserCtxt(ctxt);
1681 }
1682 }
1683
1684 /************************************************************************
1685 * *
1686 * Stream Test processing *
1687 * *
1688 ************************************************************************/
1689 #ifdef LIBXML_READER_ENABLED
processNode(xmlTextReaderPtr reader)1690 static void processNode(xmlTextReaderPtr reader) {
1691 const xmlChar *name, *value;
1692 int type, empty;
1693
1694 type = xmlTextReaderNodeType(reader);
1695 empty = xmlTextReaderIsEmptyElement(reader);
1696
1697 if (debug) {
1698 name = xmlTextReaderConstName(reader);
1699 if (name == NULL)
1700 name = BAD_CAST "--";
1701
1702 value = xmlTextReaderConstValue(reader);
1703
1704
1705 printf("%d %d %s %d %d",
1706 xmlTextReaderDepth(reader),
1707 type,
1708 name,
1709 empty,
1710 xmlTextReaderHasValue(reader));
1711 if (value == NULL)
1712 printf("\n");
1713 else {
1714 printf(" %s\n", value);
1715 }
1716 }
1717 #ifdef LIBXML_PATTERN_ENABLED
1718 if (patternc) {
1719 xmlChar *path = NULL;
1720 int match = -1;
1721
1722 if (type == XML_READER_TYPE_ELEMENT) {
1723 /* do the check only on element start */
1724 match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
1725
1726 if (match) {
1727 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
1728 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
1729 printf("Node %s matches pattern %s\n", path, pattern);
1730 #else
1731 printf("Node %s matches pattern %s\n",
1732 xmlTextReaderConstName(reader), pattern);
1733 #endif
1734 }
1735 }
1736 if (patstream != NULL) {
1737 int ret;
1738
1739 if (type == XML_READER_TYPE_ELEMENT) {
1740 ret = xmlStreamPush(patstream,
1741 xmlTextReaderConstLocalName(reader),
1742 xmlTextReaderConstNamespaceUri(reader));
1743 if (ret < 0) {
1744 fprintf(stderr, "xmlStreamPush() failure\n");
1745 xmlFreeStreamCtxt(patstream);
1746 patstream = NULL;
1747 } else if (ret != match) {
1748 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
1749 if (path == NULL) {
1750 path = xmlGetNodePath(
1751 xmlTextReaderCurrentNode(reader));
1752 }
1753 #endif
1754 fprintf(stderr,
1755 "xmlPatternMatch and xmlStreamPush disagree\n");
1756 if (path != NULL)
1757 fprintf(stderr, " pattern %s node %s\n",
1758 pattern, path);
1759 else
1760 fprintf(stderr, " pattern %s node %s\n",
1761 pattern, xmlTextReaderConstName(reader));
1762 }
1763
1764 }
1765 if ((type == XML_READER_TYPE_END_ELEMENT) ||
1766 ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
1767 ret = xmlStreamPop(patstream);
1768 if (ret < 0) {
1769 fprintf(stderr, "xmlStreamPop() failure\n");
1770 xmlFreeStreamCtxt(patstream);
1771 patstream = NULL;
1772 }
1773 }
1774 }
1775 if (path != NULL)
1776 xmlFree(path);
1777 }
1778 #endif
1779 }
1780
streamFile(char * filename)1781 static void streamFile(char *filename) {
1782 xmlTextReaderPtr reader;
1783 int ret;
1784 #ifdef HAVE_MMAP
1785 int fd = -1;
1786 struct stat info;
1787 const char *base = NULL;
1788 xmlParserInputBufferPtr input = NULL;
1789
1790 if (memory) {
1791 if (stat(filename, &info) < 0)
1792 return;
1793 if ((fd = open(filename, O_RDONLY)) < 0)
1794 return;
1795 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
1796 if (base == (void *) MAP_FAILED) {
1797 close(fd);
1798 fprintf(stderr, "mmap failure for file %s\n", filename);
1799 progresult = XMLLINT_ERR_RDFILE;
1800 return;
1801 }
1802
1803 reader = xmlReaderForMemory(base, info.st_size, filename,
1804 NULL, options);
1805 } else
1806 #endif
1807 reader = xmlReaderForFile(filename, NULL, options);
1808 #ifdef LIBXML_PATTERN_ENABLED
1809 if (pattern != NULL) {
1810 patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
1811 if (patternc == NULL) {
1812 xmlGenericError(xmlGenericErrorContext,
1813 "Pattern %s failed to compile\n", pattern);
1814 progresult = XMLLINT_ERR_SCHEMAPAT;
1815 pattern = NULL;
1816 }
1817 }
1818 if (patternc != NULL) {
1819 patstream = xmlPatternGetStreamCtxt(patternc);
1820 if (patstream != NULL) {
1821 ret = xmlStreamPush(patstream, NULL, NULL);
1822 if (ret < 0) {
1823 fprintf(stderr, "xmlStreamPush() failure\n");
1824 xmlFreeStreamCtxt(patstream);
1825 patstream = NULL;
1826 }
1827 }
1828 }
1829 #endif
1830
1831
1832 if (reader != NULL) {
1833 #ifdef LIBXML_VALID_ENABLED
1834 if (valid)
1835 xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
1836 else
1837 #endif /* LIBXML_VALID_ENABLED */
1838 if (loaddtd)
1839 xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
1840 #ifdef LIBXML_SCHEMAS_ENABLED
1841 if (relaxng != NULL) {
1842 if ((timing) && (!repeat)) {
1843 startTimer();
1844 }
1845 ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
1846 if (ret < 0) {
1847 xmlGenericError(xmlGenericErrorContext,
1848 "Relax-NG schema %s failed to compile\n", relaxng);
1849 progresult = XMLLINT_ERR_SCHEMACOMP;
1850 relaxng = NULL;
1851 }
1852 if ((timing) && (!repeat)) {
1853 endTimer("Compiling the schemas");
1854 }
1855 }
1856 if (schema != NULL) {
1857 if ((timing) && (!repeat)) {
1858 startTimer();
1859 }
1860 ret = xmlTextReaderSchemaValidate(reader, schema);
1861 if (ret < 0) {
1862 xmlGenericError(xmlGenericErrorContext,
1863 "XSD schema %s failed to compile\n", schema);
1864 progresult = XMLLINT_ERR_SCHEMACOMP;
1865 schema = NULL;
1866 }
1867 if ((timing) && (!repeat)) {
1868 endTimer("Compiling the schemas");
1869 }
1870 }
1871 #endif
1872
1873 /*
1874 * Process all nodes in sequence
1875 */
1876 if ((timing) && (!repeat)) {
1877 startTimer();
1878 }
1879 ret = xmlTextReaderRead(reader);
1880 while (ret == 1) {
1881 if ((debug)
1882 #ifdef LIBXML_PATTERN_ENABLED
1883 || (patternc)
1884 #endif
1885 )
1886 processNode(reader);
1887 ret = xmlTextReaderRead(reader);
1888 }
1889 if ((timing) && (!repeat)) {
1890 #ifdef LIBXML_SCHEMAS_ENABLED
1891 if (relaxng != NULL)
1892 endTimer("Parsing and validating");
1893 else
1894 #endif
1895 #ifdef LIBXML_VALID_ENABLED
1896 if (valid)
1897 endTimer("Parsing and validating");
1898 else
1899 #endif
1900 endTimer("Parsing");
1901 }
1902
1903 #ifdef LIBXML_VALID_ENABLED
1904 if (valid) {
1905 if (xmlTextReaderIsValid(reader) != 1) {
1906 xmlGenericError(xmlGenericErrorContext,
1907 "Document %s does not validate\n", filename);
1908 progresult = XMLLINT_ERR_VALID;
1909 }
1910 }
1911 #endif /* LIBXML_VALID_ENABLED */
1912 #ifdef LIBXML_SCHEMAS_ENABLED
1913 if ((relaxng != NULL) || (schema != NULL)) {
1914 if (xmlTextReaderIsValid(reader) != 1) {
1915 fprintf(stderr, "%s fails to validate\n", filename);
1916 progresult = XMLLINT_ERR_VALID;
1917 } else {
1918 if (!quiet) {
1919 fprintf(stderr, "%s validates\n", filename);
1920 }
1921 }
1922 }
1923 #endif
1924 /*
1925 * Done, cleanup and status
1926 */
1927 xmlFreeTextReader(reader);
1928 if (ret != 0) {
1929 fprintf(stderr, "%s : failed to parse\n", filename);
1930 progresult = XMLLINT_ERR_UNCLASS;
1931 }
1932 } else {
1933 fprintf(stderr, "Unable to open %s\n", filename);
1934 progresult = XMLLINT_ERR_UNCLASS;
1935 }
1936 #ifdef LIBXML_PATTERN_ENABLED
1937 if (patstream != NULL) {
1938 xmlFreeStreamCtxt(patstream);
1939 patstream = NULL;
1940 }
1941 #endif
1942 #ifdef HAVE_MMAP
1943 if (memory) {
1944 xmlFreeParserInputBuffer(input);
1945 munmap((char *) base, info.st_size);
1946 close(fd);
1947 }
1948 #endif
1949 }
1950
walkDoc(xmlDocPtr doc)1951 static void walkDoc(xmlDocPtr doc) {
1952 xmlTextReaderPtr reader;
1953 int ret;
1954
1955 #ifdef LIBXML_PATTERN_ENABLED
1956 xmlNodePtr root;
1957 const xmlChar *namespaces[22];
1958 int i;
1959 xmlNsPtr ns;
1960
1961 root = xmlDocGetRootElement(doc);
1962 if (root == NULL ) {
1963 xmlGenericError(xmlGenericErrorContext,
1964 "Document does not have a root element");
1965 progresult = XMLLINT_ERR_UNCLASS;
1966 return;
1967 }
1968 for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) {
1969 namespaces[i++] = ns->href;
1970 namespaces[i++] = ns->prefix;
1971 }
1972 namespaces[i++] = NULL;
1973 namespaces[i] = NULL;
1974
1975 if (pattern != NULL) {
1976 patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict,
1977 0, &namespaces[0]);
1978 if (patternc == NULL) {
1979 xmlGenericError(xmlGenericErrorContext,
1980 "Pattern %s failed to compile\n", pattern);
1981 progresult = XMLLINT_ERR_SCHEMAPAT;
1982 pattern = NULL;
1983 }
1984 }
1985 if (patternc != NULL) {
1986 patstream = xmlPatternGetStreamCtxt(patternc);
1987 if (patstream != NULL) {
1988 ret = xmlStreamPush(patstream, NULL, NULL);
1989 if (ret < 0) {
1990 fprintf(stderr, "xmlStreamPush() failure\n");
1991 xmlFreeStreamCtxt(patstream);
1992 patstream = NULL;
1993 }
1994 }
1995 }
1996 #endif /* LIBXML_PATTERN_ENABLED */
1997 reader = xmlReaderWalker(doc);
1998 if (reader != NULL) {
1999 if ((timing) && (!repeat)) {
2000 startTimer();
2001 }
2002 ret = xmlTextReaderRead(reader);
2003 while (ret == 1) {
2004 if ((debug)
2005 #ifdef LIBXML_PATTERN_ENABLED
2006 || (patternc)
2007 #endif
2008 )
2009 processNode(reader);
2010 ret = xmlTextReaderRead(reader);
2011 }
2012 if ((timing) && (!repeat)) {
2013 endTimer("walking through the doc");
2014 }
2015 xmlFreeTextReader(reader);
2016 if (ret != 0) {
2017 fprintf(stderr, "failed to walk through the doc\n");
2018 progresult = XMLLINT_ERR_UNCLASS;
2019 }
2020 } else {
2021 fprintf(stderr, "Failed to crate a reader from the document\n");
2022 progresult = XMLLINT_ERR_UNCLASS;
2023 }
2024 #ifdef LIBXML_PATTERN_ENABLED
2025 if (patstream != NULL) {
2026 xmlFreeStreamCtxt(patstream);
2027 patstream = NULL;
2028 }
2029 #endif
2030 }
2031 #endif /* LIBXML_READER_ENABLED */
2032
2033 #ifdef LIBXML_XPATH_ENABLED
2034 /************************************************************************
2035 * *
2036 * XPath Query *
2037 * *
2038 ************************************************************************/
2039
doXPathDump(xmlXPathObjectPtr cur)2040 static void doXPathDump(xmlXPathObjectPtr cur) {
2041 switch(cur->type) {
2042 case XPATH_NODESET: {
2043 int i;
2044 xmlNodePtr node;
2045 #ifdef LIBXML_OUTPUT_ENABLED
2046 xmlOutputBufferPtr buf;
2047
2048 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) {
2049 fprintf(stderr, "XPath set is empty\n");
2050 progresult = XMLLINT_ERR_XPATH;
2051 break;
2052 }
2053 buf = xmlOutputBufferCreateFile(stdout, NULL);
2054 if (buf == NULL) {
2055 fprintf(stderr, "Out of memory for XPath\n");
2056 progresult = XMLLINT_ERR_MEM;
2057 return;
2058 }
2059 for (i = 0;i < cur->nodesetval->nodeNr;i++) {
2060 node = cur->nodesetval->nodeTab[i];
2061 xmlNodeDumpOutput(buf, NULL, node, 0, 0, NULL);
2062 xmlOutputBufferWrite(buf, 1, "\n");
2063 }
2064 xmlOutputBufferClose(buf);
2065 #else
2066 printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
2067 #endif
2068 break;
2069 }
2070 case XPATH_BOOLEAN:
2071 if (cur->boolval) printf("true\n");
2072 else printf("false\n");
2073 break;
2074 case XPATH_NUMBER:
2075 switch (xmlXPathIsInf(cur->floatval)) {
2076 case 1:
2077 printf("Infinity\n");
2078 break;
2079 case -1:
2080 printf("-Infinity\n");
2081 break;
2082 default:
2083 if (xmlXPathIsNaN(cur->floatval)) {
2084 printf("NaN\n");
2085 } else {
2086 printf("%0g\n", cur->floatval);
2087 }
2088 }
2089 break;
2090 case XPATH_STRING:
2091 printf("%s\n", (const char *) cur->stringval);
2092 break;
2093 case XPATH_UNDEFINED:
2094 fprintf(stderr, "XPath Object is uninitialized\n");
2095 progresult = XMLLINT_ERR_XPATH;
2096 break;
2097 default:
2098 fprintf(stderr, "XPath object of unexpected type\n");
2099 progresult = XMLLINT_ERR_XPATH;
2100 break;
2101 }
2102 }
2103
doXPathQuery(xmlDocPtr doc,const char * query)2104 static void doXPathQuery(xmlDocPtr doc, const char *query) {
2105 xmlXPathContextPtr ctxt;
2106 xmlXPathObjectPtr res;
2107
2108 ctxt = xmlXPathNewContext(doc);
2109 if (ctxt == NULL) {
2110 fprintf(stderr, "Out of memory for XPath\n");
2111 progresult = XMLLINT_ERR_MEM;
2112 return;
2113 }
2114 ctxt->node = (xmlNodePtr) doc;
2115 res = xmlXPathEval(BAD_CAST query, ctxt);
2116 xmlXPathFreeContext(ctxt);
2117
2118 if (res == NULL) {
2119 fprintf(stderr, "XPath evaluation failure\n");
2120 progresult = XMLLINT_ERR_XPATH;
2121 return;
2122 }
2123 doXPathDump(res);
2124 xmlXPathFreeObject(res);
2125 }
2126 #endif /* LIBXML_XPATH_ENABLED */
2127
2128 /************************************************************************
2129 * *
2130 * Tree Test processing *
2131 * *
2132 ************************************************************************/
parseAndPrintFile(char * filename,xmlParserCtxtPtr rectxt)2133 static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
2134 xmlDocPtr doc = NULL;
2135 #ifdef LIBXML_TREE_ENABLED
2136 xmlDocPtr tmp;
2137 #endif /* LIBXML_TREE_ENABLED */
2138
2139 if ((timing) && (!repeat))
2140 startTimer();
2141
2142
2143 #ifdef LIBXML_TREE_ENABLED
2144 if (filename == NULL) {
2145 if (generate) {
2146 xmlNodePtr n;
2147
2148 doc = xmlNewDoc(BAD_CAST "1.0");
2149 n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
2150 xmlNodeSetContent(n, BAD_CAST "abc");
2151 xmlDocSetRootElement(doc, n);
2152 }
2153 }
2154 #endif /* LIBXML_TREE_ENABLED */
2155 #ifdef LIBXML_HTML_ENABLED
2156 #ifdef LIBXML_PUSH_ENABLED
2157 else if ((html) && (push)) {
2158 FILE *f;
2159
2160 if ((filename[0] == '-') && (filename[1] == 0)) {
2161 f = stdin;
2162 } else {
2163 f = fopen(filename, "rb");
2164 }
2165 if (f != NULL) {
2166 int res;
2167 char chars[4096];
2168 htmlParserCtxtPtr ctxt;
2169
2170 res = fread(chars, 1, 4, f);
2171 if (res > 0) {
2172 ctxt = htmlCreatePushParserCtxt(NULL, NULL,
2173 chars, res, filename, XML_CHAR_ENCODING_NONE);
2174 if (ctxt == NULL) {
2175 progresult = XMLLINT_ERR_MEM;
2176 if (f != stdin)
2177 fclose(f);
2178 return;
2179 }
2180 htmlCtxtUseOptions(ctxt, options);
2181 while ((res = fread(chars, 1, pushsize, f)) > 0) {
2182 htmlParseChunk(ctxt, chars, res, 0);
2183 }
2184 htmlParseChunk(ctxt, chars, 0, 1);
2185 doc = ctxt->myDoc;
2186 htmlFreeParserCtxt(ctxt);
2187 }
2188 if (f != stdin)
2189 fclose(f);
2190 }
2191 }
2192 #endif /* LIBXML_PUSH_ENABLED */
2193 #ifdef HAVE_MMAP
2194 else if ((html) && (memory)) {
2195 int fd;
2196 struct stat info;
2197 const char *base;
2198 if (stat(filename, &info) < 0)
2199 return;
2200 if ((fd = open(filename, O_RDONLY)) < 0)
2201 return;
2202 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2203 if (base == (void *) MAP_FAILED) {
2204 close(fd);
2205 fprintf(stderr, "mmap failure for file %s\n", filename);
2206 progresult = XMLLINT_ERR_RDFILE;
2207 return;
2208 }
2209
2210 doc = htmlReadMemory((char *) base, info.st_size, filename,
2211 NULL, options);
2212
2213 munmap((char *) base, info.st_size);
2214 close(fd);
2215 }
2216 #endif
2217 else if (html) {
2218 doc = htmlReadFile(filename, NULL, options);
2219 }
2220 #endif /* LIBXML_HTML_ENABLED */
2221 else {
2222 #ifdef LIBXML_PUSH_ENABLED
2223 /*
2224 * build an XML tree from a string;
2225 */
2226 if (push) {
2227 FILE *f;
2228
2229 /* '-' Usually means stdin -<sven@zen.org> */
2230 if ((filename[0] == '-') && (filename[1] == 0)) {
2231 f = stdin;
2232 } else {
2233 f = fopen(filename, "rb");
2234 }
2235 if (f != NULL) {
2236 int ret;
2237 int res, size = 1024;
2238 char chars[1024];
2239 xmlParserCtxtPtr ctxt;
2240
2241 /* if (repeat) size = 1024; */
2242 res = fread(chars, 1, 4, f);
2243 if (res > 0) {
2244 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
2245 chars, res, filename);
2246 if (ctxt == NULL) {
2247 progresult = XMLLINT_ERR_MEM;
2248 if (f != stdin)
2249 fclose(f);
2250 return;
2251 }
2252 xmlCtxtUseOptions(ctxt, options);
2253 while ((res = fread(chars, 1, size, f)) > 0) {
2254 xmlParseChunk(ctxt, chars, res, 0);
2255 }
2256 xmlParseChunk(ctxt, chars, 0, 1);
2257 doc = ctxt->myDoc;
2258 ret = ctxt->wellFormed;
2259 xmlFreeParserCtxt(ctxt);
2260 if ((!ret) && (!recovery)) {
2261 xmlFreeDoc(doc);
2262 doc = NULL;
2263 }
2264 }
2265 if (f != stdin)
2266 fclose(f);
2267 }
2268 } else
2269 #endif /* LIBXML_PUSH_ENABLED */
2270 if (testIO) {
2271 if ((filename[0] == '-') && (filename[1] == 0)) {
2272 doc = xmlReadFd(0, NULL, NULL, options);
2273 } else {
2274 FILE *f;
2275
2276 f = fopen(filename, "rb");
2277 if (f != NULL) {
2278 if (rectxt == NULL)
2279 doc = xmlReadIO(myRead, myClose, f, filename, NULL,
2280 options);
2281 else
2282 doc = xmlCtxtReadIO(rectxt, myRead, myClose, f,
2283 filename, NULL, options);
2284 } else
2285 doc = NULL;
2286 }
2287 } else if (htmlout) {
2288 xmlParserCtxtPtr ctxt;
2289
2290 if (rectxt == NULL) {
2291 ctxt = xmlNewParserCtxt();
2292 if (ctxt == NULL) {
2293 progresult = XMLLINT_ERR_MEM;
2294 return;
2295 }
2296 } else {
2297 ctxt = rectxt;
2298 }
2299
2300 ctxt->sax->error = xmlHTMLError;
2301 ctxt->sax->warning = xmlHTMLWarning;
2302 ctxt->vctxt.error = xmlHTMLValidityError;
2303 ctxt->vctxt.warning = xmlHTMLValidityWarning;
2304
2305 doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2306
2307 if (rectxt == NULL)
2308 xmlFreeParserCtxt(ctxt);
2309 #ifdef HAVE_MMAP
2310 } else if (memory) {
2311 int fd;
2312 struct stat info;
2313 const char *base;
2314 if (stat(filename, &info) < 0)
2315 return;
2316 if ((fd = open(filename, O_RDONLY)) < 0)
2317 return;
2318 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2319 if (base == (void *) MAP_FAILED) {
2320 close(fd);
2321 fprintf(stderr, "mmap failure for file %s\n", filename);
2322 progresult = XMLLINT_ERR_RDFILE;
2323 return;
2324 }
2325
2326 if (rectxt == NULL)
2327 doc = xmlReadMemory((char *) base, info.st_size,
2328 filename, NULL, options);
2329 else
2330 doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
2331 filename, NULL, options);
2332
2333 munmap((char *) base, info.st_size);
2334 close(fd);
2335 #endif
2336 #ifdef LIBXML_VALID_ENABLED
2337 } else if (valid) {
2338 xmlParserCtxtPtr ctxt = NULL;
2339
2340 if (rectxt == NULL) {
2341 ctxt = xmlNewParserCtxt();
2342 if (ctxt == NULL) {
2343 progresult = XMLLINT_ERR_MEM;
2344 return;
2345 }
2346 } else {
2347 ctxt = rectxt;
2348 }
2349
2350 doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2351
2352 if (ctxt->valid == 0)
2353 progresult = XMLLINT_ERR_RDFILE;
2354 if (rectxt == NULL)
2355 xmlFreeParserCtxt(ctxt);
2356 #endif /* LIBXML_VALID_ENABLED */
2357 } else {
2358 if (rectxt != NULL)
2359 doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
2360 else {
2361 #ifdef LIBXML_SAX1_ENABLED
2362 if (sax1)
2363 doc = xmlParseFile(filename);
2364 else
2365 #endif /* LIBXML_SAX1_ENABLED */
2366 doc = xmlReadFile(filename, NULL, options);
2367 }
2368 }
2369 }
2370
2371 /*
2372 * If we don't have a document we might as well give up. Do we
2373 * want an error message here? <sven@zen.org> */
2374 if (doc == NULL) {
2375 progresult = XMLLINT_ERR_UNCLASS;
2376 return;
2377 }
2378
2379 if ((timing) && (!repeat)) {
2380 endTimer("Parsing");
2381 }
2382
2383 /*
2384 * Remove DOCTYPE nodes
2385 */
2386 if (dropdtd) {
2387 xmlDtdPtr dtd;
2388
2389 dtd = xmlGetIntSubset(doc);
2390 if (dtd != NULL) {
2391 xmlUnlinkNode((xmlNodePtr)dtd);
2392 doc->intSubset = NULL;
2393 xmlFreeDtd(dtd);
2394 }
2395 }
2396
2397 #ifdef LIBXML_XINCLUDE_ENABLED
2398 if (xinclude) {
2399 if ((timing) && (!repeat)) {
2400 startTimer();
2401 }
2402 if (xmlXIncludeProcessFlags(doc, options) < 0)
2403 progresult = XMLLINT_ERR_UNCLASS;
2404 if ((timing) && (!repeat)) {
2405 endTimer("Xinclude processing");
2406 }
2407 }
2408 #endif
2409
2410 #ifdef LIBXML_XPATH_ENABLED
2411 if (xpathquery != NULL) {
2412 doXPathQuery(doc, xpathquery);
2413 }
2414 #endif
2415
2416 #ifdef LIBXML_DEBUG_ENABLED
2417 #ifdef LIBXML_XPATH_ENABLED
2418 /*
2419 * shell interaction
2420 */
2421 if (shell) {
2422 xmlXPathOrderDocElems(doc);
2423 xmlShell(doc, filename, xmlShellReadline, stdout);
2424 }
2425 #endif
2426 #endif
2427
2428 #ifdef LIBXML_TREE_ENABLED
2429 /*
2430 * test intermediate copy if needed.
2431 */
2432 if (copy) {
2433 tmp = doc;
2434 if (timing) {
2435 startTimer();
2436 }
2437 doc = xmlCopyDoc(doc, 1);
2438 if (timing) {
2439 endTimer("Copying");
2440 }
2441 if (timing) {
2442 startTimer();
2443 }
2444 xmlFreeDoc(tmp);
2445 if (timing) {
2446 endTimer("Freeing original");
2447 }
2448 }
2449 #endif /* LIBXML_TREE_ENABLED */
2450
2451 #ifdef LIBXML_VALID_ENABLED
2452 if ((insert) && (!html)) {
2453 const xmlChar* list[256];
2454 int nb, i;
2455 xmlNodePtr node;
2456
2457 if (doc->children != NULL) {
2458 node = doc->children;
2459 while ((node != NULL) && (node->last == NULL)) node = node->next;
2460 if (node != NULL) {
2461 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
2462 if (nb < 0) {
2463 fprintf(stderr, "could not get valid list of elements\n");
2464 } else if (nb == 0) {
2465 fprintf(stderr, "No element can be inserted under root\n");
2466 } else {
2467 fprintf(stderr, "%d element types can be inserted under root:\n",
2468 nb);
2469 for (i = 0;i < nb;i++) {
2470 fprintf(stderr, "%s\n", (char *) list[i]);
2471 }
2472 }
2473 }
2474 }
2475 }else
2476 #endif /* LIBXML_VALID_ENABLED */
2477 #ifdef LIBXML_READER_ENABLED
2478 if (walker) {
2479 walkDoc(doc);
2480 }
2481 #endif /* LIBXML_READER_ENABLED */
2482 #ifdef LIBXML_OUTPUT_ENABLED
2483 if (noout == 0) {
2484 int ret;
2485
2486 /*
2487 * print it.
2488 */
2489 #ifdef LIBXML_DEBUG_ENABLED
2490 if (!debug) {
2491 #endif
2492 if ((timing) && (!repeat)) {
2493 startTimer();
2494 }
2495 #ifdef LIBXML_HTML_ENABLED
2496 if ((html) && (!xmlout)) {
2497 if (compress) {
2498 htmlSaveFile(output ? output : "-", doc);
2499 }
2500 else if (encoding != NULL) {
2501 if (format == 1) {
2502 htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
2503 }
2504 else {
2505 htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
2506 }
2507 }
2508 else if (format == 1) {
2509 htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
2510 }
2511 else {
2512 FILE *out;
2513 if (output == NULL)
2514 out = stdout;
2515 else {
2516 out = fopen(output,"wb");
2517 }
2518 if (out != NULL) {
2519 if (htmlDocDump(out, doc) < 0)
2520 progresult = XMLLINT_ERR_OUT;
2521
2522 if (output != NULL)
2523 fclose(out);
2524 } else {
2525 fprintf(stderr, "failed to open %s\n", output);
2526 progresult = XMLLINT_ERR_OUT;
2527 }
2528 }
2529 if ((timing) && (!repeat)) {
2530 endTimer("Saving");
2531 }
2532 } else
2533 #endif
2534 #ifdef LIBXML_C14N_ENABLED
2535 if (canonical) {
2536 xmlChar *result = NULL;
2537 int size;
2538
2539 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
2540 if (size >= 0) {
2541 if (write(1, result, size) == -1) {
2542 fprintf(stderr, "Can't write data\n");
2543 }
2544 xmlFree(result);
2545 } else {
2546 fprintf(stderr, "Failed to canonicalize\n");
2547 progresult = XMLLINT_ERR_OUT;
2548 }
2549 } else if (canonical_11) {
2550 xmlChar *result = NULL;
2551 int size;
2552
2553 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
2554 if (size >= 0) {
2555 if (write(1, result, size) == -1) {
2556 fprintf(stderr, "Can't write data\n");
2557 }
2558 xmlFree(result);
2559 } else {
2560 fprintf(stderr, "Failed to canonicalize\n");
2561 progresult = XMLLINT_ERR_OUT;
2562 }
2563 } else
2564 if (exc_canonical) {
2565 xmlChar *result = NULL;
2566 int size;
2567
2568 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
2569 if (size >= 0) {
2570 if (write(1, result, size) == -1) {
2571 fprintf(stderr, "Can't write data\n");
2572 }
2573 xmlFree(result);
2574 } else {
2575 fprintf(stderr, "Failed to canonicalize\n");
2576 progresult = XMLLINT_ERR_OUT;
2577 }
2578 } else
2579 #endif
2580 #ifdef HAVE_MMAP
2581 if (memory) {
2582 xmlChar *result;
2583 int len;
2584
2585 if (encoding != NULL) {
2586 if (format == 1) {
2587 xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
2588 } else {
2589 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
2590 }
2591 } else {
2592 if (format == 1)
2593 xmlDocDumpFormatMemory(doc, &result, &len, 1);
2594 else
2595 xmlDocDumpMemory(doc, &result, &len);
2596 }
2597 if (result == NULL) {
2598 fprintf(stderr, "Failed to save\n");
2599 progresult = XMLLINT_ERR_OUT;
2600 } else {
2601 if (write(1, result, len) == -1) {
2602 fprintf(stderr, "Can't write data\n");
2603 }
2604 xmlFree(result);
2605 }
2606
2607 } else
2608 #endif /* HAVE_MMAP */
2609 if (compress) {
2610 xmlSaveFile(output ? output : "-", doc);
2611 } else if (oldout) {
2612 if (encoding != NULL) {
2613 if (format == 1) {
2614 ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
2615 encoding, 1);
2616 }
2617 else {
2618 ret = xmlSaveFileEnc(output ? output : "-", doc,
2619 encoding);
2620 }
2621 if (ret < 0) {
2622 fprintf(stderr, "failed save to %s\n",
2623 output ? output : "-");
2624 progresult = XMLLINT_ERR_OUT;
2625 }
2626 } else if (format == 1) {
2627 ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
2628 if (ret < 0) {
2629 fprintf(stderr, "failed save to %s\n",
2630 output ? output : "-");
2631 progresult = XMLLINT_ERR_OUT;
2632 }
2633 } else {
2634 FILE *out;
2635 if (output == NULL)
2636 out = stdout;
2637 else {
2638 out = fopen(output,"wb");
2639 }
2640 if (out != NULL) {
2641 if (xmlDocDump(out, doc) < 0)
2642 progresult = XMLLINT_ERR_OUT;
2643
2644 if (output != NULL)
2645 fclose(out);
2646 } else {
2647 fprintf(stderr, "failed to open %s\n", output);
2648 progresult = XMLLINT_ERR_OUT;
2649 }
2650 }
2651 } else {
2652 xmlSaveCtxtPtr ctxt;
2653 int saveOpts = 0;
2654
2655 if (format == 1)
2656 saveOpts |= XML_SAVE_FORMAT;
2657 else if (format == 2)
2658 saveOpts |= XML_SAVE_WSNONSIG;
2659
2660 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2661 if (xmlout)
2662 saveOpts |= XML_SAVE_AS_XML;
2663 #endif
2664
2665 if (output == NULL)
2666 ctxt = xmlSaveToFd(1, encoding, saveOpts);
2667 else
2668 ctxt = xmlSaveToFilename(output, encoding, saveOpts);
2669
2670 if (ctxt != NULL) {
2671 if (xmlSaveDoc(ctxt, doc) < 0) {
2672 fprintf(stderr, "failed save to %s\n",
2673 output ? output : "-");
2674 progresult = XMLLINT_ERR_OUT;
2675 }
2676 xmlSaveClose(ctxt);
2677 } else {
2678 progresult = XMLLINT_ERR_OUT;
2679 }
2680 }
2681 if ((timing) && (!repeat)) {
2682 endTimer("Saving");
2683 }
2684 #ifdef LIBXML_DEBUG_ENABLED
2685 } else {
2686 FILE *out;
2687 if (output == NULL)
2688 out = stdout;
2689 else {
2690 out = fopen(output,"wb");
2691 }
2692 if (out != NULL) {
2693 xmlDebugDumpDocument(out, doc);
2694
2695 if (output != NULL)
2696 fclose(out);
2697 } else {
2698 fprintf(stderr, "failed to open %s\n", output);
2699 progresult = XMLLINT_ERR_OUT;
2700 }
2701 }
2702 #endif
2703 }
2704 #endif /* LIBXML_OUTPUT_ENABLED */
2705
2706 #ifdef LIBXML_VALID_ENABLED
2707 /*
2708 * A posteriori validation test
2709 */
2710 if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
2711 xmlDtdPtr dtd;
2712
2713 if ((timing) && (!repeat)) {
2714 startTimer();
2715 }
2716 if (dtdvalid != NULL)
2717 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
2718 else
2719 dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
2720 if ((timing) && (!repeat)) {
2721 endTimer("Parsing DTD");
2722 }
2723 if (dtd == NULL) {
2724 if (dtdvalid != NULL)
2725 xmlGenericError(xmlGenericErrorContext,
2726 "Could not parse DTD %s\n", dtdvalid);
2727 else
2728 xmlGenericError(xmlGenericErrorContext,
2729 "Could not parse DTD %s\n", dtdvalidfpi);
2730 progresult = XMLLINT_ERR_DTD;
2731 } else {
2732 xmlValidCtxtPtr cvp;
2733
2734 if ((cvp = xmlNewValidCtxt()) == NULL) {
2735 xmlGenericError(xmlGenericErrorContext,
2736 "Couldn't allocate validation context\n");
2737 progresult = XMLLINT_ERR_MEM;
2738 xmlFreeDtd(dtd);
2739 return;
2740 }
2741 cvp->userData = NULL;
2742 cvp->error = xmlGenericError;
2743 cvp->warning = xmlGenericError;
2744
2745 if ((timing) && (!repeat)) {
2746 startTimer();
2747 }
2748 if (!xmlValidateDtd(cvp, doc, dtd)) {
2749 if (dtdvalid != NULL)
2750 xmlGenericError(xmlGenericErrorContext,
2751 "Document %s does not validate against %s\n",
2752 filename, dtdvalid);
2753 else
2754 xmlGenericError(xmlGenericErrorContext,
2755 "Document %s does not validate against %s\n",
2756 filename, dtdvalidfpi);
2757 progresult = XMLLINT_ERR_VALID;
2758 }
2759 if ((timing) && (!repeat)) {
2760 endTimer("Validating against DTD");
2761 }
2762 xmlFreeValidCtxt(cvp);
2763 xmlFreeDtd(dtd);
2764 }
2765 } else if (postvalid) {
2766 xmlValidCtxtPtr cvp;
2767
2768 if ((cvp = xmlNewValidCtxt()) == NULL) {
2769 xmlGenericError(xmlGenericErrorContext,
2770 "Couldn't allocate validation context\n");
2771 progresult = XMLLINT_ERR_MEM;
2772 xmlFreeDoc(doc);
2773 return;
2774 }
2775
2776 if ((timing) && (!repeat)) {
2777 startTimer();
2778 }
2779 cvp->userData = NULL;
2780 cvp->error = xmlGenericError;
2781 cvp->warning = xmlGenericError;
2782 if (!xmlValidateDocument(cvp, doc)) {
2783 xmlGenericError(xmlGenericErrorContext,
2784 "Document %s does not validate\n", filename);
2785 progresult = XMLLINT_ERR_VALID;
2786 }
2787 if ((timing) && (!repeat)) {
2788 endTimer("Validating");
2789 }
2790 xmlFreeValidCtxt(cvp);
2791 }
2792 #endif /* LIBXML_VALID_ENABLED */
2793 #ifdef LIBXML_SCHEMATRON_ENABLED
2794 if (wxschematron != NULL) {
2795 xmlSchematronValidCtxtPtr ctxt;
2796 int ret;
2797 int flag;
2798
2799 if ((timing) && (!repeat)) {
2800 startTimer();
2801 }
2802
2803 if (debug)
2804 flag = XML_SCHEMATRON_OUT_XML;
2805 else
2806 flag = XML_SCHEMATRON_OUT_TEXT;
2807 if (noout)
2808 flag |= XML_SCHEMATRON_OUT_QUIET;
2809 ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
2810 if (ctxt == NULL) {
2811 progresult = XMLLINT_ERR_MEM;
2812 xmlFreeDoc(doc);
2813 return;
2814 }
2815 #if 0
2816 xmlSchematronSetValidErrors(ctxt, xmlGenericError, xmlGenericError,
2817 NULL);
2818 #endif
2819 ret = xmlSchematronValidateDoc(ctxt, doc);
2820 if (ret == 0) {
2821 if (!quiet) {
2822 fprintf(stderr, "%s validates\n", filename);
2823 }
2824 } else if (ret > 0) {
2825 fprintf(stderr, "%s fails to validate\n", filename);
2826 progresult = XMLLINT_ERR_VALID;
2827 } else {
2828 fprintf(stderr, "%s validation generated an internal error\n",
2829 filename);
2830 progresult = XMLLINT_ERR_VALID;
2831 }
2832 xmlSchematronFreeValidCtxt(ctxt);
2833 if ((timing) && (!repeat)) {
2834 endTimer("Validating");
2835 }
2836 }
2837 #endif
2838 #ifdef LIBXML_SCHEMAS_ENABLED
2839 if (relaxngschemas != NULL) {
2840 xmlRelaxNGValidCtxtPtr ctxt;
2841 int ret;
2842
2843 if ((timing) && (!repeat)) {
2844 startTimer();
2845 }
2846
2847 ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2848 if (ctxt == NULL) {
2849 progresult = XMLLINT_ERR_MEM;
2850 xmlFreeDoc(doc);
2851 return;
2852 }
2853 xmlRelaxNGSetValidErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
2854 ret = xmlRelaxNGValidateDoc(ctxt, doc);
2855 if (ret == 0) {
2856 if (!quiet) {
2857 fprintf(stderr, "%s validates\n", filename);
2858 }
2859 } else if (ret > 0) {
2860 fprintf(stderr, "%s fails to validate\n", filename);
2861 progresult = XMLLINT_ERR_VALID;
2862 } else {
2863 fprintf(stderr, "%s validation generated an internal error\n",
2864 filename);
2865 progresult = XMLLINT_ERR_VALID;
2866 }
2867 xmlRelaxNGFreeValidCtxt(ctxt);
2868 if ((timing) && (!repeat)) {
2869 endTimer("Validating");
2870 }
2871 } else if (wxschemas != NULL) {
2872 xmlSchemaValidCtxtPtr ctxt;
2873 int ret;
2874
2875 if ((timing) && (!repeat)) {
2876 startTimer();
2877 }
2878
2879 ctxt = xmlSchemaNewValidCtxt(wxschemas);
2880 if (ctxt == NULL) {
2881 progresult = XMLLINT_ERR_MEM;
2882 xmlFreeDoc(doc);
2883 return;
2884 }
2885 xmlSchemaSetValidErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
2886 ret = xmlSchemaValidateDoc(ctxt, doc);
2887 if (ret == 0) {
2888 if (!quiet) {
2889 fprintf(stderr, "%s validates\n", filename);
2890 }
2891 } else if (ret > 0) {
2892 fprintf(stderr, "%s fails to validate\n", filename);
2893 progresult = XMLLINT_ERR_VALID;
2894 } else {
2895 fprintf(stderr, "%s validation generated an internal error\n",
2896 filename);
2897 progresult = XMLLINT_ERR_VALID;
2898 }
2899 xmlSchemaFreeValidCtxt(ctxt);
2900 if ((timing) && (!repeat)) {
2901 endTimer("Validating");
2902 }
2903 }
2904 #endif
2905
2906 #ifdef LIBXML_DEBUG_ENABLED
2907 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2908 if ((debugent) && (!html))
2909 xmlDebugDumpEntities(stderr, doc);
2910 #endif
2911 #endif
2912
2913 /*
2914 * free it.
2915 */
2916 if ((timing) && (!repeat)) {
2917 startTimer();
2918 }
2919 xmlFreeDoc(doc);
2920 if ((timing) && (!repeat)) {
2921 endTimer("Freeing");
2922 }
2923 }
2924
2925 /************************************************************************
2926 * *
2927 * Usage and Main *
2928 * *
2929 ************************************************************************/
2930
showVersion(const char * name)2931 static void showVersion(const char *name) {
2932 fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
2933 fprintf(stderr, " compiled with: ");
2934 if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
2935 if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
2936 if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
2937 if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
2938 if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
2939 if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
2940 if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
2941 if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
2942 if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP ");
2943 if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP ");
2944 if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
2945 if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML ");
2946 if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy ");
2947 if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N ");
2948 if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog ");
2949 if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath ");
2950 if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer ");
2951 if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude ");
2952 if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv ");
2953 if (xmlHasFeature(XML_WITH_ICU)) fprintf(stderr, "ICU ");
2954 if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X ");
2955 if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode ");
2956 if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps ");
2957 if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata ");
2958 if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr ");
2959 if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas ");
2960 if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron ");
2961 if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules ");
2962 if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug ");
2963 if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug ");
2964 if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug ");
2965 if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
2966 if (xmlHasFeature(XML_WITH_LZMA)) fprintf(stderr, "Lzma ");
2967 fprintf(stderr, "\n");
2968 }
2969
usage(FILE * f,const char * name)2970 static void usage(FILE *f, const char *name) {
2971 fprintf(f, "Usage : %s [options] XMLfiles ...\n", name);
2972 #ifdef LIBXML_OUTPUT_ENABLED
2973 fprintf(f, "\tParse the XML files and output the result of the parsing\n");
2974 #else
2975 fprintf(f, "\tParse the XML files\n");
2976 #endif /* LIBXML_OUTPUT_ENABLED */
2977 fprintf(f, "\t--version : display the version of the XML library used\n");
2978 #ifdef LIBXML_DEBUG_ENABLED
2979 fprintf(f, "\t--debug : dump a debug tree of the in-memory document\n");
2980 fprintf(f, "\t--shell : run a navigating shell\n");
2981 fprintf(f, "\t--debugent : debug the entities defined in the document\n");
2982 #else
2983 #ifdef LIBXML_READER_ENABLED
2984 fprintf(f, "\t--debug : dump the nodes content when using --stream\n");
2985 #endif /* LIBXML_READER_ENABLED */
2986 #endif
2987 #ifdef LIBXML_TREE_ENABLED
2988 fprintf(f, "\t--copy : used to test the internal copy implementation\n");
2989 #endif /* LIBXML_TREE_ENABLED */
2990 fprintf(f, "\t--recover : output what was parsable on broken XML documents\n");
2991 fprintf(f, "\t--huge : remove any internal arbitrary parser limits\n");
2992 fprintf(f, "\t--noent : substitute entity references by their value\n");
2993 fprintf(f, "\t--noenc : ignore any encoding specified inside the document\n");
2994 fprintf(f, "\t--noout : don't output the result tree\n");
2995 fprintf(f, "\t--path 'paths': provide a set of paths for resources\n");
2996 fprintf(f, "\t--load-trace : print trace of all external entities loaded\n");
2997 fprintf(f, "\t--nonet : refuse to fetch DTDs or entities over network\n");
2998 fprintf(f, "\t--nocompact : do not generate compact text nodes\n");
2999 fprintf(f, "\t--htmlout : output results as HTML\n");
3000 fprintf(f, "\t--nowrap : do not put HTML doc wrapper\n");
3001 #ifdef LIBXML_VALID_ENABLED
3002 fprintf(f, "\t--valid : validate the document in addition to std well-formed check\n");
3003 fprintf(f, "\t--postvalid : do a posteriori validation, i.e after parsing\n");
3004 fprintf(f, "\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
3005 fprintf(f, "\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
3006 #endif /* LIBXML_VALID_ENABLED */
3007 fprintf(f, "\t--quiet : be quiet when succeeded\n");
3008 fprintf(f, "\t--timing : print some timings\n");
3009 fprintf(f, "\t--output file or -o file: save to a given file\n");
3010 fprintf(f, "\t--repeat : repeat 100 times, for timing or profiling\n");
3011 fprintf(f, "\t--insert : ad-hoc test for valid insertions\n");
3012 #ifdef LIBXML_OUTPUT_ENABLED
3013 #ifdef LIBXML_ZLIB_ENABLED
3014 fprintf(f, "\t--compress : turn on gzip compression of output\n");
3015 #endif
3016 #endif /* LIBXML_OUTPUT_ENABLED */
3017 #ifdef LIBXML_HTML_ENABLED
3018 fprintf(f, "\t--html : use the HTML parser\n");
3019 fprintf(f, "\t--xmlout : force to use the XML serializer when using --html\n");
3020 fprintf(f, "\t--nodefdtd : do not default HTML doctype\n");
3021 #endif
3022 #ifdef LIBXML_PUSH_ENABLED
3023 fprintf(f, "\t--push : use the push mode of the parser\n");
3024 fprintf(f, "\t--pushsmall : use the push mode of the parser using tiny increments\n");
3025 #endif /* LIBXML_PUSH_ENABLED */
3026 #ifdef HAVE_MMAP
3027 fprintf(f, "\t--memory : parse from memory\n");
3028 #endif
3029 fprintf(f, "\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
3030 fprintf(f, "\t--nowarning : do not emit warnings from parser/validator\n");
3031 fprintf(f, "\t--noblanks : drop (ignorable?) blanks spaces\n");
3032 fprintf(f, "\t--nocdata : replace cdata section with text nodes\n");
3033 #ifdef LIBXML_OUTPUT_ENABLED
3034 fprintf(f, "\t--format : reformat/reindent the output\n");
3035 fprintf(f, "\t--encode encoding : output in the given encoding\n");
3036 fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n");
3037 fprintf(f, "\t--pretty STYLE : pretty-print in a particular style\n");
3038 fprintf(f, "\t 0 Do not pretty print\n");
3039 fprintf(f, "\t 1 Format the XML content, as --format\n");
3040 fprintf(f, "\t 2 Add whitespace inside tags, preserving content\n");
3041 #endif /* LIBXML_OUTPUT_ENABLED */
3042 fprintf(f, "\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
3043 fprintf(f, "\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
3044 fprintf(f, "\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
3045 #ifdef LIBXML_C14N_ENABLED
3046 #endif /* LIBXML_C14N_ENABLED */
3047 fprintf(f, "\t--nsclean : remove redundant namespace declarations\n");
3048 fprintf(f, "\t--testIO : test user I/O support\n");
3049 #ifdef LIBXML_CATALOG_ENABLED
3050 fprintf(f, "\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
3051 fprintf(f, "\t otherwise XML Catalogs starting from \n");
3052 fprintf(f, "\t %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
3053 fprintf(f, "\t--nocatalogs: deactivate all catalogs\n");
3054 #endif
3055 fprintf(f, "\t--auto : generate a small doc on the fly\n");
3056 #ifdef LIBXML_XINCLUDE_ENABLED
3057 fprintf(f, "\t--xinclude : do XInclude processing\n");
3058 fprintf(f, "\t--noxincludenode : same but do not generate XInclude nodes\n");
3059 fprintf(f, "\t--nofixup-base-uris : do not fixup xml:base uris\n");
3060 #endif
3061 fprintf(f, "\t--loaddtd : fetch external DTD\n");
3062 fprintf(f, "\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
3063 #ifdef LIBXML_READER_ENABLED
3064 fprintf(f, "\t--stream : use the streaming interface to process very large files\n");
3065 fprintf(f, "\t--walker : create a reader and walk though the resulting doc\n");
3066 #ifdef LIBXML_PATTERN_ENABLED
3067 fprintf(f, "\t--pattern pattern_value : test the pattern support\n");
3068 #endif
3069 #endif /* LIBXML_READER_ENABLED */
3070 fprintf(f, "\t--chkregister : verify the node registration code\n");
3071 #ifdef LIBXML_SCHEMAS_ENABLED
3072 fprintf(f, "\t--relaxng schema : do RelaxNG validation against the schema\n");
3073 fprintf(f, "\t--schema schema : do validation against the WXS schema\n");
3074 #endif
3075 #ifdef LIBXML_SCHEMATRON_ENABLED
3076 fprintf(f, "\t--schematron schema : do validation against a schematron\n");
3077 #endif
3078 #ifdef LIBXML_SAX1_ENABLED
3079 fprintf(f, "\t--sax1: use the old SAX1 interfaces for processing\n");
3080 #endif
3081 fprintf(f, "\t--sax: do not build a tree but work just at the SAX level\n");
3082 fprintf(f, "\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
3083 #ifdef LIBXML_XPATH_ENABLED
3084 fprintf(f, "\t--xpath expr: evaluate the XPath expression, imply --noout\n");
3085 #endif
3086
3087 fprintf(f, "\nLibxml project home page: https://gitlab.gnome.org/GNOME/libxml2\n");
3088 }
3089
registerNode(xmlNodePtr node)3090 static void registerNode(xmlNodePtr node)
3091 {
3092 node->_private = malloc(sizeof(long));
3093 if (node->_private == NULL) {
3094 fprintf(stderr, "Out of memory in xmllint:registerNode()\n");
3095 exit(XMLLINT_ERR_MEM);
3096 }
3097 *(long*)node->_private = (long) 0x81726354;
3098 nbregister++;
3099 }
3100
deregisterNode(xmlNodePtr node)3101 static void deregisterNode(xmlNodePtr node)
3102 {
3103 assert(node->_private != NULL);
3104 assert(*(long*)node->_private == (long) 0x81726354);
3105 free(node->_private);
3106 nbregister--;
3107 }
3108
3109 int
main(int argc,char ** argv)3110 main(int argc, char **argv) {
3111 int i, acount;
3112 int files = 0;
3113 int version = 0;
3114 const char* indent;
3115
3116 if (argc <= 1) {
3117 usage(stderr, argv[0]);
3118 return(XMLLINT_ERR_UNCLASS);
3119 }
3120
3121 /* xmlMemSetup must be called before initializing the parser. */
3122 for (i = 1; i < argc ; i++) {
3123 if (argv[i][0] != '-')
3124 continue;
3125
3126 if ((!strcmp(argv[i], "-maxmem")) ||
3127 (!strcmp(argv[i], "--maxmem"))) {
3128 i++;
3129 if ((i >= argc) || (sscanf(argv[i], "%d", &maxmem) != 1)) {
3130 maxmem = 0;
3131 }
3132 }
3133 }
3134 if (maxmem != 0)
3135 xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc, myStrdupFunc);
3136
3137 LIBXML_TEST_VERSION
3138
3139 for (i = 1; i < argc ; i++) {
3140 if (argv[i][0] != '-' || argv[i][1] == 0)
3141 continue;
3142
3143 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
3144 debug++;
3145 else
3146 #ifdef LIBXML_DEBUG_ENABLED
3147 if ((!strcmp(argv[i], "-shell")) ||
3148 (!strcmp(argv[i], "--shell"))) {
3149 shell++;
3150 noout = 1;
3151 } else
3152 #endif
3153 #ifdef LIBXML_TREE_ENABLED
3154 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
3155 copy++;
3156 else
3157 #endif /* LIBXML_TREE_ENABLED */
3158 if ((!strcmp(argv[i], "-recover")) ||
3159 (!strcmp(argv[i], "--recover"))) {
3160 recovery++;
3161 options |= XML_PARSE_RECOVER;
3162 } else if ((!strcmp(argv[i], "-huge")) ||
3163 (!strcmp(argv[i], "--huge"))) {
3164 options |= XML_PARSE_HUGE;
3165 } else if ((!strcmp(argv[i], "-noent")) ||
3166 (!strcmp(argv[i], "--noent"))) {
3167 noent++;
3168 options |= XML_PARSE_NOENT;
3169 } else if ((!strcmp(argv[i], "-noenc")) ||
3170 (!strcmp(argv[i], "--noenc"))) {
3171 noenc++;
3172 options |= XML_PARSE_IGNORE_ENC;
3173 } else if ((!strcmp(argv[i], "-nsclean")) ||
3174 (!strcmp(argv[i], "--nsclean"))) {
3175 options |= XML_PARSE_NSCLEAN;
3176 } else if ((!strcmp(argv[i], "-nocdata")) ||
3177 (!strcmp(argv[i], "--nocdata"))) {
3178 options |= XML_PARSE_NOCDATA;
3179 } else if ((!strcmp(argv[i], "-nodict")) ||
3180 (!strcmp(argv[i], "--nodict"))) {
3181 options |= XML_PARSE_NODICT;
3182 } else if ((!strcmp(argv[i], "-version")) ||
3183 (!strcmp(argv[i], "--version"))) {
3184 showVersion(argv[0]);
3185 version = 1;
3186 } else if ((!strcmp(argv[i], "-noout")) ||
3187 (!strcmp(argv[i], "--noout")))
3188 noout++;
3189 #ifdef LIBXML_OUTPUT_ENABLED
3190 else if ((!strcmp(argv[i], "-o")) ||
3191 (!strcmp(argv[i], "-output")) ||
3192 (!strcmp(argv[i], "--output"))) {
3193 i++;
3194 output = argv[i];
3195 }
3196 #endif /* LIBXML_OUTPUT_ENABLED */
3197 else if ((!strcmp(argv[i], "-htmlout")) ||
3198 (!strcmp(argv[i], "--htmlout")))
3199 htmlout++;
3200 else if ((!strcmp(argv[i], "-nowrap")) ||
3201 (!strcmp(argv[i], "--nowrap")))
3202 nowrap++;
3203 #ifdef LIBXML_HTML_ENABLED
3204 else if ((!strcmp(argv[i], "-html")) ||
3205 (!strcmp(argv[i], "--html"))) {
3206 html++;
3207 }
3208 else if ((!strcmp(argv[i], "-xmlout")) ||
3209 (!strcmp(argv[i], "--xmlout"))) {
3210 xmlout++;
3211 } else if ((!strcmp(argv[i], "-nodefdtd")) ||
3212 (!strcmp(argv[i], "--nodefdtd"))) {
3213 nodefdtd++;
3214 options |= HTML_PARSE_NODEFDTD;
3215 }
3216 #endif /* LIBXML_HTML_ENABLED */
3217 else if ((!strcmp(argv[i], "-loaddtd")) ||
3218 (!strcmp(argv[i], "--loaddtd"))) {
3219 loaddtd++;
3220 options |= XML_PARSE_DTDLOAD;
3221 } else if ((!strcmp(argv[i], "-dtdattr")) ||
3222 (!strcmp(argv[i], "--dtdattr"))) {
3223 loaddtd++;
3224 dtdattrs++;
3225 options |= XML_PARSE_DTDATTR;
3226 }
3227 #ifdef LIBXML_VALID_ENABLED
3228 else if ((!strcmp(argv[i], "-valid")) ||
3229 (!strcmp(argv[i], "--valid"))) {
3230 valid++;
3231 options |= XML_PARSE_DTDVALID;
3232 } else if ((!strcmp(argv[i], "-postvalid")) ||
3233 (!strcmp(argv[i], "--postvalid"))) {
3234 postvalid++;
3235 loaddtd++;
3236 options |= XML_PARSE_DTDLOAD;
3237 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
3238 (!strcmp(argv[i], "--dtdvalid"))) {
3239 i++;
3240 dtdvalid = argv[i];
3241 loaddtd++;
3242 options |= XML_PARSE_DTDLOAD;
3243 } else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3244 (!strcmp(argv[i], "--dtdvalidfpi"))) {
3245 i++;
3246 dtdvalidfpi = argv[i];
3247 loaddtd++;
3248 options |= XML_PARSE_DTDLOAD;
3249 }
3250 #endif /* LIBXML_VALID_ENABLED */
3251 else if ((!strcmp(argv[i], "-dropdtd")) ||
3252 (!strcmp(argv[i], "--dropdtd")))
3253 dropdtd++;
3254 else if ((!strcmp(argv[i], "-insert")) ||
3255 (!strcmp(argv[i], "--insert")))
3256 insert++;
3257 else if ((!strcmp(argv[i], "-quiet")) ||
3258 (!strcmp(argv[i], "--quiet")))
3259 quiet++;
3260 else if ((!strcmp(argv[i], "-timing")) ||
3261 (!strcmp(argv[i], "--timing")))
3262 timing++;
3263 else if ((!strcmp(argv[i], "-auto")) ||
3264 (!strcmp(argv[i], "--auto")))
3265 generate++;
3266 else if ((!strcmp(argv[i], "-repeat")) ||
3267 (!strcmp(argv[i], "--repeat"))) {
3268 if (repeat)
3269 repeat *= 10;
3270 else
3271 repeat = 100;
3272 }
3273 #ifdef LIBXML_PUSH_ENABLED
3274 else if ((!strcmp(argv[i], "-push")) ||
3275 (!strcmp(argv[i], "--push")))
3276 push++;
3277 else if ((!strcmp(argv[i], "-pushsmall")) ||
3278 (!strcmp(argv[i], "--pushsmall"))) {
3279 push++;
3280 pushsize = 10;
3281 }
3282 #endif /* LIBXML_PUSH_ENABLED */
3283 #ifdef HAVE_MMAP
3284 else if ((!strcmp(argv[i], "-memory")) ||
3285 (!strcmp(argv[i], "--memory")))
3286 memory++;
3287 #endif
3288 else if ((!strcmp(argv[i], "-testIO")) ||
3289 (!strcmp(argv[i], "--testIO")))
3290 testIO++;
3291 #ifdef LIBXML_XINCLUDE_ENABLED
3292 else if ((!strcmp(argv[i], "-xinclude")) ||
3293 (!strcmp(argv[i], "--xinclude"))) {
3294 xinclude++;
3295 options |= XML_PARSE_XINCLUDE;
3296 }
3297 else if ((!strcmp(argv[i], "-noxincludenode")) ||
3298 (!strcmp(argv[i], "--noxincludenode"))) {
3299 xinclude++;
3300 options |= XML_PARSE_XINCLUDE;
3301 options |= XML_PARSE_NOXINCNODE;
3302 }
3303 else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
3304 (!strcmp(argv[i], "--nofixup-base-uris"))) {
3305 xinclude++;
3306 options |= XML_PARSE_XINCLUDE;
3307 options |= XML_PARSE_NOBASEFIX;
3308 }
3309 #endif
3310 #ifdef LIBXML_OUTPUT_ENABLED
3311 #ifdef LIBXML_ZLIB_ENABLED
3312 else if ((!strcmp(argv[i], "-compress")) ||
3313 (!strcmp(argv[i], "--compress"))) {
3314 compress++;
3315 xmlSetCompressMode(9);
3316 }
3317 #endif
3318 #endif /* LIBXML_OUTPUT_ENABLED */
3319 else if ((!strcmp(argv[i], "-nowarning")) ||
3320 (!strcmp(argv[i], "--nowarning"))) {
3321 xmlGetWarningsDefaultValue = 0;
3322 xmlPedanticParserDefault(0);
3323 options |= XML_PARSE_NOWARNING;
3324 }
3325 else if ((!strcmp(argv[i], "-pedantic")) ||
3326 (!strcmp(argv[i], "--pedantic"))) {
3327 xmlGetWarningsDefaultValue = 1;
3328 xmlPedanticParserDefault(1);
3329 options |= XML_PARSE_PEDANTIC;
3330 }
3331 #ifdef LIBXML_DEBUG_ENABLED
3332 else if ((!strcmp(argv[i], "-debugent")) ||
3333 (!strcmp(argv[i], "--debugent"))) {
3334 debugent++;
3335 xmlParserDebugEntities = 1;
3336 }
3337 #endif
3338 #ifdef LIBXML_C14N_ENABLED
3339 else if ((!strcmp(argv[i], "-c14n")) ||
3340 (!strcmp(argv[i], "--c14n"))) {
3341 canonical++;
3342 options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3343 }
3344 else if ((!strcmp(argv[i], "-c14n11")) ||
3345 (!strcmp(argv[i], "--c14n11"))) {
3346 canonical_11++;
3347 options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3348 }
3349 else if ((!strcmp(argv[i], "-exc-c14n")) ||
3350 (!strcmp(argv[i], "--exc-c14n"))) {
3351 exc_canonical++;
3352 options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3353 }
3354 #endif
3355 #ifdef LIBXML_CATALOG_ENABLED
3356 else if ((!strcmp(argv[i], "-catalogs")) ||
3357 (!strcmp(argv[i], "--catalogs"))) {
3358 catalogs++;
3359 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
3360 (!strcmp(argv[i], "--nocatalogs"))) {
3361 nocatalogs++;
3362 }
3363 #endif
3364 else if ((!strcmp(argv[i], "-encode")) ||
3365 (!strcmp(argv[i], "--encode"))) {
3366 i++;
3367 encoding = argv[i];
3368 /*
3369 * OK it's for testing purposes
3370 */
3371 xmlAddEncodingAlias("UTF-8", "DVEnc");
3372 }
3373 else if ((!strcmp(argv[i], "-noblanks")) ||
3374 (!strcmp(argv[i], "--noblanks"))) {
3375 noblanks++;
3376 xmlKeepBlanksDefault(0);
3377 options |= XML_PARSE_NOBLANKS;
3378 }
3379 else if ((!strcmp(argv[i], "-maxmem")) ||
3380 (!strcmp(argv[i], "--maxmem"))) {
3381 i++;
3382 }
3383 else if ((!strcmp(argv[i], "-format")) ||
3384 (!strcmp(argv[i], "--format"))) {
3385 noblanks++;
3386 #ifdef LIBXML_OUTPUT_ENABLED
3387 format = 1;
3388 #endif /* LIBXML_OUTPUT_ENABLED */
3389 xmlKeepBlanksDefault(0);
3390 }
3391 else if ((!strcmp(argv[i], "-pretty")) ||
3392 (!strcmp(argv[i], "--pretty"))) {
3393 i++;
3394 #ifdef LIBXML_OUTPUT_ENABLED
3395 if (argv[i] != NULL) {
3396 format = atoi(argv[i]);
3397 if (format == 1) {
3398 noblanks++;
3399 xmlKeepBlanksDefault(0);
3400 }
3401 }
3402 #endif /* LIBXML_OUTPUT_ENABLED */
3403 }
3404 #ifdef LIBXML_READER_ENABLED
3405 else if ((!strcmp(argv[i], "-stream")) ||
3406 (!strcmp(argv[i], "--stream"))) {
3407 stream++;
3408 }
3409 else if ((!strcmp(argv[i], "-walker")) ||
3410 (!strcmp(argv[i], "--walker"))) {
3411 walker++;
3412 noout++;
3413 #ifdef LIBXML_PATTERN_ENABLED
3414 } else if ((!strcmp(argv[i], "-pattern")) ||
3415 (!strcmp(argv[i], "--pattern"))) {
3416 i++;
3417 pattern = argv[i];
3418 #endif
3419 }
3420 #endif /* LIBXML_READER_ENABLED */
3421 #ifdef LIBXML_SAX1_ENABLED
3422 else if ((!strcmp(argv[i], "-sax1")) ||
3423 (!strcmp(argv[i], "--sax1"))) {
3424 sax1++;
3425 options |= XML_PARSE_SAX1;
3426 }
3427 #endif /* LIBXML_SAX1_ENABLED */
3428 else if ((!strcmp(argv[i], "-sax")) ||
3429 (!strcmp(argv[i], "--sax"))) {
3430 sax++;
3431 }
3432 else if ((!strcmp(argv[i], "-chkregister")) ||
3433 (!strcmp(argv[i], "--chkregister"))) {
3434 chkregister++;
3435 #ifdef LIBXML_SCHEMAS_ENABLED
3436 } else if ((!strcmp(argv[i], "-relaxng")) ||
3437 (!strcmp(argv[i], "--relaxng"))) {
3438 i++;
3439 relaxng = argv[i];
3440 noent++;
3441 options |= XML_PARSE_NOENT;
3442 } else if ((!strcmp(argv[i], "-schema")) ||
3443 (!strcmp(argv[i], "--schema"))) {
3444 i++;
3445 schema = argv[i];
3446 noent++;
3447 #endif
3448 #ifdef LIBXML_SCHEMATRON_ENABLED
3449 } else if ((!strcmp(argv[i], "-schematron")) ||
3450 (!strcmp(argv[i], "--schematron"))) {
3451 i++;
3452 schematron = argv[i];
3453 noent++;
3454 #endif
3455 } else if ((!strcmp(argv[i], "-nonet")) ||
3456 (!strcmp(argv[i], "--nonet"))) {
3457 options |= XML_PARSE_NONET;
3458 xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
3459 } else if ((!strcmp(argv[i], "-nocompact")) ||
3460 (!strcmp(argv[i], "--nocompact"))) {
3461 options &= ~XML_PARSE_COMPACT;
3462 } else if ((!strcmp(argv[i], "-load-trace")) ||
3463 (!strcmp(argv[i], "--load-trace"))) {
3464 load_trace++;
3465 } else if ((!strcmp(argv[i], "-path")) ||
3466 (!strcmp(argv[i], "--path"))) {
3467 i++;
3468 parsePath(BAD_CAST argv[i]);
3469 #ifdef LIBXML_XPATH_ENABLED
3470 } else if ((!strcmp(argv[i], "-xpath")) ||
3471 (!strcmp(argv[i], "--xpath"))) {
3472 i++;
3473 noout++;
3474 xpathquery = argv[i];
3475 #endif
3476 } else if ((!strcmp(argv[i], "-oldxml10")) ||
3477 (!strcmp(argv[i], "--oldxml10"))) {
3478 oldxml10++;
3479 options |= XML_PARSE_OLD10;
3480 } else {
3481 fprintf(stderr, "Unknown option %s\n", argv[i]);
3482 usage(stderr, argv[0]);
3483 return(XMLLINT_ERR_UNCLASS);
3484 }
3485 }
3486
3487 #ifdef LIBXML_CATALOG_ENABLED
3488 if (nocatalogs == 0) {
3489 if (catalogs) {
3490 const char *catal;
3491
3492 catal = getenv("SGML_CATALOG_FILES");
3493 if (catal != NULL) {
3494 xmlLoadCatalogs(catal);
3495 } else {
3496 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
3497 }
3498 }
3499 }
3500 #endif
3501
3502 #ifdef LIBXML_SAX1_ENABLED
3503 if (sax1)
3504 xmlSAXDefaultVersion(1);
3505 else
3506 xmlSAXDefaultVersion(2);
3507 #endif /* LIBXML_SAX1_ENABLED */
3508
3509 if (chkregister) {
3510 xmlRegisterNodeDefault(registerNode);
3511 xmlDeregisterNodeDefault(deregisterNode);
3512 }
3513
3514 indent = getenv("XMLLINT_INDENT");
3515 if(indent != NULL) {
3516 xmlTreeIndentString = indent;
3517 }
3518
3519
3520 defaultEntityLoader = xmlGetExternalEntityLoader();
3521 xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
3522
3523 xmlLineNumbersDefault(1);
3524 if (loaddtd != 0)
3525 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
3526 if (dtdattrs)
3527 xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
3528 if (noent != 0) xmlSubstituteEntitiesDefault(1);
3529 #ifdef LIBXML_VALID_ENABLED
3530 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
3531 #endif /* LIBXML_VALID_ENABLED */
3532 if ((htmlout) && (!nowrap)) {
3533 xmlGenericError(xmlGenericErrorContext,
3534 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
3535 xmlGenericError(xmlGenericErrorContext,
3536 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
3537 xmlGenericError(xmlGenericErrorContext,
3538 "<html><head><title>%s output</title></head>\n",
3539 argv[0]);
3540 xmlGenericError(xmlGenericErrorContext,
3541 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
3542 argv[0]);
3543 }
3544
3545 #ifdef LIBXML_SCHEMATRON_ENABLED
3546 if ((schematron != NULL) && (sax == 0)
3547 #ifdef LIBXML_READER_ENABLED
3548 && (stream == 0)
3549 #endif /* LIBXML_READER_ENABLED */
3550 ) {
3551 xmlSchematronParserCtxtPtr ctxt;
3552
3553 /* forces loading the DTDs */
3554 xmlLoadExtDtdDefaultValue |= 1;
3555 options |= XML_PARSE_DTDLOAD;
3556 if (timing) {
3557 startTimer();
3558 }
3559 ctxt = xmlSchematronNewParserCtxt(schematron);
3560 if (ctxt == NULL) {
3561 progresult = XMLLINT_ERR_MEM;
3562 goto error;
3563 }
3564 #if 0
3565 xmlSchematronSetParserErrors(ctxt, xmlGenericError, xmlGenericError,
3566 NULL);
3567 #endif
3568 wxschematron = xmlSchematronParse(ctxt);
3569 if (wxschematron == NULL) {
3570 xmlGenericError(xmlGenericErrorContext,
3571 "Schematron schema %s failed to compile\n", schematron);
3572 progresult = XMLLINT_ERR_SCHEMACOMP;
3573 schematron = NULL;
3574 }
3575 xmlSchematronFreeParserCtxt(ctxt);
3576 if (timing) {
3577 endTimer("Compiling the schemas");
3578 }
3579 }
3580 #endif
3581 #ifdef LIBXML_SCHEMAS_ENABLED
3582 if ((relaxng != NULL) && (sax == 0)
3583 #ifdef LIBXML_READER_ENABLED
3584 && (stream == 0)
3585 #endif /* LIBXML_READER_ENABLED */
3586 ) {
3587 xmlRelaxNGParserCtxtPtr ctxt;
3588
3589 /* forces loading the DTDs */
3590 xmlLoadExtDtdDefaultValue |= 1;
3591 options |= XML_PARSE_DTDLOAD;
3592 if (timing) {
3593 startTimer();
3594 }
3595 ctxt = xmlRelaxNGNewParserCtxt(relaxng);
3596 if (ctxt == NULL) {
3597 progresult = XMLLINT_ERR_MEM;
3598 goto error;
3599 }
3600 xmlRelaxNGSetParserErrors(ctxt, xmlGenericError, xmlGenericError,
3601 NULL);
3602 relaxngschemas = xmlRelaxNGParse(ctxt);
3603 if (relaxngschemas == NULL) {
3604 xmlGenericError(xmlGenericErrorContext,
3605 "Relax-NG schema %s failed to compile\n", relaxng);
3606 progresult = XMLLINT_ERR_SCHEMACOMP;
3607 relaxng = NULL;
3608 }
3609 xmlRelaxNGFreeParserCtxt(ctxt);
3610 if (timing) {
3611 endTimer("Compiling the schemas");
3612 }
3613 } else if ((schema != NULL)
3614 #ifdef LIBXML_READER_ENABLED
3615 && (stream == 0)
3616 #endif
3617 ) {
3618 xmlSchemaParserCtxtPtr ctxt;
3619
3620 if (timing) {
3621 startTimer();
3622 }
3623 ctxt = xmlSchemaNewParserCtxt(schema);
3624 if (ctxt == NULL) {
3625 progresult = XMLLINT_ERR_MEM;
3626 goto error;
3627 }
3628 xmlSchemaSetParserErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
3629 wxschemas = xmlSchemaParse(ctxt);
3630 if (wxschemas == NULL) {
3631 xmlGenericError(xmlGenericErrorContext,
3632 "WXS schema %s failed to compile\n", schema);
3633 progresult = XMLLINT_ERR_SCHEMACOMP;
3634 schema = NULL;
3635 }
3636 xmlSchemaFreeParserCtxt(ctxt);
3637 if (timing) {
3638 endTimer("Compiling the schemas");
3639 }
3640 }
3641 #endif /* LIBXML_SCHEMAS_ENABLED */
3642 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3643 if ((pattern != NULL) && (walker == 0)) {
3644 patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
3645 if (patternc == NULL) {
3646 xmlGenericError(xmlGenericErrorContext,
3647 "Pattern %s failed to compile\n", pattern);
3648 progresult = XMLLINT_ERR_SCHEMAPAT;
3649 pattern = NULL;
3650 }
3651 }
3652 #endif /* LIBXML_READER_ENABLED && LIBXML_PATTERN_ENABLED */
3653 for (i = 1; i < argc ; i++) {
3654 if ((!strcmp(argv[i], "-encode")) ||
3655 (!strcmp(argv[i], "--encode"))) {
3656 i++;
3657 continue;
3658 } else if ((!strcmp(argv[i], "-o")) ||
3659 (!strcmp(argv[i], "-output")) ||
3660 (!strcmp(argv[i], "--output"))) {
3661 i++;
3662 continue;
3663 }
3664 #ifdef LIBXML_VALID_ENABLED
3665 if ((!strcmp(argv[i], "-dtdvalid")) ||
3666 (!strcmp(argv[i], "--dtdvalid"))) {
3667 i++;
3668 continue;
3669 }
3670 if ((!strcmp(argv[i], "-path")) ||
3671 (!strcmp(argv[i], "--path"))) {
3672 i++;
3673 continue;
3674 }
3675 if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3676 (!strcmp(argv[i], "--dtdvalidfpi"))) {
3677 i++;
3678 continue;
3679 }
3680 #endif /* LIBXML_VALID_ENABLED */
3681 if ((!strcmp(argv[i], "-relaxng")) ||
3682 (!strcmp(argv[i], "--relaxng"))) {
3683 i++;
3684 continue;
3685 }
3686 if ((!strcmp(argv[i], "-maxmem")) ||
3687 (!strcmp(argv[i], "--maxmem"))) {
3688 i++;
3689 continue;
3690 }
3691 if ((!strcmp(argv[i], "-pretty")) ||
3692 (!strcmp(argv[i], "--pretty"))) {
3693 i++;
3694 continue;
3695 }
3696 if ((!strcmp(argv[i], "-schema")) ||
3697 (!strcmp(argv[i], "--schema"))) {
3698 i++;
3699 continue;
3700 }
3701 if ((!strcmp(argv[i], "-schematron")) ||
3702 (!strcmp(argv[i], "--schematron"))) {
3703 i++;
3704 continue;
3705 }
3706 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3707 if ((!strcmp(argv[i], "-pattern")) ||
3708 (!strcmp(argv[i], "--pattern"))) {
3709 i++;
3710 continue;
3711 }
3712 #endif
3713 #ifdef LIBXML_XPATH_ENABLED
3714 if ((!strcmp(argv[i], "-xpath")) ||
3715 (!strcmp(argv[i], "--xpath"))) {
3716 i++;
3717 continue;
3718 }
3719 #endif
3720 if ((timing) && (repeat))
3721 startTimer();
3722 /* Remember file names. "-" means stdin. <sven@zen.org> */
3723 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
3724 if (repeat) {
3725 xmlParserCtxtPtr ctxt = NULL;
3726
3727 for (acount = 0;acount < repeat;acount++) {
3728 #ifdef LIBXML_READER_ENABLED
3729 if (stream != 0) {
3730 streamFile(argv[i]);
3731 } else {
3732 #endif /* LIBXML_READER_ENABLED */
3733 if (sax) {
3734 testSAX(argv[i]);
3735 } else {
3736 if (ctxt == NULL)
3737 ctxt = xmlNewParserCtxt();
3738 parseAndPrintFile(argv[i], ctxt);
3739 }
3740 #ifdef LIBXML_READER_ENABLED
3741 }
3742 #endif /* LIBXML_READER_ENABLED */
3743 }
3744 if (ctxt != NULL)
3745 xmlFreeParserCtxt(ctxt);
3746 } else {
3747 nbregister = 0;
3748
3749 #ifdef LIBXML_READER_ENABLED
3750 if (stream != 0)
3751 streamFile(argv[i]);
3752 else
3753 #endif /* LIBXML_READER_ENABLED */
3754 if (sax) {
3755 testSAX(argv[i]);
3756 } else {
3757 parseAndPrintFile(argv[i], NULL);
3758 }
3759
3760 if ((chkregister) && (nbregister != 0)) {
3761 fprintf(stderr, "Registration count off: %d\n", nbregister);
3762 progresult = XMLLINT_ERR_RDREGIS;
3763 }
3764 }
3765 files ++;
3766 if ((timing) && (repeat)) {
3767 endTimer("%d iterations", repeat);
3768 }
3769 }
3770 }
3771 if (generate)
3772 parseAndPrintFile(NULL, NULL);
3773 if ((htmlout) && (!nowrap)) {
3774 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
3775 }
3776 if ((files == 0) && (!generate) && (version == 0)) {
3777 usage(stderr, argv[0]);
3778 progresult = XMLLINT_ERR_UNCLASS;
3779 }
3780 #ifdef LIBXML_SCHEMATRON_ENABLED
3781 if (wxschematron != NULL)
3782 xmlSchematronFree(wxschematron);
3783 #endif
3784 #ifdef LIBXML_SCHEMAS_ENABLED
3785 if (relaxngschemas != NULL)
3786 xmlRelaxNGFree(relaxngschemas);
3787 if (wxschemas != NULL)
3788 xmlSchemaFree(wxschemas);
3789 #endif
3790 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED)
3791 if (patternc != NULL)
3792 xmlFreePattern(patternc);
3793 #endif
3794
3795 /* Avoid unused label warning if features are disabled. */
3796 goto error;
3797
3798 error:
3799 xmlCleanupParser();
3800 xmlMemoryDump();
3801
3802 return(progresult);
3803 }
3804
3805