blob: 2b2e89bc2ac4a9583c42a464a599b5b4aaa5d4b4 [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 */
Daniel Veillardb05deb71999-08-10 19:04:08 +000064 NULL, /* getParameterEntity */
Daniel Veillard5099ae81999-04-21 20:12:07 +000065};
66
67xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
Daniel Veillard011b63c1999-06-02 17:44:04 +000068extern xmlSAXHandlerPtr debugSAXHandler;
Daniel Veillard5099ae81999-04-21 20:12:07 +000069
70/*
71 * Note: there is a couple of errors introduced on purpose.
72 */
73static CHAR buffer[] =
74"<?xml version=\"1.0\"?>\n\
75<?xml:namespace ns = \"http://www.ietf.org/standards/dav/\" prefix = \"D\"?>\n\
76<?xml:namespace ns = \"http://www.w3.com/standards/z39.50/\" prefix = \"Z\"?>\n\
77<D:propertyupdate>\n\
78<D:set a=\"'toto'\" b>\n\
79 <D:prop>\n\
80 <Z:authors>\n\
81 <Z:Author>Jim Whitehead</Z:Author>\n\
82 <Z:Author>Roy Fielding</Z:Author>\n\
83 </Z:authors>\n\
84 </D:prop>\n\
85 </D:set>\n\
86 <D:remove>\n\
87 <D:prop><Z:Copyright-Owner/></D:prop>\n\
88 </D:remove>\n\
89</D:propertyupdate>\n\
90\n\
91";
92
93/************************************************************************
94 * *
95 * Debug Handlers *
96 * *
97 ************************************************************************/
98
99/**
100 * isStandaloneDebug:
101 * @ctxt: An XML parser context
102 *
103 * Is this document tagged standalone ?
104 *
105 * Returns 1 if true
106 */
107int
108isStandaloneDebug(xmlParserCtxtPtr ctxt)
109{
Daniel Veillard27d88741999-05-29 11:51:49 +0000110 fprintf(stdout, "SAX.isStandalone()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000111 return(0);
112}
113
114/**
115 * hasInternalSubsetDebug:
116 * @ctxt: An XML parser context
117 *
118 * Does this document has an internal subset
119 *
120 * Returns 1 if true
121 */
122int
123hasInternalSubsetDebug(xmlParserCtxtPtr ctxt)
124{
Daniel Veillard27d88741999-05-29 11:51:49 +0000125 fprintf(stdout, "SAX.hasInternalSubset()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000126 return(0);
127}
128
129/**
130 * hasExternalSubsetDebug:
131 * @ctxt: An XML parser context
132 *
133 * Does this document has an external subset
134 *
135 * Returns 1 if true
136 */
137int
138hasExternalSubsetDebug(xmlParserCtxtPtr ctxt)
139{
Daniel Veillard27d88741999-05-29 11:51:49 +0000140 fprintf(stdout, "SAX.hasExternalSubset()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000141 return(0);
142}
143
144/**
145 * hasInternalSubsetDebug:
146 * @ctxt: An XML parser context
147 *
148 * Does this document has an internal subset
149 */
150void
151internalSubsetDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
152 const CHAR *ExternalID, const CHAR *SystemID)
153{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000154 xmlDtdPtr externalSubset;
155
Daniel Veillard27d88741999-05-29 11:51:49 +0000156 fprintf(stdout, "SAX.internalSubset(%s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000157 name, ExternalID, SystemID);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000158
159 if ((ExternalID != NULL) || (SystemID != NULL)) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000160 externalSubset = xmlParseDTD(ExternalID, SystemID);
161 if (externalSubset != NULL) {
162 xmlFreeDtd(externalSubset);
163 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000164 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000165}
166
167/**
168 * resolveEntityDebug:
169 * @ctxt: An XML parser context
170 * @publicId: The public ID of the entity
171 * @systemId: The system ID of the entity
172 *
173 * Special entity resolver, better left to the parser, it has
174 * more context than the application layer.
175 * The default behaviour is to NOT resolve the entities, in that case
176 * the ENTITY_REF nodes are built in the structure (and the parameter
177 * values).
178 *
179 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
180 */
181xmlParserInputPtr
182resolveEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId)
183{
Daniel Veillard14fff061999-06-22 21:49:07 +0000184
185 fprintf(stdout, "SAX.resolveEntity(");
186 if (publicId != NULL)
187 fprintf(stdout, "%s", (char *)publicId);
188 else
189 fprintf(stdout, " ");
190 if (systemId != NULL)
191 fprintf(stdout, ", %s)\n", (char *)systemId);
192 else
193 fprintf(stdout, ", )\n");
Daniel Veillard011b63c1999-06-02 17:44:04 +0000194 if (systemId != NULL) {
195 return(xmlNewInputFromFile(ctxt, systemId));
196 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000197 return(NULL);
198}
199
200/**
201 * getEntityDebug:
202 * @ctxt: An XML parser context
203 * @name: The entity name
204 *
205 * Get an entity by name
206 *
207 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
208 */
209xmlEntityPtr
210getEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
211{
Daniel Veillard27d88741999-05-29 11:51:49 +0000212 fprintf(stdout, "SAX.getEntity(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000213 return(NULL);
214}
215
Daniel Veillardb05deb71999-08-10 19:04:08 +0000216/**
217 * getParameterEntityDebug:
218 * @ctxt: An XML parser context
219 * @name: The entity name
220 *
221 * Get a parameter entity by name
222 *
223 * Returns the xmlParserInputPtr
224 */
225xmlEntityPtr
226getParameterEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
227{
228 fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
229 return(NULL);
230}
231
Daniel Veillard5099ae81999-04-21 20:12:07 +0000232
233/**
234 * entityDeclDebug:
235 * @ctxt: An XML parser context
236 * @name: the entity name
237 * @type: the entity type
238 * @publicId: The public ID of the entity
239 * @systemId: The system ID of the entity
240 * @content: the entity value (without processing).
241 *
242 * An entity definition has been parsed
243 */
244void
245entityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
246 const CHAR *publicId, const CHAR *systemId, CHAR *content)
247{
Daniel Veillard27d88741999-05-29 11:51:49 +0000248 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000249 name, type, publicId, systemId, content);
250}
251
252/**
253 * attributeDeclDebug:
254 * @ctxt: An XML parser context
255 * @name: the attribute name
256 * @type: the attribute type
257 *
258 * An attribute definition has been parsed
259 */
260void
261attributeDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *elem, const CHAR *name,
262 int type, int def, const CHAR *defaultValue,
263 xmlEnumerationPtr tree)
264{
Daniel Veillard27d88741999-05-29 11:51:49 +0000265 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000266 elem, name, type, def, defaultValue);
267}
268
269/**
270 * elementDeclDebug:
271 * @ctxt: An XML parser context
272 * @name: the element name
273 * @type: the element type
274 * @content: the element value (without processing).
275 *
276 * An element definition has been parsed
277 */
278void
279elementDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
280 xmlElementContentPtr content)
281{
Daniel Veillard27d88741999-05-29 11:51:49 +0000282 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000283 name, type);
284}
285
286/**
287 * notationDeclDebug:
288 * @ctxt: An XML parser context
289 * @name: The name of the notation
290 * @publicId: The public ID of the entity
291 * @systemId: The system ID of the entity
292 *
293 * What to do when a notation declaration has been parsed.
294 * TODO Not handled currently.
295 */
296void
297notationDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
298 const CHAR *publicId, const CHAR *systemId)
299{
Daniel Veillard27d88741999-05-29 11:51:49 +0000300 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000301 (char *) name, (char *) publicId, (char *) systemId);
302}
303
304/**
305 * unparsedEntityDeclDebug:
306 * @ctxt: An XML parser context
307 * @name: The name of the entity
308 * @publicId: The public ID of the entity
309 * @systemId: The system ID of the entity
310 * @notationName: the name of the notation
311 *
312 * What to do when an unparsed entity declaration is parsed
313 * TODO Create an Entity node.
314 */
315void
316unparsedEntityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
317 const CHAR *publicId, const CHAR *systemId,
318 const CHAR *notationName)
319{
Daniel Veillard27d88741999-05-29 11:51:49 +0000320 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000321 (char *) name, (char *) publicId, (char *) systemId,
322 (char *) notationName);
323}
324
325/**
326 * setDocumentLocatorDebug:
327 * @ctxt: An XML parser context
328 * @loc: A SAX Locator
329 *
330 * Receive the document locator at startup, actually xmlDefaultSAXLocator
331 * Everything is available on the context, so this is useless in our case.
332 */
333void
334setDocumentLocatorDebug(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc)
335{
Daniel Veillard27d88741999-05-29 11:51:49 +0000336 fprintf(stdout, "SAX.setDocumentLocator()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000337}
338
339/**
340 * startDocumentDebug:
341 * @ctxt: An XML parser context
342 *
343 * called when the document start being processed.
344 */
345void
346startDocumentDebug(xmlParserCtxtPtr ctxt)
347{
Daniel Veillard27d88741999-05-29 11:51:49 +0000348 fprintf(stdout, "SAX.startDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000349}
350
351/**
352 * endDocumentDebug:
353 * @ctxt: An XML parser context
354 *
355 * called when the document end has been detected.
356 */
357void
358endDocumentDebug(xmlParserCtxtPtr ctxt)
359{
Daniel Veillard27d88741999-05-29 11:51:49 +0000360 fprintf(stdout, "SAX.endDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000361}
362
363/**
364 * startElementDebug:
365 * @ctxt: An XML parser context
366 * @name: The element name
367 *
368 * called when an opening tag has been processed.
369 * TODO We currently have a small pblm with the arguments ...
370 */
371void
372startElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR **atts)
373{
374 int i;
375
Daniel Veillard27d88741999-05-29 11:51:49 +0000376 fprintf(stdout, "SAX.startElement(%s", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000377 if (atts != NULL) {
378 for (i = 0;(atts[i] != NULL);i++) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000379 fprintf(stdout, ", %s='", atts[i++]);
380 fprintf(stdout, "%s'", atts[i]);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000381 }
382 }
Daniel Veillard27d88741999-05-29 11:51:49 +0000383 fprintf(stdout, ")\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000384}
385
386/**
387 * endElementDebug:
388 * @ctxt: An XML parser context
389 * @name: The element name
390 *
391 * called when the end of an element has been detected.
392 */
393void
394endElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
395{
Daniel Veillard27d88741999-05-29 11:51:49 +0000396 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000397}
398
399/**
400 * charactersDebug:
401 * @ctxt: An XML parser context
402 * @ch: a CHAR string
403 * @len: the number of CHAR
404 *
405 * receiving some chars from the parser.
406 * Question: how much at a time ???
407 */
408void
409charactersDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
410{
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000411 int i;
412
413 fprintf(stdout, "SAX.characters(");
414 for (i = 0;(i < len) && (i < 30);i++)
415 fprintf(stdout, "%c", ch[i]);
416 fprintf(stdout, ", %d)\n", len);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000417}
418
419/**
420 * referenceDebug:
421 * @ctxt: An XML parser context
422 * @name: The entity name
423 *
424 * called when an entity reference is detected.
425 */
426void
427referenceDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
428{
Daniel Veillard27d88741999-05-29 11:51:49 +0000429 fprintf(stdout, "SAX.reference(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000430}
431
432/**
433 * ignorableWhitespaceDebug:
434 * @ctxt: An XML parser context
435 * @ch: a CHAR string
436 * @start: the first char in the string
437 * @len: the number of CHAR
438 *
439 * receiving some ignorable whitespaces from the parser.
440 * Question: how much at a time ???
441 */
442void
443ignorableWhitespaceDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
444{
Daniel Veillard27d88741999-05-29 11:51:49 +0000445 fprintf(stdout, "SAX.ignorableWhitespace(%.30s, %d)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000446 (char *) ch, len);
447}
448
449/**
450 * processingInstructionDebug:
451 * @ctxt: An XML parser context
452 * @target: the target name
453 * @data: the PI data's
454 * @len: the number of CHAR
455 *
456 * A processing instruction has been parsed.
457 */
458void
459processingInstructionDebug(xmlParserCtxtPtr ctxt, const CHAR *target,
460 const CHAR *data)
461{
Daniel Veillard27d88741999-05-29 11:51:49 +0000462 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000463 (char *) target, (char *) data);
464}
465
466/**
467 * commentDebug:
468 * @ctxt: An XML parser context
469 * @value: the comment content
470 *
471 * A comment has been parsed.
472 */
473void
474commentDebug(xmlParserCtxtPtr ctxt, const CHAR *value)
475{
Daniel Veillard27d88741999-05-29 11:51:49 +0000476 fprintf(stdout, "SAX.comment(%s)\n", value);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000477}
478
479/**
480 * warningDebug:
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 warning messages, gives file, line, position and
486 * extra parameters.
487 */
488void
489warningDebug(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.warning: ");
495 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000496 va_end(args);
497}
498
499/**
500 * errorDebug:
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 error messages, gives file, line, position and
506 * extra parameters.
507 */
508void
509errorDebug(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.error: ");
515 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000516 va_end(args);
517}
518
519/**
520 * fatalErrorDebug:
521 * @ctxt: An XML parser context
522 * @msg: the message to display/transmit
523 * @...: extra parameters for the message display
524 *
525 * Display and format a fatalError messages, gives file, line, position and
526 * extra parameters.
527 */
528void
529fatalErrorDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
530{
531 va_list args;
532
533 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000534 fprintf(stdout, "SAX.fatalError: ");
535 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000536 va_end(args);
537}
538
539xmlSAXHandler debugSAXHandlerStruct = {
540 internalSubsetDebug,
541 isStandaloneDebug,
542 hasInternalSubsetDebug,
543 hasExternalSubsetDebug,
544 resolveEntityDebug,
545 getEntityDebug,
546 entityDeclDebug,
547 notationDeclDebug,
548 attributeDeclDebug,
549 elementDeclDebug,
550 unparsedEntityDeclDebug,
551 setDocumentLocatorDebug,
552 startDocumentDebug,
553 endDocumentDebug,
554 startElementDebug,
555 endElementDebug,
556 referenceDebug,
557 charactersDebug,
558 ignorableWhitespaceDebug,
559 processingInstructionDebug,
560 commentDebug,
561 warningDebug,
562 errorDebug,
563 fatalErrorDebug,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000564 getParameterEntityDebug,
Daniel Veillard5099ae81999-04-21 20:12:07 +0000565};
566
567xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
568
569/************************************************************************
570 * *
571 * Debug *
572 * *
573 ************************************************************************/
574
575void parseAndPrintFile(char *filename) {
576 xmlDocPtr doc;
577
578 /*
579 * Empty callbacks for checking
580 */
581 doc = xmlSAXParseFile(emptySAXHandler, filename, 0);
582 if (doc != NULL) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000583 fprintf(stdout, "xmlSAXParseFile returned non-NULL\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000584 xmlDocDump(stdout, doc);
585 }
586
587 /*
588 * Debug callback
589 */
590 doc = xmlSAXParseFile(debugSAXHandler, filename, 0);
591 if (doc != NULL) {
592 fprintf(stderr, "xmlSAXParseFile returned non-NULL\n");
593 xmlDocDump(stdout, doc);
594 }
595}
596
597void parseAndPrintBuffer(CHAR *buf) {
598 xmlDocPtr doc;
599
600 /*
601 * Empty callbacks for checking
602 */
603 doc = xmlSAXParseDoc(emptySAXHandler, buf, 0);
604 if (doc != NULL) {
605 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
606 xmlDocDump(stdout, doc);
607 }
608
609 /*
610 * Debug callback
611 */
612 doc = xmlSAXParseDoc(debugSAXHandler, buf, 0);
613 if (doc != NULL) {
614 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
615 xmlDocDump(stdout, doc);
616 }
617}
618
619int main(int argc, char **argv) {
620 int i;
621 int files = 0;
622
623 for (i = 1; i < argc ; i++) {
624 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
625 debug++;
626 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
627 copy++;
628 else if ((!strcmp(argv[i], "-recover")) ||
629 (!strcmp(argv[i], "--recover")))
630 recovery++;
631 }
632 for (i = 1; i < argc ; i++) {
633 if (argv[i][0] != '-') {
634 parseAndPrintFile(argv[i]);
635 files ++;
636 }
637 }
638 if (files == 0) {
639 printf("\nFirst test for the parser, with errors\n");
640 parseAndPrintBuffer(buffer);
641 }
642
643 return(0);
644}