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 xmlOutputBufferPtr buf;
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 buf = xmlOutputBufferCreateFile(stdout, NULL);
2082 if (buf == 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 xmlNodeDumpOutput(buf, node->doc, node, 0, 0, NULL);
2090 xmlOutputBufferWrite(buf, 1, "\n");
2091 }
2092 xmlOutputBufferClose(buf);
2093 #else
2094 printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
2095 #endif
2096 break;
2097 }
2098 case XPATH_BOOLEAN:
2099 if (cur->boolval) printf("true\n");
2100 else printf("false\n");
2101 break;
2102 case XPATH_NUMBER:
2103 switch (xmlXPathIsInf(cur->floatval)) {
2104 case 1:
2105 printf("Infinity\n");
2106 break;
2107 case -1:
2108 printf("-Infinity\n");
2109 break;
2110 default:
2111 if (xmlXPathIsNaN(cur->floatval)) {
2112 printf("NaN\n");
2113 } else {
2114 printf("%0g\n", cur->floatval);
2115 }
2116 }
2117 break;
2118 case XPATH_STRING:
2119 printf("%s\n", (const char *) cur->stringval);
2120 break;
2121 case XPATH_UNDEFINED:
2122 fprintf(stderr, "XPath Object is uninitialized\n");
2123 progresult = XMLLINT_ERR_XPATH;
2124 break;
2125 default:
2126 fprintf(stderr, "XPath object of unexpected type\n");
2127 progresult = XMLLINT_ERR_XPATH;
2128 break;
2129 }
2130 }
2131
doXPathQuery(xmlDocPtr doc,const char * query)2132 static void doXPathQuery(xmlDocPtr doc, const char *query) {
2133 xmlXPathContextPtr ctxt;
2134 xmlXPathObjectPtr res;
2135
2136 ctxt = xmlXPathNewContext(doc);
2137 if (ctxt == NULL) {
2138 fprintf(stderr, "Out of memory for XPath\n");
2139 progresult = XMLLINT_ERR_MEM;
2140 return;
2141 }
2142 ctxt->node = (xmlNodePtr) doc;
2143 res = xmlXPathEval(BAD_CAST query, ctxt);
2144 xmlXPathFreeContext(ctxt);
2145
2146 if (res == NULL) {
2147 fprintf(stderr, "XPath evaluation failure\n");
2148 progresult = XMLLINT_ERR_XPATH;
2149 return;
2150 }
2151 doXPathDump(res);
2152 xmlXPathFreeObject(res);
2153 }
2154 #endif /* LIBXML_XPATH_ENABLED */
2155
2156 /************************************************************************
2157 * *
2158 * Tree Test processing *
2159 * *
2160 ************************************************************************/
parseAndPrintFile(char * filename,xmlParserCtxtPtr rectxt)2161 static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
2162 xmlDocPtr doc = NULL;
2163 #ifdef LIBXML_TREE_ENABLED
2164 xmlDocPtr tmp;
2165 #endif /* LIBXML_TREE_ENABLED */
2166
2167 if ((timing) && (!repeat))
2168 startTimer();
2169
2170
2171 #ifdef LIBXML_TREE_ENABLED
2172 if (filename == NULL) {
2173 if (generate) {
2174 xmlNodePtr n;
2175
2176 doc = xmlNewDoc(BAD_CAST "1.0");
2177 n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL);
2178 xmlNodeSetContent(n, BAD_CAST "abc");
2179 xmlDocSetRootElement(doc, n);
2180 }
2181 }
2182 #endif /* LIBXML_TREE_ENABLED */
2183 #ifdef LIBXML_HTML_ENABLED
2184 #ifdef LIBXML_PUSH_ENABLED
2185 else if ((html) && (push)) {
2186 FILE *f;
2187
2188 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2189 f = fopen(filename, "rb");
2190 #elif defined(__OS400__)
2191 f = fopen(filename, "rb");
2192 #else
2193 f = fopen(filename, "r");
2194 #endif
2195 if (f != NULL) {
2196 int res;
2197 char chars[4096];
2198 htmlParserCtxtPtr ctxt;
2199
2200 res = fread(chars, 1, 4, f);
2201 if (res > 0) {
2202 ctxt = htmlCreatePushParserCtxt(NULL, NULL,
2203 chars, res, filename, XML_CHAR_ENCODING_NONE);
2204 xmlCtxtUseOptions(ctxt, options);
2205 while ((res = fread(chars, 1, pushsize, f)) > 0) {
2206 htmlParseChunk(ctxt, chars, res, 0);
2207 }
2208 htmlParseChunk(ctxt, chars, 0, 1);
2209 doc = ctxt->myDoc;
2210 htmlFreeParserCtxt(ctxt);
2211 }
2212 fclose(f);
2213 }
2214 }
2215 #endif /* LIBXML_PUSH_ENABLED */
2216 #ifdef HAVE_MMAP
2217 else if ((html) && (memory)) {
2218 int fd;
2219 struct stat info;
2220 const char *base;
2221 if (stat(filename, &info) < 0)
2222 return;
2223 if ((fd = open(filename, O_RDONLY)) < 0)
2224 return;
2225 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2226 if (base == (void *) MAP_FAILED) {
2227 close(fd);
2228 fprintf(stderr, "mmap failure for file %s\n", filename);
2229 progresult = XMLLINT_ERR_RDFILE;
2230 return;
2231 }
2232
2233 doc = htmlReadMemory((char *) base, info.st_size, filename,
2234 NULL, options);
2235
2236 munmap((char *) base, info.st_size);
2237 close(fd);
2238 }
2239 #endif
2240 else if (html) {
2241 doc = htmlReadFile(filename, NULL, options);
2242 }
2243 #endif /* LIBXML_HTML_ENABLED */
2244 else {
2245 #ifdef LIBXML_PUSH_ENABLED
2246 /*
2247 * build an XML tree from a string;
2248 */
2249 if (push) {
2250 FILE *f;
2251
2252 /* '-' Usually means stdin -<sven@zen.org> */
2253 if ((filename[0] == '-') && (filename[1] == 0)) {
2254 f = stdin;
2255 } else {
2256 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2257 f = fopen(filename, "rb");
2258 #elif defined(__OS400__)
2259 f = fopen(filename, "rb");
2260 #else
2261 f = fopen(filename, "r");
2262 #endif
2263 }
2264 if (f != NULL) {
2265 int ret;
2266 int res, size = 1024;
2267 char chars[1024];
2268 xmlParserCtxtPtr ctxt;
2269
2270 /* if (repeat) size = 1024; */
2271 res = fread(chars, 1, 4, f);
2272 if (res > 0) {
2273 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
2274 chars, res, filename);
2275 xmlCtxtUseOptions(ctxt, options);
2276 while ((res = fread(chars, 1, size, f)) > 0) {
2277 xmlParseChunk(ctxt, chars, res, 0);
2278 }
2279 xmlParseChunk(ctxt, chars, 0, 1);
2280 doc = ctxt->myDoc;
2281 ret = ctxt->wellFormed;
2282 xmlFreeParserCtxt(ctxt);
2283 if (!ret) {
2284 xmlFreeDoc(doc);
2285 doc = NULL;
2286 }
2287 }
2288 if (f != stdin)
2289 fclose(f);
2290 }
2291 } else
2292 #endif /* LIBXML_PUSH_ENABLED */
2293 if (testIO) {
2294 if ((filename[0] == '-') && (filename[1] == 0)) {
2295 doc = xmlReadFd(0, NULL, NULL, options);
2296 } else {
2297 FILE *f;
2298
2299 #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
2300 f = fopen(filename, "rb");
2301 #elif defined(__OS400__)
2302 f = fopen(filename, "rb");
2303 #else
2304 f = fopen(filename, "r");
2305 #endif
2306 if (f != NULL) {
2307 if (rectxt == NULL)
2308 doc = xmlReadIO(myRead, myClose, f, filename, NULL,
2309 options);
2310 else
2311 doc = xmlCtxtReadIO(rectxt, myRead, myClose, f,
2312 filename, NULL, options);
2313 } else
2314 doc = NULL;
2315 }
2316 } else if (htmlout) {
2317 xmlParserCtxtPtr ctxt;
2318
2319 if (rectxt == NULL)
2320 ctxt = xmlNewParserCtxt();
2321 else
2322 ctxt = rectxt;
2323 if (ctxt == NULL) {
2324 doc = NULL;
2325 } else {
2326 ctxt->sax->error = xmlHTMLError;
2327 ctxt->sax->warning = xmlHTMLWarning;
2328 ctxt->vctxt.error = xmlHTMLValidityError;
2329 ctxt->vctxt.warning = xmlHTMLValidityWarning;
2330
2331 doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2332
2333 if (rectxt == NULL)
2334 xmlFreeParserCtxt(ctxt);
2335 }
2336 #ifdef HAVE_MMAP
2337 } else if (memory) {
2338 int fd;
2339 struct stat info;
2340 const char *base;
2341 if (stat(filename, &info) < 0)
2342 return;
2343 if ((fd = open(filename, O_RDONLY)) < 0)
2344 return;
2345 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
2346 if (base == (void *) MAP_FAILED) {
2347 close(fd);
2348 fprintf(stderr, "mmap failure for file %s\n", filename);
2349 progresult = XMLLINT_ERR_RDFILE;
2350 return;
2351 }
2352
2353 if (rectxt == NULL)
2354 doc = xmlReadMemory((char *) base, info.st_size,
2355 filename, NULL, options);
2356 else
2357 doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size,
2358 filename, NULL, options);
2359
2360 munmap((char *) base, info.st_size);
2361 close(fd);
2362 #endif
2363 #ifdef LIBXML_VALID_ENABLED
2364 } else if (valid) {
2365 xmlParserCtxtPtr ctxt = NULL;
2366
2367 if (rectxt == NULL)
2368 ctxt = xmlNewParserCtxt();
2369 else
2370 ctxt = rectxt;
2371 if (ctxt == NULL) {
2372 doc = NULL;
2373 } else {
2374 doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
2375
2376 if (ctxt->valid == 0)
2377 progresult = XMLLINT_ERR_RDFILE;
2378 if (rectxt == NULL)
2379 xmlFreeParserCtxt(ctxt);
2380 }
2381 #endif /* LIBXML_VALID_ENABLED */
2382 } else {
2383 if (rectxt != NULL)
2384 doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
2385 else {
2386 #ifdef LIBXML_SAX1_ENABLED
2387 if (sax1)
2388 doc = xmlParseFile(filename);
2389 else
2390 #endif /* LIBXML_SAX1_ENABLED */
2391 doc = xmlReadFile(filename, NULL, options);
2392 }
2393 }
2394 }
2395
2396 /*
2397 * If we don't have a document we might as well give up. Do we
2398 * want an error message here? <sven@zen.org> */
2399 if (doc == NULL) {
2400 progresult = XMLLINT_ERR_UNCLASS;
2401 return;
2402 }
2403
2404 if ((timing) && (!repeat)) {
2405 endTimer("Parsing");
2406 }
2407
2408 /*
2409 * Remove DOCTYPE nodes
2410 */
2411 if (dropdtd) {
2412 xmlDtdPtr dtd;
2413
2414 dtd = xmlGetIntSubset(doc);
2415 if (dtd != NULL) {
2416 xmlUnlinkNode((xmlNodePtr)dtd);
2417 xmlFreeDtd(dtd);
2418 }
2419 }
2420
2421 #ifdef LIBXML_XINCLUDE_ENABLED
2422 if (xinclude) {
2423 if ((timing) && (!repeat)) {
2424 startTimer();
2425 }
2426 if (xmlXIncludeProcessFlags(doc, options) < 0)
2427 progresult = XMLLINT_ERR_UNCLASS;
2428 if ((timing) && (!repeat)) {
2429 endTimer("Xinclude processing");
2430 }
2431 }
2432 #endif
2433
2434 #ifdef LIBXML_XPATH_ENABLED
2435 if (xpathquery != NULL) {
2436 doXPathQuery(doc, xpathquery);
2437 }
2438 #endif
2439
2440 #ifdef LIBXML_DEBUG_ENABLED
2441 #ifdef LIBXML_XPATH_ENABLED
2442 /*
2443 * shell interaction
2444 */
2445 if (shell) {
2446 xmlXPathOrderDocElems(doc);
2447 xmlShell(doc, filename, xmlShellReadline, stdout);
2448 }
2449 #endif
2450 #endif
2451
2452 #ifdef LIBXML_TREE_ENABLED
2453 /*
2454 * test intermediate copy if needed.
2455 */
2456 if (copy) {
2457 tmp = doc;
2458 if (timing) {
2459 startTimer();
2460 }
2461 doc = xmlCopyDoc(doc, 1);
2462 if (timing) {
2463 endTimer("Copying");
2464 }
2465 if (timing) {
2466 startTimer();
2467 }
2468 xmlFreeDoc(tmp);
2469 if (timing) {
2470 endTimer("Freeing original");
2471 }
2472 }
2473 #endif /* LIBXML_TREE_ENABLED */
2474
2475 #ifdef LIBXML_VALID_ENABLED
2476 if ((insert) && (!html)) {
2477 const xmlChar* list[256];
2478 int nb, i;
2479 xmlNodePtr node;
2480
2481 if (doc->children != NULL) {
2482 node = doc->children;
2483 while ((node != NULL) && (node->last == NULL)) node = node->next;
2484 if (node != NULL) {
2485 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
2486 if (nb < 0) {
2487 fprintf(stderr, "could not get valid list of elements\n");
2488 } else if (nb == 0) {
2489 fprintf(stderr, "No element can be inserted under root\n");
2490 } else {
2491 fprintf(stderr, "%d element types can be inserted under root:\n",
2492 nb);
2493 for (i = 0;i < nb;i++) {
2494 fprintf(stderr, "%s\n", (char *) list[i]);
2495 }
2496 }
2497 }
2498 }
2499 }else
2500 #endif /* LIBXML_VALID_ENABLED */
2501 #ifdef LIBXML_READER_ENABLED
2502 if (walker) {
2503 walkDoc(doc);
2504 }
2505 #endif /* LIBXML_READER_ENABLED */
2506 #ifdef LIBXML_OUTPUT_ENABLED
2507 if (noout == 0) {
2508 int ret;
2509
2510 /*
2511 * print it.
2512 */
2513 #ifdef LIBXML_DEBUG_ENABLED
2514 if (!debug) {
2515 #endif
2516 if ((timing) && (!repeat)) {
2517 startTimer();
2518 }
2519 #ifdef LIBXML_HTML_ENABLED
2520 if ((html) && (!xmlout)) {
2521 if (compress) {
2522 htmlSaveFile(output ? output : "-", doc);
2523 }
2524 else if (encoding != NULL) {
2525 if (format == 1) {
2526 htmlSaveFileFormat(output ? output : "-", doc, encoding, 1);
2527 }
2528 else {
2529 htmlSaveFileFormat(output ? output : "-", doc, encoding, 0);
2530 }
2531 }
2532 else if (format == 1) {
2533 htmlSaveFileFormat(output ? output : "-", doc, NULL, 1);
2534 }
2535 else {
2536 FILE *out;
2537 if (output == NULL)
2538 out = stdout;
2539 else {
2540 out = fopen(output,"wb");
2541 }
2542 if (out != NULL) {
2543 if (htmlDocDump(out, doc) < 0)
2544 progresult = XMLLINT_ERR_OUT;
2545
2546 if (output != NULL)
2547 fclose(out);
2548 } else {
2549 fprintf(stderr, "failed to open %s\n", output);
2550 progresult = XMLLINT_ERR_OUT;
2551 }
2552 }
2553 if ((timing) && (!repeat)) {
2554 endTimer("Saving");
2555 }
2556 } else
2557 #endif
2558 #ifdef LIBXML_C14N_ENABLED
2559 if (canonical) {
2560 xmlChar *result = NULL;
2561 int size;
2562
2563 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
2564 if (size >= 0) {
2565 if (write(1, result, size) == -1) {
2566 fprintf(stderr, "Can't write data\n");
2567 }
2568 xmlFree(result);
2569 } else {
2570 fprintf(stderr, "Failed to canonicalize\n");
2571 progresult = XMLLINT_ERR_OUT;
2572 }
2573 } else if (canonical_11) {
2574 xmlChar *result = NULL;
2575 int size;
2576
2577 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
2578 if (size >= 0) {
2579 if (write(1, result, size) == -1) {
2580 fprintf(stderr, "Can't write data\n");
2581 }
2582 xmlFree(result);
2583 } else {
2584 fprintf(stderr, "Failed to canonicalize\n");
2585 progresult = XMLLINT_ERR_OUT;
2586 }
2587 } else
2588 if (exc_canonical) {
2589 xmlChar *result = NULL;
2590 int size;
2591
2592 size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
2593 if (size >= 0) {
2594 if (write(1, result, size) == -1) {
2595 fprintf(stderr, "Can't write data\n");
2596 }
2597 xmlFree(result);
2598 } else {
2599 fprintf(stderr, "Failed to canonicalize\n");
2600 progresult = XMLLINT_ERR_OUT;
2601 }
2602 } else
2603 #endif
2604 #ifdef HAVE_MMAP
2605 if (memory) {
2606 xmlChar *result;
2607 int len;
2608
2609 if (encoding != NULL) {
2610 if (format == 1) {
2611 xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
2612 } else {
2613 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
2614 }
2615 } else {
2616 if (format == 1)
2617 xmlDocDumpFormatMemory(doc, &result, &len, 1);
2618 else
2619 xmlDocDumpMemory(doc, &result, &len);
2620 }
2621 if (result == NULL) {
2622 fprintf(stderr, "Failed to save\n");
2623 progresult = XMLLINT_ERR_OUT;
2624 } else {
2625 if (write(1, result, len) == -1) {
2626 fprintf(stderr, "Can't write data\n");
2627 }
2628 xmlFree(result);
2629 }
2630
2631 } else
2632 #endif /* HAVE_MMAP */
2633 if (compress) {
2634 xmlSaveFile(output ? output : "-", doc);
2635 } else if (oldout) {
2636 if (encoding != NULL) {
2637 if (format == 1) {
2638 ret = xmlSaveFormatFileEnc(output ? output : "-", doc,
2639 encoding, 1);
2640 }
2641 else {
2642 ret = xmlSaveFileEnc(output ? output : "-", doc,
2643 encoding);
2644 }
2645 if (ret < 0) {
2646 fprintf(stderr, "failed save to %s\n",
2647 output ? output : "-");
2648 progresult = XMLLINT_ERR_OUT;
2649 }
2650 } else if (format == 1) {
2651 ret = xmlSaveFormatFile(output ? output : "-", doc, 1);
2652 if (ret < 0) {
2653 fprintf(stderr, "failed save to %s\n",
2654 output ? output : "-");
2655 progresult = XMLLINT_ERR_OUT;
2656 }
2657 } else {
2658 FILE *out;
2659 if (output == NULL)
2660 out = stdout;
2661 else {
2662 out = fopen(output,"wb");
2663 }
2664 if (out != NULL) {
2665 if (xmlDocDump(out, doc) < 0)
2666 progresult = XMLLINT_ERR_OUT;
2667
2668 if (output != NULL)
2669 fclose(out);
2670 } else {
2671 fprintf(stderr, "failed to open %s\n", output);
2672 progresult = XMLLINT_ERR_OUT;
2673 }
2674 }
2675 } else {
2676 xmlSaveCtxtPtr ctxt;
2677 int saveOpts = 0;
2678
2679 if (format == 1)
2680 saveOpts |= XML_SAVE_FORMAT;
2681 else if (format == 2)
2682 saveOpts |= XML_SAVE_WSNONSIG;
2683
2684 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2685 if (xmlout)
2686 saveOpts |= XML_SAVE_AS_XML;
2687 #endif
2688
2689 if (output == NULL)
2690 ctxt = xmlSaveToFd(1, encoding, saveOpts);
2691 else
2692 ctxt = xmlSaveToFilename(output, encoding, saveOpts);
2693
2694 if (ctxt != NULL) {
2695 if (xmlSaveDoc(ctxt, doc) < 0) {
2696 fprintf(stderr, "failed save to %s\n",
2697 output ? output : "-");
2698 progresult = XMLLINT_ERR_OUT;
2699 }
2700 xmlSaveClose(ctxt);
2701 } else {
2702 progresult = XMLLINT_ERR_OUT;
2703 }
2704 }
2705 if ((timing) && (!repeat)) {
2706 endTimer("Saving");
2707 }
2708 #ifdef LIBXML_DEBUG_ENABLED
2709 } else {
2710 FILE *out;
2711 if (output == NULL)
2712 out = stdout;
2713 else {
2714 out = fopen(output,"wb");
2715 }
2716 if (out != NULL) {
2717 xmlDebugDumpDocument(out, doc);
2718
2719 if (output != NULL)
2720 fclose(out);
2721 } else {
2722 fprintf(stderr, "failed to open %s\n", output);
2723 progresult = XMLLINT_ERR_OUT;
2724 }
2725 }
2726 #endif
2727 }
2728 #endif /* LIBXML_OUTPUT_ENABLED */
2729
2730 #ifdef LIBXML_VALID_ENABLED
2731 /*
2732 * A posteriori validation test
2733 */
2734 if ((dtdvalid != NULL) || (dtdvalidfpi != NULL)) {
2735 xmlDtdPtr dtd;
2736
2737 if ((timing) && (!repeat)) {
2738 startTimer();
2739 }
2740 if (dtdvalid != NULL)
2741 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
2742 else
2743 dtd = xmlParseDTD((const xmlChar *)dtdvalidfpi, NULL);
2744 if ((timing) && (!repeat)) {
2745 endTimer("Parsing DTD");
2746 }
2747 if (dtd == NULL) {
2748 if (dtdvalid != NULL)
2749 xmlGenericError(xmlGenericErrorContext,
2750 "Could not parse DTD %s\n", dtdvalid);
2751 else
2752 xmlGenericError(xmlGenericErrorContext,
2753 "Could not parse DTD %s\n", dtdvalidfpi);
2754 progresult = XMLLINT_ERR_DTD;
2755 } else {
2756 xmlValidCtxtPtr cvp;
2757
2758 if ((cvp = xmlNewValidCtxt()) == NULL) {
2759 xmlGenericError(xmlGenericErrorContext,
2760 "Couldn't allocate validation context\n");
2761 exit(-1);
2762 }
2763 cvp->userData = (void *) stderr;
2764 cvp->error = (xmlValidityErrorFunc) fprintf;
2765 cvp->warning = (xmlValidityWarningFunc) fprintf;
2766
2767 if ((timing) && (!repeat)) {
2768 startTimer();
2769 }
2770 if (!xmlValidateDtd(cvp, doc, dtd)) {
2771 if (dtdvalid != NULL)
2772 xmlGenericError(xmlGenericErrorContext,
2773 "Document %s does not validate against %s\n",
2774 filename, dtdvalid);
2775 else
2776 xmlGenericError(xmlGenericErrorContext,
2777 "Document %s does not validate against %s\n",
2778 filename, dtdvalidfpi);
2779 progresult = XMLLINT_ERR_VALID;
2780 }
2781 if ((timing) && (!repeat)) {
2782 endTimer("Validating against DTD");
2783 }
2784 xmlFreeValidCtxt(cvp);
2785 xmlFreeDtd(dtd);
2786 }
2787 } else if (postvalid) {
2788 xmlValidCtxtPtr cvp;
2789
2790 if ((cvp = xmlNewValidCtxt()) == NULL) {
2791 xmlGenericError(xmlGenericErrorContext,
2792 "Couldn't allocate validation context\n");
2793 exit(-1);
2794 }
2795
2796 if ((timing) && (!repeat)) {
2797 startTimer();
2798 }
2799 cvp->userData = (void *) stderr;
2800 cvp->error = (xmlValidityErrorFunc) fprintf;
2801 cvp->warning = (xmlValidityWarningFunc) fprintf;
2802 if (!xmlValidateDocument(cvp, doc)) {
2803 xmlGenericError(xmlGenericErrorContext,
2804 "Document %s does not validate\n", filename);
2805 progresult = XMLLINT_ERR_VALID;
2806 }
2807 if ((timing) && (!repeat)) {
2808 endTimer("Validating");
2809 }
2810 xmlFreeValidCtxt(cvp);
2811 }
2812 #endif /* LIBXML_VALID_ENABLED */
2813 #ifdef LIBXML_SCHEMATRON_ENABLED
2814 if (wxschematron != NULL) {
2815 xmlSchematronValidCtxtPtr ctxt;
2816 int ret;
2817 int flag;
2818
2819 if ((timing) && (!repeat)) {
2820 startTimer();
2821 }
2822
2823 if (debug)
2824 flag = XML_SCHEMATRON_OUT_XML;
2825 else
2826 flag = XML_SCHEMATRON_OUT_TEXT;
2827 if (noout)
2828 flag |= XML_SCHEMATRON_OUT_QUIET;
2829 ctxt = xmlSchematronNewValidCtxt(wxschematron, flag);
2830 #if 0
2831 xmlSchematronSetValidErrors(ctxt,
2832 (xmlSchematronValidityErrorFunc) fprintf,
2833 (xmlSchematronValidityWarningFunc) fprintf,
2834 stderr);
2835 #endif
2836 ret = xmlSchematronValidateDoc(ctxt, doc);
2837 if (ret == 0) {
2838 fprintf(stderr, "%s validates\n", filename);
2839 } else if (ret > 0) {
2840 fprintf(stderr, "%s fails to validate\n", filename);
2841 progresult = XMLLINT_ERR_VALID;
2842 } else {
2843 fprintf(stderr, "%s validation generated an internal error\n",
2844 filename);
2845 progresult = XMLLINT_ERR_VALID;
2846 }
2847 xmlSchematronFreeValidCtxt(ctxt);
2848 if ((timing) && (!repeat)) {
2849 endTimer("Validating");
2850 }
2851 }
2852 #endif
2853 #ifdef LIBXML_SCHEMAS_ENABLED
2854 if (relaxngschemas != NULL) {
2855 xmlRelaxNGValidCtxtPtr ctxt;
2856 int ret;
2857
2858 if ((timing) && (!repeat)) {
2859 startTimer();
2860 }
2861
2862 ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2863 xmlRelaxNGSetValidErrors(ctxt,
2864 (xmlRelaxNGValidityErrorFunc) fprintf,
2865 (xmlRelaxNGValidityWarningFunc) fprintf,
2866 stderr);
2867 ret = xmlRelaxNGValidateDoc(ctxt, doc);
2868 if (ret == 0) {
2869 fprintf(stderr, "%s validates\n", filename);
2870 } else if (ret > 0) {
2871 fprintf(stderr, "%s fails to validate\n", filename);
2872 progresult = XMLLINT_ERR_VALID;
2873 } else {
2874 fprintf(stderr, "%s validation generated an internal error\n",
2875 filename);
2876 progresult = XMLLINT_ERR_VALID;
2877 }
2878 xmlRelaxNGFreeValidCtxt(ctxt);
2879 if ((timing) && (!repeat)) {
2880 endTimer("Validating");
2881 }
2882 } else if (wxschemas != NULL) {
2883 xmlSchemaValidCtxtPtr ctxt;
2884 int ret;
2885
2886 if ((timing) && (!repeat)) {
2887 startTimer();
2888 }
2889
2890 ctxt = xmlSchemaNewValidCtxt(wxschemas);
2891 xmlSchemaSetValidErrors(ctxt,
2892 (xmlSchemaValidityErrorFunc) fprintf,
2893 (xmlSchemaValidityWarningFunc) fprintf,
2894 stderr);
2895 ret = xmlSchemaValidateDoc(ctxt, doc);
2896 if (ret == 0) {
2897 fprintf(stderr, "%s validates\n", filename);
2898 } else if (ret > 0) {
2899 fprintf(stderr, "%s fails to validate\n", filename);
2900 progresult = XMLLINT_ERR_VALID;
2901 } else {
2902 fprintf(stderr, "%s validation generated an internal error\n",
2903 filename);
2904 progresult = XMLLINT_ERR_VALID;
2905 }
2906 xmlSchemaFreeValidCtxt(ctxt);
2907 if ((timing) && (!repeat)) {
2908 endTimer("Validating");
2909 }
2910 }
2911 #endif
2912
2913 #ifdef LIBXML_DEBUG_ENABLED
2914 #if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
2915 if ((debugent) && (!html))
2916 xmlDebugDumpEntities(stderr, doc);
2917 #endif
2918 #endif
2919
2920 /*
2921 * free it.
2922 */
2923 if ((timing) && (!repeat)) {
2924 startTimer();
2925 }
2926 xmlFreeDoc(doc);
2927 if ((timing) && (!repeat)) {
2928 endTimer("Freeing");
2929 }
2930 }
2931
2932 /************************************************************************
2933 * *
2934 * Usage and Main *
2935 * *
2936 ************************************************************************/
2937
showVersion(const char * name)2938 static void showVersion(const char *name) {
2939 fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
2940 fprintf(stderr, " compiled with: ");
2941 if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads ");
2942 if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree ");
2943 if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output ");
2944 if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push ");
2945 if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader ");
2946 if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns ");
2947 if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer ");
2948 if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 ");
2949 if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP ");
2950 if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP ");
2951 if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid ");
2952 if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML ");
2953 if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy ");
2954 if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N ");
2955 if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog ");
2956 if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath ");
2957 if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer ");
2958 if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude ");
2959 if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv ");
2960 if (xmlHasFeature(XML_WITH_ICU)) fprintf(stderr, "ICU ");
2961 if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X ");
2962 if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode ");
2963 if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps ");
2964 if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata ");
2965 if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr ");
2966 if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas ");
2967 if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron ");
2968 if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules ");
2969 if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug ");
2970 if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug ");
2971 if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug ");
2972 if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib ");
2973 if (xmlHasFeature(XML_WITH_LZMA)) fprintf(stderr, "Lzma ");
2974 fprintf(stderr, "\n");
2975 }
2976
usage(FILE * f,const char * name)2977 static void usage(FILE *f, const char *name) {
2978 fprintf(f, "Usage : %s [options] XMLfiles ...\n", name);
2979 #ifdef LIBXML_OUTPUT_ENABLED
2980 fprintf(f, "\tParse the XML files and output the result of the parsing\n");
2981 #else
2982 fprintf(f, "\tParse the XML files\n");
2983 #endif /* LIBXML_OUTPUT_ENABLED */
2984 fprintf(f, "\t--version : display the version of the XML library used\n");
2985 #ifdef LIBXML_DEBUG_ENABLED
2986 fprintf(f, "\t--debug : dump a debug tree of the in-memory document\n");
2987 fprintf(f, "\t--shell : run a navigating shell\n");
2988 fprintf(f, "\t--debugent : debug the entities defined in the document\n");
2989 #else
2990 #ifdef LIBXML_READER_ENABLED
2991 fprintf(f, "\t--debug : dump the nodes content when using --stream\n");
2992 #endif /* LIBXML_READER_ENABLED */
2993 #endif
2994 #ifdef LIBXML_TREE_ENABLED
2995 fprintf(f, "\t--copy : used to test the internal copy implementation\n");
2996 #endif /* LIBXML_TREE_ENABLED */
2997 fprintf(f, "\t--recover : output what was parsable on broken XML documents\n");
2998 fprintf(f, "\t--huge : remove any internal arbitrary parser limits\n");
2999 fprintf(f, "\t--noent : substitute entity references by their value\n");
3000 fprintf(f, "\t--noenc : ignore any encoding specified inside the document\n");
3001 fprintf(f, "\t--noout : don't output the result tree\n");
3002 fprintf(f, "\t--path 'paths': provide a set of paths for resources\n");
3003 fprintf(f, "\t--load-trace : print trace of all external entities loaded\n");
3004 fprintf(f, "\t--nonet : refuse to fetch DTDs or entities over network\n");
3005 fprintf(f, "\t--nocompact : do not generate compact text nodes\n");
3006 fprintf(f, "\t--htmlout : output results as HTML\n");
3007 fprintf(f, "\t--nowrap : do not put HTML doc wrapper\n");
3008 #ifdef LIBXML_VALID_ENABLED
3009 fprintf(f, "\t--valid : validate the document in addition to std well-formed check\n");
3010 fprintf(f, "\t--postvalid : do a posteriori validation, i.e after parsing\n");
3011 fprintf(f, "\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
3012 fprintf(f, "\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n");
3013 #endif /* LIBXML_VALID_ENABLED */
3014 fprintf(f, "\t--timing : print some timings\n");
3015 fprintf(f, "\t--output file or -o file: save to a given file\n");
3016 fprintf(f, "\t--repeat : repeat 100 times, for timing or profiling\n");
3017 fprintf(f, "\t--insert : ad-hoc test for valid insertions\n");
3018 #ifdef LIBXML_OUTPUT_ENABLED
3019 #ifdef LIBXML_ZLIB_ENABLED
3020 fprintf(f, "\t--compress : turn on gzip compression of output\n");
3021 #endif
3022 #endif /* LIBXML_OUTPUT_ENABLED */
3023 #ifdef LIBXML_HTML_ENABLED
3024 fprintf(f, "\t--html : use the HTML parser\n");
3025 fprintf(f, "\t--xmlout : force to use the XML serializer when using --html\n");
3026 fprintf(f, "\t--nodefdtd : do not default HTML doctype\n");
3027 #endif
3028 #ifdef LIBXML_PUSH_ENABLED
3029 fprintf(f, "\t--push : use the push mode of the parser\n");
3030 fprintf(f, "\t--pushsmall : use the push mode of the parser using tiny increments\n");
3031 #endif /* LIBXML_PUSH_ENABLED */
3032 #ifdef HAVE_MMAP
3033 fprintf(f, "\t--memory : parse from memory\n");
3034 #endif
3035 fprintf(f, "\t--maxmem nbbytes : limits memory allocation to nbbytes bytes\n");
3036 fprintf(f, "\t--nowarning : do not emit warnings from parser/validator\n");
3037 fprintf(f, "\t--noblanks : drop (ignorable?) blanks spaces\n");
3038 fprintf(f, "\t--nocdata : replace cdata section with text nodes\n");
3039 #ifdef LIBXML_OUTPUT_ENABLED
3040 fprintf(f, "\t--format : reformat/reindent the output\n");
3041 fprintf(f, "\t--encode encoding : output in the given encoding\n");
3042 fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n");
3043 fprintf(f, "\t--pretty STYLE : pretty-print in a particular style\n");
3044 fprintf(f, "\t 0 Do not pretty print\n");
3045 fprintf(f, "\t 1 Format the XML content, as --format\n");
3046 fprintf(f, "\t 2 Add whitespace inside tags, preserving content\n");
3047 #endif /* LIBXML_OUTPUT_ENABLED */
3048 fprintf(f, "\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
3049 fprintf(f, "\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
3050 fprintf(f, "\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
3051 #ifdef LIBXML_C14N_ENABLED
3052 #endif /* LIBXML_C14N_ENABLED */
3053 fprintf(f, "\t--nsclean : remove redundant namespace declarations\n");
3054 fprintf(f, "\t--testIO : test user I/O support\n");
3055 #ifdef LIBXML_CATALOG_ENABLED
3056 fprintf(f, "\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
3057 fprintf(f, "\t otherwise XML Catalogs starting from \n");
3058 fprintf(f, "\t %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
3059 fprintf(f, "\t--nocatalogs: deactivate all catalogs\n");
3060 #endif
3061 fprintf(f, "\t--auto : generate a small doc on the fly\n");
3062 #ifdef LIBXML_XINCLUDE_ENABLED
3063 fprintf(f, "\t--xinclude : do XInclude processing\n");
3064 fprintf(f, "\t--noxincludenode : same but do not generate XInclude nodes\n");
3065 fprintf(f, "\t--nofixup-base-uris : do not fixup xml:base uris\n");
3066 #endif
3067 fprintf(f, "\t--loaddtd : fetch external DTD\n");
3068 fprintf(f, "\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
3069 #ifdef LIBXML_READER_ENABLED
3070 fprintf(f, "\t--stream : use the streaming interface to process very large files\n");
3071 fprintf(f, "\t--walker : create a reader and walk though the resulting doc\n");
3072 #endif /* LIBXML_READER_ENABLED */
3073 #ifdef LIBXML_PATTERN_ENABLED
3074 fprintf(f, "\t--pattern pattern_value : test the pattern support\n");
3075 #endif
3076 fprintf(f, "\t--chkregister : verify the node registration code\n");
3077 #ifdef LIBXML_SCHEMAS_ENABLED
3078 fprintf(f, "\t--relaxng schema : do RelaxNG validation against the schema\n");
3079 fprintf(f, "\t--schema schema : do validation against the WXS schema\n");
3080 #endif
3081 #ifdef LIBXML_SCHEMATRON_ENABLED
3082 fprintf(f, "\t--schematron schema : do validation against a schematron\n");
3083 #endif
3084 #ifdef LIBXML_SAX1_ENABLED
3085 fprintf(f, "\t--sax1: use the old SAX1 interfaces for processing\n");
3086 #endif
3087 fprintf(f, "\t--sax: do not build a tree but work just at the SAX level\n");
3088 fprintf(f, "\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
3089 #ifdef LIBXML_XPATH_ENABLED
3090 fprintf(f, "\t--xpath expr: evaluate the XPath expression, imply --noout\n");
3091 #endif
3092
3093 fprintf(f, "\nLibxml project home page: http://xmlsoft.org/\n");
3094 fprintf(f, "To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
3095 }
3096
registerNode(xmlNodePtr node)3097 static void registerNode(xmlNodePtr node)
3098 {
3099 node->_private = malloc(sizeof(long));
3100 if (node->_private == NULL) {
3101 fprintf(stderr, "Out of memory in xmllint:registerNode()\n");
3102 exit(XMLLINT_ERR_MEM);
3103 }
3104 *(long*)node->_private = (long) 0x81726354;
3105 nbregister++;
3106 }
3107
deregisterNode(xmlNodePtr node)3108 static void deregisterNode(xmlNodePtr node)
3109 {
3110 assert(node->_private != NULL);
3111 assert(*(long*)node->_private == (long) 0x81726354);
3112 free(node->_private);
3113 nbregister--;
3114 }
3115
3116 int
main(int argc,char ** argv)3117 main(int argc, char **argv) {
3118 int i, acount;
3119 int files = 0;
3120 int version = 0;
3121 const char* indent;
3122
3123 if (argc <= 1) {
3124 usage(stderr, argv[0]);
3125 return(1);
3126 }
3127 LIBXML_TEST_VERSION
3128 for (i = 1; i < argc ; i++) {
3129 if (!strcmp(argv[i], "-"))
3130 break;
3131
3132 if (argv[i][0] != '-')
3133 continue;
3134 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
3135 debug++;
3136 else
3137 #ifdef LIBXML_DEBUG_ENABLED
3138 if ((!strcmp(argv[i], "-shell")) ||
3139 (!strcmp(argv[i], "--shell"))) {
3140 shell++;
3141 noout = 1;
3142 } else
3143 #endif
3144 #ifdef LIBXML_TREE_ENABLED
3145 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
3146 copy++;
3147 else
3148 #endif /* LIBXML_TREE_ENABLED */
3149 if ((!strcmp(argv[i], "-recover")) ||
3150 (!strcmp(argv[i], "--recover"))) {
3151 recovery++;
3152 options |= XML_PARSE_RECOVER;
3153 } else if ((!strcmp(argv[i], "-huge")) ||
3154 (!strcmp(argv[i], "--huge"))) {
3155 options |= XML_PARSE_HUGE;
3156 } else if ((!strcmp(argv[i], "-noent")) ||
3157 (!strcmp(argv[i], "--noent"))) {
3158 noent++;
3159 options |= XML_PARSE_NOENT;
3160 } else if ((!strcmp(argv[i], "-noenc")) ||
3161 (!strcmp(argv[i], "--noenc"))) {
3162 noenc++;
3163 options |= XML_PARSE_IGNORE_ENC;
3164 } else if ((!strcmp(argv[i], "-nsclean")) ||
3165 (!strcmp(argv[i], "--nsclean"))) {
3166 options |= XML_PARSE_NSCLEAN;
3167 } else if ((!strcmp(argv[i], "-nocdata")) ||
3168 (!strcmp(argv[i], "--nocdata"))) {
3169 options |= XML_PARSE_NOCDATA;
3170 } else if ((!strcmp(argv[i], "-nodict")) ||
3171 (!strcmp(argv[i], "--nodict"))) {
3172 options |= XML_PARSE_NODICT;
3173 } else if ((!strcmp(argv[i], "-version")) ||
3174 (!strcmp(argv[i], "--version"))) {
3175 showVersion(argv[0]);
3176 version = 1;
3177 } else if ((!strcmp(argv[i], "-noout")) ||
3178 (!strcmp(argv[i], "--noout")))
3179 noout++;
3180 #ifdef LIBXML_OUTPUT_ENABLED
3181 else if ((!strcmp(argv[i], "-o")) ||
3182 (!strcmp(argv[i], "-output")) ||
3183 (!strcmp(argv[i], "--output"))) {
3184 i++;
3185 output = argv[i];
3186 }
3187 #endif /* LIBXML_OUTPUT_ENABLED */
3188 else if ((!strcmp(argv[i], "-htmlout")) ||
3189 (!strcmp(argv[i], "--htmlout")))
3190 htmlout++;
3191 else if ((!strcmp(argv[i], "-nowrap")) ||
3192 (!strcmp(argv[i], "--nowrap")))
3193 nowrap++;
3194 #ifdef LIBXML_HTML_ENABLED
3195 else if ((!strcmp(argv[i], "-html")) ||
3196 (!strcmp(argv[i], "--html"))) {
3197 html++;
3198 }
3199 else if ((!strcmp(argv[i], "-xmlout")) ||
3200 (!strcmp(argv[i], "--xmlout"))) {
3201 xmlout++;
3202 } else if ((!strcmp(argv[i], "-nodefdtd")) ||
3203 (!strcmp(argv[i], "--nodefdtd"))) {
3204 nodefdtd++;
3205 options |= HTML_PARSE_NODEFDTD;
3206 }
3207 #endif /* LIBXML_HTML_ENABLED */
3208 else if ((!strcmp(argv[i], "-loaddtd")) ||
3209 (!strcmp(argv[i], "--loaddtd"))) {
3210 loaddtd++;
3211 options |= XML_PARSE_DTDLOAD;
3212 } else if ((!strcmp(argv[i], "-dtdattr")) ||
3213 (!strcmp(argv[i], "--dtdattr"))) {
3214 loaddtd++;
3215 dtdattrs++;
3216 options |= XML_PARSE_DTDATTR;
3217 }
3218 #ifdef LIBXML_VALID_ENABLED
3219 else if ((!strcmp(argv[i], "-valid")) ||
3220 (!strcmp(argv[i], "--valid"))) {
3221 valid++;
3222 options |= XML_PARSE_DTDVALID;
3223 } else if ((!strcmp(argv[i], "-postvalid")) ||
3224 (!strcmp(argv[i], "--postvalid"))) {
3225 postvalid++;
3226 loaddtd++;
3227 options |= XML_PARSE_DTDLOAD;
3228 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
3229 (!strcmp(argv[i], "--dtdvalid"))) {
3230 i++;
3231 dtdvalid = argv[i];
3232 loaddtd++;
3233 options |= XML_PARSE_DTDLOAD;
3234 } else if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3235 (!strcmp(argv[i], "--dtdvalidfpi"))) {
3236 i++;
3237 dtdvalidfpi = argv[i];
3238 loaddtd++;
3239 options |= XML_PARSE_DTDLOAD;
3240 }
3241 #endif /* LIBXML_VALID_ENABLED */
3242 else if ((!strcmp(argv[i], "-dropdtd")) ||
3243 (!strcmp(argv[i], "--dropdtd")))
3244 dropdtd++;
3245 else if ((!strcmp(argv[i], "-insert")) ||
3246 (!strcmp(argv[i], "--insert")))
3247 insert++;
3248 else if ((!strcmp(argv[i], "-timing")) ||
3249 (!strcmp(argv[i], "--timing")))
3250 timing++;
3251 else if ((!strcmp(argv[i], "-auto")) ||
3252 (!strcmp(argv[i], "--auto")))
3253 generate++;
3254 else if ((!strcmp(argv[i], "-repeat")) ||
3255 (!strcmp(argv[i], "--repeat"))) {
3256 if (repeat)
3257 repeat *= 10;
3258 else
3259 repeat = 100;
3260 }
3261 #ifdef LIBXML_PUSH_ENABLED
3262 else if ((!strcmp(argv[i], "-push")) ||
3263 (!strcmp(argv[i], "--push")))
3264 push++;
3265 else if ((!strcmp(argv[i], "-pushsmall")) ||
3266 (!strcmp(argv[i], "--pushsmall"))) {
3267 push++;
3268 pushsize = 10;
3269 }
3270 #endif /* LIBXML_PUSH_ENABLED */
3271 #ifdef HAVE_MMAP
3272 else if ((!strcmp(argv[i], "-memory")) ||
3273 (!strcmp(argv[i], "--memory")))
3274 memory++;
3275 #endif
3276 else if ((!strcmp(argv[i], "-testIO")) ||
3277 (!strcmp(argv[i], "--testIO")))
3278 testIO++;
3279 #ifdef LIBXML_XINCLUDE_ENABLED
3280 else if ((!strcmp(argv[i], "-xinclude")) ||
3281 (!strcmp(argv[i], "--xinclude"))) {
3282 xinclude++;
3283 options |= XML_PARSE_XINCLUDE;
3284 }
3285 else if ((!strcmp(argv[i], "-noxincludenode")) ||
3286 (!strcmp(argv[i], "--noxincludenode"))) {
3287 xinclude++;
3288 options |= XML_PARSE_XINCLUDE;
3289 options |= XML_PARSE_NOXINCNODE;
3290 }
3291 else if ((!strcmp(argv[i], "-nofixup-base-uris")) ||
3292 (!strcmp(argv[i], "--nofixup-base-uris"))) {
3293 xinclude++;
3294 options |= XML_PARSE_XINCLUDE;
3295 options |= XML_PARSE_NOBASEFIX;
3296 }
3297 #endif
3298 #ifdef LIBXML_OUTPUT_ENABLED
3299 #ifdef LIBXML_ZLIB_ENABLED
3300 else if ((!strcmp(argv[i], "-compress")) ||
3301 (!strcmp(argv[i], "--compress"))) {
3302 compress++;
3303 xmlSetCompressMode(9);
3304 }
3305 #endif
3306 #endif /* LIBXML_OUTPUT_ENABLED */
3307 else if ((!strcmp(argv[i], "-nowarning")) ||
3308 (!strcmp(argv[i], "--nowarning"))) {
3309 xmlGetWarningsDefaultValue = 0;
3310 xmlPedanticParserDefault(0);
3311 options |= XML_PARSE_NOWARNING;
3312 }
3313 else if ((!strcmp(argv[i], "-pedantic")) ||
3314 (!strcmp(argv[i], "--pedantic"))) {
3315 xmlGetWarningsDefaultValue = 1;
3316 xmlPedanticParserDefault(1);
3317 options |= XML_PARSE_PEDANTIC;
3318 }
3319 #ifdef LIBXML_DEBUG_ENABLED
3320 else if ((!strcmp(argv[i], "-debugent")) ||
3321 (!strcmp(argv[i], "--debugent"))) {
3322 debugent++;
3323 xmlParserDebugEntities = 1;
3324 }
3325 #endif
3326 #ifdef LIBXML_C14N_ENABLED
3327 else if ((!strcmp(argv[i], "-c14n")) ||
3328 (!strcmp(argv[i], "--c14n"))) {
3329 canonical++;
3330 options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3331 }
3332 else if ((!strcmp(argv[i], "-c14n11")) ||
3333 (!strcmp(argv[i], "--c14n11"))) {
3334 canonical_11++;
3335 options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3336 }
3337 else if ((!strcmp(argv[i], "-exc-c14n")) ||
3338 (!strcmp(argv[i], "--exc-c14n"))) {
3339 exc_canonical++;
3340 options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
3341 }
3342 #endif
3343 #ifdef LIBXML_CATALOG_ENABLED
3344 else if ((!strcmp(argv[i], "-catalogs")) ||
3345 (!strcmp(argv[i], "--catalogs"))) {
3346 catalogs++;
3347 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
3348 (!strcmp(argv[i], "--nocatalogs"))) {
3349 nocatalogs++;
3350 }
3351 #endif
3352 else if ((!strcmp(argv[i], "-encode")) ||
3353 (!strcmp(argv[i], "--encode"))) {
3354 i++;
3355 encoding = argv[i];
3356 /*
3357 * OK it's for testing purposes
3358 */
3359 xmlAddEncodingAlias("UTF-8", "DVEnc");
3360 }
3361 else if ((!strcmp(argv[i], "-noblanks")) ||
3362 (!strcmp(argv[i], "--noblanks"))) {
3363 noblanks++;
3364 xmlKeepBlanksDefault(0);
3365 options |= XML_PARSE_NOBLANKS;
3366 }
3367 else if ((!strcmp(argv[i], "-maxmem")) ||
3368 (!strcmp(argv[i], "--maxmem"))) {
3369 i++;
3370 if (sscanf(argv[i], "%d", &maxmem) == 1) {
3371 xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc,
3372 myStrdupFunc);
3373 } else {
3374 maxmem = 0;
3375 }
3376 }
3377 else if ((!strcmp(argv[i], "-format")) ||
3378 (!strcmp(argv[i], "--format"))) {
3379 noblanks++;
3380 #ifdef LIBXML_OUTPUT_ENABLED
3381 format = 1;
3382 #endif /* LIBXML_OUTPUT_ENABLED */
3383 xmlKeepBlanksDefault(0);
3384 }
3385 else if ((!strcmp(argv[i], "-pretty")) ||
3386 (!strcmp(argv[i], "--pretty"))) {
3387 i++;
3388 #ifdef LIBXML_OUTPUT_ENABLED
3389 if (argv[i] != NULL) {
3390 format = atoi(argv[i]);
3391 if (format == 1) {
3392 noblanks++;
3393 xmlKeepBlanksDefault(0);
3394 }
3395 }
3396 #endif /* LIBXML_OUTPUT_ENABLED */
3397 }
3398 #ifdef LIBXML_READER_ENABLED
3399 else if ((!strcmp(argv[i], "-stream")) ||
3400 (!strcmp(argv[i], "--stream"))) {
3401 stream++;
3402 }
3403 else if ((!strcmp(argv[i], "-walker")) ||
3404 (!strcmp(argv[i], "--walker"))) {
3405 walker++;
3406 noout++;
3407 }
3408 #endif /* LIBXML_READER_ENABLED */
3409 #ifdef LIBXML_SAX1_ENABLED
3410 else if ((!strcmp(argv[i], "-sax1")) ||
3411 (!strcmp(argv[i], "--sax1"))) {
3412 sax1++;
3413 options |= XML_PARSE_SAX1;
3414 }
3415 #endif /* LIBXML_SAX1_ENABLED */
3416 else if ((!strcmp(argv[i], "-sax")) ||
3417 (!strcmp(argv[i], "--sax"))) {
3418 sax++;
3419 }
3420 else if ((!strcmp(argv[i], "-chkregister")) ||
3421 (!strcmp(argv[i], "--chkregister"))) {
3422 chkregister++;
3423 #ifdef LIBXML_SCHEMAS_ENABLED
3424 } else if ((!strcmp(argv[i], "-relaxng")) ||
3425 (!strcmp(argv[i], "--relaxng"))) {
3426 i++;
3427 relaxng = argv[i];
3428 noent++;
3429 options |= XML_PARSE_NOENT;
3430 } else if ((!strcmp(argv[i], "-schema")) ||
3431 (!strcmp(argv[i], "--schema"))) {
3432 i++;
3433 schema = argv[i];
3434 noent++;
3435 #endif
3436 #ifdef LIBXML_SCHEMATRON_ENABLED
3437 } else if ((!strcmp(argv[i], "-schematron")) ||
3438 (!strcmp(argv[i], "--schematron"))) {
3439 i++;
3440 schematron = argv[i];
3441 noent++;
3442 #endif
3443 } else if ((!strcmp(argv[i], "-nonet")) ||
3444 (!strcmp(argv[i], "--nonet"))) {
3445 options |= XML_PARSE_NONET;
3446 xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
3447 } else if ((!strcmp(argv[i], "-nocompact")) ||
3448 (!strcmp(argv[i], "--nocompact"))) {
3449 options &= ~XML_PARSE_COMPACT;
3450 } else if ((!strcmp(argv[i], "-load-trace")) ||
3451 (!strcmp(argv[i], "--load-trace"))) {
3452 load_trace++;
3453 } else if ((!strcmp(argv[i], "-path")) ||
3454 (!strcmp(argv[i], "--path"))) {
3455 i++;
3456 parsePath(BAD_CAST argv[i]);
3457 #ifdef LIBXML_PATTERN_ENABLED
3458 } else if ((!strcmp(argv[i], "-pattern")) ||
3459 (!strcmp(argv[i], "--pattern"))) {
3460 i++;
3461 pattern = argv[i];
3462 #endif
3463 #ifdef LIBXML_XPATH_ENABLED
3464 } else if ((!strcmp(argv[i], "-xpath")) ||
3465 (!strcmp(argv[i], "--xpath"))) {
3466 i++;
3467 noout++;
3468 xpathquery = argv[i];
3469 #endif
3470 } else if ((!strcmp(argv[i], "-oldxml10")) ||
3471 (!strcmp(argv[i], "--oldxml10"))) {
3472 oldxml10++;
3473 options |= XML_PARSE_OLD10;
3474 } else {
3475 fprintf(stderr, "Unknown option %s\n", argv[i]);
3476 usage(stderr, argv[0]);
3477 return(1);
3478 }
3479 }
3480
3481 #ifdef LIBXML_CATALOG_ENABLED
3482 if (nocatalogs == 0) {
3483 if (catalogs) {
3484 const char *catal;
3485
3486 catal = getenv("SGML_CATALOG_FILES");
3487 if (catal != NULL) {
3488 xmlLoadCatalogs(catal);
3489 } else {
3490 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
3491 }
3492 }
3493 }
3494 #endif
3495
3496 #ifdef LIBXML_SAX1_ENABLED
3497 if (sax1)
3498 xmlSAXDefaultVersion(1);
3499 else
3500 xmlSAXDefaultVersion(2);
3501 #endif /* LIBXML_SAX1_ENABLED */
3502
3503 if (chkregister) {
3504 xmlRegisterNodeDefault(registerNode);
3505 xmlDeregisterNodeDefault(deregisterNode);
3506 }
3507
3508 indent = getenv("XMLLINT_INDENT");
3509 if(indent != NULL) {
3510 xmlTreeIndentString = indent;
3511 }
3512
3513
3514 defaultEntityLoader = xmlGetExternalEntityLoader();
3515 xmlSetExternalEntityLoader(xmllintExternalEntityLoader);
3516
3517 xmlLineNumbersDefault(1);
3518 if (loaddtd != 0)
3519 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
3520 if (dtdattrs)
3521 xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
3522 if (noent != 0) xmlSubstituteEntitiesDefault(1);
3523 #ifdef LIBXML_VALID_ENABLED
3524 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
3525 #endif /* LIBXML_VALID_ENABLED */
3526 if ((htmlout) && (!nowrap)) {
3527 xmlGenericError(xmlGenericErrorContext,
3528 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
3529 xmlGenericError(xmlGenericErrorContext,
3530 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
3531 xmlGenericError(xmlGenericErrorContext,
3532 "<html><head><title>%s output</title></head>\n",
3533 argv[0]);
3534 xmlGenericError(xmlGenericErrorContext,
3535 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
3536 argv[0]);
3537 }
3538
3539 #ifdef LIBXML_SCHEMATRON_ENABLED
3540 if ((schematron != NULL) && (sax == 0)
3541 #ifdef LIBXML_READER_ENABLED
3542 && (stream == 0)
3543 #endif /* LIBXML_READER_ENABLED */
3544 ) {
3545 xmlSchematronParserCtxtPtr ctxt;
3546
3547 /* forces loading the DTDs */
3548 xmlLoadExtDtdDefaultValue |= 1;
3549 options |= XML_PARSE_DTDLOAD;
3550 if (timing) {
3551 startTimer();
3552 }
3553 ctxt = xmlSchematronNewParserCtxt(schematron);
3554 #if 0
3555 xmlSchematronSetParserErrors(ctxt,
3556 (xmlSchematronValidityErrorFunc) fprintf,
3557 (xmlSchematronValidityWarningFunc) fprintf,
3558 stderr);
3559 #endif
3560 wxschematron = xmlSchematronParse(ctxt);
3561 if (wxschematron == NULL) {
3562 xmlGenericError(xmlGenericErrorContext,
3563 "Schematron schema %s failed to compile\n", schematron);
3564 progresult = XMLLINT_ERR_SCHEMACOMP;
3565 schematron = NULL;
3566 }
3567 xmlSchematronFreeParserCtxt(ctxt);
3568 if (timing) {
3569 endTimer("Compiling the schemas");
3570 }
3571 }
3572 #endif
3573 #ifdef LIBXML_SCHEMAS_ENABLED
3574 if ((relaxng != NULL) && (sax == 0)
3575 #ifdef LIBXML_READER_ENABLED
3576 && (stream == 0)
3577 #endif /* LIBXML_READER_ENABLED */
3578 ) {
3579 xmlRelaxNGParserCtxtPtr ctxt;
3580
3581 /* forces loading the DTDs */
3582 xmlLoadExtDtdDefaultValue |= 1;
3583 options |= XML_PARSE_DTDLOAD;
3584 if (timing) {
3585 startTimer();
3586 }
3587 ctxt = xmlRelaxNGNewParserCtxt(relaxng);
3588 xmlRelaxNGSetParserErrors(ctxt,
3589 (xmlRelaxNGValidityErrorFunc) fprintf,
3590 (xmlRelaxNGValidityWarningFunc) fprintf,
3591 stderr);
3592 relaxngschemas = xmlRelaxNGParse(ctxt);
3593 if (relaxngschemas == NULL) {
3594 xmlGenericError(xmlGenericErrorContext,
3595 "Relax-NG schema %s failed to compile\n", relaxng);
3596 progresult = XMLLINT_ERR_SCHEMACOMP;
3597 relaxng = NULL;
3598 }
3599 xmlRelaxNGFreeParserCtxt(ctxt);
3600 if (timing) {
3601 endTimer("Compiling the schemas");
3602 }
3603 } else if ((schema != NULL)
3604 #ifdef LIBXML_READER_ENABLED
3605 && (stream == 0)
3606 #endif
3607 ) {
3608 xmlSchemaParserCtxtPtr ctxt;
3609
3610 if (timing) {
3611 startTimer();
3612 }
3613 ctxt = xmlSchemaNewParserCtxt(schema);
3614 xmlSchemaSetParserErrors(ctxt,
3615 (xmlSchemaValidityErrorFunc) fprintf,
3616 (xmlSchemaValidityWarningFunc) fprintf,
3617 stderr);
3618 wxschemas = xmlSchemaParse(ctxt);
3619 if (wxschemas == NULL) {
3620 xmlGenericError(xmlGenericErrorContext,
3621 "WXS schema %s failed to compile\n", schema);
3622 progresult = XMLLINT_ERR_SCHEMACOMP;
3623 schema = NULL;
3624 }
3625 xmlSchemaFreeParserCtxt(ctxt);
3626 if (timing) {
3627 endTimer("Compiling the schemas");
3628 }
3629 }
3630 #endif /* LIBXML_SCHEMAS_ENABLED */
3631 #ifdef LIBXML_PATTERN_ENABLED
3632 if ((pattern != NULL)
3633 #ifdef LIBXML_READER_ENABLED
3634 && (walker == 0)
3635 #endif
3636 ) {
3637 patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL);
3638 if (patternc == NULL) {
3639 xmlGenericError(xmlGenericErrorContext,
3640 "Pattern %s failed to compile\n", pattern);
3641 progresult = XMLLINT_ERR_SCHEMAPAT;
3642 pattern = NULL;
3643 }
3644 }
3645 #endif /* LIBXML_PATTERN_ENABLED */
3646 for (i = 1; i < argc ; i++) {
3647 if ((!strcmp(argv[i], "-encode")) ||
3648 (!strcmp(argv[i], "--encode"))) {
3649 i++;
3650 continue;
3651 } else if ((!strcmp(argv[i], "-o")) ||
3652 (!strcmp(argv[i], "-output")) ||
3653 (!strcmp(argv[i], "--output"))) {
3654 i++;
3655 continue;
3656 }
3657 #ifdef LIBXML_VALID_ENABLED
3658 if ((!strcmp(argv[i], "-dtdvalid")) ||
3659 (!strcmp(argv[i], "--dtdvalid"))) {
3660 i++;
3661 continue;
3662 }
3663 if ((!strcmp(argv[i], "-path")) ||
3664 (!strcmp(argv[i], "--path"))) {
3665 i++;
3666 continue;
3667 }
3668 if ((!strcmp(argv[i], "-dtdvalidfpi")) ||
3669 (!strcmp(argv[i], "--dtdvalidfpi"))) {
3670 i++;
3671 continue;
3672 }
3673 #endif /* LIBXML_VALID_ENABLED */
3674 if ((!strcmp(argv[i], "-relaxng")) ||
3675 (!strcmp(argv[i], "--relaxng"))) {
3676 i++;
3677 continue;
3678 }
3679 if ((!strcmp(argv[i], "-maxmem")) ||
3680 (!strcmp(argv[i], "--maxmem"))) {
3681 i++;
3682 continue;
3683 }
3684 if ((!strcmp(argv[i], "-pretty")) ||
3685 (!strcmp(argv[i], "--pretty"))) {
3686 i++;
3687 continue;
3688 }
3689 if ((!strcmp(argv[i], "-schema")) ||
3690 (!strcmp(argv[i], "--schema"))) {
3691 i++;
3692 continue;
3693 }
3694 if ((!strcmp(argv[i], "-schematron")) ||
3695 (!strcmp(argv[i], "--schematron"))) {
3696 i++;
3697 continue;
3698 }
3699 #ifdef LIBXML_PATTERN_ENABLED
3700 if ((!strcmp(argv[i], "-pattern")) ||
3701 (!strcmp(argv[i], "--pattern"))) {
3702 i++;
3703 continue;
3704 }
3705 #endif
3706 #ifdef LIBXML_XPATH_ENABLED
3707 if ((!strcmp(argv[i], "-xpath")) ||
3708 (!strcmp(argv[i], "--xpath"))) {
3709 i++;
3710 continue;
3711 }
3712 #endif
3713 if ((timing) && (repeat))
3714 startTimer();
3715 /* Remember file names. "-" means stdin. <sven@zen.org> */
3716 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
3717 if (repeat) {
3718 xmlParserCtxtPtr ctxt = NULL;
3719
3720 for (acount = 0;acount < repeat;acount++) {
3721 #ifdef LIBXML_READER_ENABLED
3722 if (stream != 0) {
3723 streamFile(argv[i]);
3724 } else {
3725 #endif /* LIBXML_READER_ENABLED */
3726 if (sax) {
3727 testSAX(argv[i]);
3728 } else {
3729 if (ctxt == NULL)
3730 ctxt = xmlNewParserCtxt();
3731 parseAndPrintFile(argv[i], ctxt);
3732 }
3733 #ifdef LIBXML_READER_ENABLED
3734 }
3735 #endif /* LIBXML_READER_ENABLED */
3736 }
3737 if (ctxt != NULL)
3738 xmlFreeParserCtxt(ctxt);
3739 } else {
3740 nbregister = 0;
3741
3742 #ifdef LIBXML_READER_ENABLED
3743 if (stream != 0)
3744 streamFile(argv[i]);
3745 else
3746 #endif /* LIBXML_READER_ENABLED */
3747 if (sax) {
3748 testSAX(argv[i]);
3749 } else {
3750 parseAndPrintFile(argv[i], NULL);
3751 }
3752
3753 if ((chkregister) && (nbregister != 0)) {
3754 fprintf(stderr, "Registration count off: %d\n", nbregister);
3755 progresult = XMLLINT_ERR_RDREGIS;
3756 }
3757 }
3758 files ++;
3759 if ((timing) && (repeat)) {
3760 endTimer("%d iterations", repeat);
3761 }
3762 }
3763 }
3764 if (generate)
3765 parseAndPrintFile(NULL, NULL);
3766 if ((htmlout) && (!nowrap)) {
3767 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
3768 }
3769 if ((files == 0) && (!generate) && (version == 0)) {
3770 usage(stderr, argv[0]);
3771 }
3772 #ifdef LIBXML_SCHEMATRON_ENABLED
3773 if (wxschematron != NULL)
3774 xmlSchematronFree(wxschematron);
3775 #endif
3776 #ifdef LIBXML_SCHEMAS_ENABLED
3777 if (relaxngschemas != NULL)
3778 xmlRelaxNGFree(relaxngschemas);
3779 if (wxschemas != NULL)
3780 xmlSchemaFree(wxschemas);
3781 xmlRelaxNGCleanupTypes();
3782 #endif
3783 #ifdef LIBXML_PATTERN_ENABLED
3784 if (patternc != NULL)
3785 xmlFreePattern(patternc);
3786 #endif
3787 xmlCleanupParser();
3788 xmlMemoryDump();
3789
3790 return(progresult);
3791 }
3792
3793