error.c 27 KB

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