blob: 8d6469153bdac86eca6ed75adb5b7c19ca0d07e7 [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 Veillard27d88741999-05-29 11:51:49 +0000180 fprintf(stdout, "SAX.resolveEntity(%s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000181 (char *)publicId, (char *)systemId);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000182 if (systemId != NULL) {
183 return(xmlNewInputFromFile(ctxt, systemId));
184 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000185 return(NULL);
186}
187
188/**
189 * getEntityDebug:
190 * @ctxt: An XML parser context
191 * @name: The entity name
192 *
193 * Get an entity by name
194 *
195 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
196 */
197xmlEntityPtr
198getEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
199{
Daniel Veillard27d88741999-05-29 11:51:49 +0000200 fprintf(stdout, "SAX.getEntity(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000201 return(NULL);
202}
203
204
205/**
206 * entityDeclDebug:
207 * @ctxt: An XML parser context
208 * @name: the entity name
209 * @type: the entity type
210 * @publicId: The public ID of the entity
211 * @systemId: The system ID of the entity
212 * @content: the entity value (without processing).
213 *
214 * An entity definition has been parsed
215 */
216void
217entityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
218 const CHAR *publicId, const CHAR *systemId, CHAR *content)
219{
Daniel Veillard27d88741999-05-29 11:51:49 +0000220 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000221 name, type, publicId, systemId, content);
222}
223
224/**
225 * attributeDeclDebug:
226 * @ctxt: An XML parser context
227 * @name: the attribute name
228 * @type: the attribute type
229 *
230 * An attribute definition has been parsed
231 */
232void
233attributeDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *elem, const CHAR *name,
234 int type, int def, const CHAR *defaultValue,
235 xmlEnumerationPtr tree)
236{
Daniel Veillard27d88741999-05-29 11:51:49 +0000237 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000238 elem, name, type, def, defaultValue);
239}
240
241/**
242 * elementDeclDebug:
243 * @ctxt: An XML parser context
244 * @name: the element name
245 * @type: the element type
246 * @content: the element value (without processing).
247 *
248 * An element definition has been parsed
249 */
250void
251elementDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
252 xmlElementContentPtr content)
253{
Daniel Veillard27d88741999-05-29 11:51:49 +0000254 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000255 name, type);
256}
257
258/**
259 * notationDeclDebug:
260 * @ctxt: An XML parser context
261 * @name: The name of the notation
262 * @publicId: The public ID of the entity
263 * @systemId: The system ID of the entity
264 *
265 * What to do when a notation declaration has been parsed.
266 * TODO Not handled currently.
267 */
268void
269notationDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
270 const CHAR *publicId, const CHAR *systemId)
271{
Daniel Veillard27d88741999-05-29 11:51:49 +0000272 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000273 (char *) name, (char *) publicId, (char *) systemId);
274}
275
276/**
277 * unparsedEntityDeclDebug:
278 * @ctxt: An XML parser context
279 * @name: The name of the entity
280 * @publicId: The public ID of the entity
281 * @systemId: The system ID of the entity
282 * @notationName: the name of the notation
283 *
284 * What to do when an unparsed entity declaration is parsed
285 * TODO Create an Entity node.
286 */
287void
288unparsedEntityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
289 const CHAR *publicId, const CHAR *systemId,
290 const CHAR *notationName)
291{
Daniel Veillard27d88741999-05-29 11:51:49 +0000292 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000293 (char *) name, (char *) publicId, (char *) systemId,
294 (char *) notationName);
295}
296
297/**
298 * setDocumentLocatorDebug:
299 * @ctxt: An XML parser context
300 * @loc: A SAX Locator
301 *
302 * Receive the document locator at startup, actually xmlDefaultSAXLocator
303 * Everything is available on the context, so this is useless in our case.
304 */
305void
306setDocumentLocatorDebug(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc)
307{
Daniel Veillard27d88741999-05-29 11:51:49 +0000308 fprintf(stdout, "SAX.setDocumentLocator()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000309}
310
311/**
312 * startDocumentDebug:
313 * @ctxt: An XML parser context
314 *
315 * called when the document start being processed.
316 */
317void
318startDocumentDebug(xmlParserCtxtPtr ctxt)
319{
Daniel Veillard27d88741999-05-29 11:51:49 +0000320 fprintf(stdout, "SAX.startDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000321}
322
323/**
324 * endDocumentDebug:
325 * @ctxt: An XML parser context
326 *
327 * called when the document end has been detected.
328 */
329void
330endDocumentDebug(xmlParserCtxtPtr ctxt)
331{
Daniel Veillard27d88741999-05-29 11:51:49 +0000332 fprintf(stdout, "SAX.endDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000333}
334
335/**
336 * startElementDebug:
337 * @ctxt: An XML parser context
338 * @name: The element name
339 *
340 * called when an opening tag has been processed.
341 * TODO We currently have a small pblm with the arguments ...
342 */
343void
344startElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR **atts)
345{
346 int i;
347
Daniel Veillard27d88741999-05-29 11:51:49 +0000348 fprintf(stdout, "SAX.startElement(%s", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000349 if (atts != NULL) {
350 for (i = 0;(atts[i] != NULL);i++) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000351 fprintf(stdout, ", %s='", atts[i++]);
352 fprintf(stdout, "%s'", atts[i]);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000353 }
354 }
Daniel Veillard27d88741999-05-29 11:51:49 +0000355 fprintf(stdout, ")\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000356}
357
358/**
359 * endElementDebug:
360 * @ctxt: An XML parser context
361 * @name: The element name
362 *
363 * called when the end of an element has been detected.
364 */
365void
366endElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
367{
Daniel Veillard27d88741999-05-29 11:51:49 +0000368 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000369}
370
371/**
372 * charactersDebug:
373 * @ctxt: An XML parser context
374 * @ch: a CHAR string
375 * @len: the number of CHAR
376 *
377 * receiving some chars from the parser.
378 * Question: how much at a time ???
379 */
380void
381charactersDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
382{
Daniel Veillard27d88741999-05-29 11:51:49 +0000383 fprintf(stdout, "SAX.characters(%.30s, %d)\n", (char *) ch, len);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000384}
385
386/**
387 * referenceDebug:
388 * @ctxt: An XML parser context
389 * @name: The entity name
390 *
391 * called when an entity reference is detected.
392 */
393void
394referenceDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
395{
Daniel Veillard27d88741999-05-29 11:51:49 +0000396 fprintf(stdout, "SAX.reference(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000397}
398
399/**
400 * ignorableWhitespaceDebug:
401 * @ctxt: An XML parser context
402 * @ch: a CHAR string
403 * @start: the first char in the string
404 * @len: the number of CHAR
405 *
406 * receiving some ignorable whitespaces from the parser.
407 * Question: how much at a time ???
408 */
409void
410ignorableWhitespaceDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
411{
Daniel Veillard27d88741999-05-29 11:51:49 +0000412 fprintf(stdout, "SAX.ignorableWhitespace(%.30s, %d)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000413 (char *) ch, len);
414}
415
416/**
417 * processingInstructionDebug:
418 * @ctxt: An XML parser context
419 * @target: the target name
420 * @data: the PI data's
421 * @len: the number of CHAR
422 *
423 * A processing instruction has been parsed.
424 */
425void
426processingInstructionDebug(xmlParserCtxtPtr ctxt, const CHAR *target,
427 const CHAR *data)
428{
Daniel Veillard27d88741999-05-29 11:51:49 +0000429 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000430 (char *) target, (char *) data);
431}
432
433/**
434 * commentDebug:
435 * @ctxt: An XML parser context
436 * @value: the comment content
437 *
438 * A comment has been parsed.
439 */
440void
441commentDebug(xmlParserCtxtPtr ctxt, const CHAR *value)
442{
Daniel Veillard27d88741999-05-29 11:51:49 +0000443 fprintf(stdout, "SAX.comment(%s)\n", value);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000444}
445
446/**
447 * warningDebug:
448 * @ctxt: An XML parser context
449 * @msg: the message to display/transmit
450 * @...: extra parameters for the message display
451 *
452 * Display and format a warning messages, gives file, line, position and
453 * extra parameters.
454 */
455void
456warningDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
457{
458 va_list args;
459
460 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000461 fprintf(stdout, "SAX.warning: ");
462 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000463 va_end(args);
464}
465
466/**
467 * errorDebug:
468 * @ctxt: An XML parser context
469 * @msg: the message to display/transmit
470 * @...: extra parameters for the message display
471 *
472 * Display and format a error messages, gives file, line, position and
473 * extra parameters.
474 */
475void
476errorDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
477{
478 va_list args;
479
480 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000481 fprintf(stdout, "SAX.error: ");
482 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000483 va_end(args);
484}
485
486/**
487 * fatalErrorDebug:
488 * @ctxt: An XML parser context
489 * @msg: the message to display/transmit
490 * @...: extra parameters for the message display
491 *
492 * Display and format a fatalError messages, gives file, line, position and
493 * extra parameters.
494 */
495void
496fatalErrorDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
497{
498 va_list args;
499
500 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000501 fprintf(stdout, "SAX.fatalError: ");
502 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000503 va_end(args);
504}
505
506xmlSAXHandler debugSAXHandlerStruct = {
507 internalSubsetDebug,
508 isStandaloneDebug,
509 hasInternalSubsetDebug,
510 hasExternalSubsetDebug,
511 resolveEntityDebug,
512 getEntityDebug,
513 entityDeclDebug,
514 notationDeclDebug,
515 attributeDeclDebug,
516 elementDeclDebug,
517 unparsedEntityDeclDebug,
518 setDocumentLocatorDebug,
519 startDocumentDebug,
520 endDocumentDebug,
521 startElementDebug,
522 endElementDebug,
523 referenceDebug,
524 charactersDebug,
525 ignorableWhitespaceDebug,
526 processingInstructionDebug,
527 commentDebug,
528 warningDebug,
529 errorDebug,
530 fatalErrorDebug,
531};
532
533xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
534
535/************************************************************************
536 * *
537 * Debug *
538 * *
539 ************************************************************************/
540
541void parseAndPrintFile(char *filename) {
542 xmlDocPtr doc;
543
544 /*
545 * Empty callbacks for checking
546 */
547 doc = xmlSAXParseFile(emptySAXHandler, filename, 0);
548 if (doc != NULL) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000549 fprintf(stdout, "xmlSAXParseFile returned non-NULL\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000550 xmlDocDump(stdout, doc);
551 }
552
553 /*
554 * Debug callback
555 */
556 doc = xmlSAXParseFile(debugSAXHandler, filename, 0);
557 if (doc != NULL) {
558 fprintf(stderr, "xmlSAXParseFile returned non-NULL\n");
559 xmlDocDump(stdout, doc);
560 }
561}
562
563void parseAndPrintBuffer(CHAR *buf) {
564 xmlDocPtr doc;
565
566 /*
567 * Empty callbacks for checking
568 */
569 doc = xmlSAXParseDoc(emptySAXHandler, buf, 0);
570 if (doc != NULL) {
571 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
572 xmlDocDump(stdout, doc);
573 }
574
575 /*
576 * Debug callback
577 */
578 doc = xmlSAXParseDoc(debugSAXHandler, buf, 0);
579 if (doc != NULL) {
580 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
581 xmlDocDump(stdout, doc);
582 }
583}
584
585int main(int argc, char **argv) {
586 int i;
587 int files = 0;
588
589 for (i = 1; i < argc ; i++) {
590 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
591 debug++;
592 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
593 copy++;
594 else if ((!strcmp(argv[i], "-recover")) ||
595 (!strcmp(argv[i], "--recover")))
596 recovery++;
597 }
598 for (i = 1; i < argc ; i++) {
599 if (argv[i][0] != '-') {
600 parseAndPrintFile(argv[i]);
601 files ++;
602 }
603 }
604 if (files == 0) {
605 printf("\nFirst test for the parser, with errors\n");
606 parseAndPrintBuffer(buffer);
607 }
608
609 return(0);
610}