PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/libxml2-2.7.8/error.c

https://bitbucket.org/ArminW/3p-libxml
C | 989 lines | 676 code | 70 blank | 243 comment | 347 complexity | 39636a40d571cc5f07aa05a99cf25ee5 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) && (domain == XML_FROM_PARSER))
  272. channel(data, "Entity: line %d: ", line);
  273. }
  274. if (name != NULL) {
  275. channel(data, "element %s: ", name);
  276. }
  277. switch (domain) {
  278. case XML_FROM_PARSER:
  279. channel(data, "parser ");
  280. break;
  281. case XML_FROM_NAMESPACE:
  282. channel(data, "namespace ");
  283. break;
  284. case XML_FROM_DTD:
  285. case XML_FROM_VALID:
  286. channel(data, "validity ");
  287. break;
  288. case XML_FROM_HTML:
  289. channel(data, "HTML parser ");
  290. break;
  291. case XML_FROM_MEMORY:
  292. channel(data, "memory ");
  293. break;
  294. case XML_FROM_OUTPUT:
  295. channel(data, "output ");
  296. break;
  297. case XML_FROM_IO:
  298. channel(data, "I/O ");
  299. break;
  300. case XML_FROM_XINCLUDE:
  301. channel(data, "XInclude ");
  302. break;
  303. case XML_FROM_XPATH:
  304. channel(data, "XPath ");
  305. break;
  306. case XML_FROM_XPOINTER:
  307. channel(data, "parser ");
  308. break;
  309. case XML_FROM_REGEXP:
  310. channel(data, "regexp ");
  311. break;
  312. case XML_FROM_MODULE:
  313. channel(data, "module ");
  314. break;
  315. case XML_FROM_SCHEMASV:
  316. channel(data, "Schemas validity ");
  317. break;
  318. case XML_FROM_SCHEMASP:
  319. channel(data, "Schemas parser ");
  320. break;
  321. case XML_FROM_RELAXNGP:
  322. channel(data, "Relax-NG parser ");
  323. break;
  324. case XML_FROM_RELAXNGV:
  325. channel(data, "Relax-NG validity ");
  326. break;
  327. case XML_FROM_CATALOG:
  328. channel(data, "Catalog ");
  329. break;
  330. case XML_FROM_C14N:
  331. channel(data, "C14N ");
  332. break;
  333. case XML_FROM_XSLT:
  334. channel(data, "XSLT ");
  335. break;
  336. case XML_FROM_I18N:
  337. channel(data, "encoding ");
  338. break;
  339. default:
  340. break;
  341. }
  342. switch (level) {
  343. case XML_ERR_NONE:
  344. channel(data, ": ");
  345. break;
  346. case XML_ERR_WARNING:
  347. channel(data, "warning : ");
  348. break;
  349. case XML_ERR_ERROR:
  350. channel(data, "error : ");
  351. break;
  352. case XML_ERR_FATAL:
  353. channel(data, "error : ");
  354. break;
  355. }
  356. if (str != NULL) {
  357. int len;
  358. len = xmlStrlen((const xmlChar *)str);
  359. if ((len > 0) && (str[len - 1] != '\n'))
  360. channel(data, "%s\n", str);
  361. else
  362. channel(data, "%s", str);
  363. } else {
  364. channel(data, "%s\n", "out of memory error");
  365. }
  366. if (ctxt != NULL) {
  367. xmlParserPrintFileContextInternal(input, channel, data);
  368. if (cur != NULL) {
  369. if (cur->filename)
  370. channel(data, "%s:%d: \n", cur->filename, cur->line);
  371. else if ((line != 0) && (domain == XML_FROM_PARSER))
  372. channel(data, "Entity: line %d: \n", cur->line);
  373. xmlParserPrintFileContextInternal(cur, channel, data);
  374. }
  375. }
  376. if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
  377. (err->int1 < 100) &&
  378. (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
  379. xmlChar buf[150];
  380. int i;
  381. channel(data, "%s\n", err->str1);
  382. for (i=0;i < err->int1;i++)
  383. buf[i] = ' ';
  384. buf[i++] = '^';
  385. buf[i] = 0;
  386. channel(data, "%s\n", buf);
  387. }
  388. }
  389. /**
  390. * __xmlRaiseError:
  391. * @schannel: the structured callback channel
  392. * @channel: the old callback channel
  393. * @data: the callback data
  394. * @ctx: the parser context or NULL
  395. * @ctx: the parser context or NULL
  396. * @domain: the domain for the error
  397. * @code: the code for the error
  398. * @level: the xmlErrorLevel for the error
  399. * @file: the file source of the error (or NULL)
  400. * @line: the line of the error or 0 if N/A
  401. * @str1: extra string info
  402. * @str2: extra string info
  403. * @str3: extra string info
  404. * @int1: extra int info
  405. * @col: column number of the error or 0 if N/A
  406. * @msg: the message to display/transmit
  407. * @...: extra parameters for the message display
  408. *
  409. * Update the appropriate global or contextual error structure,
  410. * then forward the error message down the parser or generic
  411. * error callback handler
  412. */
  413. void XMLCDECL
  414. __xmlRaiseError(xmlStructuredErrorFunc schannel,
  415. xmlGenericErrorFunc channel, void *data, void *ctx,
  416. void *nod, int domain, int code, xmlErrorLevel level,
  417. const char *file, int line, const char *str1,
  418. const char *str2, const char *str3, int int1, int col,
  419. const char *msg, ...)
  420. {
  421. xmlParserCtxtPtr ctxt = NULL;
  422. xmlNodePtr node = (xmlNodePtr) nod;
  423. char *str = NULL;
  424. xmlParserInputPtr input = NULL;
  425. xmlErrorPtr to = &xmlLastError;
  426. xmlNodePtr baseptr = NULL;
  427. if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
  428. return;
  429. if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
  430. (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
  431. (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
  432. ctxt = (xmlParserCtxtPtr) ctx;
  433. if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
  434. (ctxt->sax->initialized == XML_SAX2_MAGIC))
  435. schannel = ctxt->sax->serror;
  436. }
  437. /*
  438. * Check if structured error handler set
  439. */
  440. if (schannel == NULL) {
  441. schannel = xmlStructuredError;
  442. /*
  443. * if user has defined handler, change data ptr to user's choice
  444. */
  445. if (schannel != NULL)
  446. data = xmlStructuredErrorContext;
  447. }
  448. if ((domain == XML_FROM_VALID) &&
  449. ((channel == xmlParserValidityError) ||
  450. (channel == xmlParserValidityWarning))) {
  451. ctxt = (xmlParserCtxtPtr) ctx;
  452. if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
  453. (ctxt->sax->initialized == XML_SAX2_MAGIC))
  454. schannel = ctxt->sax->serror;
  455. }
  456. if (code == XML_ERR_OK)
  457. return;
  458. /*
  459. * Formatting the message
  460. */
  461. if (msg == NULL) {
  462. str = (char *) xmlStrdup(BAD_CAST "No error message provided");
  463. } else {
  464. XML_GET_VAR_STR(msg, str);
  465. }
  466. /*
  467. * specific processing if a parser context is provided
  468. */
  469. if (ctxt != NULL) {
  470. if (file == NULL) {
  471. input = ctxt->input;
  472. if ((input != NULL) && (input->filename == NULL) &&
  473. (ctxt->inputNr > 1)) {
  474. input = ctxt->inputTab[ctxt->inputNr - 2];
  475. }
  476. if (input != NULL) {
  477. file = input->filename;
  478. line = input->line;
  479. col = input->col;
  480. }
  481. }
  482. to = &ctxt->lastError;
  483. } else if ((node != NULL) && (file == NULL)) {
  484. int i;
  485. if ((node->doc != NULL) && (node->doc->URL != NULL)) {
  486. baseptr = node;
  487. /* file = (const char *) node->doc->URL; */
  488. }
  489. for (i = 0;
  490. ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
  491. i++)
  492. node = node->parent;
  493. if ((baseptr == NULL) && (node != NULL) &&
  494. (node->doc != NULL) && (node->doc->URL != NULL))
  495. baseptr = node;
  496. if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
  497. line = node->line;
  498. }
  499. /*
  500. * Save the information about the error
  501. */
  502. xmlResetError(to);
  503. to->domain = domain;
  504. to->code = code;
  505. to->message = str;
  506. to->level = level;
  507. if (file != NULL)
  508. to->file = (char *) xmlStrdup((const xmlChar *) file);
  509. else if (baseptr != NULL) {
  510. #ifdef LIBXML_XINCLUDE_ENABLED
  511. /*
  512. * We check if the error is within an XInclude section and,
  513. * if so, attempt to print out the href of the XInclude instead
  514. * of the usual "base" (doc->URL) for the node (bug 152623).
  515. */
  516. xmlNodePtr prev = baseptr;
  517. int inclcount = 0;
  518. while (prev != NULL) {
  519. if (prev->prev == NULL)
  520. prev = prev->parent;
  521. else {
  522. prev = prev->prev;
  523. if (prev->type == XML_XINCLUDE_START) {
  524. if (--inclcount < 0)
  525. break;
  526. } else if (prev->type == XML_XINCLUDE_END)
  527. inclcount++;
  528. }
  529. }
  530. if (prev != NULL) {
  531. if (prev->type == XML_XINCLUDE_START) {
  532. prev->type = XML_ELEMENT_NODE;
  533. to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
  534. prev->type = XML_XINCLUDE_START;
  535. } else {
  536. to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
  537. }
  538. } else
  539. #endif
  540. to->file = (char *) xmlStrdup(baseptr->doc->URL);
  541. if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
  542. to->file = (char *) xmlStrdup(node->doc->URL);
  543. }
  544. }
  545. to->line = line;
  546. if (str1 != NULL)
  547. to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
  548. if (str2 != NULL)
  549. to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
  550. if (str3 != NULL)
  551. to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
  552. to->int1 = int1;
  553. to->int2 = col;
  554. to->node = node;
  555. to->ctxt = ctx;
  556. if (to != &xmlLastError)
  557. xmlCopyError(to,&xmlLastError);
  558. /*
  559. * Find the callback channel if channel param is NULL
  560. */
  561. if ((ctxt != NULL) && (channel == NULL) &&
  562. (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
  563. if (level == XML_ERR_WARNING)
  564. channel = ctxt->sax->warning;
  565. else
  566. channel = ctxt->sax->error;
  567. data = ctxt->userData;
  568. } else if (channel == NULL) {
  569. if ((schannel == NULL) && (xmlStructuredError != NULL)) {
  570. schannel = xmlStructuredError;
  571. data = xmlStructuredErrorContext;
  572. } else {
  573. channel = xmlGenericError;
  574. if (!data) {
  575. data = xmlGenericErrorContext;
  576. }
  577. }
  578. }
  579. if (schannel != NULL) {
  580. schannel(data, to);
  581. return;
  582. }
  583. if (channel == NULL)
  584. return;
  585. if ((channel == xmlParserError) ||
  586. (channel == xmlParserWarning) ||
  587. (channel == xmlParserValidityError) ||
  588. (channel == xmlParserValidityWarning))
  589. xmlReportError(to, ctxt, str, NULL, NULL);
  590. else if ((channel == (xmlGenericErrorFunc) fprintf) ||
  591. (channel == xmlGenericErrorDefaultFunc))
  592. xmlReportError(to, ctxt, str, channel, data);
  593. else
  594. channel(data, "%s", str);
  595. }
  596. /**
  597. * __xmlSimpleError:
  598. * @domain: where the error comes from
  599. * @code: the error code
  600. * @node: the context node
  601. * @extra: extra informations
  602. *
  603. * Handle an out of memory condition
  604. */
  605. void
  606. __xmlSimpleError(int domain, int code, xmlNodePtr node,
  607. const char *msg, const char *extra)
  608. {
  609. if (code == XML_ERR_NO_MEMORY) {
  610. if (extra)
  611. __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
  612. XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
  613. NULL, NULL, 0, 0,
  614. "Memory allocation failed : %s\n", extra);
  615. else
  616. __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
  617. XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
  618. NULL, NULL, 0, 0, "Memory allocation failed\n");
  619. } else {
  620. __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
  621. code, XML_ERR_ERROR, NULL, 0, extra,
  622. NULL, NULL, 0, 0, msg, extra);
  623. }
  624. }
  625. /**
  626. * xmlParserError:
  627. * @ctx: an XML parser context
  628. * @msg: the message to display/transmit
  629. * @...: extra parameters for the message display
  630. *
  631. * Display and format an error messages, gives file, line, position and
  632. * extra parameters.
  633. */
  634. void XMLCDECL
  635. xmlParserError(void *ctx, const char *msg, ...)
  636. {
  637. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  638. xmlParserInputPtr input = NULL;
  639. xmlParserInputPtr cur = NULL;
  640. char * str;
  641. if (ctxt != NULL) {
  642. input = ctxt->input;
  643. if ((input != NULL) && (input->filename == NULL) &&
  644. (ctxt->inputNr > 1)) {
  645. cur = input;
  646. input = ctxt->inputTab[ctxt->inputNr - 2];
  647. }
  648. xmlParserPrintFileInfo(input);
  649. }
  650. xmlGenericError(xmlGenericErrorContext, "error: ");
  651. XML_GET_VAR_STR(msg, str);
  652. xmlGenericError(xmlGenericErrorContext, "%s", str);
  653. if (str != NULL)
  654. xmlFree(str);
  655. if (ctxt != NULL) {
  656. xmlParserPrintFileContext(input);
  657. if (cur != NULL) {
  658. xmlParserPrintFileInfo(cur);
  659. xmlGenericError(xmlGenericErrorContext, "\n");
  660. xmlParserPrintFileContext(cur);
  661. }
  662. }
  663. }
  664. /**
  665. * xmlParserWarning:
  666. * @ctx: an XML parser context
  667. * @msg: the message to display/transmit
  668. * @...: extra parameters for the message display
  669. *
  670. * Display and format a warning messages, gives file, line, position and
  671. * extra parameters.
  672. */
  673. void XMLCDECL
  674. xmlParserWarning(void *ctx, const char *msg, ...)
  675. {
  676. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  677. xmlParserInputPtr input = NULL;
  678. xmlParserInputPtr cur = NULL;
  679. char * str;
  680. if (ctxt != NULL) {
  681. input = ctxt->input;
  682. if ((input != NULL) && (input->filename == NULL) &&
  683. (ctxt->inputNr > 1)) {
  684. cur = input;
  685. input = ctxt->inputTab[ctxt->inputNr - 2];
  686. }
  687. xmlParserPrintFileInfo(input);
  688. }
  689. xmlGenericError(xmlGenericErrorContext, "warning: ");
  690. XML_GET_VAR_STR(msg, str);
  691. xmlGenericError(xmlGenericErrorContext, "%s", str);
  692. if (str != NULL)
  693. xmlFree(str);
  694. if (ctxt != NULL) {
  695. xmlParserPrintFileContext(input);
  696. if (cur != NULL) {
  697. xmlParserPrintFileInfo(cur);
  698. xmlGenericError(xmlGenericErrorContext, "\n");
  699. xmlParserPrintFileContext(cur);
  700. }
  701. }
  702. }
  703. /************************************************************************
  704. * *
  705. * Handling of validation errors *
  706. * *
  707. ************************************************************************/
  708. /**
  709. * xmlParserValidityError:
  710. * @ctx: an XML parser context
  711. * @msg: the message to display/transmit
  712. * @...: extra parameters for the message display
  713. *
  714. * Display and format an validity error messages, gives file,
  715. * line, position and extra parameters.
  716. */
  717. void XMLCDECL
  718. xmlParserValidityError(void *ctx, const char *msg, ...)
  719. {
  720. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  721. xmlParserInputPtr input = NULL;
  722. char * str;
  723. int len = xmlStrlen((const xmlChar *) msg);
  724. static int had_info = 0;
  725. if ((len > 1) && (msg[len - 2] != ':')) {
  726. if (ctxt != NULL) {
  727. input = ctxt->input;
  728. if ((input->filename == NULL) && (ctxt->inputNr > 1))
  729. input = ctxt->inputTab[ctxt->inputNr - 2];
  730. if (had_info == 0) {
  731. xmlParserPrintFileInfo(input);
  732. }
  733. }
  734. xmlGenericError(xmlGenericErrorContext, "validity error: ");
  735. had_info = 0;
  736. } else {
  737. had_info = 1;
  738. }
  739. XML_GET_VAR_STR(msg, str);
  740. xmlGenericError(xmlGenericErrorContext, "%s", str);
  741. if (str != NULL)
  742. xmlFree(str);
  743. if ((ctxt != NULL) && (input != NULL)) {
  744. xmlParserPrintFileContext(input);
  745. }
  746. }
  747. /**
  748. * xmlParserValidityWarning:
  749. * @ctx: an XML parser context
  750. * @msg: the message to display/transmit
  751. * @...: extra parameters for the message display
  752. *
  753. * Display and format a validity warning messages, gives file, line,
  754. * position and extra parameters.
  755. */
  756. void XMLCDECL
  757. xmlParserValidityWarning(void *ctx, const char *msg, ...)
  758. {
  759. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  760. xmlParserInputPtr input = NULL;
  761. char * str;
  762. int len = xmlStrlen((const xmlChar *) msg);
  763. if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
  764. input = ctxt->input;
  765. if ((input->filename == NULL) && (ctxt->inputNr > 1))
  766. input = ctxt->inputTab[ctxt->inputNr - 2];
  767. xmlParserPrintFileInfo(input);
  768. }
  769. xmlGenericError(xmlGenericErrorContext, "validity warning: ");
  770. XML_GET_VAR_STR(msg, str);
  771. xmlGenericError(xmlGenericErrorContext, "%s", str);
  772. if (str != NULL)
  773. xmlFree(str);
  774. if (ctxt != NULL) {
  775. xmlParserPrintFileContext(input);
  776. }
  777. }
  778. /************************************************************************
  779. * *
  780. * Extended Error Handling *
  781. * *
  782. ************************************************************************/
  783. /**
  784. * xmlGetLastError:
  785. *
  786. * Get the last global error registered. This is per thread if compiled
  787. * with thread support.
  788. *
  789. * Returns NULL if no error occured or a pointer to the error
  790. */
  791. xmlErrorPtr
  792. xmlGetLastError(void)
  793. {
  794. if (xmlLastError.code == XML_ERR_OK)
  795. return (NULL);
  796. return (&xmlLastError);
  797. }
  798. /**
  799. * xmlResetError:
  800. * @err: pointer to the error.
  801. *
  802. * Cleanup the error.
  803. */
  804. void
  805. xmlResetError(xmlErrorPtr err)
  806. {
  807. if (err == NULL)
  808. return;
  809. if (err->code == XML_ERR_OK)
  810. return;
  811. if (err->message != NULL)
  812. xmlFree(err->message);
  813. if (err->file != NULL)
  814. xmlFree(err->file);
  815. if (err->str1 != NULL)
  816. xmlFree(err->str1);
  817. if (err->str2 != NULL)
  818. xmlFree(err->str2);
  819. if (err->str3 != NULL)
  820. xmlFree(err->str3);
  821. memset(err, 0, sizeof(xmlError));
  822. err->code = XML_ERR_OK;
  823. }
  824. /**
  825. * xmlResetLastError:
  826. *
  827. * Cleanup the last global error registered. For parsing error
  828. * this does not change the well-formedness result.
  829. */
  830. void
  831. xmlResetLastError(void)
  832. {
  833. if (xmlLastError.code == XML_ERR_OK)
  834. return;
  835. xmlResetError(&xmlLastError);
  836. }
  837. /**
  838. * xmlCtxtGetLastError:
  839. * @ctx: an XML parser context
  840. *
  841. * Get the last parsing error registered.
  842. *
  843. * Returns NULL if no error occured or a pointer to the error
  844. */
  845. xmlErrorPtr
  846. xmlCtxtGetLastError(void *ctx)
  847. {
  848. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  849. if (ctxt == NULL)
  850. return (NULL);
  851. if (ctxt->lastError.code == XML_ERR_OK)
  852. return (NULL);
  853. return (&ctxt->lastError);
  854. }
  855. /**
  856. * xmlCtxtResetLastError:
  857. * @ctx: an XML parser context
  858. *
  859. * Cleanup the last global error registered. For parsing error
  860. * this does not change the well-formedness result.
  861. */
  862. void
  863. xmlCtxtResetLastError(void *ctx)
  864. {
  865. xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  866. if (ctxt == NULL)
  867. return;
  868. ctxt->errNo = XML_ERR_OK;
  869. if (ctxt->lastError.code == XML_ERR_OK)
  870. return;
  871. xmlResetError(&ctxt->lastError);
  872. }
  873. /**
  874. * xmlCopyError:
  875. * @from: a source error
  876. * @to: a target error
  877. *
  878. * Save the original error to the new place.
  879. *
  880. * Returns 0 in case of success and -1 in case of error.
  881. */
  882. int
  883. xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
  884. char *message, *file, *str1, *str2, *str3;
  885. if ((from == NULL) || (to == NULL))
  886. return(-1);
  887. message = (char *) xmlStrdup((xmlChar *) from->message);
  888. file = (char *) xmlStrdup ((xmlChar *) from->file);
  889. str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
  890. str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
  891. str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
  892. if (to->message != NULL)
  893. xmlFree(to->message);
  894. if (to->file != NULL)
  895. xmlFree(to->file);
  896. if (to->str1 != NULL)
  897. xmlFree(to->str1);
  898. if (to->str2 != NULL)
  899. xmlFree(to->str2);
  900. if (to->str3 != NULL)
  901. xmlFree(to->str3);
  902. to->domain = from->domain;
  903. to->code = from->code;
  904. to->level = from->level;
  905. to->line = from->line;
  906. to->node = from->node;
  907. to->int1 = from->int1;
  908. to->int2 = from->int2;
  909. to->node = from->node;
  910. to->ctxt = from->ctxt;
  911. to->message = message;
  912. to->file = file;
  913. to->str1 = str1;
  914. to->str2 = str2;
  915. to->str3 = str3;
  916. return 0;
  917. }
  918. #define bottom_error
  919. #include "elfgcchack.h"