PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/error.c

https://bitbucket.org/vaporoid/libxml2
C | 996 lines | 682 code | 71 blank | 243 comment | 341 complexity | 00ccd7999f590786183ffe1ee5762d5f MD5 | raw file
  1. /*
  2. * error.c: module displaying/handling XML parser errors
  3. *
  4. * See Copyright for the status of this software.
  5. *
  6. * Daniel Veillard <daniel@veillard.com>
  7. */
  8. #define IN_LIBXML
  9. #include "libxml.h"
  10. #include <string.h>
  11. #include <stdarg.h>
  12. #include <libxml/parser.h>
  13. #include <libxml/xmlerror.h>
  14. #include <libxml/xmlmemory.h>
  15. #include <libxml/globals.h>
  16. void XMLCDECL xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED,
  17. const char *msg,
  18. ...);
  19. #define XML_GET_VAR_STR(msg, str) { \
  20. int size, prev_size = -1; \
  21. int chars; \
  22. char *larger; \
  23. va_list ap; \
  24. \
  25. str = (char *) xmlMalloc(150); \
  26. if (str != NULL) { \
  27. \
  28. size = 150; \
  29. \
  30. while (size < 64000) { \
  31. va_start(ap, msg); \
  32. chars = vsnprintf(str, size, msg, ap); \
  33. va_end(ap); \
  34. if ((chars > -1) && (chars < size)) { \
  35. if (prev_size == chars) { \
  36. break; \
  37. } else { \
  38. prev_size = chars; \
  39. } \
  40. } \
  41. if (chars > -1) \
  42. size += chars + 1; \
  43. else \
  44. size += 100; \
  45. if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
  46. break; \
  47. } \
  48. str = larger; \
  49. }} \
  50. }
  51. /************************************************************************
  52. * *
  53. * Handling of out of context errors *
  54. * *
  55. ************************************************************************/
  56. /**
  57. * xmlGenericErrorDefaultFunc:
  58. * @ctx: an error context
  59. * @msg: the message to display/transmit
  60. * @...: extra parameters for the message display
  61. *
  62. * Default handler for out of context error messages.
  63. */
  64. void XMLCDECL
  65. xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
  66. va_list args;
  67. if (xmlGenericErrorContext == NULL)
  68. xmlGenericErrorContext = (void *) stderr;
  69. va_start(args, msg);
  70. vfprintf((FILE *)xmlGenericErrorContext, msg, args);
  71. va_end(args);
  72. }
  73. /**
  74. * initGenericErrorDefaultFunc:
  75. * @handler: the handler
  76. *
  77. * Set or reset (if NULL) the default handler for generic errors
  78. * to the builtin error function.
  79. */
  80. void
  81. initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
  82. {
  83. if (handler == NULL)
  84. xmlGenericError = xmlGenericErrorDefaultFunc;
  85. else
  86. xmlGenericError = (*handler);
  87. }
  88. /**
  89. * xmlSetGenericErrorFunc:
  90. * @ctx: the new error handling context
  91. * @handler: the new handler function
  92. *
  93. * Function to reset the handler and the error context for out of
  94. * context error messages.
  95. * This simply means that @handler will be called for subsequent
  96. * error messages while not parsing nor validating. And @ctx will
  97. * be passed as first argument to @handler
  98. * One can simply force messages to be emitted to another FILE * than
  99. * stderr by setting @ctx to this file handle and @handler to NULL.
  100. * For multi-threaded applications, this must be set separately for each thread.
  101. */
  102. void
  103. xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
  104. xmlGenericErrorContext = ctx;
  105. if (handler != NULL)
  106. xmlGenericError = handler;
  107. else
  108. xmlGenericError = xmlGenericErrorDefaultFunc;
  109. }
  110. /**
  111. * xmlSetStructuredErrorFunc:
  112. * @ctx: the new error handling context
  113. * @handler: the new handler function
  114. *
  115. * Function to reset the handler and the error context for out of
  116. * context structured error messages.
  117. * This simply means that @handler will be called for subsequent
  118. * error messages while not parsing nor validating. And @ctx will
  119. * be passed as first argument to @handler
  120. * For multi-threaded applications, this must be set separately for each thread.
  121. */
  122. void
  123. xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
  124. xmlStructuredErrorContext = ctx;
  125. xmlStructuredError = handler;
  126. }
  127. /************************************************************************
  128. * *
  129. * Handling of parsing errors *
  130. * *
  131. ************************************************************************/
  132. /**
  133. * xmlParserPrintFileInfo:
  134. * @input: an xmlParserInputPtr input
  135. *
  136. * Displays the associated file and line informations for the current input
  137. */
  138. void
  139. xmlParserPrintFileInfo(xmlParserInputPtr input) {
  140. if (input != NULL) {
  141. if (input->filename)
  142. xmlGenericError(xmlGenericErrorContext,
  143. "%s:%d: ", input->filename,
  144. input->line);
  145. else
  146. xmlGenericError(xmlGenericErrorContext,
  147. "Entity: line %d: ", input->line);
  148. }
  149. }
  150. /**
  151. * xmlParserPrintFileContext:
  152. * @input: an xmlParserInputPtr input
  153. *
  154. * Displays current context within the input content for error tracking
  155. */
  156. static void
  157. xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
  158. xmlGenericErrorFunc channel, void *data ) {
  159. const xmlChar *cur, *base;
  160. unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
  161. xmlChar content[81]; /* space for 80 chars + line terminator */
  162. xmlChar *ctnt;
  163. if (input == NULL) return;
  164. cur = input->cur;
  165. base = input->base;
  166. /* skip backwards over any end-of-lines */
  167. while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
  168. cur--;
  169. }
  170. n = 0;
  171. /* search backwards for beginning-of-line (to max buff size) */
  172. while ((n++ < (sizeof(content)-1)) && (cur > base) &&
  173. (*(cur) != '\n') && (*(cur) != '\r'))
  174. cur--;
  175. if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
  176. /* calculate the error position in terms of the current position */
  177. col = input->cur - cur;
  178. /* search forward for end-of-line (to max buff size) */
  179. n = 0;
  180. ctnt = content;
  181. /* copy selected text to our buffer */
  182. while ((*cur != 0) && (*(cur) != '\n') &&
  183. (*(cur) != '\r') && (n < sizeof(content)-1)) {
  184. *ctnt++ = *cur++;
  185. n++;
  186. }
  187. *ctnt = 0;
  188. /* print out the selected text */
  189. channel(data ,"%s\n", content);
  190. /* create blank line with problem pointer */
  191. n = 0;
  192. ctnt = content;
  193. /* (leave buffer space for pointer + line terminator) */
  194. while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
  195. if (*(ctnt) != '\t')
  196. *(ctnt) = ' ';
  197. ctnt++;
  198. }
  199. *ctnt++ = '^';
  200. *ctnt = 0;
  201. channel(data ,"%s\n", content);
  202. }
  203. /**
  204. * xmlParserPrintFileContext:
  205. * @input: an xmlParserInputPtr input
  206. *
  207. * Displays current context within the input content for error tracking
  208. */
  209. void
  210. xmlParserPrintFileContext(xmlParserInputPtr input) {
  211. xmlParserPrintFileContextInternal(input, xmlGenericError,
  212. xmlGenericErrorContext);
  213. }
  214. /**
  215. * xmlReportError:
  216. * @err: the error
  217. * @ctx: the parser context or NULL
  218. * @str: the formatted error message
  219. *
  220. * Report an erro with its context, replace the 4 old error/warning
  221. * routines.
  222. */
  223. static void
  224. xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
  225. xmlGenericErrorFunc channel, void *data)
  226. {
  227. char *file = NULL;
  228. int line = 0;
  229. int code = -1;
  230. int domain;
  231. const xmlChar *name = NULL;
  232. xmlNodePtr node;
  233. xmlErrorLevel level;
  234. xmlParserInputPtr input = NULL;
  235. xmlParserInputPtr cur = NULL;
  236. if (err == NULL)
  237. return;
  238. if (channel == NULL) {
  239. channel = xmlGenericError;
  240. data = xmlGenericErrorContext;
  241. }
  242. file = err->file;
  243. line = err->line;
  244. code = err->code;
  245. domain = err->domain;
  246. level = err->level;
  247. node = err->node;
  248. if (code == XML_ERR_OK)
  249. return;
  250. if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
  251. name = node->name;
  252. /*
  253. * Maintain the compatibility with the legacy error handling
  254. */
  255. if (ctxt != NULL) {
  256. input = ctxt->input;
  257. if ((input != NULL) && (input->filename == NULL) &&
  258. (ctxt->inputNr > 1)) {
  259. cur = input;
  260. input = ctxt->inputTab[ctxt->inputNr - 2];
  261. }
  262. if (input != NULL) {
  263. if (input->filename)
  264. channel(data, "%s:%d: ", input->filename, input->line);
  265. else if ((line != 0) && (domain == XML_FROM_PARSER))
  266. channel(data, "Entity: line %d: ", input->line);
  267. }
  268. } else {
  269. if (file != NULL)
  270. channel(data, "%s:%d: ", file, line);
  271. else if ((line != 0) &&
  272. ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
  273. (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
  274. (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
  275. channel(data, "Entity: line %d: ", line);
  276. }
  277. if (name != NULL) {
  278. channel(data, "element %s: ", name);
  279. }
  280. switch (domain) {
  281. case XML_FROM_PARSER:
  282. channel(data, "parser ");
  283. break;
  284. case XML_FROM_NAMESPACE:
  285. channel(data, "namespace ");
  286. break;
  287. case XML_FROM_DTD:
  288. case XML_FROM_VALID:
  289. channel(data, "validity ");
  290. break;
  291. case XML_FROM_HTML:
  292. channel(data, "HTML parser ");
  293. break;
  294. case XML_FROM_MEMORY:
  295. channel(data, "memory ");
  296. break;
  297. case XML_FROM_OUTPUT:
  298. channel(data, "output ");
  299. break;
  300. case XML_FROM_IO:
  301. channel(data, "I/O ");
  302. break;
  303. case XML_FROM_XINCLUDE:
  304. channel(data, "XInclude ");
  305. break;
  306. case XML_FROM_XPATH:
  307. channel(data, "XPath ");
  308. break;
  309. case XML_FROM_XPOINTER:
  310. channel(data, "parser ");
  311. break;
  312. case XML_FROM_REGEXP:
  313. channel(data, "regexp ");
  314. break;
  315. case XML_FROM_MODULE:
  316. channel(data, "module ");
  317. break;
  318. case XML_FROM_SCHEMASV:
  319. channel(data, "Schemas validity ");
  320. break;
  321. case XML_FROM_SCHEMASP:
  322. channel(data, "Schemas parser ");
  323. break;
  324. case XML_FROM_RELAXNGP:
  325. channel(data, "Relax-NG parser ");
  326. break;
  327. case XML_FROM_RELAXNGV:
  328. channel(data, "Relax-NG validity ");
  329. break;
  330. case XML_FROM_CATALOG:
  331. channel(data, "Catalog ");
  332. break;
  333. case XML_FROM_C14N:
  334. channel(data, "C14N ");
  335. break;
  336. case XML_FROM_XSLT:
  337. channel(data, "XSLT ");
  338. break;
  339. case XML_FROM_I18N:
  340. channel(data, "encoding ");
  341. break;
  342. case XML_FROM_SCHEMATRONV:
  343. channel(data, "schematron ");
  344. break;
  345. case XML_FROM_BUFFER:
  346. channel(data, "internal buffer ");
  347. break;
  348. case XML_FROM_URI:
  349. channel(data, "URI ");
  350. break;
  351. default:
  352. break;
  353. }
  354. switch (level) {
  355. case XML_ERR_NONE:
  356. channel(data, ": ");
  357. break;
  358. case XML_ERR_WARNING:
  359. channel(data, "warning : ");
  360. break;
  361. case XML_ERR_ERROR:
  362. channel(data, "error : ");
  363. break;
  364. case XML_ERR_FATAL:
  365. channel(data, "error : ");
  366. break;
  367. }
  368. if (str != NULL) {
  369. int len;
  370. len = xmlStrlen((const xmlChar *)str);
  371. if ((len > 0) && (str[len - 1] != '\n'))
  372. channel(data, "%s\n", str);
  373. else
  374. channel(data, "%s", str);
  375. } else {
  376. channel(data, "%s\n", "out of memory error");
  377. }
  378. if (ctxt != NULL) {
  379. xmlParserPrintFileContextInternal(input, channel, data);
  380. if (cur != NULL) {
  381. if (cur->filename)
  382. channel(data, "%s:%d: \n", cur->filename, cur->line);
  383. else if ((line != 0) && (domain == XML_FROM_PARSER))
  384. channel(data, "Entity: line %d: \n", cur->line);
  385. xmlParserPrintFileContextInternal(cur, channel, data);
  386. }
  387. }
  388. if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
  389. (err->int1 < 100) &&
  390. (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
  391. xmlChar buf[150];
  392. int i;
  393. channel(data, "%s\n", err->str1);
  394. for (i=0;i < err->int1;i++)
  395. buf[i] = ' ';
  396. buf[i++] = '^';
  397. buf[i] = 0;
  398. channel(data, "%s\n", buf);
  399. }
  400. }
  401. /**
  402. * __xmlRaiseError:
  403. * @schannel: the structured callback channel
  404. * @channel: the old callback channel
  405. * @data: the callback data
  406. * @ctx: the parser context or NULL
  407. * @ctx: the parser context or NULL
  408. * @domain: the domain for the error
  409. * @code: the code for the error
  410. * @level: the xmlErrorLevel for the error
  411. * @file: the file source of the error (or NULL)
  412. * @line: the line of the error or 0 if N/A
  413. * @str1: extra string info
  414. * @str2: extra string info
  415. * @str3: extra string info
  416. * @int1: extra int info
  417. * @col: column number of the error or 0 if N/A
  418. * @msg: the message to display/transmit
  419. * @...: extra parameters for the message display
  420. *
  421. * Update the appropriate global or contextual error structure,
  422. * then forward the error message down the parser or generic
  423. * error callback handler
  424. */
  425. void XMLCDECL
  426. __xmlRaiseError(xmlStructuredErrorFunc schannel,
  427. xmlGenericErrorFunc channel, void *data, void *ctx,
  428. void *nod, int domain, int code, xmlErrorLevel level,
  429. const char *file, int line, const char *str1,
  430. const char *str2, const char *str3, int int1, int col,
  431. const char *msg, ...)
  432. {
  433. xmlParserCtxtPtr ctxt = NULL;
  434. xmlNodePtr node = (xmlNodePtr) nod;
  435. char *str = NULL;
  436. xmlParserInputPtr input = NULL;
  437. xmlErrorPtr to = &xmlLastError;
  438. xmlNodePtr baseptr = NULL;
  439. if (code == XML_ERR_OK)
  440. return;
  441. if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
  442. return;
  443. if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
  444. (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
  445. (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
  446. ctxt = (xmlParserCtxtPtr) ctx;
  447. if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
  448. (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
  449. (ctxt->sax->serror != NULL)) {
  450. schannel = ctxt->sax->serror;
  451. data = ctxt->userData;
  452. }
  453. }
  454. /*
  455. * Check if structured error handler set
  456. */
  457. if (schannel == NULL) {
  458. schannel = xmlStructuredError;
  459. /*
  460. * if user has defined handler, change data ptr to user's choice
  461. */
  462. if (schannel != NULL)
  463. data = xmlStructuredErrorContext;
  464. }
  465. /*
  466. * Formatting the message
  467. */
  468. if (msg == NULL) {
  469. str = (char *) xmlStrdup(BAD_CAST "No error message provided");
  470. } else {
  471. XML_GET_VAR_STR(msg, str);
  472. }
  473. /*
  474. * specific processing if a parser context is provided
  475. */
  476. if (ctxt != NULL) {
  477. if (file == NULL) {
  478. input = ctxt->input;
  479. if ((input != NULL) && (input->filename == NULL) &&
  480. (ctxt->inputNr > 1)) {
  481. input = ctxt->inputTab[ctxt->inputNr - 2];
  482. }
  483. if (input != NULL) {
  484. file = input->filename;
  485. line = input->line;
  486. col = input->col;
  487. }
  488. }
  489. to = &ctxt->lastError;
  490. } else if ((node != NULL) && (file == NULL)) {
  491. int i;
  492. if ((node->doc != NULL) && (node->doc->URL != NULL)) {
  493. baseptr = node;
  494. /* file = (const char *) node->doc->URL; */
  495. }
  496. for (i = 0;
  497. ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
  498. i++)
  499. node = node->parent;
  500. if ((baseptr == NULL) && (node != NULL) &&
  501. (node->doc != NULL) && (node->doc->URL != NULL))
  502. baseptr = node;
  503. if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
  504. line = node->line;
  505. if ((line == 0) || (line == 65535))
  506. line = xmlGetLineNo(node);
  507. }
  508. /*
  509. * Save the information about the error
  510. */
  511. xmlResetError(to);
  512. to->domain = domain;
  513. to->code = code;
  514. to->message = str;
  515. to->level = level;
  516. if (file != NULL)
  517. to->file = (char *) xmlStrdup((const xmlChar *) file);
  518. else if (baseptr != NULL) {
  519. #ifdef LIBXML_XINCLUDE_ENABLED
  520. /*
  521. * We check if the error is within an XInclude section and,
  522. * if so, attempt to print out the href of the XInclude instead
  523. * of the usual "base" (doc->URL) for the node (bug 152623).
  524. */
  525. xmlNodePtr prev = baseptr;
  526. int inclcount = 0;
  527. while (prev != NULL) {
  528. if (prev->prev == NULL)
  529. prev = prev->parent;
  530. else {
  531. prev = prev->prev;
  532. if (prev->type == XML_XINCLUDE_START) {
  533. if (--inclcount < 0)
  534. break;
  535. } else if (prev->type == XML_XINCLUDE_END)
  536. inclcount++;
  537. }
  538. }
  539. if (prev != NULL) {
  540. if (prev->type == XML_XINCLUDE_START) {
  541. prev->type = XML_ELEMENT_NODE;
  542. to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
  543. prev->type = XML_XINCLUDE_START;
  544. } else {
  545. to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
  546. }
  547. } else
  548. #endif
  549. to->file = (char *) xmlStrdup(baseptr->doc->URL);
  550. if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
  551. to->file = (char *) xmlStrdup(node->doc->URL);
  552. }
  553. }
  554. to->line = line;
  555. if (str1 != NULL)
  556. to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
  557. if (str2 != NULL)
  558. to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
  559. if (str3 != NULL)
  560. to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
  561. to->int1 = int1;
  562. to->int2 = col;
  563. to->node = node;
  564. to->ctxt = ctx;
  565. if (to != &xmlLastError)
  566. xmlCopyError(to,&xmlLastError);
  567. if (schannel != NULL) {
  568. schannel(data, to);
  569. return;
  570. }
  571. /*
  572. * Find the callback channel if channel param is NULL
  573. */
  574. if ((ctxt != NULL) && (channel == NULL) &&
  575. (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
  576. if (level == XML_ERR_WARNING)
  577. channel = ctxt->sax->warning;
  578. else
  579. channel = ctxt->sax->error;
  580. data = ctxt->userData;
  581. } else if (channel == NULL) {
  582. channel = xmlGenericError;
  583. if (ctxt != NULL) {
  584. data = ctxt;
  585. } else {
  586. data = xmlGenericErrorContext;
  587. }
  588. }
  589. if (channel == NULL)
  590. return;
  591. if ((channel == xmlParserError) ||
  592. (channel == xmlParserWarning) ||
  593. (channel == xmlParserValidityError) ||
  594. (channel == xmlParserValidityWarning))
  595. xmlReportError(to, ctxt, str, NULL, NULL);
  596. else if ((channel == (xmlGenericErrorFunc) fprintf) ||
  597. (channel == xmlGenericErrorDefaultFunc))
  598. xmlReportError(to, ctxt, str, channel, data);
  599. else
  600. channel(data, "%s", str);
  601. }
  602. /**
  603. * __xmlSimpleError:
  604. * @domain: where the error comes from
  605. * @code: the error code
  606. * @node: the context node
  607. * @extra: extra informations
  608. *
  609. * Handle an out of memory condition
  610. */
  611. void
  612. __xmlSimpleError(int domain, int code, xmlNodePtr node,
  613. const char *msg, const char *extra)
  614. {
  615. if (code == XML_ERR_NO_MEMORY) {
  616. if (extra)
  617. __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
  618. XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
  619. NULL, NULL, 0, 0,
  620. "Memory allocation failed : %s\n", extra);
  621. else
  622. __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
  623. XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
  624. NULL, NULL, 0, 0, "Memory allocation failed\n");
  625. } else {
  626. __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
  627. code, XML_ERR_ERROR, NULL, 0, extra,
  628. NULL, NULL, 0, 0, msg, extra);
  629. }
  630. }
  631. /**
  632. * xmlParserError:
  633. * @ctx: an XML parser context
  634. * @msg: the message to display/transmit
  635. * @...: extra parameters for the message display
  636. *
  637. * Display and format an error messages, gives file, line, position and
  638. * extra parameters.
  639. */
  640. void XMLCDECL
  641. xmlParserError(void *ctx, const char *msg, ...)
  642. {
  643. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  644. xmlParserInputPtr input = NULL;
  645. xmlParserInputPtr cur = NULL;
  646. char * str;
  647. if (ctxt != NULL) {
  648. input = ctxt->input;
  649. if ((input != NULL) && (input->filename == NULL) &&
  650. (ctxt->inputNr > 1)) {
  651. cur = input;
  652. input = ctxt->inputTab[ctxt->inputNr - 2];
  653. }
  654. xmlParserPrintFileInfo(input);
  655. }
  656. xmlGenericError(xmlGenericErrorContext, "error: ");
  657. XML_GET_VAR_STR(msg, str);
  658. xmlGenericError(xmlGenericErrorContext, "%s", str);
  659. if (str != NULL)
  660. xmlFree(str);
  661. if (ctxt != NULL) {
  662. xmlParserPrintFileContext(input);
  663. if (cur != NULL) {
  664. xmlParserPrintFileInfo(cur);
  665. xmlGenericError(xmlGenericErrorContext, "\n");
  666. xmlParserPrintFileContext(cur);
  667. }
  668. }
  669. }
  670. /**
  671. * xmlParserWarning:
  672. * @ctx: an XML parser context
  673. * @msg: the message to display/transmit
  674. * @...: extra parameters for the message display
  675. *
  676. * Display and format a warning messages, gives file, line, position and
  677. * extra parameters.
  678. */
  679. void XMLCDECL
  680. xmlParserWarning(void *ctx, const char *msg, ...)
  681. {
  682. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  683. xmlParserInputPtr input = NULL;
  684. xmlParserInputPtr cur = NULL;
  685. char * str;
  686. if (ctxt != NULL) {
  687. input = ctxt->input;
  688. if ((input != NULL) && (input->filename == NULL) &&
  689. (ctxt->inputNr > 1)) {
  690. cur = input;
  691. input = ctxt->inputTab[ctxt->inputNr - 2];
  692. }
  693. xmlParserPrintFileInfo(input);
  694. }
  695. xmlGenericError(xmlGenericErrorContext, "warning: ");
  696. XML_GET_VAR_STR(msg, str);
  697. xmlGenericError(xmlGenericErrorContext, "%s", str);
  698. if (str != NULL)
  699. xmlFree(str);
  700. if (ctxt != NULL) {
  701. xmlParserPrintFileContext(input);
  702. if (cur != NULL) {
  703. xmlParserPrintFileInfo(cur);
  704. xmlGenericError(xmlGenericErrorContext, "\n");
  705. xmlParserPrintFileContext(cur);
  706. }
  707. }
  708. }
  709. /************************************************************************
  710. * *
  711. * Handling of validation errors *
  712. * *
  713. ************************************************************************/
  714. /**
  715. * xmlParserValidityError:
  716. * @ctx: an XML parser context
  717. * @msg: the message to display/transmit
  718. * @...: extra parameters for the message display
  719. *
  720. * Display and format an validity error messages, gives file,
  721. * line, position and extra parameters.
  722. */
  723. void XMLCDECL
  724. xmlParserValidityError(void *ctx, const char *msg, ...)
  725. {
  726. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  727. xmlParserInputPtr input = NULL;
  728. char * str;
  729. int len = xmlStrlen((const xmlChar *) msg);
  730. static int had_info = 0;
  731. if ((len > 1) && (msg[len - 2] != ':')) {
  732. if (ctxt != NULL) {
  733. input = ctxt->input;
  734. if ((input->filename == NULL) && (ctxt->inputNr > 1))
  735. input = ctxt->inputTab[ctxt->inputNr - 2];
  736. if (had_info == 0) {
  737. xmlParserPrintFileInfo(input);
  738. }
  739. }
  740. xmlGenericError(xmlGenericErrorContext, "validity error: ");
  741. had_info = 0;
  742. } else {
  743. had_info = 1;
  744. }
  745. XML_GET_VAR_STR(msg, str);
  746. xmlGenericError(xmlGenericErrorContext, "%s", str);
  747. if (str != NULL)
  748. xmlFree(str);
  749. if ((ctxt != NULL) && (input != NULL)) {
  750. xmlParserPrintFileContext(input);
  751. }
  752. }
  753. /**
  754. * xmlParserValidityWarning:
  755. * @ctx: an XML parser context
  756. * @msg: the message to display/transmit
  757. * @...: extra parameters for the message display
  758. *
  759. * Display and format a validity warning messages, gives file, line,
  760. * position and extra parameters.
  761. */
  762. void XMLCDECL
  763. xmlParserValidityWarning(void *ctx, const char *msg, ...)
  764. {
  765. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  766. xmlParserInputPtr input = NULL;
  767. char * str;
  768. int len = xmlStrlen((const xmlChar *) msg);
  769. if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
  770. input = ctxt->input;
  771. if ((input->filename == NULL) && (ctxt->inputNr > 1))
  772. input = ctxt->inputTab[ctxt->inputNr - 2];
  773. xmlParserPrintFileInfo(input);
  774. }
  775. xmlGenericError(xmlGenericErrorContext, "validity warning: ");
  776. XML_GET_VAR_STR(msg, str);
  777. xmlGenericError(xmlGenericErrorContext, "%s", str);
  778. if (str != NULL)
  779. xmlFree(str);
  780. if (ctxt != NULL) {
  781. xmlParserPrintFileContext(input);
  782. }
  783. }
  784. /************************************************************************
  785. * *
  786. * Extended Error Handling *
  787. * *
  788. ************************************************************************/
  789. /**
  790. * xmlGetLastError:
  791. *
  792. * Get the last global error registered. This is per thread if compiled
  793. * with thread support.
  794. *
  795. * Returns NULL if no error occured or a pointer to the error
  796. */
  797. xmlErrorPtr
  798. xmlGetLastError(void)
  799. {
  800. if (xmlLastError.code == XML_ERR_OK)
  801. return (NULL);
  802. return (&xmlLastError);
  803. }
  804. /**
  805. * xmlResetError:
  806. * @err: pointer to the error.
  807. *
  808. * Cleanup the error.
  809. */
  810. void
  811. xmlResetError(xmlErrorPtr err)
  812. {
  813. if (err == NULL)
  814. return;
  815. if (err->code == XML_ERR_OK)
  816. return;
  817. if (err->message != NULL)
  818. xmlFree(err->message);
  819. if (err->file != NULL)
  820. xmlFree(err->file);
  821. if (err->str1 != NULL)
  822. xmlFree(err->str1);
  823. if (err->str2 != NULL)
  824. xmlFree(err->str2);
  825. if (err->str3 != NULL)
  826. xmlFree(err->str3);
  827. memset(err, 0, sizeof(xmlError));
  828. err->code = XML_ERR_OK;
  829. }
  830. /**
  831. * xmlResetLastError:
  832. *
  833. * Cleanup the last global error registered. For parsing error
  834. * this does not change the well-formedness result.
  835. */
  836. void
  837. xmlResetLastError(void)
  838. {
  839. if (xmlLastError.code == XML_ERR_OK)
  840. return;
  841. xmlResetError(&xmlLastError);
  842. }
  843. /**
  844. * xmlCtxtGetLastError:
  845. * @ctx: an XML parser context
  846. *
  847. * Get the last parsing error registered.
  848. *
  849. * Returns NULL if no error occured or a pointer to the error
  850. */
  851. xmlErrorPtr
  852. xmlCtxtGetLastError(void *ctx)
  853. {
  854. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  855. if (ctxt == NULL)
  856. return (NULL);
  857. if (ctxt->lastError.code == XML_ERR_OK)
  858. return (NULL);
  859. return (&ctxt->lastError);
  860. }
  861. /**
  862. * xmlCtxtResetLastError:
  863. * @ctx: an XML parser context
  864. *
  865. * Cleanup the last global error registered. For parsing error
  866. * this does not change the well-formedness result.
  867. */
  868. void
  869. xmlCtxtResetLastError(void *ctx)
  870. {
  871. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  872. if (ctxt == NULL)
  873. return;
  874. ctxt->errNo = XML_ERR_OK;
  875. if (ctxt->lastError.code == XML_ERR_OK)
  876. return;
  877. xmlResetError(&ctxt->lastError);
  878. }
  879. /**
  880. * xmlCopyError:
  881. * @from: a source error
  882. * @to: a target error
  883. *
  884. * Save the original error to the new place.
  885. *
  886. * Returns 0 in case of success and -1 in case of error.
  887. */
  888. int
  889. xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
  890. char *message, *file, *str1, *str2, *str3;
  891. if ((from == NULL) || (to == NULL))
  892. return(-1);
  893. message = (char *) xmlStrdup((xmlChar *) from->message);
  894. file = (char *) xmlStrdup ((xmlChar *) from->file);
  895. str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
  896. str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
  897. str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
  898. if (to->message != NULL)
  899. xmlFree(to->message);
  900. if (to->file != NULL)
  901. xmlFree(to->file);
  902. if (to->str1 != NULL)
  903. xmlFree(to->str1);
  904. if (to->str2 != NULL)
  905. xmlFree(to->str2);
  906. if (to->str3 != NULL)
  907. xmlFree(to->str3);
  908. to->domain = from->domain;
  909. to->code = from->code;
  910. to->level = from->level;
  911. to->line = from->line;
  912. to->node = from->node;
  913. to->int1 = from->int1;
  914. to->int2 = from->int2;
  915. to->node = from->node;
  916. to->ctxt = from->ctxt;
  917. to->message = message;
  918. to->file = file;
  919. to->str1 = str1;
  920. to->str2 = str2;
  921. to->str3 = str3;
  922. return 0;
  923. }
  924. #define bottom_error
  925. #include "elfgcchack.h"