source: trunk/third/libxml2/error.c @ 21532

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