1/* 2 * testSAX.c : a small tester program for parsing using the SAX API. 3 * 4 * See Copyright for the status of this software. 5 * 6 * daniel@veillard.com 7 */ 8 9#include "libxml.h" 10 11#ifdef HAVE_SYS_TIME_H 12#include <sys/time.h> 13#endif 14#ifdef HAVE_SYS_TIMEB_H 15#include <sys/timeb.h> 16#endif 17#ifdef HAVE_TIME_H 18#include <time.h> 19#endif 20 21#ifdef LIBXML_SAX1_ENABLED 22#include <string.h> 23#include <stdarg.h> 24 25#ifdef HAVE_SYS_TYPES_H 26#include <sys/types.h> 27#endif 28#ifdef HAVE_SYS_STAT_H 29#include <sys/stat.h> 30#endif 31#ifdef HAVE_FCNTL_H 32#include <fcntl.h> 33#endif 34#ifdef HAVE_UNISTD_H 35#include <unistd.h> 36#endif 37#ifdef HAVE_STDLIB_H 38#include <stdlib.h> 39#endif 40#ifdef HAVE_STRING_H 41#include <string.h> 42#endif 43 44 45#include <libxml/globals.h> 46#include <libxml/xmlerror.h> 47#include <libxml/parser.h> 48#include <libxml/parserInternals.h> /* only for xmlNewInputFromFile() */ 49#include <libxml/tree.h> 50#include <libxml/debugXML.h> 51#include <libxml/xmlmemory.h> 52 53static int debug = 0; 54static int copy = 0; 55static int recovery = 0; 56static int push = 0; 57static int speed = 0; 58static int noent = 0; 59static int quiet = 0; 60static int nonull = 0; 61static int sax2 = 0; 62static int repeat = 0; 63static int callbacks = 0; 64static int timing = 0; 65 66/* 67 * Timing routines. 68 */ 69/* 70 * Internal timing routines to remove the necessity to have unix-specific 71 * function calls 72 */ 73 74#ifndef HAVE_GETTIMEOFDAY 75#ifdef HAVE_SYS_TIMEB_H 76#ifdef HAVE_SYS_TIME_H 77#ifdef HAVE_FTIME 78 79static int 80my_gettimeofday(struct timeval *tvp, void *tzp) 81{ 82 struct timeb timebuffer; 83 84 ftime(&timebuffer); 85 if (tvp) { 86 tvp->tv_sec = timebuffer.time; 87 tvp->tv_usec = timebuffer.millitm * 1000L; 88 } 89 return (0); 90} 91#define HAVE_GETTIMEOFDAY 1 92#define gettimeofday my_gettimeofday 93 94#endif /* HAVE_FTIME */ 95#endif /* HAVE_SYS_TIME_H */ 96#endif /* HAVE_SYS_TIMEB_H */ 97#endif /* !HAVE_GETTIMEOFDAY */ 98 99#if defined(HAVE_GETTIMEOFDAY) 100static struct timeval begin, end; 101 102/* 103 * startTimer: call where you want to start timing 104 */ 105static void 106startTimer(void) 107{ 108 gettimeofday(&begin, NULL); 109} 110 111/* 112 * endTimer: call where you want to stop timing and to print out a 113 * message about the timing performed; format is a printf 114 * type argument 115 */ 116static void XMLCDECL 117endTimer(const char *fmt, ...) 118{ 119 long msec; 120 va_list ap; 121 122 gettimeofday(&end, NULL); 123 msec = end.tv_sec - begin.tv_sec; 124 msec *= 1000; 125 msec += (end.tv_usec - begin.tv_usec) / 1000; 126 127#ifndef HAVE_STDARG_H 128#error "endTimer required stdarg functions" 129#endif 130 va_start(ap, fmt); 131 vfprintf(stderr, fmt, ap); 132 va_end(ap); 133 134 fprintf(stderr, " took %ld ms\n", msec); 135} 136#elif defined(HAVE_TIME_H) 137/* 138 * No gettimeofday function, so we have to make do with calling clock. 139 * This is obviously less accurate, but there's little we can do about 140 * that. 141 */ 142#ifndef CLOCKS_PER_SEC 143#define CLOCKS_PER_SEC 100 144#endif 145 146static clock_t begin, end; 147static void 148startTimer(void) 149{ 150 begin = clock(); 151} 152static void XMLCDECL 153endTimer(const char *fmt, ...) 154{ 155 long msec; 156 va_list ap; 157 158 end = clock(); 159 msec = ((end - begin) * 1000) / CLOCKS_PER_SEC; 160 161#ifndef HAVE_STDARG_H 162#error "endTimer required stdarg functions" 163#endif 164 va_start(ap, fmt); 165 vfprintf(stderr, fmt, ap); 166 va_end(ap); 167 fprintf(stderr, " took %ld ms\n", msec); 168} 169#else 170 171/* 172 * We don't have a gettimeofday or time.h, so we just don't do timing 173 */ 174static void 175startTimer(void) 176{ 177 /* 178 * Do nothing 179 */ 180} 181static void XMLCDECL 182endTimer(char *format, ...) 183{ 184 /* 185 * We cannot do anything because we don't have a timing function 186 */ 187#ifdef HAVE_STDARG_H 188 va_start(ap, format); 189 vfprintf(stderr, format, ap); 190 va_end(ap); 191 fprintf(stderr, " was not timed\n", msec); 192#else 193 /* We don't have gettimeofday, time or stdarg.h, what crazy world is 194 * this ?! 195 */ 196#endif 197} 198#endif 199 200/* 201 * empty SAX block 202 */ 203static xmlSAXHandler emptySAXHandlerStruct = { 204 NULL, /* internalSubset */ 205 NULL, /* isStandalone */ 206 NULL, /* hasInternalSubset */ 207 NULL, /* hasExternalSubset */ 208 NULL, /* resolveEntity */ 209 NULL, /* getEntity */ 210 NULL, /* entityDecl */ 211 NULL, /* notationDecl */ 212 NULL, /* attributeDecl */ 213 NULL, /* elementDecl */ 214 NULL, /* unparsedEntityDecl */ 215 NULL, /* setDocumentLocator */ 216 NULL, /* startDocument */ 217 NULL, /* endDocument */ 218 NULL, /* startElement */ 219 NULL, /* endElement */ 220 NULL, /* reference */ 221 NULL, /* characters */ 222 NULL, /* ignorableWhitespace */ 223 NULL, /* processingInstruction */ 224 NULL, /* comment */ 225 NULL, /* xmlParserWarning */ 226 NULL, /* xmlParserError */ 227 NULL, /* xmlParserError */ 228 NULL, /* getParameterEntity */ 229 NULL, /* cdataBlock; */ 230 NULL, /* externalSubset; */ 231 1, 232 NULL, 233 NULL, /* startElementNs */ 234 NULL, /* endElementNs */ 235 NULL /* xmlStructuredErrorFunc */ 236}; 237 238static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct; 239extern xmlSAXHandlerPtr debugSAXHandler; 240 241/************************************************************************ 242 * * 243 * Debug Handlers * 244 * * 245 ************************************************************************/ 246 247/** 248 * isStandaloneDebug: 249 * @ctxt: An XML parser context 250 * 251 * Is this document tagged standalone ? 252 * 253 * Returns 1 if true 254 */ 255static int 256isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED) 257{ 258 callbacks++; 259 if (quiet) 260 return(0); 261 fprintf(stdout, "SAX.isStandalone()\n"); 262 return(0); 263} 264 265/** 266 * hasInternalSubsetDebug: 267 * @ctxt: An XML parser context 268 * 269 * Does this document has an internal subset 270 * 271 * Returns 1 if true 272 */ 273static int 274hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED) 275{ 276 callbacks++; 277 if (quiet) 278 return(0); 279 fprintf(stdout, "SAX.hasInternalSubset()\n"); 280 return(0); 281} 282 283/** 284 * hasExternalSubsetDebug: 285 * @ctxt: An XML parser context 286 * 287 * Does this document has an external subset 288 * 289 * Returns 1 if true 290 */ 291static int 292hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED) 293{ 294 callbacks++; 295 if (quiet) 296 return(0); 297 fprintf(stdout, "SAX.hasExternalSubset()\n"); 298 return(0); 299} 300 301/** 302 * internalSubsetDebug: 303 * @ctxt: An XML parser context 304 * 305 * Does this document has an internal subset 306 */ 307static void 308internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 309 const xmlChar *ExternalID, const xmlChar *SystemID) 310{ 311 callbacks++; 312 if (quiet) 313 return; 314 fprintf(stdout, "SAX.internalSubset(%s,", name); 315 if (ExternalID == NULL) 316 fprintf(stdout, " ,"); 317 else 318 fprintf(stdout, " %s,", ExternalID); 319 if (SystemID == NULL) 320 fprintf(stdout, " )\n"); 321 else 322 fprintf(stdout, " %s)\n", SystemID); 323} 324 325/** 326 * externalSubsetDebug: 327 * @ctxt: An XML parser context 328 * 329 * Does this document has an external subset 330 */ 331static void 332externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 333 const xmlChar *ExternalID, const xmlChar *SystemID) 334{ 335 callbacks++; 336 if (quiet) 337 return; 338 fprintf(stdout, "SAX.externalSubset(%s,", name); 339 if (ExternalID == NULL) 340 fprintf(stdout, " ,"); 341 else 342 fprintf(stdout, " %s,", ExternalID); 343 if (SystemID == NULL) 344 fprintf(stdout, " )\n"); 345 else 346 fprintf(stdout, " %s)\n", SystemID); 347} 348 349/** 350 * resolveEntityDebug: 351 * @ctxt: An XML parser context 352 * @publicId: The public ID of the entity 353 * @systemId: The system ID of the entity 354 * 355 * Special entity resolver, better left to the parser, it has 356 * more context than the application layer. 357 * The default behaviour is to NOT resolve the entities, in that case 358 * the ENTITY_REF nodes are built in the structure (and the parameter 359 * values). 360 * 361 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 362 */ 363static xmlParserInputPtr 364resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId) 365{ 366 callbacks++; 367 if (quiet) 368 return(NULL); 369 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 370 371 372 fprintf(stdout, "SAX.resolveEntity("); 373 if (publicId != NULL) 374 fprintf(stdout, "%s", (char *)publicId); 375 else 376 fprintf(stdout, " "); 377 if (systemId != NULL) 378 fprintf(stdout, ", %s)\n", (char *)systemId); 379 else 380 fprintf(stdout, ", )\n"); 381/********* 382 if (systemId != NULL) { 383 return(xmlNewInputFromFile(ctxt, (char *) systemId)); 384 } 385 *********/ 386 return(NULL); 387} 388 389/** 390 * getEntityDebug: 391 * @ctxt: An XML parser context 392 * @name: The entity name 393 * 394 * Get an entity by name 395 * 396 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 397 */ 398static xmlEntityPtr 399getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 400{ 401 callbacks++; 402 if (quiet) 403 return(NULL); 404 fprintf(stdout, "SAX.getEntity(%s)\n", name); 405 return(NULL); 406} 407 408/** 409 * getParameterEntityDebug: 410 * @ctxt: An XML parser context 411 * @name: The entity name 412 * 413 * Get a parameter entity by name 414 * 415 * Returns the xmlParserInputPtr 416 */ 417static xmlEntityPtr 418getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 419{ 420 callbacks++; 421 if (quiet) 422 return(NULL); 423 fprintf(stdout, "SAX.getParameterEntity(%s)\n", name); 424 return(NULL); 425} 426 427 428/** 429 * entityDeclDebug: 430 * @ctxt: An XML parser context 431 * @name: the entity name 432 * @type: the entity type 433 * @publicId: The public ID of the entity 434 * @systemId: The system ID of the entity 435 * @content: the entity value (without processing). 436 * 437 * An entity definition has been parsed 438 */ 439static void 440entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type, 441 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) 442{ 443const xmlChar *nullstr = BAD_CAST "(null)"; 444 /* not all libraries handle printing null pointers nicely */ 445 if (publicId == NULL) 446 publicId = nullstr; 447 if (systemId == NULL) 448 systemId = nullstr; 449 if (content == NULL) 450 content = (xmlChar *)nullstr; 451 callbacks++; 452 if (quiet) 453 return; 454 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n", 455 name, type, publicId, systemId, content); 456} 457 458/** 459 * attributeDeclDebug: 460 * @ctxt: An XML parser context 461 * @name: the attribute name 462 * @type: the attribute type 463 * 464 * An attribute definition has been parsed 465 */ 466static void 467attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem, 468 const xmlChar * name, int type, int def, 469 const xmlChar * defaultValue, xmlEnumerationPtr tree) 470{ 471 callbacks++; 472 if (quiet) 473 return; 474 if (defaultValue == NULL) 475 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n", 476 elem, name, type, def); 477 else 478 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n", 479 elem, name, type, def, defaultValue); 480 xmlFreeEnumeration(tree); 481} 482 483/** 484 * elementDeclDebug: 485 * @ctxt: An XML parser context 486 * @name: the element name 487 * @type: the element type 488 * @content: the element value (without processing). 489 * 490 * An element definition has been parsed 491 */ 492static void 493elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type, 494 xmlElementContentPtr content ATTRIBUTE_UNUSED) 495{ 496 callbacks++; 497 if (quiet) 498 return; 499 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n", 500 name, type); 501} 502 503/** 504 * notationDeclDebug: 505 * @ctxt: An XML parser context 506 * @name: The name of the notation 507 * @publicId: The public ID of the entity 508 * @systemId: The system ID of the entity 509 * 510 * What to do when a notation declaration has been parsed. 511 */ 512static void 513notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 514 const xmlChar *publicId, const xmlChar *systemId) 515{ 516 callbacks++; 517 if (quiet) 518 return; 519 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n", 520 (char *) name, (char *) publicId, (char *) systemId); 521} 522 523/** 524 * unparsedEntityDeclDebug: 525 * @ctxt: An XML parser context 526 * @name: The name of the entity 527 * @publicId: The public ID of the entity 528 * @systemId: The system ID of the entity 529 * @notationName: the name of the notation 530 * 531 * What to do when an unparsed entity declaration is parsed 532 */ 533static void 534unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 535 const xmlChar *publicId, const xmlChar *systemId, 536 const xmlChar *notationName) 537{ 538const xmlChar *nullstr = BAD_CAST "(null)"; 539 540 if (publicId == NULL) 541 publicId = nullstr; 542 if (systemId == NULL) 543 systemId = nullstr; 544 if (notationName == NULL) 545 notationName = nullstr; 546 callbacks++; 547 if (quiet) 548 return; 549 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n", 550 (char *) name, (char *) publicId, (char *) systemId, 551 (char *) notationName); 552} 553 554/** 555 * setDocumentLocatorDebug: 556 * @ctxt: An XML parser context 557 * @loc: A SAX Locator 558 * 559 * Receive the document locator at startup, actually xmlDefaultSAXLocator 560 * Everything is available on the context, so this is useless in our case. 561 */ 562static void 563setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED) 564{ 565 callbacks++; 566 if (quiet) 567 return; 568 fprintf(stdout, "SAX.setDocumentLocator()\n"); 569} 570 571/** 572 * startDocumentDebug: 573 * @ctxt: An XML parser context 574 * 575 * called when the document start being processed. 576 */ 577static void 578startDocumentDebug(void *ctx ATTRIBUTE_UNUSED) 579{ 580 callbacks++; 581 if (quiet) 582 return; 583 fprintf(stdout, "SAX.startDocument()\n"); 584} 585 586/** 587 * endDocumentDebug: 588 * @ctxt: An XML parser context 589 * 590 * called when the document end has been detected. 591 */ 592static void 593endDocumentDebug(void *ctx ATTRIBUTE_UNUSED) 594{ 595 callbacks++; 596 if (quiet) 597 return; 598 fprintf(stdout, "SAX.endDocument()\n"); 599} 600 601/** 602 * startElementDebug: 603 * @ctxt: An XML parser context 604 * @name: The element name 605 * 606 * called when an opening tag has been processed. 607 */ 608static void 609startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts) 610{ 611 int i; 612 613 callbacks++; 614 if (quiet) 615 return; 616 fprintf(stdout, "SAX.startElement(%s", (char *) name); 617 if (atts != NULL) { 618 for (i = 0;(atts[i] != NULL);i++) { 619 fprintf(stdout, ", %s='", atts[i++]); 620 if (atts[i] != NULL) 621 fprintf(stdout, "%s'", atts[i]); 622 } 623 } 624 fprintf(stdout, ")\n"); 625} 626 627/** 628 * endElementDebug: 629 * @ctxt: An XML parser context 630 * @name: The element name 631 * 632 * called when the end of an element has been detected. 633 */ 634static void 635endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 636{ 637 callbacks++; 638 if (quiet) 639 return; 640 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name); 641} 642 643/** 644 * charactersDebug: 645 * @ctxt: An XML parser context 646 * @ch: a xmlChar string 647 * @len: the number of xmlChar 648 * 649 * receiving some chars from the parser. 650 * Question: how much at a time ??? 651 */ 652static void 653charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) 654{ 655 char output[40]; 656 int i; 657 658 callbacks++; 659 if (quiet) 660 return; 661 for (i = 0;(i<len) && (i < 30);i++) 662 output[i] = ch[i]; 663 output[i] = 0; 664 665 fprintf(stdout, "SAX.characters(%s, %d)\n", output, len); 666} 667 668/** 669 * referenceDebug: 670 * @ctxt: An XML parser context 671 * @name: The entity name 672 * 673 * called when an entity reference is detected. 674 */ 675static void 676referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 677{ 678 callbacks++; 679 if (quiet) 680 return; 681 fprintf(stdout, "SAX.reference(%s)\n", name); 682} 683 684/** 685 * ignorableWhitespaceDebug: 686 * @ctxt: An XML parser context 687 * @ch: a xmlChar string 688 * @start: the first char in the string 689 * @len: the number of xmlChar 690 * 691 * receiving some ignorable whitespaces from the parser. 692 * Question: how much at a time ??? 693 */ 694static void 695ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) 696{ 697 char output[40]; 698 int i; 699 700 callbacks++; 701 if (quiet) 702 return; 703 for (i = 0;(i<len) && (i < 30);i++) 704 output[i] = ch[i]; 705 output[i] = 0; 706 fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", output, len); 707} 708 709/** 710 * processingInstructionDebug: 711 * @ctxt: An XML parser context 712 * @target: the target name 713 * @data: the PI data's 714 * @len: the number of xmlChar 715 * 716 * A processing instruction has been parsed. 717 */ 718static void 719processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target, 720 const xmlChar *data) 721{ 722 callbacks++; 723 if (quiet) 724 return; 725 if (data != NULL) 726 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n", 727 (char *) target, (char *) data); 728 else 729 fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n", 730 (char *) target); 731} 732 733/** 734 * cdataBlockDebug: 735 * @ctx: the user data (XML parser context) 736 * @value: The pcdata content 737 * @len: the block length 738 * 739 * called when a pcdata block has been parsed 740 */ 741static void 742cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len) 743{ 744 callbacks++; 745 if (quiet) 746 return; 747 fprintf(stdout, "SAX.pcdata(%.20s, %d)\n", 748 (char *) value, len); 749} 750 751/** 752 * commentDebug: 753 * @ctxt: An XML parser context 754 * @value: the comment content 755 * 756 * A comment has been parsed. 757 */ 758static void 759commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value) 760{ 761 callbacks++; 762 if (quiet) 763 return; 764 fprintf(stdout, "SAX.comment(%s)\n", value); 765} 766 767/** 768 * warningDebug: 769 * @ctxt: An XML parser context 770 * @msg: the message to display/transmit 771 * @...: extra parameters for the message display 772 * 773 * Display and format a warning messages, gives file, line, position and 774 * extra parameters. 775 */ 776static void XMLCDECL 777warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) 778{ 779 va_list args; 780 781 callbacks++; 782 if (quiet) 783 return; 784 va_start(args, msg); 785 fprintf(stdout, "SAX.warning: "); 786 vfprintf(stdout, msg, args); 787 va_end(args); 788} 789 790/** 791 * errorDebug: 792 * @ctxt: An XML parser context 793 * @msg: the message to display/transmit 794 * @...: extra parameters for the message display 795 * 796 * Display and format a error messages, gives file, line, position and 797 * extra parameters. 798 */ 799static void XMLCDECL 800errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) 801{ 802 va_list args; 803 804 callbacks++; 805 if (quiet) 806 return; 807 va_start(args, msg); 808 fprintf(stdout, "SAX.error: "); 809 vfprintf(stdout, msg, args); 810 va_end(args); 811} 812 813/** 814 * fatalErrorDebug: 815 * @ctxt: An XML parser context 816 * @msg: the message to display/transmit 817 * @...: extra parameters for the message display 818 * 819 * Display and format a fatalError messages, gives file, line, position and 820 * extra parameters. 821 */ 822static void XMLCDECL 823fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) 824{ 825 va_list args; 826 827 callbacks++; 828 if (quiet) 829 return; 830 va_start(args, msg); 831 fprintf(stdout, "SAX.fatalError: "); 832 vfprintf(stdout, msg, args); 833 va_end(args); 834} 835 836static xmlSAXHandler debugSAXHandlerStruct = { 837 internalSubsetDebug, 838 isStandaloneDebug, 839 hasInternalSubsetDebug, 840 hasExternalSubsetDebug, 841 resolveEntityDebug, 842 getEntityDebug, 843 entityDeclDebug, 844 notationDeclDebug, 845 attributeDeclDebug, 846 elementDeclDebug, 847 unparsedEntityDeclDebug, 848 setDocumentLocatorDebug, 849 startDocumentDebug, 850 endDocumentDebug, 851 startElementDebug, 852 endElementDebug, 853 referenceDebug, 854 charactersDebug, 855 ignorableWhitespaceDebug, 856 processingInstructionDebug, 857 commentDebug, 858 warningDebug, 859 errorDebug, 860 fatalErrorDebug, 861 getParameterEntityDebug, 862 cdataBlockDebug, 863 externalSubsetDebug, 864 1, 865 NULL, 866 NULL, 867 NULL, 868 NULL 869}; 870 871xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct; 872 873/* 874 * SAX2 specific callbacks 875 */ 876/** 877 * startElementNsDebug: 878 * @ctxt: An XML parser context 879 * @name: The element name 880 * 881 * called when an opening tag has been processed. 882 */ 883static void 884startElementNsDebug(void *ctx ATTRIBUTE_UNUSED, 885 const xmlChar *localname, 886 const xmlChar *prefix, 887 const xmlChar *URI, 888 int nb_namespaces, 889 const xmlChar **namespaces, 890 int nb_attributes, 891 int nb_defaulted, 892 const xmlChar **attributes) 893{ 894 int i; 895 896 callbacks++; 897 if (quiet) 898 return; 899 fprintf(stdout, "SAX.startElementNs(%s", (char *) localname); 900 if (prefix == NULL) 901 fprintf(stdout, ", NULL"); 902 else 903 fprintf(stdout, ", %s", (char *) prefix); 904 if (URI == NULL) 905 fprintf(stdout, ", NULL"); 906 else 907 fprintf(stdout, ", '%s'", (char *) URI); 908 fprintf(stdout, ", %d", nb_namespaces); 909 910 if (namespaces != NULL) { 911 for (i = 0;i < nb_namespaces * 2;i++) { 912 fprintf(stdout, ", xmlns"); 913 if (namespaces[i] != NULL) 914 fprintf(stdout, ":%s", namespaces[i]); 915 i++; 916 fprintf(stdout, "='%s'", namespaces[i]); 917 } 918 } 919 fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted); 920 if (attributes != NULL) { 921 for (i = 0;i < nb_attributes * 5;i += 5) { 922 if (attributes[i + 1] != NULL) 923 fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]); 924 else 925 fprintf(stdout, ", %s='", attributes[i]); 926 fprintf(stdout, "%.4s...', %d", attributes[i + 3], 927 (int)(attributes[i + 4] - attributes[i + 3])); 928 } 929 } 930 fprintf(stdout, ")\n"); 931} 932 933/** 934 * endElementDebug: 935 * @ctxt: An XML parser context 936 * @name: The element name 937 * 938 * called when the end of an element has been detected. 939 */ 940static void 941endElementNsDebug(void *ctx ATTRIBUTE_UNUSED, 942 const xmlChar *localname, 943 const xmlChar *prefix, 944 const xmlChar *URI) 945{ 946 callbacks++; 947 if (quiet) 948 return; 949 fprintf(stdout, "SAX.endElementNs(%s", (char *) localname); 950 if (prefix == NULL) 951 fprintf(stdout, ", NULL"); 952 else 953 fprintf(stdout, ", %s", (char *) prefix); 954 if (URI == NULL) 955 fprintf(stdout, ", NULL)\n"); 956 else 957 fprintf(stdout, ", '%s')\n", (char *) URI); 958} 959 960static xmlSAXHandler debugSAX2HandlerStruct = { 961 internalSubsetDebug, 962 isStandaloneDebug, 963 hasInternalSubsetDebug, 964 hasExternalSubsetDebug, 965 resolveEntityDebug, 966 getEntityDebug, 967 entityDeclDebug, 968 notationDeclDebug, 969 attributeDeclDebug, 970 elementDeclDebug, 971 unparsedEntityDeclDebug, 972 setDocumentLocatorDebug, 973 startDocumentDebug, 974 endDocumentDebug, 975 NULL, 976 NULL, 977 referenceDebug, 978 charactersDebug, 979 ignorableWhitespaceDebug, 980 processingInstructionDebug, 981 commentDebug, 982 warningDebug, 983 errorDebug, 984 fatalErrorDebug, 985 getParameterEntityDebug, 986 cdataBlockDebug, 987 externalSubsetDebug, 988 XML_SAX2_MAGIC, 989 NULL, 990 startElementNsDebug, 991 endElementNsDebug, 992 NULL 993}; 994 995static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct; 996 997/************************************************************************ 998 * * 999 * Debug * 1000 * * 1001 ************************************************************************/ 1002 1003static void 1004parseAndPrintFile(char *filename) { 1005 int res; 1006 1007#ifdef LIBXML_PUSH_ENABLED 1008 if (push) { 1009 FILE *f; 1010 1011 if ((!quiet) && (!nonull)) { 1012 /* 1013 * Empty callbacks for checking 1014 */ 1015#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) 1016 f = fopen(filename, "rb"); 1017#else 1018 f = fopen(filename, "r"); 1019#endif 1020 if (f != NULL) { 1021 int ret; 1022 char chars[10]; 1023 xmlParserCtxtPtr ctxt; 1024 1025 ret = fread(chars, 1, 4, f); 1026 if (ret > 0) { 1027 ctxt = xmlCreatePushParserCtxt(emptySAXHandler, NULL, 1028 chars, ret, filename); 1029 while ((ret = fread(chars, 1, 3, f)) > 0) { 1030 xmlParseChunk(ctxt, chars, ret, 0); 1031 } 1032 xmlParseChunk(ctxt, chars, 0, 1); 1033 xmlFreeParserCtxt(ctxt); 1034 } 1035 fclose(f); 1036 } else { 1037 xmlGenericError(xmlGenericErrorContext, 1038 "Cannot read file %s\n", filename); 1039 } 1040 } 1041 /* 1042 * Debug callback 1043 */ 1044#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) 1045 f = fopen(filename, "rb"); 1046#else 1047 f = fopen(filename, "r"); 1048#endif 1049 if (f != NULL) { 1050 int ret; 1051 char chars[10]; 1052 xmlParserCtxtPtr ctxt; 1053 1054 ret = fread(chars, 1, 4, f); 1055 if (ret > 0) { 1056 if (sax2) 1057 ctxt = xmlCreatePushParserCtxt(debugSAX2Handler, NULL, 1058 chars, ret, filename); 1059 else 1060 ctxt = xmlCreatePushParserCtxt(debugSAXHandler, NULL, 1061 chars, ret, filename); 1062 while ((ret = fread(chars, 1, 3, f)) > 0) { 1063 xmlParseChunk(ctxt, chars, ret, 0); 1064 } 1065 ret = xmlParseChunk(ctxt, chars, 0, 1); 1066 xmlFreeParserCtxt(ctxt); 1067 if (ret != 0) { 1068 fprintf(stdout, 1069 "xmlSAXUserParseFile returned error %d\n", ret); 1070 } 1071 } 1072 fclose(f); 1073 } 1074 } else { 1075#endif /* LIBXML_PUSH_ENABLED */ 1076 if (!speed) { 1077 /* 1078 * Empty callbacks for checking 1079 */ 1080 if ((!quiet) && (!nonull)) { 1081 res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename); 1082 if (res != 0) { 1083 fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res); 1084 } 1085 } 1086 1087 /* 1088 * Debug callback 1089 */ 1090 callbacks = 0; 1091 if (repeat) { 1092 int i; 1093 for (i = 0;i < 99;i++) { 1094 if (sax2) 1095 res = xmlSAXUserParseFile(debugSAX2Handler, NULL, 1096 filename); 1097 else 1098 res = xmlSAXUserParseFile(debugSAXHandler, NULL, 1099 filename); 1100 } 1101 } 1102 if (sax2) 1103 res = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename); 1104 else 1105 res = xmlSAXUserParseFile(debugSAXHandler, NULL, filename); 1106 if (res != 0) { 1107 fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res); 1108 } 1109 if (quiet) 1110 fprintf(stdout, "%d callbacks generated\n", callbacks); 1111 } else { 1112 /* 1113 * test 100x the SAX parse 1114 */ 1115 int i; 1116 1117 for (i = 0; i<100;i++) 1118 res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename); 1119 if (res != 0) { 1120 fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res); 1121 } 1122 } 1123#ifdef LIBXML_PUSH_ENABLED 1124 } 1125#endif 1126} 1127 1128 1129int main(int argc, char **argv) { 1130 int i; 1131 int files = 0; 1132 1133 LIBXML_TEST_VERSION /* be safe, plus calls xmlInitParser */ 1134 1135 for (i = 1; i < argc ; i++) { 1136 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) 1137 debug++; 1138 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy"))) 1139 copy++; 1140 else if ((!strcmp(argv[i], "-recover")) || 1141 (!strcmp(argv[i], "--recover"))) 1142 recovery++; 1143 else if ((!strcmp(argv[i], "-push")) || 1144 (!strcmp(argv[i], "--push"))) 1145#ifdef LIBXML_PUSH_ENABLED 1146 push++; 1147#else 1148 fprintf(stderr,"'push' not enabled in library - ignoring\n"); 1149#endif /* LIBXML_PUSH_ENABLED */ 1150 else if ((!strcmp(argv[i], "-speed")) || 1151 (!strcmp(argv[i], "--speed"))) 1152 speed++; 1153 else if ((!strcmp(argv[i], "-timing")) || 1154 (!strcmp(argv[i], "--timing"))) { 1155 nonull++; 1156 timing++; 1157 quiet++; 1158 } else if ((!strcmp(argv[i], "-repeat")) || 1159 (!strcmp(argv[i], "--repeat"))) { 1160 repeat++; 1161 quiet++; 1162 } else if ((!strcmp(argv[i], "-noent")) || 1163 (!strcmp(argv[i], "--noent"))) 1164 noent++; 1165 else if ((!strcmp(argv[i], "-quiet")) || 1166 (!strcmp(argv[i], "--quiet"))) 1167 quiet++; 1168 else if ((!strcmp(argv[i], "-sax2")) || 1169 (!strcmp(argv[i], "--sax2"))) 1170 sax2++; 1171 else if ((!strcmp(argv[i], "-nonull")) || 1172 (!strcmp(argv[i], "--nonull"))) 1173 nonull++; 1174 } 1175 if (noent != 0) xmlSubstituteEntitiesDefault(1); 1176 for (i = 1; i < argc ; i++) { 1177 if (argv[i][0] != '-') { 1178 if (timing) { 1179 startTimer(); 1180 } 1181 parseAndPrintFile(argv[i]); 1182 if (timing) { 1183 endTimer("Parsing"); 1184 } 1185 files ++; 1186 } 1187 } 1188 xmlCleanupParser(); 1189 xmlMemoryDump(); 1190 1191 return(0); 1192} 1193#else 1194int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 1195 printf("%s : SAX1 parsing support not compiled in\n", argv[0]); 1196 return(0); 1197} 1198#endif /* LIBXML_SAX1_ENABLED */ 1199