dsrc isn't necessary for this repo
[client-tools.git] / src / external / 3rd / library / libxml / testSAX.c
blobcf2846784f94f51ff11a7e6220debb4d211b4358
1 /*
2 * testSAX.c : a small tester program for parsing using the SAX API.
4 * See Copyright for the status of this software.
6 * daniel@veillard.com
7 */
9 #include "libxml.h"
11 #include <string.h>
12 #include <stdarg.h>
14 #ifdef HAVE_SYS_TYPES_H
15 #include <sys/types.h>
16 #endif
17 #ifdef HAVE_SYS_STAT_H
18 #include <sys/stat.h>
19 #endif
20 #ifdef HAVE_FCNTL_H
21 #include <fcntl.h>
22 #endif
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #ifdef HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
34 #include <libxml/globals.h>
35 #include <libxml/xmlerror.h>
36 #include <libxml/parser.h>
37 #include <libxml/parserInternals.h> /* only for xmlNewInputFromFile() */
38 #include <libxml/tree.h>
39 #include <libxml/debugXML.h>
40 #include <libxml/xmlmemory.h>
42 static int debug = 0;
43 static int copy = 0;
44 static int recovery = 0;
45 static int push = 0;
46 static int speed = 0;
47 static int noent = 0;
48 static int quiet = 0;
49 static int callbacks = 0;
51 xmlSAXHandler emptySAXHandlerStruct = {
52 NULL, /* internalSubset */
53 NULL, /* isStandalone */
54 NULL, /* hasInternalSubset */
55 NULL, /* hasExternalSubset */
56 NULL, /* resolveEntity */
57 NULL, /* getEntity */
58 NULL, /* entityDecl */
59 NULL, /* notationDecl */
60 NULL, /* attributeDecl */
61 NULL, /* elementDecl */
62 NULL, /* unparsedEntityDecl */
63 NULL, /* setDocumentLocator */
64 NULL, /* startDocument */
65 NULL, /* endDocument */
66 NULL, /* startElement */
67 NULL, /* endElement */
68 NULL, /* reference */
69 NULL, /* characters */
70 NULL, /* ignorableWhitespace */
71 NULL, /* processingInstruction */
72 NULL, /* comment */
73 NULL, /* xmlParserWarning */
74 NULL, /* xmlParserError */
75 NULL, /* xmlParserError */
76 NULL, /* getParameterEntity */
77 NULL, /* cdataBlock; */
78 NULL, /* externalSubset; */
82 xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
83 extern xmlSAXHandlerPtr debugSAXHandler;
85 /************************************************************************
86 * *
87 * Debug Handlers *
88 * *
89 ************************************************************************/
91 /**
92 * isStandaloneDebug:
93 * @ctxt: An XML parser context
95 * Is this document tagged standalone ?
97 * Returns 1 if true
99 static int
100 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
102 callbacks++;
103 if (quiet)
104 return(0);
105 fprintf(stdout, "SAX.isStandalone()\n");
106 return(0);
110 * hasInternalSubsetDebug:
111 * @ctxt: An XML parser context
113 * Does this document has an internal subset
115 * Returns 1 if true
117 static int
118 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
120 callbacks++;
121 if (quiet)
122 return(0);
123 fprintf(stdout, "SAX.hasInternalSubset()\n");
124 return(0);
128 * hasExternalSubsetDebug:
129 * @ctxt: An XML parser context
131 * Does this document has an external subset
133 * Returns 1 if true
135 static int
136 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
138 callbacks++;
139 if (quiet)
140 return(0);
141 fprintf(stdout, "SAX.hasExternalSubset()\n");
142 return(0);
146 * internalSubsetDebug:
147 * @ctxt: An XML parser context
149 * Does this document has an internal subset
151 static void
152 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
153 const xmlChar *ExternalID, const xmlChar *SystemID)
155 callbacks++;
156 if (quiet)
157 return;
158 fprintf(stdout, "SAX.internalSubset(%s,", name);
159 if (ExternalID == NULL)
160 fprintf(stdout, " ,");
161 else
162 fprintf(stdout, " %s,", ExternalID);
163 if (SystemID == NULL)
164 fprintf(stdout, " )\n");
165 else
166 fprintf(stdout, " %s)\n", SystemID);
170 * externalSubsetDebug:
171 * @ctxt: An XML parser context
173 * Does this document has an external subset
175 static void
176 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
177 const xmlChar *ExternalID, const xmlChar *SystemID)
179 callbacks++;
180 if (quiet)
181 return;
182 fprintf(stdout, "SAX.externalSubset(%s,", name);
183 if (ExternalID == NULL)
184 fprintf(stdout, " ,");
185 else
186 fprintf(stdout, " %s,", ExternalID);
187 if (SystemID == NULL)
188 fprintf(stdout, " )\n");
189 else
190 fprintf(stdout, " %s)\n", SystemID);
194 * resolveEntityDebug:
195 * @ctxt: An XML parser context
196 * @publicId: The public ID of the entity
197 * @systemId: The system ID of the entity
199 * Special entity resolver, better left to the parser, it has
200 * more context than the application layer.
201 * The default behaviour is to NOT resolve the entities, in that case
202 * the ENTITY_REF nodes are built in the structure (and the parameter
203 * values).
205 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
207 static xmlParserInputPtr
208 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
210 callbacks++;
211 if (quiet)
212 return(NULL);
213 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
216 fprintf(stdout, "SAX.resolveEntity(");
217 if (publicId != NULL)
218 fprintf(stdout, "%s", (char *)publicId);
219 else
220 fprintf(stdout, " ");
221 if (systemId != NULL)
222 fprintf(stdout, ", %s)\n", (char *)systemId);
223 else
224 fprintf(stdout, ", )\n");
225 /*********
226 if (systemId != NULL) {
227 return(xmlNewInputFromFile(ctxt, (char *) systemId));
229 *********/
230 return(NULL);
234 * getEntityDebug:
235 * @ctxt: An XML parser context
236 * @name: The entity name
238 * Get an entity by name
240 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
242 static xmlEntityPtr
243 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
245 callbacks++;
246 if (quiet)
247 return(NULL);
248 fprintf(stdout, "SAX.getEntity(%s)\n", name);
249 return(NULL);
253 * getParameterEntityDebug:
254 * @ctxt: An XML parser context
255 * @name: The entity name
257 * Get a parameter entity by name
259 * Returns the xmlParserInputPtr
261 static xmlEntityPtr
262 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
264 callbacks++;
265 if (quiet)
266 return(NULL);
267 fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
268 return(NULL);
273 * entityDeclDebug:
274 * @ctxt: An XML parser context
275 * @name: the entity name
276 * @type: the entity type
277 * @publicId: The public ID of the entity
278 * @systemId: The system ID of the entity
279 * @content: the entity value (without processing).
281 * An entity definition has been parsed
283 static void
284 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
285 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
287 callbacks++;
288 if (quiet)
289 return;
290 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
291 name, type, publicId, systemId, content);
295 * attributeDeclDebug:
296 * @ctxt: An XML parser context
297 * @name: the attribute name
298 * @type: the attribute type
300 * An attribute definition has been parsed
302 static void
303 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *elem, const xmlChar *name,
304 int type, int def, const xmlChar *defaultValue,
305 xmlEnumerationPtr tree ATTRIBUTE_UNUSED)
307 callbacks++;
308 if (quiet)
309 return;
310 if (defaultValue == NULL)
311 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
312 elem, name, type, def);
313 else
314 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
315 elem, name, type, def, defaultValue);
319 * elementDeclDebug:
320 * @ctxt: An XML parser context
321 * @name: the element name
322 * @type: the element type
323 * @content: the element value (without processing).
325 * An element definition has been parsed
327 static void
328 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
329 xmlElementContentPtr content ATTRIBUTE_UNUSED)
331 callbacks++;
332 if (quiet)
333 return;
334 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
335 name, type);
339 * notationDeclDebug:
340 * @ctxt: An XML parser context
341 * @name: The name of the notation
342 * @publicId: The public ID of the entity
343 * @systemId: The system ID of the entity
345 * What to do when a notation declaration has been parsed.
347 static void
348 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
349 const xmlChar *publicId, const xmlChar *systemId)
351 callbacks++;
352 if (quiet)
353 return;
354 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
355 (char *) name, (char *) publicId, (char *) systemId);
359 * unparsedEntityDeclDebug:
360 * @ctxt: An XML parser context
361 * @name: The name of the entity
362 * @publicId: The public ID of the entity
363 * @systemId: The system ID of the entity
364 * @notationName: the name of the notation
366 * What to do when an unparsed entity declaration is parsed
368 static void
369 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
370 const xmlChar *publicId, const xmlChar *systemId,
371 const xmlChar *notationName)
373 callbacks++;
374 if (quiet)
375 return;
376 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
377 (char *) name, (char *) publicId, (char *) systemId,
378 (char *) notationName);
382 * setDocumentLocatorDebug:
383 * @ctxt: An XML parser context
384 * @loc: A SAX Locator
386 * Receive the document locator at startup, actually xmlDefaultSAXLocator
387 * Everything is available on the context, so this is useless in our case.
389 static void
390 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
392 callbacks++;
393 if (quiet)
394 return;
395 fprintf(stdout, "SAX.setDocumentLocator()\n");
399 * startDocumentDebug:
400 * @ctxt: An XML parser context
402 * called when the document start being processed.
404 static void
405 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
407 callbacks++;
408 if (quiet)
409 return;
410 fprintf(stdout, "SAX.startDocument()\n");
414 * endDocumentDebug:
415 * @ctxt: An XML parser context
417 * called when the document end has been detected.
419 static void
420 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
422 callbacks++;
423 if (quiet)
424 return;
425 fprintf(stdout, "SAX.endDocument()\n");
429 * startElementDebug:
430 * @ctxt: An XML parser context
431 * @name: The element name
433 * called when an opening tag has been processed.
435 static void
436 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
438 int i;
440 callbacks++;
441 if (quiet)
442 return;
443 fprintf(stdout, "SAX.startElement(%s", (char *) name);
444 if (atts != NULL) {
445 for (i = 0;(atts[i] != NULL);i++) {
446 fprintf(stdout, ", %s='", atts[i++]);
447 if (atts[i] != NULL)
448 fprintf(stdout, "%s'", atts[i]);
451 fprintf(stdout, ")\n");
455 * endElementDebug:
456 * @ctxt: An XML parser context
457 * @name: The element name
459 * called when the end of an element has been detected.
461 static void
462 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
464 callbacks++;
465 if (quiet)
466 return;
467 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
471 * charactersDebug:
472 * @ctxt: An XML parser context
473 * @ch: a xmlChar string
474 * @len: the number of xmlChar
476 * receiving some chars from the parser.
477 * Question: how much at a time ???
479 static void
480 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
482 char output[40];
483 int i;
485 callbacks++;
486 if (quiet)
487 return;
488 for (i = 0;(i<len) && (i < 30);i++)
489 output[i] = ch[i];
490 output[i] = 0;
492 fprintf(stdout, "SAX.characters(%s, %d)\n", output, len);
496 * referenceDebug:
497 * @ctxt: An XML parser context
498 * @name: The entity name
500 * called when an entity reference is detected.
502 static void
503 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
505 callbacks++;
506 if (quiet)
507 return;
508 fprintf(stdout, "SAX.reference(%s)\n", name);
512 * ignorableWhitespaceDebug:
513 * @ctxt: An XML parser context
514 * @ch: a xmlChar string
515 * @start: the first char in the string
516 * @len: the number of xmlChar
518 * receiving some ignorable whitespaces from the parser.
519 * Question: how much at a time ???
521 static void
522 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
524 char output[40];
525 int i;
527 callbacks++;
528 if (quiet)
529 return;
530 for (i = 0;(i<len) && (i < 30);i++)
531 output[i] = ch[i];
532 output[i] = 0;
533 fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
537 * processingInstructionDebug:
538 * @ctxt: An XML parser context
539 * @target: the target name
540 * @data: the PI data's
541 * @len: the number of xmlChar
543 * A processing instruction has been parsed.
545 static void
546 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
547 const xmlChar *data)
549 callbacks++;
550 if (quiet)
551 return;
552 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
553 (char *) target, (char *) data);
557 * cdataBlockDebug:
558 * @ctx: the user data (XML parser context)
559 * @value: The pcdata content
560 * @len: the block length
562 * called when a pcdata block has been parsed
564 static void
565 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
567 callbacks++;
568 if (quiet)
569 return;
570 fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
571 (char *) value, len);
575 * commentDebug:
576 * @ctxt: An XML parser context
577 * @value: the comment content
579 * A comment has been parsed.
581 static void
582 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
584 callbacks++;
585 if (quiet)
586 return;
587 fprintf(stdout, "SAX.comment(%s)\n", value);
591 * warningDebug:
592 * @ctxt: An XML parser context
593 * @msg: the message to display/transmit
594 * @...: extra parameters for the message display
596 * Display and format a warning messages, gives file, line, position and
597 * extra parameters.
599 static void
600 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
602 va_list args;
604 callbacks++;
605 if (quiet)
606 return;
607 va_start(args, msg);
608 fprintf(stdout, "SAX.warning: ");
609 vfprintf(stdout, msg, args);
610 va_end(args);
614 * errorDebug:
615 * @ctxt: An XML parser context
616 * @msg: the message to display/transmit
617 * @...: extra parameters for the message display
619 * Display and format a error messages, gives file, line, position and
620 * extra parameters.
622 static void
623 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
625 va_list args;
627 callbacks++;
628 if (quiet)
629 return;
630 va_start(args, msg);
631 fprintf(stdout, "SAX.error: ");
632 vfprintf(stdout, msg, args);
633 va_end(args);
637 * fatalErrorDebug:
638 * @ctxt: An XML parser context
639 * @msg: the message to display/transmit
640 * @...: extra parameters for the message display
642 * Display and format a fatalError messages, gives file, line, position and
643 * extra parameters.
645 static void
646 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
648 va_list args;
650 callbacks++;
651 if (quiet)
652 return;
653 va_start(args, msg);
654 fprintf(stdout, "SAX.fatalError: ");
655 vfprintf(stdout, msg, args);
656 va_end(args);
659 xmlSAXHandler debugSAXHandlerStruct = {
660 internalSubsetDebug,
661 isStandaloneDebug,
662 hasInternalSubsetDebug,
663 hasExternalSubsetDebug,
664 resolveEntityDebug,
665 getEntityDebug,
666 entityDeclDebug,
667 notationDeclDebug,
668 attributeDeclDebug,
669 elementDeclDebug,
670 unparsedEntityDeclDebug,
671 setDocumentLocatorDebug,
672 startDocumentDebug,
673 endDocumentDebug,
674 startElementDebug,
675 endElementDebug,
676 referenceDebug,
677 charactersDebug,
678 ignorableWhitespaceDebug,
679 processingInstructionDebug,
680 commentDebug,
681 warningDebug,
682 errorDebug,
683 fatalErrorDebug,
684 getParameterEntityDebug,
685 cdataBlockDebug,
686 externalSubsetDebug,
690 xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
692 /************************************************************************
694 * Debug *
696 ************************************************************************/
698 static void
699 parseAndPrintFile(char *filename) {
700 int res;
702 if (push) {
703 FILE *f;
706 * Empty callbacks for checking
708 f = fopen(filename, "r");
709 if (f != NULL) {
710 int ret;
711 char chars[10];
712 xmlParserCtxtPtr ctxt;
714 ret = fread(chars, 1, 4, f);
715 if (ret > 0) {
716 ctxt = xmlCreatePushParserCtxt(emptySAXHandler, NULL,
717 chars, ret, filename);
718 while ((ret = fread(chars, 1, 3, f)) > 0) {
719 xmlParseChunk(ctxt, chars, ret, 0);
721 xmlParseChunk(ctxt, chars, 0, 1);
722 xmlFreeParserCtxt(ctxt);
724 fclose(f);
725 } else {
726 xmlGenericError(xmlGenericErrorContext,
727 "Cannot read file %s\n", filename);
730 * Debug callback
732 f = fopen(filename, "r");
733 if (f != NULL) {
734 int ret;
735 char chars[10];
736 xmlParserCtxtPtr ctxt;
738 ret = fread(chars, 1, 4, f);
739 if (ret > 0) {
740 ctxt = xmlCreatePushParserCtxt(debugSAXHandler, NULL,
741 chars, ret, filename);
742 while ((ret = fread(chars, 1, 3, f)) > 0) {
743 xmlParseChunk(ctxt, chars, ret, 0);
745 ret = xmlParseChunk(ctxt, chars, 0, 1);
746 xmlFreeParserCtxt(ctxt);
747 if (ret != 0) {
748 fprintf(stdout,
749 "xmlSAXUserParseFile returned error %d\n", ret);
752 fclose(f);
754 } else {
755 if (!speed) {
757 * Empty callbacks for checking
759 if (!quiet) {
760 res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
761 if (res != 0) {
762 fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
767 * Debug callback
769 callbacks = 0;
770 res = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
771 if (res != 0) {
772 fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
774 if (quiet)
775 fprintf(stdout, "%d callbacks generated\n", callbacks);
776 } else {
778 * test 100x the SAX parse
780 int i;
782 for (i = 0; i<100;i++)
783 res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
784 if (res != 0) {
785 fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
792 int main(int argc, char **argv) {
793 int i;
794 int files = 0;
796 for (i = 1; i < argc ; i++) {
797 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
798 debug++;
799 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
800 copy++;
801 else if ((!strcmp(argv[i], "-recover")) ||
802 (!strcmp(argv[i], "--recover")))
803 recovery++;
804 else if ((!strcmp(argv[i], "-push")) ||
805 (!strcmp(argv[i], "--push")))
806 push++;
807 else if ((!strcmp(argv[i], "-speed")) ||
808 (!strcmp(argv[i], "--speed")))
809 speed++;
810 else if ((!strcmp(argv[i], "-noent")) ||
811 (!strcmp(argv[i], "--noent")))
812 noent++;
813 else if ((!strcmp(argv[i], "-quiet")) ||
814 (!strcmp(argv[i], "--quiet")))
815 quiet++;
817 if (noent != 0) xmlSubstituteEntitiesDefault(1);
818 for (i = 1; i < argc ; i++) {
819 if (argv[i][0] != '-') {
820 parseAndPrintFile(argv[i]);
821 files ++;
824 xmlCleanupParser();
825 xmlMemoryDump();
827 return(0);