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