source: trunk/third/libxml2/testSAX.c @ 21532

Revision 21532, 26.9 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21531, which included commits to RCS files with non-trunk default branches.
Line 
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
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
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
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 */
203xmlSAXHandler 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
238xmlSAXHandlerPtr 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
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
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
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
836xmlSAXHandler 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
960xmlSAXHandler 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
995xmlSAXHandlerPtr 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 */
Note: See TracBrowser for help on using the repository browser.