testSAX.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  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. #include "libxml.h"
  9. #ifdef HAVE_SYS_TIME_H
  10. #include <sys/time.h>
  11. #endif
  12. #ifdef HAVE_SYS_TIMEB_H
  13. #include <sys/timeb.h>
  14. #endif
  15. #ifdef HAVE_TIME_H
  16. #include <time.h>
  17. #endif
  18. #ifdef LIBXML_SAX1_ENABLED
  19. #include <string.h>
  20. #include <stdarg.h>
  21. #ifdef HAVE_SYS_TYPES_H
  22. #include <sys/types.h>
  23. #endif
  24. #ifdef HAVE_SYS_STAT_H
  25. #include <sys/stat.h>
  26. #endif
  27. #ifdef HAVE_FCNTL_H
  28. #include <fcntl.h>
  29. #endif
  30. #ifdef HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #ifdef HAVE_STDLIB_H
  34. #include <stdlib.h>
  35. #endif
  36. #ifdef HAVE_STRING_H
  37. #include <string.h>
  38. #endif
  39. #include <libxml/globals.h>
  40. #include <libxml/xmlerror.h>
  41. #include <libxml/parser.h>
  42. #include <libxml/parserInternals.h> /* only for xmlNewInputFromFile() */
  43. #include <libxml/tree.h>
  44. #include <libxml/debugXML.h>
  45. #include <libxml/xmlmemory.h>
  46. static int debug = 0;
  47. static int copy = 0;
  48. static int recovery = 0;
  49. static int push = 0;
  50. static int speed = 0;
  51. static int noent = 0;
  52. static int quiet = 0;
  53. static int nonull = 0;
  54. static int sax2 = 0;
  55. static int repeat = 0;
  56. static int callbacks = 0;
  57. static int timing = 0;
  58. /*
  59. * Timing routines.
  60. */
  61. /*
  62. * Internal timing routines to remove the necessity to have unix-specific
  63. * function calls
  64. */
  65. #ifndef HAVE_GETTIMEOFDAY
  66. #ifdef HAVE_SYS_TIMEB_H
  67. #ifdef HAVE_SYS_TIME_H
  68. #ifdef HAVE_FTIME
  69. static int
  70. my_gettimeofday(struct timeval *tvp, void *tzp)
  71. {
  72. struct timeb timebuffer;
  73. ftime(&timebuffer);
  74. if (tvp) {
  75. tvp->tv_sec = timebuffer.time;
  76. tvp->tv_usec = timebuffer.millitm * 1000L;
  77. }
  78. return (0);
  79. }
  80. #define HAVE_GETTIMEOFDAY 1
  81. #define gettimeofday my_gettimeofday
  82. #endif /* HAVE_FTIME */
  83. #endif /* HAVE_SYS_TIME_H */
  84. #endif /* HAVE_SYS_TIMEB_H */
  85. #endif /* !HAVE_GETTIMEOFDAY */
  86. #if defined(HAVE_GETTIMEOFDAY)
  87. static struct timeval begin, end;
  88. /*
  89. * startTimer: call where you want to start timing
  90. */
  91. static void
  92. startTimer(void)
  93. {
  94. gettimeofday(&begin, NULL);
  95. }
  96. /*
  97. * endTimer: call where you want to stop timing and to print out a
  98. * message about the timing performed; format is a printf
  99. * type argument
  100. */
  101. static void XMLCDECL
  102. endTimer(const char *fmt, ...)
  103. {
  104. long msec;
  105. va_list ap;
  106. gettimeofday(&end, NULL);
  107. msec = end.tv_sec - begin.tv_sec;
  108. msec *= 1000;
  109. msec += (end.tv_usec - begin.tv_usec) / 1000;
  110. #ifndef HAVE_STDARG_H
  111. #error "endTimer required stdarg functions"
  112. #endif
  113. va_start(ap, fmt);
  114. vfprintf(stderr, fmt, ap);
  115. va_end(ap);
  116. fprintf(stderr, " took %ld ms\n", msec);
  117. }
  118. #elif defined(HAVE_TIME_H)
  119. /*
  120. * No gettimeofday function, so we have to make do with calling clock.
  121. * This is obviously less accurate, but there's little we can do about
  122. * that.
  123. */
  124. #ifndef CLOCKS_PER_SEC
  125. #define CLOCKS_PER_SEC 100
  126. #endif
  127. static clock_t begin, end;
  128. static void
  129. startTimer(void)
  130. {
  131. begin = clock();
  132. }
  133. static void XMLCDECL
  134. endTimer(const char *fmt, ...)
  135. {
  136. long msec;
  137. va_list ap;
  138. end = clock();
  139. msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
  140. #ifndef HAVE_STDARG_H
  141. #error "endTimer required stdarg functions"
  142. #endif
  143. va_start(ap, fmt);
  144. vfprintf(stderr, fmt, ap);
  145. va_end(ap);
  146. fprintf(stderr, " took %ld ms\n", msec);
  147. }
  148. #else
  149. /*
  150. * We don't have a gettimeofday or time.h, so we just don't do timing
  151. */
  152. static void
  153. startTimer(void)
  154. {
  155. /*
  156. * Do nothing
  157. */
  158. }
  159. static void XMLCDECL
  160. endTimer(char *format, ...)
  161. {
  162. /*
  163. * We cannot do anything because we don't have a timing function
  164. */
  165. #ifdef HAVE_STDARG_H
  166. va_start(ap, format);
  167. vfprintf(stderr, format, ap);
  168. va_end(ap);
  169. fprintf(stderr, " was not timed\n", msec);
  170. #else
  171. /* We don't have gettimeofday, time or stdarg.h, what crazy world is
  172. * this ?!
  173. */
  174. #endif
  175. }
  176. #endif
  177. /*
  178. * empty SAX block
  179. */
  180. static xmlSAXHandler emptySAXHandlerStruct = {
  181. NULL, /* internalSubset */
  182. NULL, /* isStandalone */
  183. NULL, /* hasInternalSubset */
  184. NULL, /* hasExternalSubset */
  185. NULL, /* resolveEntity */
  186. NULL, /* getEntity */
  187. NULL, /* entityDecl */
  188. NULL, /* notationDecl */
  189. NULL, /* attributeDecl */
  190. NULL, /* elementDecl */
  191. NULL, /* unparsedEntityDecl */
  192. NULL, /* setDocumentLocator */
  193. NULL, /* startDocument */
  194. NULL, /* endDocument */
  195. NULL, /* startElement */
  196. NULL, /* endElement */
  197. NULL, /* reference */
  198. NULL, /* characters */
  199. NULL, /* ignorableWhitespace */
  200. NULL, /* processingInstruction */
  201. NULL, /* comment */
  202. NULL, /* xmlParserWarning */
  203. NULL, /* xmlParserError */
  204. NULL, /* xmlParserError */
  205. NULL, /* getParameterEntity */
  206. NULL, /* cdataBlock; */
  207. NULL, /* externalSubset; */
  208. 1,
  209. NULL,
  210. NULL, /* startElementNs */
  211. NULL, /* endElementNs */
  212. NULL /* xmlStructuredErrorFunc */
  213. };
  214. static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
  215. extern xmlSAXHandlerPtr debugSAXHandler;
  216. /************************************************************************
  217. * *
  218. * Debug Handlers *
  219. * *
  220. ************************************************************************/
  221. /**
  222. * isStandaloneDebug:
  223. * @ctxt: An XML parser context
  224. *
  225. * Is this document tagged standalone ?
  226. *
  227. * Returns 1 if true
  228. */
  229. static int
  230. isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
  231. {
  232. callbacks++;
  233. if (quiet)
  234. return(0);
  235. fprintf(stdout, "SAX.isStandalone()\n");
  236. return(0);
  237. }
  238. /**
  239. * hasInternalSubsetDebug:
  240. * @ctxt: An XML parser context
  241. *
  242. * Does this document has an internal subset
  243. *
  244. * Returns 1 if true
  245. */
  246. static int
  247. hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
  248. {
  249. callbacks++;
  250. if (quiet)
  251. return(0);
  252. fprintf(stdout, "SAX.hasInternalSubset()\n");
  253. return(0);
  254. }
  255. /**
  256. * hasExternalSubsetDebug:
  257. * @ctxt: An XML parser context
  258. *
  259. * Does this document has an external subset
  260. *
  261. * Returns 1 if true
  262. */
  263. static int
  264. hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
  265. {
  266. callbacks++;
  267. if (quiet)
  268. return(0);
  269. fprintf(stdout, "SAX.hasExternalSubset()\n");
  270. return(0);
  271. }
  272. /**
  273. * internalSubsetDebug:
  274. * @ctxt: An XML parser context
  275. *
  276. * Does this document has an internal subset
  277. */
  278. static void
  279. internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  280. const xmlChar *ExternalID, const xmlChar *SystemID)
  281. {
  282. callbacks++;
  283. if (quiet)
  284. return;
  285. fprintf(stdout, "SAX.internalSubset(%s,", name);
  286. if (ExternalID == NULL)
  287. fprintf(stdout, " ,");
  288. else
  289. fprintf(stdout, " %s,", ExternalID);
  290. if (SystemID == NULL)
  291. fprintf(stdout, " )\n");
  292. else
  293. fprintf(stdout, " %s)\n", SystemID);
  294. }
  295. /**
  296. * externalSubsetDebug:
  297. * @ctxt: An XML parser context
  298. *
  299. * Does this document has an external subset
  300. */
  301. static void
  302. externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  303. const xmlChar *ExternalID, const xmlChar *SystemID)
  304. {
  305. callbacks++;
  306. if (quiet)
  307. return;
  308. fprintf(stdout, "SAX.externalSubset(%s,", name);
  309. if (ExternalID == NULL)
  310. fprintf(stdout, " ,");
  311. else
  312. fprintf(stdout, " %s,", ExternalID);
  313. if (SystemID == NULL)
  314. fprintf(stdout, " )\n");
  315. else
  316. fprintf(stdout, " %s)\n", SystemID);
  317. }
  318. /**
  319. * resolveEntityDebug:
  320. * @ctxt: An XML parser context
  321. * @publicId: The public ID of the entity
  322. * @systemId: The system ID of the entity
  323. *
  324. * Special entity resolver, better left to the parser, it has
  325. * more context than the application layer.
  326. * The default behaviour is to NOT resolve the entities, in that case
  327. * the ENTITY_REF nodes are built in the structure (and the parameter
  328. * values).
  329. *
  330. * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
  331. */
  332. static xmlParserInputPtr
  333. resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
  334. {
  335. callbacks++;
  336. if (quiet)
  337. return(NULL);
  338. /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
  339. fprintf(stdout, "SAX.resolveEntity(");
  340. if (publicId != NULL)
  341. fprintf(stdout, "%s", (char *)publicId);
  342. else
  343. fprintf(stdout, " ");
  344. if (systemId != NULL)
  345. fprintf(stdout, ", %s)\n", (char *)systemId);
  346. else
  347. fprintf(stdout, ", )\n");
  348. /*********
  349. if (systemId != NULL) {
  350. return(xmlNewInputFromFile(ctxt, (char *) systemId));
  351. }
  352. *********/
  353. return(NULL);
  354. }
  355. /**
  356. * getEntityDebug:
  357. * @ctxt: An XML parser context
  358. * @name: The entity name
  359. *
  360. * Get an entity by name
  361. *
  362. * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
  363. */
  364. static xmlEntityPtr
  365. getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  366. {
  367. callbacks++;
  368. if (quiet)
  369. return(NULL);
  370. fprintf(stdout, "SAX.getEntity(%s)\n", name);
  371. return(NULL);
  372. }
  373. /**
  374. * getParameterEntityDebug:
  375. * @ctxt: An XML parser context
  376. * @name: The entity name
  377. *
  378. * Get a parameter entity by name
  379. *
  380. * Returns the xmlParserInputPtr
  381. */
  382. static xmlEntityPtr
  383. getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  384. {
  385. callbacks++;
  386. if (quiet)
  387. return(NULL);
  388. fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
  389. return(NULL);
  390. }
  391. /**
  392. * entityDeclDebug:
  393. * @ctxt: An XML parser context
  394. * @name: the entity name
  395. * @type: the entity type
  396. * @publicId: The public ID of the entity
  397. * @systemId: The system ID of the entity
  398. * @content: the entity value (without processing).
  399. *
  400. * An entity definition has been parsed
  401. */
  402. static void
  403. entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
  404. const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
  405. {
  406. const xmlChar *nullstr = BAD_CAST "(null)";
  407. /* not all libraries handle printing null pointers nicely */
  408. if (publicId == NULL)
  409. publicId = nullstr;
  410. if (systemId == NULL)
  411. systemId = nullstr;
  412. if (content == NULL)
  413. content = (xmlChar *)nullstr;
  414. callbacks++;
  415. if (quiet)
  416. return;
  417. fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
  418. name, type, publicId, systemId, content);
  419. }
  420. /**
  421. * attributeDeclDebug:
  422. * @ctxt: An XML parser context
  423. * @name: the attribute name
  424. * @type: the attribute type
  425. *
  426. * An attribute definition has been parsed
  427. */
  428. static void
  429. attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
  430. const xmlChar * name, int type, int def,
  431. const xmlChar * defaultValue, xmlEnumerationPtr tree)
  432. {
  433. callbacks++;
  434. if (quiet)
  435. return;
  436. if (defaultValue == NULL)
  437. fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
  438. elem, name, type, def);
  439. else
  440. fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
  441. elem, name, type, def, defaultValue);
  442. xmlFreeEnumeration(tree);
  443. }
  444. /**
  445. * elementDeclDebug:
  446. * @ctxt: An XML parser context
  447. * @name: the element name
  448. * @type: the element type
  449. * @content: the element value (without processing).
  450. *
  451. * An element definition has been parsed
  452. */
  453. static void
  454. elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
  455. xmlElementContentPtr content ATTRIBUTE_UNUSED)
  456. {
  457. callbacks++;
  458. if (quiet)
  459. return;
  460. fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
  461. name, type);
  462. }
  463. /**
  464. * notationDeclDebug:
  465. * @ctxt: An XML parser context
  466. * @name: The name of the notation
  467. * @publicId: The public ID of the entity
  468. * @systemId: The system ID of the entity
  469. *
  470. * What to do when a notation declaration has been parsed.
  471. */
  472. static void
  473. notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  474. const xmlChar *publicId, const xmlChar *systemId)
  475. {
  476. callbacks++;
  477. if (quiet)
  478. return;
  479. fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
  480. (char *) name, (char *) publicId, (char *) systemId);
  481. }
  482. /**
  483. * unparsedEntityDeclDebug:
  484. * @ctxt: An XML parser context
  485. * @name: The name of the entity
  486. * @publicId: The public ID of the entity
  487. * @systemId: The system ID of the entity
  488. * @notationName: the name of the notation
  489. *
  490. * What to do when an unparsed entity declaration is parsed
  491. */
  492. static void
  493. unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  494. const xmlChar *publicId, const xmlChar *systemId,
  495. const xmlChar *notationName)
  496. {
  497. const xmlChar *nullstr = BAD_CAST "(null)";
  498. if (publicId == NULL)
  499. publicId = nullstr;
  500. if (systemId == NULL)
  501. systemId = nullstr;
  502. if (notationName == NULL)
  503. notationName = nullstr;
  504. callbacks++;
  505. if (quiet)
  506. return;
  507. fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
  508. (char *) name, (char *) publicId, (char *) systemId,
  509. (char *) notationName);
  510. }
  511. /**
  512. * setDocumentLocatorDebug:
  513. * @ctxt: An XML parser context
  514. * @loc: A SAX Locator
  515. *
  516. * Receive the document locator at startup, actually xmlDefaultSAXLocator
  517. * Everything is available on the context, so this is useless in our case.
  518. */
  519. static void
  520. setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
  521. {
  522. callbacks++;
  523. if (quiet)
  524. return;
  525. fprintf(stdout, "SAX.setDocumentLocator()\n");
  526. }
  527. /**
  528. * startDocumentDebug:
  529. * @ctxt: An XML parser context
  530. *
  531. * called when the document start being processed.
  532. */
  533. static void
  534. startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
  535. {
  536. callbacks++;
  537. if (quiet)
  538. return;
  539. fprintf(stdout, "SAX.startDocument()\n");
  540. }
  541. /**
  542. * endDocumentDebug:
  543. * @ctxt: An XML parser context
  544. *
  545. * called when the document end has been detected.
  546. */
  547. static void
  548. endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
  549. {
  550. callbacks++;
  551. if (quiet)
  552. return;
  553. fprintf(stdout, "SAX.endDocument()\n");
  554. }
  555. /**
  556. * startElementDebug:
  557. * @ctxt: An XML parser context
  558. * @name: The element name
  559. *
  560. * called when an opening tag has been processed.
  561. */
  562. static void
  563. startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
  564. {
  565. int i;
  566. callbacks++;
  567. if (quiet)
  568. return;
  569. fprintf(stdout, "SAX.startElement(%s", (char *) name);
  570. if (atts != NULL) {
  571. for (i = 0;(atts[i] != NULL);i++) {
  572. fprintf(stdout, ", %s='", atts[i++]);
  573. if (atts[i] != NULL)
  574. fprintf(stdout, "%s'", atts[i]);
  575. }
  576. }
  577. fprintf(stdout, ")\n");
  578. }
  579. /**
  580. * endElementDebug:
  581. * @ctxt: An XML parser context
  582. * @name: The element name
  583. *
  584. * called when the end of an element has been detected.
  585. */
  586. static void
  587. endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  588. {
  589. callbacks++;
  590. if (quiet)
  591. return;
  592. fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
  593. }
  594. /**
  595. * charactersDebug:
  596. * @ctxt: An XML parser context
  597. * @ch: a xmlChar string
  598. * @len: the number of xmlChar
  599. *
  600. * receiving some chars from the parser.
  601. * Question: how much at a time ???
  602. */
  603. static void
  604. charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
  605. {
  606. char output[40];
  607. int i;
  608. callbacks++;
  609. if (quiet)
  610. return;
  611. for (i = 0;(i<len) && (i < 30);i++)
  612. output[i] = ch[i];
  613. output[i] = 0;
  614. fprintf(stdout, "SAX.characters(%s, %d)\n", output, len);
  615. }
  616. /**
  617. * referenceDebug:
  618. * @ctxt: An XML parser context
  619. * @name: The entity name
  620. *
  621. * called when an entity reference is detected.
  622. */
  623. static void
  624. referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  625. {
  626. callbacks++;
  627. if (quiet)
  628. return;
  629. fprintf(stdout, "SAX.reference(%s)\n", name);
  630. }
  631. /**
  632. * ignorableWhitespaceDebug:
  633. * @ctxt: An XML parser context
  634. * @ch: a xmlChar string
  635. * @start: the first char in the string
  636. * @len: the number of xmlChar
  637. *
  638. * receiving some ignorable whitespaces from the parser.
  639. * Question: how much at a time ???
  640. */
  641. static void
  642. ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
  643. {
  644. char output[40];
  645. int i;
  646. callbacks++;
  647. if (quiet)
  648. return;
  649. for (i = 0;(i<len) && (i < 30);i++)
  650. output[i] = ch[i];
  651. output[i] = 0;
  652. fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
  653. }
  654. /**
  655. * processingInstructionDebug:
  656. * @ctxt: An XML parser context
  657. * @target: the target name
  658. * @data: the PI data's
  659. * @len: the number of xmlChar
  660. *
  661. * A processing instruction has been parsed.
  662. */
  663. static void
  664. processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
  665. const xmlChar *data)
  666. {
  667. callbacks++;
  668. if (quiet)
  669. return;
  670. if (data != NULL)
  671. fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
  672. (char *) target, (char *) data);
  673. else
  674. fprintf(stdout, "SAX.processingInstruction(%s, NULL)\n",
  675. (char *) target);
  676. }
  677. /**
  678. * cdataBlockDebug:
  679. * @ctx: the user data (XML parser context)
  680. * @value: The pcdata content
  681. * @len: the block length
  682. *
  683. * called when a pcdata block has been parsed
  684. */
  685. static void
  686. cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
  687. {
  688. callbacks++;
  689. if (quiet)
  690. return;
  691. fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
  692. (char *) value, len);
  693. }
  694. /**
  695. * commentDebug:
  696. * @ctxt: An XML parser context
  697. * @value: the comment content
  698. *
  699. * A comment has been parsed.
  700. */
  701. static void
  702. commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
  703. {
  704. callbacks++;
  705. if (quiet)
  706. return;
  707. fprintf(stdout, "SAX.comment(%s)\n", value);
  708. }
  709. /**
  710. * warningDebug:
  711. * @ctxt: An XML parser context
  712. * @msg: the message to display/transmit
  713. * @...: extra parameters for the message display
  714. *
  715. * Display and format a warning messages, gives file, line, position and
  716. * extra parameters.
  717. */
  718. static void XMLCDECL
  719. warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
  720. {
  721. va_list args;
  722. callbacks++;
  723. if (quiet)
  724. return;
  725. va_start(args, msg);
  726. fprintf(stdout, "SAX.warning: ");
  727. vfprintf(stdout, msg, args);
  728. va_end(args);
  729. }
  730. /**
  731. * errorDebug:
  732. * @ctxt: An XML parser context
  733. * @msg: the message to display/transmit
  734. * @...: extra parameters for the message display
  735. *
  736. * Display and format a error messages, gives file, line, position and
  737. * extra parameters.
  738. */
  739. static void XMLCDECL
  740. errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
  741. {
  742. va_list args;
  743. callbacks++;
  744. if (quiet)
  745. return;
  746. va_start(args, msg);
  747. fprintf(stdout, "SAX.error: ");
  748. vfprintf(stdout, msg, args);
  749. va_end(args);
  750. }
  751. /**
  752. * fatalErrorDebug:
  753. * @ctxt: An XML parser context
  754. * @msg: the message to display/transmit
  755. * @...: extra parameters for the message display
  756. *
  757. * Display and format a fatalError messages, gives file, line, position and
  758. * extra parameters.
  759. */
  760. static void XMLCDECL
  761. fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
  762. {
  763. va_list args;
  764. callbacks++;
  765. if (quiet)
  766. return;
  767. va_start(args, msg);
  768. fprintf(stdout, "SAX.fatalError: ");
  769. vfprintf(stdout, msg, args);
  770. va_end(args);
  771. }
  772. static xmlSAXHandler debugSAXHandlerStruct = {
  773. internalSubsetDebug,
  774. isStandaloneDebug,
  775. hasInternalSubsetDebug,
  776. hasExternalSubsetDebug,
  777. resolveEntityDebug,
  778. getEntityDebug,
  779. entityDeclDebug,
  780. notationDeclDebug,
  781. attributeDeclDebug,
  782. elementDeclDebug,
  783. unparsedEntityDeclDebug,
  784. setDocumentLocatorDebug,
  785. startDocumentDebug,
  786. endDocumentDebug,
  787. startElementDebug,
  788. endElementDebug,
  789. referenceDebug,
  790. charactersDebug,
  791. ignorableWhitespaceDebug,
  792. processingInstructionDebug,
  793. commentDebug,
  794. warningDebug,
  795. errorDebug,
  796. fatalErrorDebug,
  797. getParameterEntityDebug,
  798. cdataBlockDebug,
  799. externalSubsetDebug,
  800. 1,
  801. NULL,
  802. NULL,
  803. NULL,
  804. NULL
  805. };
  806. xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
  807. /*
  808. * SAX2 specific callbacks
  809. */
  810. /**
  811. * startElementNsDebug:
  812. * @ctxt: An XML parser context
  813. * @name: The element name
  814. *
  815. * called when an opening tag has been processed.
  816. */
  817. static void
  818. startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
  819. const xmlChar *localname,
  820. const xmlChar *prefix,
  821. const xmlChar *URI,
  822. int nb_namespaces,
  823. const xmlChar **namespaces,
  824. int nb_attributes,
  825. int nb_defaulted,
  826. const xmlChar **attributes)
  827. {
  828. int i;
  829. callbacks++;
  830. if (quiet)
  831. return;
  832. fprintf(stdout, "SAX.startElementNs(%s", (char *) localname);
  833. if (prefix == NULL)
  834. fprintf(stdout, ", NULL");
  835. else
  836. fprintf(stdout, ", %s", (char *) prefix);
  837. if (URI == NULL)
  838. fprintf(stdout, ", NULL");
  839. else
  840. fprintf(stdout, ", '%s'", (char *) URI);
  841. fprintf(stdout, ", %d", nb_namespaces);
  842. if (namespaces != NULL) {
  843. for (i = 0;i < nb_namespaces * 2;i++) {
  844. fprintf(stdout, ", xmlns");
  845. if (namespaces[i] != NULL)
  846. fprintf(stdout, ":%s", namespaces[i]);
  847. i++;
  848. fprintf(stdout, "='%s'", namespaces[i]);
  849. }
  850. }
  851. fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
  852. if (attributes != NULL) {
  853. for (i = 0;i < nb_attributes * 5;i += 5) {
  854. if (attributes[i + 1] != NULL)
  855. fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
  856. else
  857. fprintf(stdout, ", %s='", attributes[i]);
  858. fprintf(stdout, "%.4s...', %d", attributes[i + 3],
  859. (int)(attributes[i + 4] - attributes[i + 3]));
  860. }
  861. }
  862. fprintf(stdout, ")\n");
  863. }
  864. /**
  865. * endElementDebug:
  866. * @ctxt: An XML parser context
  867. * @name: The element name
  868. *
  869. * called when the end of an element has been detected.
  870. */
  871. static void
  872. endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
  873. const xmlChar *localname,
  874. const xmlChar *prefix,
  875. const xmlChar *URI)
  876. {
  877. callbacks++;
  878. if (quiet)
  879. return;
  880. fprintf(stdout, "SAX.endElementNs(%s", (char *) localname);
  881. if (prefix == NULL)
  882. fprintf(stdout, ", NULL");
  883. else
  884. fprintf(stdout, ", %s", (char *) prefix);
  885. if (URI == NULL)
  886. fprintf(stdout, ", NULL)\n");
  887. else
  888. fprintf(stdout, ", '%s')\n", (char *) URI);
  889. }
  890. static xmlSAXHandler debugSAX2HandlerStruct = {
  891. internalSubsetDebug,
  892. isStandaloneDebug,
  893. hasInternalSubsetDebug,
  894. hasExternalSubsetDebug,
  895. resolveEntityDebug,
  896. getEntityDebug,
  897. entityDeclDebug,
  898. notationDeclDebug,
  899. attributeDeclDebug,
  900. elementDeclDebug,
  901. unparsedEntityDeclDebug,
  902. setDocumentLocatorDebug,
  903. startDocumentDebug,
  904. endDocumentDebug,
  905. NULL,
  906. NULL,
  907. referenceDebug,
  908. charactersDebug,
  909. ignorableWhitespaceDebug,
  910. processingInstructionDebug,
  911. commentDebug,
  912. warningDebug,
  913. errorDebug,
  914. fatalErrorDebug,
  915. getParameterEntityDebug,
  916. cdataBlockDebug,
  917. externalSubsetDebug,
  918. XML_SAX2_MAGIC,
  919. NULL,
  920. startElementNsDebug,
  921. endElementNsDebug,
  922. NULL
  923. };
  924. static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
  925. /************************************************************************
  926. * *
  927. * Debug *
  928. * *
  929. ************************************************************************/
  930. static void
  931. parseAndPrintFile(char *filename) {
  932. int res;
  933. #ifdef LIBXML_PUSH_ENABLED
  934. if (push) {
  935. FILE *f;
  936. if ((!quiet) && (!nonull)) {
  937. /*
  938. * Empty callbacks for checking
  939. */
  940. #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
  941. f = fopen(filename, "rb");
  942. #else
  943. f = fopen(filename, "r");
  944. #endif
  945. if (f != NULL) {
  946. int ret;
  947. char chars[10];
  948. xmlParserCtxtPtr ctxt;
  949. ret = fread(chars, 1, 4, f);
  950. if (ret > 0) {
  951. ctxt = xmlCreatePushParserCtxt(emptySAXHandler, NULL,
  952. chars, ret, filename);
  953. while ((ret = fread(chars, 1, 3, f)) > 0) {
  954. xmlParseChunk(ctxt, chars, ret, 0);
  955. }
  956. xmlParseChunk(ctxt, chars, 0, 1);
  957. xmlFreeParserCtxt(ctxt);
  958. }
  959. fclose(f);
  960. } else {
  961. xmlGenericError(xmlGenericErrorContext,
  962. "Cannot read file %s\n", filename);
  963. }
  964. }
  965. /*
  966. * Debug callback
  967. */
  968. #if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__)
  969. f = fopen(filename, "rb");
  970. #else
  971. f = fopen(filename, "r");
  972. #endif
  973. if (f != NULL) {
  974. int ret;
  975. char chars[10];
  976. xmlParserCtxtPtr ctxt;
  977. ret = fread(chars, 1, 4, f);
  978. if (ret > 0) {
  979. if (sax2)
  980. ctxt = xmlCreatePushParserCtxt(debugSAX2Handler, NULL,
  981. chars, ret, filename);
  982. else
  983. ctxt = xmlCreatePushParserCtxt(debugSAXHandler, NULL,
  984. chars, ret, filename);
  985. while ((ret = fread(chars, 1, 3, f)) > 0) {
  986. xmlParseChunk(ctxt, chars, ret, 0);
  987. }
  988. ret = xmlParseChunk(ctxt, chars, 0, 1);
  989. xmlFreeParserCtxt(ctxt);
  990. if (ret != 0) {
  991. fprintf(stdout,
  992. "xmlSAXUserParseFile returned error %d\n", ret);
  993. }
  994. }
  995. fclose(f);
  996. }
  997. } else {
  998. #endif /* LIBXML_PUSH_ENABLED */
  999. if (!speed) {
  1000. /*
  1001. * Empty callbacks for checking
  1002. */
  1003. if ((!quiet) && (!nonull)) {
  1004. res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
  1005. if (res != 0) {
  1006. fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
  1007. }
  1008. }
  1009. /*
  1010. * Debug callback
  1011. */
  1012. callbacks = 0;
  1013. if (repeat) {
  1014. int i;
  1015. for (i = 0;i < 99;i++) {
  1016. if (sax2)
  1017. res = xmlSAXUserParseFile(debugSAX2Handler, NULL,
  1018. filename);
  1019. else
  1020. res = xmlSAXUserParseFile(debugSAXHandler, NULL,
  1021. filename);
  1022. }
  1023. }
  1024. if (sax2)
  1025. res = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
  1026. else
  1027. res = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
  1028. if (res != 0) {
  1029. fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
  1030. }
  1031. if (quiet)
  1032. fprintf(stdout, "%d callbacks generated\n", callbacks);
  1033. } else {
  1034. /*
  1035. * test 100x the SAX parse
  1036. */
  1037. int i;
  1038. for (i = 0; i<100;i++)
  1039. res = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
  1040. if (res != 0) {
  1041. fprintf(stdout, "xmlSAXUserParseFile returned error %d\n", res);
  1042. }
  1043. }
  1044. #ifdef LIBXML_PUSH_ENABLED
  1045. }
  1046. #endif
  1047. }
  1048. int main(int argc, char **argv) {
  1049. int i;
  1050. int files = 0;
  1051. LIBXML_TEST_VERSION /* be safe, plus calls xmlInitParser */
  1052. for (i = 1; i < argc ; i++) {
  1053. if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
  1054. debug++;
  1055. else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
  1056. copy++;
  1057. else if ((!strcmp(argv[i], "-recover")) ||
  1058. (!strcmp(argv[i], "--recover")))
  1059. recovery++;
  1060. else if ((!strcmp(argv[i], "-push")) ||
  1061. (!strcmp(argv[i], "--push")))
  1062. #ifdef LIBXML_PUSH_ENABLED
  1063. push++;
  1064. #else
  1065. fprintf(stderr,"'push' not enabled in library - ignoring\n");
  1066. #endif /* LIBXML_PUSH_ENABLED */
  1067. else if ((!strcmp(argv[i], "-speed")) ||
  1068. (!strcmp(argv[i], "--speed")))
  1069. speed++;
  1070. else if ((!strcmp(argv[i], "-timing")) ||
  1071. (!strcmp(argv[i], "--timing"))) {
  1072. nonull++;
  1073. timing++;
  1074. quiet++;
  1075. } else if ((!strcmp(argv[i], "-repeat")) ||
  1076. (!strcmp(argv[i], "--repeat"))) {
  1077. repeat++;
  1078. quiet++;
  1079. } else if ((!strcmp(argv[i], "-noent")) ||
  1080. (!strcmp(argv[i], "--noent")))
  1081. noent++;
  1082. else if ((!strcmp(argv[i], "-quiet")) ||
  1083. (!strcmp(argv[i], "--quiet")))
  1084. quiet++;
  1085. else if ((!strcmp(argv[i], "-sax2")) ||
  1086. (!strcmp(argv[i], "--sax2")))
  1087. sax2++;
  1088. else if ((!strcmp(argv[i], "-nonull")) ||
  1089. (!strcmp(argv[i], "--nonull")))
  1090. nonull++;
  1091. }
  1092. if (noent != 0) xmlSubstituteEntitiesDefault(1);
  1093. for (i = 1; i < argc ; i++) {
  1094. if (argv[i][0] != '-') {
  1095. if (timing) {
  1096. startTimer();
  1097. }
  1098. parseAndPrintFile(argv[i]);
  1099. if (timing) {
  1100. endTimer("Parsing");
  1101. }
  1102. files ++;
  1103. }
  1104. }
  1105. xmlCleanupParser();
  1106. xmlMemoryDump();
  1107. return(0);
  1108. }
  1109. #else
  1110. int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
  1111. printf("%s : SAX1 parsing support not compiled in\n", argv[0]);
  1112. return(0);
  1113. }
  1114. #endif /* LIBXML_SAX1_ENABLED */