VirtualBox

source: vbox/trunk/src/libs/libxml2-2.12.6/error.c

Last change on this file was 104106, checked in by vboxsync, 8 weeks ago

libxml2-2.9.14: Applied and adjusted our libxml2 changes to 2.9.14. bugref:10640

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

© 2023 Oracle
ContactPrivacy policyTerms of Use