blob: 38d073c1c12951c423b1c21c237399e508b51486 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * error.c: module displaying/handling XML parser errors
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00006 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00007 */
8
Daniel Veillard34ce8be2002-03-18 19:37:11 +00009#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000010#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000011
Daniel Veillard2b8c4a12003-10-02 22:28:19 +000012#include <string.h>
Owen Taylor3473f882001-02-23 17:55:21 +000013#include <stdarg.h>
14#include <libxml/parser.h>
15#include <libxml/xmlerror.h>
Daniel Veillarde356c282001-03-10 12:32:04 +000016#include <libxml/xmlmemory.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000017#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000018
Daniel Veillard635ef722001-10-29 11:48:19 +000019void xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED,
20 const char *msg,
21 ...);
22
Daniel Veillard1c43dbf2001-06-05 17:12:52 +000023#define XML_GET_VAR_STR(msg, str) { \
24 int size; \
25 int chars; \
26 char *larger; \
27 va_list ap; \
28 \
29 str = (char *) xmlMalloc(150); \
Daniel Veillard2b8c4a12003-10-02 22:28:19 +000030 if (str != NULL) { \
Daniel Veillard1c43dbf2001-06-05 17:12:52 +000031 \
32 size = 150; \
33 \
34 while (1) { \
35 va_start(ap, msg); \
36 chars = vsnprintf(str, size, msg, ap); \
37 va_end(ap); \
38 if ((chars > -1) && (chars < size)) \
39 break; \
40 if (chars > -1) \
41 size += chars + 1; \
42 else \
43 size += 100; \
44 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
Daniel Veillard2b8c4a12003-10-02 22:28:19 +000045 break; \
Daniel Veillard1c43dbf2001-06-05 17:12:52 +000046 } \
47 str = larger; \
Daniel Veillard2b8c4a12003-10-02 22:28:19 +000048 }} \
Daniel Veillard1c43dbf2001-06-05 17:12:52 +000049}
Bjorn Reese570ff082001-06-05 12:45:55 +000050
Owen Taylor3473f882001-02-23 17:55:21 +000051/************************************************************************
52 * *
53 * Handling of out of context errors *
54 * *
55 ************************************************************************/
56
57/**
58 * xmlGenericErrorDefaultFunc:
59 * @ctx: an error context
60 * @msg: the message to display/transmit
61 * @...: extra parameters for the message display
62 *
63 * Default handler for out of context error messages.
64 */
Daniel Veillard635ef722001-10-29 11:48:19 +000065void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000066xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000067 va_list args;
68
69 if (xmlGenericErrorContext == NULL)
70 xmlGenericErrorContext = (void *) stderr;
71
72 va_start(args, msg);
73 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
74 va_end(args);
75}
76
Daniel Veillard9d06d302002-01-22 18:15:52 +000077/**
78 * initGenericErrorDefaultFunc:
79 * @handler: the handler
80 *
81 * Set or reset (if NULL) the default handler for generic errors
Daniel Veillard7424eb62003-01-24 14:14:52 +000082 * to the builtin error function.
Daniel Veillard9d06d302002-01-22 18:15:52 +000083 */
Daniel Veillardd0463562001-10-13 09:15:48 +000084void
Daniel Veillarddb5850a2002-01-18 11:49:26 +000085initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
Daniel Veillardd0463562001-10-13 09:15:48 +000086{
Daniel Veillarddb5850a2002-01-18 11:49:26 +000087 if (handler == NULL)
88 xmlGenericError = xmlGenericErrorDefaultFunc;
89 else
90 (*handler) = xmlGenericErrorDefaultFunc;
Daniel Veillardd0463562001-10-13 09:15:48 +000091}
Owen Taylor3473f882001-02-23 17:55:21 +000092
93/**
94 * xmlSetGenericErrorFunc:
95 * @ctx: the new error handling context
96 * @handler: the new handler function
97 *
98 * Function to reset the handler and the error context for out of
99 * context error messages.
100 * This simply means that @handler will be called for subsequent
101 * error messages while not parsing nor validating. And @ctx will
102 * be passed as first argument to @handler
103 * One can simply force messages to be emitted to another FILE * than
104 * stderr by setting @ctx to this file handle and @handler to NULL.
105 */
106void
107xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
108 xmlGenericErrorContext = ctx;
109 if (handler != NULL)
110 xmlGenericError = handler;
111 else
112 xmlGenericError = xmlGenericErrorDefaultFunc;
113}
114
115/************************************************************************
116 * *
117 * Handling of parsing errors *
118 * *
119 ************************************************************************/
120
121/**
122 * xmlParserPrintFileInfo:
123 * @input: an xmlParserInputPtr input
124 *
125 * Displays the associated file and line informations for the current input
126 */
127
128void
129xmlParserPrintFileInfo(xmlParserInputPtr input) {
130 if (input != NULL) {
131 if (input->filename)
132 xmlGenericError(xmlGenericErrorContext,
133 "%s:%d: ", input->filename,
134 input->line);
135 else
136 xmlGenericError(xmlGenericErrorContext,
137 "Entity: line %d: ", input->line);
138 }
139}
140
141/**
142 * xmlParserPrintFileContext:
143 * @input: an xmlParserInputPtr input
144 *
145 * Displays current context within the input content for error tracking
146 */
147
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000148static void
149xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
150 xmlGenericErrorFunc channel, void *data ) {
Daniel Veillard561b7f82002-03-20 21:55:57 +0000151 const xmlChar *cur, *base;
William M. Brackc1939562003-08-05 15:52:22 +0000152 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
William M. Brack3dd57f72003-05-13 02:06:18 +0000153 xmlChar content[81]; /* space for 80 chars + line terminator */
Daniel Veillard2be30642001-03-27 00:32:28 +0000154 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000155
Daniel Veillard561b7f82002-03-20 21:55:57 +0000156 if (input == NULL) return;
Owen Taylor3473f882001-02-23 17:55:21 +0000157 cur = input->cur;
158 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000159 /* skip backwards over any end-of-lines */
William M. Brackc1939562003-08-05 15:52:22 +0000160 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
Daniel Veillard561b7f82002-03-20 21:55:57 +0000161 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000162 }
163 n = 0;
William M. Brack3dd57f72003-05-13 02:06:18 +0000164 /* search backwards for beginning-of-line (to max buff size) */
William M. Brackc1939562003-08-05 15:52:22 +0000165 while ((n++ < (sizeof(content)-1)) && (cur > base) &&
166 (*(cur) != '\n') && (*(cur) != '\r'))
Owen Taylor3473f882001-02-23 17:55:21 +0000167 cur--;
William M. Brackc1939562003-08-05 15:52:22 +0000168 if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
William M. Brack3dd57f72003-05-13 02:06:18 +0000169 /* calculate the error position in terms of the current position */
170 col = input->cur - cur;
171 /* search forward for end-of-line (to max buff size) */
Owen Taylor3473f882001-02-23 17:55:21 +0000172 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000173 ctnt = content;
William M. Brack3dd57f72003-05-13 02:06:18 +0000174 /* copy selected text to our buffer */
William M. Brackc1939562003-08-05 15:52:22 +0000175 while ((*cur != 0) && (*(cur) != '\n') &&
176 (*(cur) != '\r') && (n < sizeof(content)-1)) {
Daniel Veillard561b7f82002-03-20 21:55:57 +0000177 *ctnt++ = *cur++;
178 n++;
Owen Taylor3473f882001-02-23 17:55:21 +0000179 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000180 *ctnt = 0;
William M. Brack3dd57f72003-05-13 02:06:18 +0000181 /* print out the selected text */
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000182 channel(data ,"%s\n", content);
Daniel Veillard2be30642001-03-27 00:32:28 +0000183 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000184 n = 0;
Daniel Veillard7533cc82001-04-24 15:52:00 +0000185 ctnt = content;
William M. Brack3dd57f72003-05-13 02:06:18 +0000186 /* (leave buffer space for pointer + line terminator) */
187 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
William M. Brackc1939562003-08-05 15:52:22 +0000188 if (*(ctnt) != '\t')
189 *(ctnt) = ' ';
William M. Brack69848302003-09-22 00:24:51 +0000190 ctnt++;
Owen Taylor3473f882001-02-23 17:55:21 +0000191 }
William M. Brack3dd57f72003-05-13 02:06:18 +0000192 *ctnt++ = '^';
193 *ctnt = 0;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000194 channel(data ,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000195}
196
Daniel Veillard561b7f82002-03-20 21:55:57 +0000197/**
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000198 * xmlParserPrintFileContext:
199 * @input: an xmlParserInputPtr input
200 *
201 * Displays current context within the input content for error tracking
Daniel Veillard561b7f82002-03-20 21:55:57 +0000202 */
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000203void
204xmlParserPrintFileContext(xmlParserInputPtr input) {
205 xmlParserPrintFileContextInternal(input, xmlGenericError,
206 xmlGenericErrorContext);
Daniel Veillard561b7f82002-03-20 21:55:57 +0000207}
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000208
209/**
210 * xmlReportError:
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000211 * @err: the error
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000212 * @ctx: the parser context or NULL
213 * @str: the formatted error message
214 *
215 * Report an erro with its context, replace the 4 old error/warning
216 * routines.
217 */
218static void
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000219xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str)
220{
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000221 char *file = NULL;
222 int line = 0;
223 int code = -1;
224 int domain;
225 xmlErrorLevel level;
226 xmlGenericErrorFunc channel;
227 xmlParserInputPtr input = NULL;
228 xmlParserInputPtr cur = NULL;
229 void *data;
230
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000231 if (err == NULL)
232 return;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000233
234 channel = xmlGenericError;
235 data = xmlGenericErrorContext;
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000236 file = err->file;
237 line = err->line;
238 code = err->code;
239 domain = err->domain;
240 level = err->level;
241
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000242 if (code == XML_ERR_OK)
243 return;
244
245 /*
246 * Maintain the compatibility with the legacy error handling
247 */
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000248 if (ctxt != NULL) {
249 input = ctxt->input;
250 if ((input != NULL) && (input->filename == NULL) &&
251 (ctxt->inputNr > 1)) {
252 cur = input;
253 input = ctxt->inputTab[ctxt->inputNr - 2];
254 }
255 if (input != NULL) {
256 if (input->filename)
257 channel(data, "%s:%d: ", input->filename, input->line);
258 else
259 channel(data, "Entity: line %d: ", input->line);
260 }
261 } else {
262 if (file != NULL)
263 channel(data, "%s:%d: ", file, line);
264 else
265 channel(data, "Entity: line %d: ", line);
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000266 }
267 if (code == XML_ERR_OK)
268 return;
269 switch (domain) {
270 case XML_FROM_PARSER:
271 channel(data, "parser ");
272 break;
273 case XML_FROM_NAMESPACE:
274 channel(data, "namespace ");
275 break;
276 case XML_FROM_DTD:
277 channel(data, "validity ");
278 break;
279 case XML_FROM_HTML:
280 channel(data, "HTML parser ");
281 break;
282 case XML_FROM_MEMORY:
283 channel(data, "memory ");
284 break;
285 case XML_FROM_OUTPUT:
286 channel(data, "output ");
287 break;
288 case XML_FROM_IO:
289 channel(data, "I/O ");
290 break;
291 case XML_FROM_XINCLUDE:
292 channel(data, "XInclude ");
293 break;
294 case XML_FROM_XPATH:
295 channel(data, "XPath ");
296 break;
297 case XML_FROM_XPOINTER:
298 channel(data, "parser ");
299 break;
300 case XML_FROM_REGEXP:
301 channel(data, "regexp ");
302 break;
303 case XML_FROM_SCHEMAS:
304 channel(data, "Schemas ");
305 break;
306 case XML_FROM_RELAXNG:
307 channel(data, "Relax-NG ");
308 break;
309 case XML_FROM_CATALOG:
310 channel(data, "Catalog ");
311 break;
312 case XML_FROM_C14N:
313 channel(data, "C14N ");
314 break;
315 case XML_FROM_XSLT:
316 channel(data, "XSLT ");
317 break;
318 default:
319 break;
320 }
321 if (code == XML_ERR_OK)
322 return;
323 switch (level) {
324 case XML_ERR_NONE:
325 channel(data, ": ");
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000326 break;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000327 case XML_ERR_WARNING:
328 channel(data, "warning : ");
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000329 break;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000330 case XML_ERR_ERROR:
331 channel(data, "error : ");
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000332 break;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000333 case XML_ERR_FATAL:
334 channel(data, "error : ");
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000335 break;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000336 }
337 if (code == XML_ERR_OK)
338 return;
339 if (str != NULL) {
340 channel(data, "%s", str);
341 } else {
342 channel(data, "%s", "out of memory error");
343 }
344 if (code == XML_ERR_OK)
345 return;
346
347 if (ctxt != NULL) {
348 xmlParserPrintFileContextInternal(input, channel, data);
349 if (cur != NULL) {
350 if (cur->filename)
351 channel(data, "%s:%d: \n", cur->filename, cur->line);
352 else
353 channel(data, "Entity: line %d: \n", cur->line);
354 xmlParserPrintFileContextInternal(cur, channel, data);
355 }
356 }
357}
358
359/**
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000360 * __xmlRaiseError:
361 * @channel: the callback channel
362 * @data: the callback data
363 * @ctx: the parser context or NULL
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000364 * @ctx: the parser context or NULL
365 * @domain: the domain for the error
366 * @code: the code for the error
367 * @level: the xmlErrorLevel for the error
368 * @file: the file source of the error (or NULL)
369 * @line: the line of the error or 0 if N/A
370 * @str1: extra string info
371 * @str2: extra string info
372 * @str3: extra string info
373 * @int1: extra int info
374 * @int2: extra int info
375 * @msg: the message to display/transmit
376 * @...: extra parameters for the message display
377 *
378 * Update teh appropriate global or contextual error structure,
379 * then forward the error message down the parser or generic
380 * error callback handler
381 */
382void
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000383__xmlRaiseError(xmlGenericErrorFunc channel, void *data, void *ctx,
384 void *nod, int domain, int code, xmlErrorLevel level,
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000385 const char *file, int line, const char *str1,
386 const char *str2, const char *str3, int int1, int int2,
387 const char *msg, ...)
388{
389 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000390 xmlNodePtr node = (xmlNodePtr) nod;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000391 char *str = NULL;
392 xmlParserInputPtr input = NULL;
393 xmlErrorPtr to = &xmlLastError;
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000394 xmlChar *base = NULL;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000395
396 if (code == XML_ERR_OK)
397 return;
398 /*
399 * Formatting the message
400 */
401 if (msg == NULL) {
402 str = (char *) xmlStrdup(BAD_CAST "No error message provided");
403 } else {
404 XML_GET_VAR_STR(msg, str);
405 }
406
407 /*
408 * specific processing if a parser context is provided
409 */
410 if (ctxt != NULL) {
411 if (file == NULL) {
412 input = ctxt->input;
413 if ((input != NULL) && (input->filename == NULL) &&
414 (ctxt->inputNr > 1)) {
415 input = ctxt->inputTab[ctxt->inputNr - 2];
416 }
417 if (input != NULL) {
418 file = input->filename;
419 line = input->line;
420 }
421 }
422 to = &ctxt->lastError;
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000423 } else if ((node != NULL) && (file == NULL)) {
424 int i;
425 base = xmlNodeGetBase(NULL, node);
426 for (i = 0;
427 ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
428 i++)
429 node = node->parent;
430 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
431 line = (int) node->content;
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000432 }
433
434 /*
435 * Save the informations about the error
436 */
437 xmlResetError(to);
438 to->domain = domain;
439 to->code = code;
440 to->message = str;
441 to->level = level;
442 if (file != NULL)
443 to->file = (char *) xmlStrdup((const xmlChar *) file);
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000444 else if (base != NULL) {
445 to->file = (char *) base;
446 file = (char *) base;
447 }
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000448 to->line = line;
449 if (str1 != NULL)
450 to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
451 if (str2 != NULL)
452 to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
453 if (str3 != NULL)
454 to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
455 to->int1 = int1;
456 to->int2 = int2;
457
458 /*
459 * Find the callback channel.
460 */
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000461 if ((ctxt != NULL) && (channel == NULL)) {
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000462 if (level == XML_ERR_WARNING)
463 channel = ctxt->sax->warning;
464 else
465 channel = ctxt->sax->error;
466 data = ctxt;
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000467 } else if (channel == NULL) {
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000468 channel = xmlGenericError;
469 data = xmlGenericErrorContext;
470 }
471 if (channel == NULL)
472 return;
473
474 if ((channel == xmlParserError) ||
475 (channel == xmlParserWarning) ||
476 (channel == xmlParserValidityError) ||
477 (channel == xmlParserValidityWarning))
Daniel Veillardbb5abab2003-10-03 22:21:51 +0000478 xmlReportError(to, ctxt, str);
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000479 else
480 channel(data, "%s", str);
481}
Daniel Veillard561b7f82002-03-20 21:55:57 +0000482
Daniel Veillarde356c282001-03-10 12:32:04 +0000483/**
Owen Taylor3473f882001-02-23 17:55:21 +0000484 * xmlParserError:
485 * @ctx: an XML parser context
486 * @msg: the message to display/transmit
487 * @...: extra parameters for the message display
488 *
489 * Display and format an error messages, gives file, line, position and
490 * extra parameters.
491 */
492void
493xmlParserError(void *ctx, const char *msg, ...)
494{
495 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
496 xmlParserInputPtr input = NULL;
497 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000498 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000499
500 if (ctxt != NULL) {
501 input = ctxt->input;
502 if ((input != NULL) && (input->filename == NULL) &&
503 (ctxt->inputNr > 1)) {
504 cur = input;
505 input = ctxt->inputTab[ctxt->inputNr - 2];
506 }
507 xmlParserPrintFileInfo(input);
508 }
509
510 xmlGenericError(xmlGenericErrorContext, "error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000511 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000512 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000513 if (str != NULL)
514 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000515
516 if (ctxt != NULL) {
517 xmlParserPrintFileContext(input);
518 if (cur != NULL) {
519 xmlParserPrintFileInfo(cur);
520 xmlGenericError(xmlGenericErrorContext, "\n");
521 xmlParserPrintFileContext(cur);
522 }
523 }
524}
525
526/**
527 * xmlParserWarning:
528 * @ctx: an XML parser context
529 * @msg: the message to display/transmit
530 * @...: extra parameters for the message display
531 *
532 * Display and format a warning messages, gives file, line, position and
533 * extra parameters.
534 */
535void
536xmlParserWarning(void *ctx, const char *msg, ...)
537{
538 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
539 xmlParserInputPtr input = NULL;
540 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000541 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000542
543 if (ctxt != NULL) {
544 input = ctxt->input;
545 if ((input != NULL) && (input->filename == NULL) &&
546 (ctxt->inputNr > 1)) {
547 cur = input;
548 input = ctxt->inputTab[ctxt->inputNr - 2];
549 }
550 xmlParserPrintFileInfo(input);
551 }
552
553 xmlGenericError(xmlGenericErrorContext, "warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000554 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000555 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000556 if (str != NULL)
557 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000558
559 if (ctxt != NULL) {
560 xmlParserPrintFileContext(input);
561 if (cur != NULL) {
562 xmlParserPrintFileInfo(cur);
563 xmlGenericError(xmlGenericErrorContext, "\n");
564 xmlParserPrintFileContext(cur);
565 }
566 }
567}
568
569/************************************************************************
570 * *
571 * Handling of validation errors *
572 * *
573 ************************************************************************/
574
575/**
576 * xmlParserValidityError:
577 * @ctx: an XML parser context
578 * @msg: the message to display/transmit
579 * @...: extra parameters for the message display
580 *
581 * Display and format an validity error messages, gives file,
582 * line, position and extra parameters.
583 */
584void
585xmlParserValidityError(void *ctx, const char *msg, ...)
586{
587 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
588 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000589 char * str;
Daniel Veillard76575762002-09-05 14:21:15 +0000590 int len = xmlStrlen((const xmlChar *) msg);
591 static int had_info = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000592
Daniel Veillard76575762002-09-05 14:21:15 +0000593 if ((len > 1) && (msg[len - 2] != ':')) {
594 if (ctxt != NULL) {
595 input = ctxt->input;
596 if ((input->filename == NULL) && (ctxt->inputNr > 1))
597 input = ctxt->inputTab[ctxt->inputNr - 2];
598
599 if (had_info == 0) {
600 xmlParserPrintFileInfo(input);
601 }
602 }
603 xmlGenericError(xmlGenericErrorContext, "validity error: ");
Daniel Veillard76575762002-09-05 14:21:15 +0000604 had_info = 0;
605 } else {
606 had_info = 1;
Owen Taylor3473f882001-02-23 17:55:21 +0000607 }
608
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000609 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000610 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000611 if (str != NULL)
612 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000613
Daniel Veillard76575762002-09-05 14:21:15 +0000614 if ((ctxt != NULL) && (input != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000615 xmlParserPrintFileContext(input);
616 }
617}
618
619/**
620 * xmlParserValidityWarning:
621 * @ctx: an XML parser context
622 * @msg: the message to display/transmit
623 * @...: extra parameters for the message display
624 *
625 * Display and format a validity warning messages, gives file, line,
626 * position and extra parameters.
627 */
628void
629xmlParserValidityWarning(void *ctx, const char *msg, ...)
630{
631 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
632 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000633 char * str;
Daniel Veillard76575762002-09-05 14:21:15 +0000634 int len = xmlStrlen((const xmlChar *) msg);
Owen Taylor3473f882001-02-23 17:55:21 +0000635
Daniel Veillard76575762002-09-05 14:21:15 +0000636 if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
Owen Taylor3473f882001-02-23 17:55:21 +0000637 input = ctxt->input;
638 if ((input->filename == NULL) && (ctxt->inputNr > 1))
639 input = ctxt->inputTab[ctxt->inputNr - 2];
640
641 xmlParserPrintFileInfo(input);
642 }
643
644 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000645 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000646 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000647 if (str != NULL)
648 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000649
650 if (ctxt != NULL) {
651 xmlParserPrintFileContext(input);
652 }
653}
654
655
Daniel Veillard2b8c4a12003-10-02 22:28:19 +0000656/************************************************************************
657 * *
658 * Extended Error Handling *
659 * *
660 ************************************************************************/
661
662/**
663 * xmlGetLastError:
664 *
665 * Get the last global error registered. This is per thread if compiled
666 * with thread support.
667 *
668 * Returns NULL if no error occured or a pointer to the error
669 */
670xmlErrorPtr
671xmlGetLastError(void)
672{
673 if (xmlLastError.code == XML_ERR_OK)
674 return (NULL);
675 return (&xmlLastError);
676}
677
678/**
679 * xmlResetError:
680 * @err: pointer to the error.
681 *
682 * Cleanup the error.
683 */
684void
685xmlResetError(xmlErrorPtr err)
686{
687 if (err == NULL)
688 return;
689 if (err->code == XML_ERR_OK)
690 return;
691 if (err->message != NULL)
692 xmlFree(err->message);
693 if (err->file != NULL)
694 xmlFree(err->file);
695 if (err->str1 != NULL)
696 xmlFree(err->str1);
697 if (err->str2 != NULL)
698 xmlFree(err->str2);
699 if (err->str3 != NULL)
700 xmlFree(err->str3);
701 memset(err, 0, sizeof(xmlError));
702 err->code = XML_ERR_OK;
703}
704
705/**
706 * xmlResetLastError:
707 *
708 * Cleanup the last global error registered. For parsing error
709 * this does not change the well-formedness result.
710 */
711void
712xmlResetLastError(void)
713{
714 if (xmlLastError.code == XML_ERR_OK)
715 return;
716 xmlResetError(&xmlLastError);
717}
718
719/**
720 * xmlCtxtGetLastError:
721 * @ctx: an XML parser context
722 *
723 * Get the last parsing error registered.
724 *
725 * Returns NULL if no error occured or a pointer to the error
726 */
727xmlErrorPtr
728xmlCtxtGetLastError(void *ctx)
729{
730 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
731
732 if (ctxt == NULL)
733 return (NULL);
734 if (ctxt->lastError.code == XML_ERR_OK)
735 return (NULL);
736 return (&ctxt->lastError);
737}
738
739/**
740 * xmlCtxtResetLastError:
741 * @ctx: an XML parser context
742 *
743 * Cleanup the last global error registered. For parsing error
744 * this does not change the well-formedness result.
745 */
746void
747xmlCtxtResetLastError(void *ctx)
748{
749 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
750
751 if (ctxt == NULL)
752 return;
753 if (ctxt->lastError.code == XML_ERR_OK)
754 return;
755 xmlResetError(&ctxt->lastError);
756}
757
758/**
759 * xmlCopyError:
760 * @from: a source error
761 * @to: a target error
762 *
763 * Save the original error to the new place.
764 *
765 * Returns 0 in case of success and -1 in case of error.
766 */
767int
768xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
769 if ((from == NULL) || (to == NULL))
770 return(-1);
771 if (to->message != NULL)
772 xmlFree(to->message);
773 if (to->file != NULL)
774 xmlFree(to->file);
775 if (to->str1 != NULL)
776 xmlFree(to->str1);
777 if (to->str2 != NULL)
778 xmlFree(to->str2);
779 if (to->str3 != NULL)
780 xmlFree(to->str3);
781 to->domain = from->domain;
782 to->code = from->code;
783 to->level = from->level;
784 to->line = from->line;
785 to->int1 = from->int1;
786 to->int2 = from->int2;
787 if (from->message != NULL)
788 to->message = (char *) xmlStrdup((xmlChar *) from->message);
789 else
790 to->message = NULL;
791 if (from->file != NULL)
792 to->file = (char *) xmlStrdup((xmlChar *) from->file);
793 else
794 to->file = NULL;
795 if (from->str1 != NULL)
796 to->str1 = (char *) xmlStrdup((xmlChar *) from->str1);
797 else
798 to->str1 = NULL;
799 if (from->str2 != NULL)
800 to->str2 = (char *) xmlStrdup((xmlChar *) from->str2);
801 else
802 to->str2 = NULL;
803 if (from->str3 != NULL)
804 to->str3 = (char *) xmlStrdup((xmlChar *) from->str3);
805 else
806 to->str3 = NULL;
807 return(0);
808}
809