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