blob: c64bc3cd114397c247e4b775ca15d0d27040fca4 [file] [log] [blame]
Daniel Veillard5099ae81999-04-21 20:12:07 +00001/*
2 * tester.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@w3.org
7 */
8
9#ifdef WIN32
10#define HAVE_FCNTL_H
11#include <io.h>
12#else
13#include <config.h>
14#endif
15#include <sys/types.h>
16#ifdef HAVE_SYS_STAT_H
17#include <sys/stat.h>
18#endif
19#ifdef HAVE_FCNTL_H
20#include <fcntl.h>
21#endif
22#ifdef HAVE_UNISTD_H
23#include <unistd.h>
24#endif
25#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
28#include <stdarg.h>
29
30#include "parser.h"
Daniel Veillard011b63c1999-06-02 17:44:04 +000031#include "parserInternals.h" /* only for xmlNewInputFromFile() */
Daniel Veillard5099ae81999-04-21 20:12:07 +000032#include "tree.h"
33#include "debugXML.h"
34
35static int debug = 0;
36static int copy = 0;
37static int recovery = 0;
38
39xmlSAXHandler emptySAXHandlerStruct = {
40 NULL, /* internalSubset */
41 NULL, /* isStandalone */
42 NULL, /* hasInternalSubset */
43 NULL, /* hasExternalSubset */
44 NULL, /* resolveEntity */
45 NULL, /* getEntity */
46 NULL, /* entityDecl */
47 NULL, /* notationDecl */
48 NULL, /* attributeDecl */
49 NULL, /* elementDecl */
50 NULL, /* unparsedEntityDecl */
51 NULL, /* setDocumentLocator */
52 NULL, /* startDocument */
53 NULL, /* endDocument */
54 NULL, /* startElement */
55 NULL, /* endElement */
56 NULL, /* reference */
57 NULL, /* characters */
58 NULL, /* ignorableWhitespace */
59 NULL, /* processingInstruction */
60 NULL, /* comment */
61 NULL, /* xmlParserWarning */
62 NULL, /* xmlParserError */
63 NULL, /* xmlParserError */
64};
65
66xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
Daniel Veillard011b63c1999-06-02 17:44:04 +000067extern xmlSAXHandlerPtr debugSAXHandler;
Daniel Veillard5099ae81999-04-21 20:12:07 +000068
69/*
70 * Note: there is a couple of errors introduced on purpose.
71 */
72static CHAR buffer[] =
73"<?xml version=\"1.0\"?>\n\
74<?xml:namespace ns = \"http://www.ietf.org/standards/dav/\" prefix = \"D\"?>\n\
75<?xml:namespace ns = \"http://www.w3.com/standards/z39.50/\" prefix = \"Z\"?>\n\
76<D:propertyupdate>\n\
77<D:set a=\"'toto'\" b>\n\
78 <D:prop>\n\
79 <Z:authors>\n\
80 <Z:Author>Jim Whitehead</Z:Author>\n\
81 <Z:Author>Roy Fielding</Z:Author>\n\
82 </Z:authors>\n\
83 </D:prop>\n\
84 </D:set>\n\
85 <D:remove>\n\
86 <D:prop><Z:Copyright-Owner/></D:prop>\n\
87 </D:remove>\n\
88</D:propertyupdate>\n\
89\n\
90";
91
92/************************************************************************
93 * *
94 * Debug Handlers *
95 * *
96 ************************************************************************/
97
98/**
99 * isStandaloneDebug:
100 * @ctxt: An XML parser context
101 *
102 * Is this document tagged standalone ?
103 *
104 * Returns 1 if true
105 */
106int
107isStandaloneDebug(xmlParserCtxtPtr ctxt)
108{
Daniel Veillard27d88741999-05-29 11:51:49 +0000109 fprintf(stdout, "SAX.isStandalone()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000110 return(0);
111}
112
113/**
114 * hasInternalSubsetDebug:
115 * @ctxt: An XML parser context
116 *
117 * Does this document has an internal subset
118 *
119 * Returns 1 if true
120 */
121int
122hasInternalSubsetDebug(xmlParserCtxtPtr ctxt)
123{
Daniel Veillard27d88741999-05-29 11:51:49 +0000124 fprintf(stdout, "SAX.hasInternalSubset()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000125 return(0);
126}
127
128/**
129 * hasExternalSubsetDebug:
130 * @ctxt: An XML parser context
131 *
132 * Does this document has an external subset
133 *
134 * Returns 1 if true
135 */
136int
137hasExternalSubsetDebug(xmlParserCtxtPtr ctxt)
138{
Daniel Veillard27d88741999-05-29 11:51:49 +0000139 fprintf(stdout, "SAX.hasExternalSubset()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000140 return(0);
141}
142
143/**
144 * hasInternalSubsetDebug:
145 * @ctxt: An XML parser context
146 *
147 * Does this document has an internal subset
148 */
149void
150internalSubsetDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
151 const CHAR *ExternalID, const CHAR *SystemID)
152{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000153 xmlDtdPtr externalSubset;
154
Daniel Veillard27d88741999-05-29 11:51:49 +0000155 fprintf(stdout, "SAX.internalSubset(%s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000156 name, ExternalID, SystemID);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000157
158 if ((ExternalID != NULL) || (SystemID != NULL)) {
159 externalSubset = xmlSAXParseDTD(debugSAXHandler, ExternalID, SystemID);
160 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000161}
162
163/**
164 * resolveEntityDebug:
165 * @ctxt: An XML parser context
166 * @publicId: The public ID of the entity
167 * @systemId: The system ID of the entity
168 *
169 * Special entity resolver, better left to the parser, it has
170 * more context than the application layer.
171 * The default behaviour is to NOT resolve the entities, in that case
172 * the ENTITY_REF nodes are built in the structure (and the parameter
173 * values).
174 *
175 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
176 */
177xmlParserInputPtr
178resolveEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId)
179{
Daniel Veillard14fff061999-06-22 21:49:07 +0000180
181 fprintf(stdout, "SAX.resolveEntity(");
182 if (publicId != NULL)
183 fprintf(stdout, "%s", (char *)publicId);
184 else
185 fprintf(stdout, " ");
186 if (systemId != NULL)
187 fprintf(stdout, ", %s)\n", (char *)systemId);
188 else
189 fprintf(stdout, ", )\n");
Daniel Veillard011b63c1999-06-02 17:44:04 +0000190 if (systemId != NULL) {
191 return(xmlNewInputFromFile(ctxt, systemId));
192 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000193 return(NULL);
194}
195
196/**
197 * getEntityDebug:
198 * @ctxt: An XML parser context
199 * @name: The entity name
200 *
201 * Get an entity by name
202 *
203 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
204 */
205xmlEntityPtr
206getEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
207{
Daniel Veillard27d88741999-05-29 11:51:49 +0000208 fprintf(stdout, "SAX.getEntity(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000209 return(NULL);
210}
211
212
213/**
214 * entityDeclDebug:
215 * @ctxt: An XML parser context
216 * @name: the entity name
217 * @type: the entity type
218 * @publicId: The public ID of the entity
219 * @systemId: The system ID of the entity
220 * @content: the entity value (without processing).
221 *
222 * An entity definition has been parsed
223 */
224void
225entityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
226 const CHAR *publicId, const CHAR *systemId, CHAR *content)
227{
Daniel Veillard27d88741999-05-29 11:51:49 +0000228 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000229 name, type, publicId, systemId, content);
230}
231
232/**
233 * attributeDeclDebug:
234 * @ctxt: An XML parser context
235 * @name: the attribute name
236 * @type: the attribute type
237 *
238 * An attribute definition has been parsed
239 */
240void
241attributeDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *elem, const CHAR *name,
242 int type, int def, const CHAR *defaultValue,
243 xmlEnumerationPtr tree)
244{
Daniel Veillard27d88741999-05-29 11:51:49 +0000245 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000246 elem, name, type, def, defaultValue);
247}
248
249/**
250 * elementDeclDebug:
251 * @ctxt: An XML parser context
252 * @name: the element name
253 * @type: the element type
254 * @content: the element value (without processing).
255 *
256 * An element definition has been parsed
257 */
258void
259elementDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
260 xmlElementContentPtr content)
261{
Daniel Veillard27d88741999-05-29 11:51:49 +0000262 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000263 name, type);
264}
265
266/**
267 * notationDeclDebug:
268 * @ctxt: An XML parser context
269 * @name: The name of the notation
270 * @publicId: The public ID of the entity
271 * @systemId: The system ID of the entity
272 *
273 * What to do when a notation declaration has been parsed.
274 * TODO Not handled currently.
275 */
276void
277notationDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
278 const CHAR *publicId, const CHAR *systemId)
279{
Daniel Veillard27d88741999-05-29 11:51:49 +0000280 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000281 (char *) name, (char *) publicId, (char *) systemId);
282}
283
284/**
285 * unparsedEntityDeclDebug:
286 * @ctxt: An XML parser context
287 * @name: The name of the entity
288 * @publicId: The public ID of the entity
289 * @systemId: The system ID of the entity
290 * @notationName: the name of the notation
291 *
292 * What to do when an unparsed entity declaration is parsed
293 * TODO Create an Entity node.
294 */
295void
296unparsedEntityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
297 const CHAR *publicId, const CHAR *systemId,
298 const CHAR *notationName)
299{
Daniel Veillard27d88741999-05-29 11:51:49 +0000300 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000301 (char *) name, (char *) publicId, (char *) systemId,
302 (char *) notationName);
303}
304
305/**
306 * setDocumentLocatorDebug:
307 * @ctxt: An XML parser context
308 * @loc: A SAX Locator
309 *
310 * Receive the document locator at startup, actually xmlDefaultSAXLocator
311 * Everything is available on the context, so this is useless in our case.
312 */
313void
314setDocumentLocatorDebug(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc)
315{
Daniel Veillard27d88741999-05-29 11:51:49 +0000316 fprintf(stdout, "SAX.setDocumentLocator()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000317}
318
319/**
320 * startDocumentDebug:
321 * @ctxt: An XML parser context
322 *
323 * called when the document start being processed.
324 */
325void
326startDocumentDebug(xmlParserCtxtPtr ctxt)
327{
Daniel Veillard27d88741999-05-29 11:51:49 +0000328 fprintf(stdout, "SAX.startDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000329}
330
331/**
332 * endDocumentDebug:
333 * @ctxt: An XML parser context
334 *
335 * called when the document end has been detected.
336 */
337void
338endDocumentDebug(xmlParserCtxtPtr ctxt)
339{
Daniel Veillard27d88741999-05-29 11:51:49 +0000340 fprintf(stdout, "SAX.endDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000341}
342
343/**
344 * startElementDebug:
345 * @ctxt: An XML parser context
346 * @name: The element name
347 *
348 * called when an opening tag has been processed.
349 * TODO We currently have a small pblm with the arguments ...
350 */
351void
352startElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR **atts)
353{
354 int i;
355
Daniel Veillard27d88741999-05-29 11:51:49 +0000356 fprintf(stdout, "SAX.startElement(%s", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000357 if (atts != NULL) {
358 for (i = 0;(atts[i] != NULL);i++) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000359 fprintf(stdout, ", %s='", atts[i++]);
360 fprintf(stdout, "%s'", atts[i]);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000361 }
362 }
Daniel Veillard27d88741999-05-29 11:51:49 +0000363 fprintf(stdout, ")\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000364}
365
366/**
367 * endElementDebug:
368 * @ctxt: An XML parser context
369 * @name: The element name
370 *
371 * called when the end of an element has been detected.
372 */
373void
374endElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
375{
Daniel Veillard27d88741999-05-29 11:51:49 +0000376 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000377}
378
379/**
380 * charactersDebug:
381 * @ctxt: An XML parser context
382 * @ch: a CHAR string
383 * @len: the number of CHAR
384 *
385 * receiving some chars from the parser.
386 * Question: how much at a time ???
387 */
388void
389charactersDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
390{
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000391 int i;
392
393 fprintf(stdout, "SAX.characters(");
394 for (i = 0;(i < len) && (i < 30);i++)
395 fprintf(stdout, "%c", ch[i]);
396 fprintf(stdout, ", %d)\n", len);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000397}
398
399/**
400 * referenceDebug:
401 * @ctxt: An XML parser context
402 * @name: The entity name
403 *
404 * called when an entity reference is detected.
405 */
406void
407referenceDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
408{
Daniel Veillard27d88741999-05-29 11:51:49 +0000409 fprintf(stdout, "SAX.reference(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000410}
411
412/**
413 * ignorableWhitespaceDebug:
414 * @ctxt: An XML parser context
415 * @ch: a CHAR string
416 * @start: the first char in the string
417 * @len: the number of CHAR
418 *
419 * receiving some ignorable whitespaces from the parser.
420 * Question: how much at a time ???
421 */
422void
423ignorableWhitespaceDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
424{
Daniel Veillard27d88741999-05-29 11:51:49 +0000425 fprintf(stdout, "SAX.ignorableWhitespace(%.30s, %d)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000426 (char *) ch, len);
427}
428
429/**
430 * processingInstructionDebug:
431 * @ctxt: An XML parser context
432 * @target: the target name
433 * @data: the PI data's
434 * @len: the number of CHAR
435 *
436 * A processing instruction has been parsed.
437 */
438void
439processingInstructionDebug(xmlParserCtxtPtr ctxt, const CHAR *target,
440 const CHAR *data)
441{
Daniel Veillard27d88741999-05-29 11:51:49 +0000442 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000443 (char *) target, (char *) data);
444}
445
446/**
447 * commentDebug:
448 * @ctxt: An XML parser context
449 * @value: the comment content
450 *
451 * A comment has been parsed.
452 */
453void
454commentDebug(xmlParserCtxtPtr ctxt, const CHAR *value)
455{
Daniel Veillard27d88741999-05-29 11:51:49 +0000456 fprintf(stdout, "SAX.comment(%s)\n", value);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000457}
458
459/**
460 * warningDebug:
461 * @ctxt: An XML parser context
462 * @msg: the message to display/transmit
463 * @...: extra parameters for the message display
464 *
465 * Display and format a warning messages, gives file, line, position and
466 * extra parameters.
467 */
468void
469warningDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
470{
471 va_list args;
472
473 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000474 fprintf(stdout, "SAX.warning: ");
475 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000476 va_end(args);
477}
478
479/**
480 * errorDebug:
481 * @ctxt: An XML parser context
482 * @msg: the message to display/transmit
483 * @...: extra parameters for the message display
484 *
485 * Display and format a error messages, gives file, line, position and
486 * extra parameters.
487 */
488void
489errorDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
490{
491 va_list args;
492
493 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000494 fprintf(stdout, "SAX.error: ");
495 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000496 va_end(args);
497}
498
499/**
500 * fatalErrorDebug:
501 * @ctxt: An XML parser context
502 * @msg: the message to display/transmit
503 * @...: extra parameters for the message display
504 *
505 * Display and format a fatalError messages, gives file, line, position and
506 * extra parameters.
507 */
508void
509fatalErrorDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
510{
511 va_list args;
512
513 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000514 fprintf(stdout, "SAX.fatalError: ");
515 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000516 va_end(args);
517}
518
519xmlSAXHandler debugSAXHandlerStruct = {
520 internalSubsetDebug,
521 isStandaloneDebug,
522 hasInternalSubsetDebug,
523 hasExternalSubsetDebug,
524 resolveEntityDebug,
525 getEntityDebug,
526 entityDeclDebug,
527 notationDeclDebug,
528 attributeDeclDebug,
529 elementDeclDebug,
530 unparsedEntityDeclDebug,
531 setDocumentLocatorDebug,
532 startDocumentDebug,
533 endDocumentDebug,
534 startElementDebug,
535 endElementDebug,
536 referenceDebug,
537 charactersDebug,
538 ignorableWhitespaceDebug,
539 processingInstructionDebug,
540 commentDebug,
541 warningDebug,
542 errorDebug,
543 fatalErrorDebug,
544};
545
546xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
547
548/************************************************************************
549 * *
550 * Debug *
551 * *
552 ************************************************************************/
553
554void parseAndPrintFile(char *filename) {
555 xmlDocPtr doc;
556
557 /*
558 * Empty callbacks for checking
559 */
560 doc = xmlSAXParseFile(emptySAXHandler, filename, 0);
561 if (doc != NULL) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000562 fprintf(stdout, "xmlSAXParseFile returned non-NULL\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000563 xmlDocDump(stdout, doc);
564 }
565
566 /*
567 * Debug callback
568 */
569 doc = xmlSAXParseFile(debugSAXHandler, filename, 0);
570 if (doc != NULL) {
571 fprintf(stderr, "xmlSAXParseFile returned non-NULL\n");
572 xmlDocDump(stdout, doc);
573 }
574}
575
576void parseAndPrintBuffer(CHAR *buf) {
577 xmlDocPtr doc;
578
579 /*
580 * Empty callbacks for checking
581 */
582 doc = xmlSAXParseDoc(emptySAXHandler, buf, 0);
583 if (doc != NULL) {
584 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
585 xmlDocDump(stdout, doc);
586 }
587
588 /*
589 * Debug callback
590 */
591 doc = xmlSAXParseDoc(debugSAXHandler, buf, 0);
592 if (doc != NULL) {
593 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
594 xmlDocDump(stdout, doc);
595 }
596}
597
598int main(int argc, char **argv) {
599 int i;
600 int files = 0;
601
602 for (i = 1; i < argc ; i++) {
603 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
604 debug++;
605 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
606 copy++;
607 else if ((!strcmp(argv[i], "-recover")) ||
608 (!strcmp(argv[i], "--recover")))
609 recovery++;
610 }
611 for (i = 1; i < argc ; i++) {
612 if (argv[i][0] != '-') {
613 parseAndPrintFile(argv[i]);
614 files ++;
615 }
616 }
617 if (files == 0) {
618 printf("\nFirst test for the parser, with errors\n");
619 parseAndPrintBuffer(buffer);
620 }
621
622 return(0);
623}