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