error.c 27 KB

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