1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "libparsifal/parsifal.h"
5 #include "libparsifal/dtdvalid.h"
6
7 #define MAKE_DIFFGRAM 1
8
9 #ifdef _MSC_VER
10 #ifdef _DEBUG
11 #include <crtdbg.h>
12 #define _CRTDBG_MAP_ALLOC
13 #endif
14 #endif
15
16 #define OUTDIR "pxpout/"
17
18 /* stack macros (from xmldef.h) */
19 #define STACK_PUSH(stack,item) (XMLVector_Append((stack), (item)))
20 #define STACK_PEEK(stack) (XMLVector_Get((stack),(stack)->length-1))
21 #define STACK_REMOVE(stack) (XMLVector_Remove((stack), (stack)->length-1))
22 #define STACK_POP(stack,item) \
23 ( ((stack)->length) ? (memcpy((item), STACK_PEEK((stack)), (stack)->itemSize), \
24 STACK_REMOVE((stack)), (item)) : NULL)
25
26 #define EMPTY_COLS(num, pfile) { int i; for (i=0; i<(num); i++) fputs("<td> </td>", (pfile)); }
27
28 #ifndef MAX_PATH
29 #define MAX_PATH 256
30 #endif
31
32 enum tagSTATES { NONE, TESTSUITE, TESTCASES, TEST } STATES;
33
34 #define PFOUT (((XMLCONFPARSER*)UserData)->pfout)
35 #define PFERR stdout
36
37 typedef struct tagXMLCONFPARSER {
38 LPXMLPARSER parser;
39 LPXMLVECTOR stateStack;
40 LPXMLDTDVALIDATOR v;
41 int state;
42 int inMixedContent;
43 /* these are xmlconf specific: */
44 LPXMLPARSER runParser;
45 int testCount;
46 int testSuccess;
47 FILE *pfout, *pffailed;
48 } XMLCONFPARSER;
49
50 typedef struct tagRUNPARSERDATA {
51 XMLCH systemID[MAX_PATH];
52 XMLCH testbasedir[MAX_PATH];
53 XMLCH intEnt[MAX_PATH];
54 } RUNPARSERDATA;
55
56 /* common routines: */
57 int cstream(BYTE *buf, int cBytes, int *cBytesActual, void *inputData);
58 int FreeInputData(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader);
59
60 /* TESTSUITE PARSER: */
61 void PrintEsc(FILE *fp, const XMLCH *str, int len);
62 int StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts);
63 int EndElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName);
64 int Characters(void *UserData, const XMLCH *Chars, int cbChars);
65 void ErrorHandler(LPXMLPARSER parser);
66 int ResolveEntity(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader);
67
68 /* RUNTEST PARSER: */
69 int RunTest(XMLCONFPARSER *xcp, char *uri);
70 int RunTestResolveEntity(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader);
71 void RunTestErrorHandler(LPXMLPARSER parser);
72 void GetBaseDir(unsigned char *fullfile, unsigned char *targetdir);
73 int StartElementDetermineValidation(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts);
74 extern int fcompare(const char *fnam1, const char *fnam2);
75
cstream(BYTE * buf,int cBytes,int * cBytesActual,void * inputData)76 int cstream(BYTE *buf, int cBytes, int *cBytesActual, void *inputData)
77 {
78 *cBytesActual = fread(buf, 1, cBytes, (FILE*)inputData);
79 return (*cBytesActual < cBytes);
80 }
81
FreeInputData(void * UserData,LPXMLENTITY entity,LPBUFFEREDISTREAM reader)82 int FreeInputData(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader)
83 {
84 fclose((FILE*)reader->inputData);
85 return 0;
86 }
87
88 /* TESTSUITE PARSER BEGIN */
89
StartElement(void * UserData,const XMLCH * uri,const XMLCH * localName,const XMLCH * qName,LPXMLVECTOR atts)90 int StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts)
91 {
92 XMLCONFPARSER *xcp = (XMLCONFPARSER*)UserData;
93 LPXMLRUNTIMEATT att;
94 int *pstate = STACK_PEEK(xcp->stateStack);
95 xcp->state = (pstate) ? *pstate : NONE;
96
97 if (xcp->inMixedContent || xcp->state == TEST) {
98 /* + other tags that allow mixed content tested here */
99 /* if we're in mixed content, we don't bother to use stack, just
100 incrementing (and decrementing in EndElement) the counter: */
101 xcp->inMixedContent++;
102 /* could call mixed content legal tag check routine here e.g.
103 if (!isvalidmixedcontent(state, qName)) return sin(); */
104 fprintf(PFOUT, "<%s>", qName);
105 return 0;
106 }
107
108 if (xcp->state == NONE && !strcmp(qName, "TESTSUITE")) {
109
110 if (att = XMLParser_GetNamedItem(xcp->parser, "PROFILE"))
111 fprintf(PFOUT, "<h1><b>%s</b></h1><br><h3>Parsifal XML Parser %s</h3>",
112 att->value, XMLParser_GetVersionString());
113 xcp->state = TESTSUITE;
114 }
115 else if (xcp->state == TESTSUITE && !strcmp(qName, "TESTCASES")) {
116
117 if (att = XMLParser_GetNamedItem(xcp->parser, "PROFILE")) {
118 /* new testcase, spit out the profile header: */
119 fprintf(PFOUT, "<br><br><h2>Testcase profile: <b>%s</b></h2><br>", att->value);
120 fputs("<table cellspacing='0'>", PFOUT); /* open table for results */
121 }
122 xcp->state = TESTCASES;
123 }
124 else if (xcp->state == TESTCASES) {
125
126 if (!strcmp(qName, "TEST")) {
127 if (att = XMLParser_GetNamedItem(xcp->parser, "URI")) {
128 /* new test, run it: */
129 if (!RunTest(xcp, att->value))
130 fprintf(PFERR, "Fatal Error running test: %s\n", att->value);
131 }
132 xcp->state = TEST;
133 }
134 else if (!strcmp(qName, "TESTCASES")) { /* for some reason
135
136 there's TESTCASES inside TESTCASES in ibm tests,
137 so it must ust be handled here: */
138 xcp->state = TESTCASES;
139 }
140 }
141 else {
142 fprintf(PFERR, "Unexpected tag: %s\n", qName);
143 return XML_ABORT;
144 }
145
146 STACK_PUSH(xcp->stateStack, &xcp->state);
147 return 0;
148 }
149
EndElement(void * UserData,const XMLCH * uri,const XMLCH * localName,const XMLCH * qName)150 int EndElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName)
151 {
152 XMLCONFPARSER *xcp = (XMLCONFPARSER*)UserData;
153 if (xcp->inMixedContent) {
154 xcp->inMixedContent--;
155 fprintf(PFOUT, "</%s>", qName); /* EM or B tags */
156 }
157 else {
158 if (STACK_POP(xcp->stateStack, &xcp->state)) {
159 if (xcp->state == TEST) {
160 /* close TEST description column and row: */
161 fputs("</td>", PFOUT);
162 EMPTY_COLS(3, PFOUT);
163 fputs("</tr>", PFOUT);
164 }
165 else if (xcp->state == TESTCASES) {
166 int *pstate = STACK_PEEK(xcp->stateStack);
167 /* check is needed 'cos there can be TESTCASES inside TESTCASES */
168 if (pstate && *pstate != TESTCASES) fputs("</table>", PFOUT);
169 }
170 }
171 }
172 return 0;
173 }
174
PrintEsc(FILE * fp,const XMLCH * str,int len)175 void PrintEsc(FILE *fp, const XMLCH *str, int len)
176 {
177 for (; len--; str++) {
178 switch(*str) {
179 case '&': fputs("&", fp); break;
180 case '\"': fputs(""", fp); break;
181 //case '\'': fprintf("'", fp); break;
182 case '<': fputs("<", fp); break;
183 case '>': fputs(">", fp); break;
184 case '\x9': fputs("	", fp); break;
185 case '\xA': fputs(" ", fp); break;
186 case '\xD': fputs(" ", fp); break;
187 default: fputc(*str, fp); break;
188 }
189 }
190 }
191
Characters(void * UserData,const XMLCH * Chars,int cbChars)192 int Characters(void *UserData, const XMLCH *Chars, int cbChars)
193 {
194 XMLCONFPARSER *xcp = (XMLCONFPARSER*)UserData;
195 if (xcp->state == TEST)
196 PrintEsc(PFOUT, Chars, cbChars);
197 return 0;
198 }
199
ErrorHandler(LPXMLPARSER parser)200 void ErrorHandler(LPXMLPARSER parser)
201 {
202 if (parser->ErrorCode != ERR_XMLP_ABORT) {
203 XMLCH *sysID = XMLParser_GetSystemID(parser);
204
205 if (sysID) fprintf(PFERR, "Parsing resource %s failed!\n", sysID);
206 fprintf(PFERR, "Error: %s\nCode: %d\nLine: %d\nColumn: %d\n",
207 parser->ErrorString, parser->ErrorCode,
208 parser->ErrorLine, parser->ErrorColumn);
209 }
210 }
211
ResolveEntity(void * UserData,LPXMLENTITY entity,LPBUFFEREDISTREAM reader)212 int ResolveEntity(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader)
213 {
214 FILE *f;
215 if (!(f = fopen(entity->systemID, "rb"))) {
216 fprintf(PFERR, "error opening file '%s'!\n", entity->systemID);
217 return XML_ABORT;
218 }
219 reader->inputData = f;
220 return 0;
221 }
222 /* TESTSUITE PARSER END */
223
224 /* RUNTEST PARSER BEGIN */
225 /* these are parser routines that run the test itself,
226 we don't need many event handlers for it only
227 resolveEntityHandler and related stuff */
228
229
230 #define TYPE_VALID 1
231 #define TYPE_INVALID 2
232 #define TYPE_OTHER 3
233
RunTest(XMLCONFPARSER * xcp,char * uri)234 int RunTest(XMLCONFPARSER *xcp, char *uri)
235 {
236 LPXMLRUNTIMEATT att, tatt;
237 XMLCH testuri[MAX_PATH];
238 XMLCH xmlbase[MAX_PATH];
239 XMLCH id[256];
240 XMLCH *s;
241 FILE *f;
242 RUNPARSERDATA rdata;
243 int result, expect;
244 LPXMLPARSER parser = xcp->runParser;
245 int type;
246
247 if ((s = XMLParser_GetPrefixMapping(xcp->parser, "xml:base")))
248 strcpy(xmlbase, s); /* we save current xmlbase
249 (although it shouldn't get modified 'cos
250 main parser isn't running during RunTest()) */
251 else {
252 /* rmt-e2e-18:
253 External entity containing start of entity declaration is
254 base URI for system identifier, so: */
255 XMLCH *sysID = XMLParser_GetSystemID(xcp->parser);
256 if (!sysID) xmlbase[0] = '\0';
257 else GetBaseDir(sysID, xmlbase);
258 }
259
260 strcpy(testuri, xmlbase);
261 strcat(testuri, uri);
262
263 puts(testuri);
264
265 /* resolve basedir for external entities, DTD and for canonxml */
266 GetBaseDir(testuri, rdata.testbasedir);
267
268 tatt = XMLParser_GetNamedItem(xcp->parser, "TYPE");
269 if (tatt) {
270 /* "Nonvalidating parsers must also accept "invalid" testcases,
271 but validating ones must reject them." */
272 if (!strcmp(tatt->value, "valid")) type = TYPE_VALID;
273 else if (!strcmp(tatt->value, "invalid")) type = TYPE_INVALID;
274 else type = TYPE_OTHER; /* error, not-wf */
275 }
276
277 if ((f = fopen(testuri, "rb"))) {
278 #ifdef TEST_VALIDATING
279 xcp->v->UserData = &rdata;
280 xcp->v->UserFlag = type;
281 xcp->v->startElementHandlerFilter = StartElementDetermineValidation;
282 result = XMLParser_ParseValidateDTD(xcp->v, parser, cstream, f, 0);
283 #else
284 parser->UserData = &rdata;
285 result = XMLParser_Parse(parser, cstream, f, 0);
286 #endif
287 fclose(f);
288 }
289 else {
290 fprintf(PFERR, "Error opening file %s\n", testuri);
291 return 0;
292 }
293
294 xcp->testCount++;
295
296 /* 1 row columns: ID, TYPE, PASS/FAIL, ERRORSTRING
297 2 row columns: ENTITIES + OUTPUT in one col, 3 empty cols
298 3 row: test description, 3 empty cols
299 */
300 att = XMLParser_GetNamedItem(xcp->parser, "ID");
301 strcpy(id, (att) ? att->value : "unknown");
302 fputs((xcp->testCount % 2) ? "<tr bgcolor='#EEEEEE'>" : "<tr>", xcp->pfout);
303 fprintf(xcp->pfout, "<td><a href='%s'>%s</a></td>", testuri, id);
304
305 if (tatt) {
306 if (type == TYPE_VALID) expect = 1;
307 else if (type == TYPE_INVALID)
308 #ifdef TEST_VALIDATING
309 expect = 0;
310 #else
311 expect = 1;
312 #endif
313 else expect = 0;
314 fprintf(xcp->pfout, "<td>%s</td>", tatt->value);
315 if (result == expect) xcp->testSuccess++;
316 }
317 else {
318 EMPTY_COLS(1, xcp->pfout);
319 }
320
321 if (result != expect) fprintf(xcp->pffailed, "%s\n", id);
322
323 fprintf(xcp->pfout, "<td><font color='%s'>", (result == expect) ? "#008000" : "#FF0000");
324 if (result)
325 fprintf(xcp->pfout, "PASS</font></td><td> </td>");
326 else {
327 fputs("FAIL</font></td><td>", xcp->pfout);
328 #ifdef TEST_VALIDATING
329 if (parser->ErrorCode == ERR_XMLP_VALIDATION)
330 PrintEsc(xcp->pfout, xcp->v->ErrorString, strlen(xcp->v->ErrorString));
331 else
332 #endif
333 PrintEsc(xcp->pfout, parser->ErrorString, strlen(parser->ErrorString));
334 fputs("</td>", xcp->pfout);
335 }
336
337 fputs("</tr>", xcp->pfout);
338 fputs((xcp->testCount % 2) ? "<tr bgcolor='#EEEEEE'>" : "<tr>", xcp->pfout);
339
340 if ((att = XMLParser_GetNamedItem(xcp->parser, "ENTITIES")))
341 fprintf(xcp->pfout, "<td><b>entities:</b> %s ", att->value);
342 else
343 fputs("<td>", xcp->pfout);
344
345 /* OUTPUT TEST */
346 att = XMLParser_GetNamedItem(xcp->parser, "OUTPUT");
347 if (att) {
348 int compres;
349 XMLCH cmd[2048];
350 XMLCH outfile1[MAX_PATH], outfile2[MAX_PATH];
351
352 strcpy(outfile1, xmlbase);
353 strcat(outfile1, att->value);
354 sprintf(outfile2, "%s%s.xml", OUTDIR, id);
355 sprintf(cmd, "canonxml %s %s %s", testuri, outfile2, rdata.testbasedir);
356 system(cmd);
357
358 compres = fcompare(outfile1, outfile2);
359
360 fprintf(xcp->pfout, "<font color='%s'>OUTPUT:</font>",
361 (!compres) ? "#008000" : "#FF0000");
362 if (compres == -1)
363 fputs(" error", xcp->pfout);
364 else {
365 #ifdef MAKE_DIFFGRAM
366 if (compres) {
367 XMLCH difffile[MAX_PATH];
368 sprintf(difffile, "%s%s-diffgram.xml", OUTDIR, id);
369 sprintf(cmd, "xmldiff %s %s %s", outfile1, outfile2, difffile);
370 system(cmd);
371 fprintf(xcp->pfout, " <a href='%s'>1</a> <a href='%s'>2</a> <a href='%s'>diff</a>", outfile1, outfile2, difffile);
372 }
373 else
374 #endif
375 fprintf(xcp->pfout, " <a href='%s'>1</a> <a href='%s'>2</a>", outfile1, outfile2);
376 }
377 }
378 else {
379 fputs("</td>", xcp->pfout);
380 }
381 /* OUTPUT TEST END */
382
383 if (!parser->ErrorCode) {
384 EMPTY_COLS(3, xcp->pfout);
385 }
386 else {
387 EMPTY_COLS(2, xcp->pfout);
388 #ifdef TEST_VALIDATING
389 if (parser->ErrorCode == ERR_XMLP_VALIDATION)
390 fprintf(xcp->pfout, "<td>Line: %d Col: %d ", xcp->v->ErrorLine, xcp->v->ErrorColumn);
391 else
392 #endif
393 fprintf(xcp->pfout, "<td>Line: %d Col: %d ", parser->ErrorLine, parser->ErrorColumn);
394
395 if (rdata.intEnt[0]) fprintf(xcp->pfout, "in entity: '%s' ", rdata.intEnt);
396 if (rdata.systemID[0]) fprintf(xcp->pfout, "systemID: '%s'", rdata.systemID);
397 fputs("</td>", xcp->pfout);
398 }
399
400 fputs("</tr>", xcp->pfout);
401 /* open new table row for test description (reported via Characters): */
402 fputs((xcp->testCount % 2) ? "<tr bgcolor='#EEEEEE'><td>" : "<tr><td>", xcp->pfout);
403 return 1;
404 }
405
406 /* GetBaseDir gets path from <fullfile> string into
407 <targetdir> string (which must be allocated for strlen(fullfile)+1)*/
GetBaseDir(unsigned char * fullfile,unsigned char * targetdir)408 void GetBaseDir(unsigned char *fullfile, unsigned char *targetdir)
409 {
410 int slash = strlen(fullfile);
411 while(slash && *(fullfile+slash) != '/') slash--;
412 if (slash) {
413 memcpy(targetdir, fullfile, slash+1);
414 targetdir[slash+1] = '\0';
415 }
416 else {
417 targetdir[0] = '\0';
418 }
419 }
420
RunTestResolveEntity(void * UserData,LPXMLENTITY entity,LPBUFFEREDISTREAM reader)421 int RunTestResolveEntity(void *UserData, LPXMLENTITY entity, LPBUFFEREDISTREAM reader)
422 {
423 char testuri[MAX_PATH];
424 FILE *f;
425 #ifdef TEST_VALIDATING
426 RUNPARSERDATA *rdata = (RUNPARSERDATA*)((LPXMLDTDVALIDATOR)UserData)->UserData;
427 #else
428 RUNPARSERDATA *rdata = (RUNPARSERDATA*)UserData;
429 #endif
430 strcpy(testuri, rdata->testbasedir);
431 strcat(testuri, entity->systemID);
432
433 if (!(f = fopen(testuri, "rb"))) {
434 fprintf(PFERR, "Error opening file %s\n", testuri);
435 return XML_ABORT;
436 }
437 reader->inputData = f;
438 return 0;
439 }
440
RunTestErrorHandler(LPXMLPARSER parser)441 void RunTestErrorHandler(LPXMLPARSER parser)
442 {
443 XMLCH *systemID;
444 LPXMLENTITY curEnt;
445 #ifndef TEST_VALIDATING
446 RUNPARSERDATA *rdata = (RUNPARSERDATA*)parser->UserData;
447 #else
448 RUNPARSERDATA *rdata = (RUNPARSERDATA*)((LPXMLDTDVALIDATOR)parser->UserData)->UserData;
449 if (parser->ErrorCode == ERR_XMLP_VALIDATION &&
450 _XMLParser_GetFlag(parser, XMLFLAG_VALIDATION_WARNINGS)) return;
451 #endif
452 systemID = XMLParser_GetSystemID(parser);
453 curEnt = XMLParser_GetCurrentEntity(parser);
454 if (curEnt && !curEnt->systemID) strcpy(rdata->intEnt, curEnt->name);
455 else rdata->intEnt[0] = '\0';
456 if (systemID) strcpy(rdata->systemID, systemID);
457 else rdata->systemID[0] = '\0';
458 }
459
StartElementDetermineValidation(void * UserData,const XMLCH * uri,const XMLCH * localName,const XMLCH * qName,LPXMLVECTOR atts)460 int StartElementDetermineValidation(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts)
461 {
462 LPXMLDTDVALIDATOR v = (LPXMLDTDVALIDATOR)UserData;
463 if (v->UserFlag == TYPE_VALID || v->UserFlag == TYPE_INVALID) {
464 _XMLParser_SetFlag(v->parser, XMLFLAG_VALIDATION_WARNINGS, 0);
465 }
466 else {
467 _XMLParser_SetFlag(v->parser, XMLFLAG_VALIDATION_WARNINGS, 1);
468 }
469 v->startElementHandlerFilter = v->parser->startElementHandler = DTDValidate_StartElement;
470 return DTDValidate_StartElement(UserData, uri, localName, qName, atts);
471 }
472
473 /* RUNTEST PARSER END */
474
main(int argc,char * argv[])475 int main(int argc, char* argv[])
476 {
477 LPXMLPARSER parser;
478 XMLCONFPARSER parserdata;
479 FILE *f;
480 char namePffailed[100];
481
482 #ifdef _MSC_VER
483 #ifdef _DEBUG
484 int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
485 // Turn on leak-checking bit
486 tmpFlag |= _CRTDBG_LEAK_CHECK_DF; /* dump leaks to output */
487 // Set flag to the new value
488 _CrtSetDbgFlag( tmpFlag );
489 #endif
490 #endif
491
492 if (argc != 3) {
493 fprintf(PFERR, "Give filenames e.g. C:\\XMLCONF\\XMLCONF.XML RESULTS.HTML\n");
494 return 1;
495 }
496
497 /* Initialize xmlconf.xml parser: */
498 if (!XMLParser_Create(&parser)) {
499 fprintf(PFERR, "Error creating main parser in main()\n");
500 return 1;
501 }
502
503 parser->startElementHandler = StartElement;
504 parser->endElementHandler = EndElement;
505 parser->charactersHandler = Characters;
506 parser->errorHandler = ErrorHandler;
507 parser->resolveEntityHandler = ResolveEntity;
508 parser->externalEntityParsedHandler = FreeInputData;
509 parser->UserData = &parserdata;
510
511 parserdata.parser = parser;
512 parserdata.inMixedContent = 0;
513 parserdata.testCount = 0;
514 parserdata.testSuccess = 0;
515
516 /* Initialize runParser: */
517 /* we could create new parser in RunTest every time we're running
518 new test, but for extra stress testing we're using the
519 same parser: */
520 if (!XMLParser_Create(&parserdata.runParser)) {
521 fprintf(PFERR, "Error creating runParser in main()\n");
522 return 1;
523 }
524 #ifdef TEST_VALIDATING
525 parserdata.v = XMLParser_CreateDTDValidator();
526 if (!parserdata.v) {
527 fprintf(PFERR, "Error creating DTDvalidator in main()\n");
528 return 1;
529 }
530 #endif
531
532 /* make parsifal to report undefined entities and not to use skippedEntity: */
533 _XMLParser_SetFlag(parserdata.runParser, XMLFLAG_UNDEF_GENERAL_ENTITIES, 1);
534 /* assign handlers: */
535 parserdata.runParser->errorHandler = RunTestErrorHandler;
536 parserdata.runParser->resolveEntityHandler = RunTestResolveEntity;
537 parserdata.runParser->externalEntityParsedHandler = FreeInputData;
538
539 if (!XMLVector_Create(&parserdata.stateStack, 6, sizeof(int))) {
540 fprintf(PFERR, "Error creating stack in main()\n");
541 return 1;
542 }
543
544 if (!(f = fopen(argv[1], "rb"))) {
545 fprintf(PFERR, "Error opening input file %s\n", argv[1]);
546 return 1;
547 }
548
549 if (!(parserdata.pfout = fopen(argv[2], "wb"))) {
550 fprintf(PFERR, "Error opening output file %s\n", argv[2]);
551 return 1;
552 }
553
554 sprintf(namePffailed, "%s-failed-%s.txt", argv[1], XMLParser_GetVersionString());
555 if (!(parserdata.pffailed = fopen(namePffailed, "w"))) {
556 fprintf(PFERR, "Error opening output file namePffailed\n", namePffailed);
557 return 1;
558 }
559
560 fputs("<html><body>", parserdata.pfout);
561
562 XMLParser_Parse(parser, cstream, f, NULL);
563
564 fprintf(parserdata.pfout, "<br><br><b>%d</b> tests successful out of total <b>%d</b>.",
565 parserdata.testSuccess, parserdata.testCount);
566 fputs("</body></html>", parserdata.pfout);
567
568 fclose(f);
569 fclose(parserdata.pfout);
570 XMLVector_Free(parserdata.stateStack);
571 XMLParser_Free(parserdata.runParser);
572 XMLParser_Free(parser);
573 #ifdef TEST_VALIDATING
574 XMLParser_FreeDTDValidator(parserdata.v);
575 #endif
576 return 0;
577 }
578
579