updated libxml2 to 2.5.10
[TestXSLT.git] / libxml2 / error.c
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 <stdarg.h>
13 #include <libxml/parser.h>
14 #include <libxml/xmlerror.h>
15 #include <libxml/xmlmemory.h>
16 #include <libxml/globals.h>
17
18 void xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED,
19                                  const char *msg,
20                                  ...);
21
22 #define XML_GET_VAR_STR(msg, str) {                             \
23     int       size;                                             \
24     int       chars;                                            \
25     char      *larger;                                          \
26     va_list   ap;                                               \
27                                                                 \
28     str = (char *) xmlMalloc(150);                              \
29     if (str == NULL)                                            \
30         return;                                                 \
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             xmlFree(str);                                       \
46             return;                                             \
47         }                                                       \
48         str = larger;                                           \
49     }                                                           \
50 }
51
52 /************************************************************************
53  *                                                                      *
54  *                      Handling of out of context errors               *
55  *                                                                      *
56  ************************************************************************/
57
58 /**
59  * xmlGenericErrorDefaultFunc:
60  * @ctx:  an error context
61  * @msg:  the message to display/transmit
62  * @...:  extra parameters for the message display
63  * 
64  * Default handler for out of context error messages.
65  */
66 void
67 xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
68     va_list args;
69
70     if (xmlGenericErrorContext == NULL)
71         xmlGenericErrorContext = (void *) stderr;
72
73     va_start(args, msg);
74     vfprintf((FILE *)xmlGenericErrorContext, msg, args);
75     va_end(args);
76 }
77
78 /**
79  * initGenericErrorDefaultFunc:
80  * @handler:  the handler
81  * 
82  * Set or reset (if NULL) the default handler for generic errors
83  * to the builtin error function.
84  */
85 void
86 initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
87 {
88     if (handler == NULL)
89         xmlGenericError = xmlGenericErrorDefaultFunc;
90     else
91         (*handler) = xmlGenericErrorDefaultFunc;
92 }
93
94 /**
95  * xmlSetGenericErrorFunc:
96  * @ctx:  the new error handling context
97  * @handler:  the new handler function
98  *
99  * Function to reset the handler and the error context for out of
100  * context error messages.
101  * This simply means that @handler will be called for subsequent
102  * error messages while not parsing nor validating. And @ctx will
103  * be passed as first argument to @handler
104  * One can simply force messages to be emitted to another FILE * than
105  * stderr by setting @ctx to this file handle and @handler to NULL.
106  */
107 void
108 xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
109     xmlGenericErrorContext = ctx;
110     if (handler != NULL)
111         xmlGenericError = handler;
112     else
113         xmlGenericError = xmlGenericErrorDefaultFunc;
114 }
115
116 /************************************************************************
117  *                                                                      *
118  *                      Handling of parsing errors                      *
119  *                                                                      *
120  ************************************************************************/
121
122 /**
123  * xmlParserPrintFileInfo:
124  * @input:  an xmlParserInputPtr input
125  * 
126  * Displays the associated file and line informations for the current input
127  */
128
129 void
130 xmlParserPrintFileInfo(xmlParserInputPtr input) {
131     if (input != NULL) {
132         if (input->filename)
133             xmlGenericError(xmlGenericErrorContext,
134                     "%s:%d: ", input->filename,
135                     input->line);
136         else
137             xmlGenericError(xmlGenericErrorContext,
138                     "Entity: line %d: ", input->line);
139     }
140 }
141
142 /**
143  * xmlParserPrintFileContext:
144  * @input:  an xmlParserInputPtr input
145  * 
146  * Displays current context within the input content for error tracking
147  */
148
149 void
150 xmlParserPrintFileContext(xmlParserInputPtr input) {
151     const xmlChar *cur, *base;
152     unsigned int n, col;        /* GCC warns if signed, because compared with sizeof() */
153     xmlChar  content[81]; /* space for 80 chars + line terminator */
154     xmlChar *ctnt;
155
156     if (input == NULL) return;
157     cur = input->cur;
158     base = input->base;
159     /* skip backwards over any end-of-lines */
160     while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
161         cur--;
162     }
163     n = 0;
164     /* search backwards for beginning-of-line (to max buff size) */
165     while ((n++ < (sizeof(content)-1)) && (cur > base) && 
166            (*(cur) != '\n') && (*(cur) != '\r'))
167         cur--;
168     if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
169     /* 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) */
172     n = 0;
173     ctnt = content;
174     /* copy selected text to our buffer */
175     while ((*cur != 0) && (*(cur) != '\n') && 
176            (*(cur) != '\r') && (n < sizeof(content)-1)) {
177                 *ctnt++ = *cur++;
178         n++;
179     }
180     *ctnt = 0;
181     /* print out the selected text */
182     xmlGenericError(xmlGenericErrorContext,"%s\n", content);
183     /* create blank line with problem pointer */
184     n = 0;
185     ctnt = content;
186     /* (leave buffer space for pointer + line terminator) */
187     while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
188         if (*(ctnt) != '\t')
189             *(ctnt) = ' ';
190         *ctnt++;
191     }
192     *ctnt++ = '^';
193     *ctnt = 0;
194     xmlGenericError(xmlGenericErrorContext,"%s\n", content);
195 }
196
197 #if 0
198 /**
199  * xmlGetVarStr:
200  * @msg:  the message format
201  * @args:  a va_list argument list
202  *
203  * SGS contribution
204  * Get an arbitrary-sized string for an error argument
205  * The caller must free() the returned string
206  */
207 static char *
208 xmlGetVarStr(const char * msg, va_list args) {
209     int       size;
210     int       length;
211     int       chars, left;
212     char      *str, *larger;
213     va_list   ap;
214
215     str = (char *) xmlMalloc(150);
216     if (str == NULL)
217       return(NULL);
218
219     size = 150;
220     length = 0;
221
222     while (1) {
223         left = size - length;
224                     /* Try to print in the allocated space. */
225         va_start(msg, ap);
226         chars = vsnprintf(str + length, left, msg, ap);
227         va_end(ap);
228                           /* If that worked, we're done. */
229         if ((chars > -1) && (chars < left ))
230             break;
231                           /* Else try again with more space. */
232         if (chars > -1)         /* glibc 2.1 */
233             size += chars + 1;  /* precisely what is needed */
234         else                    /* glibc 2.0 */
235             size += 100;
236         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
237             xmlFree(str);
238             return(NULL);
239         }
240         str = larger;
241     }
242     return(str);
243 }
244 #endif
245
246 /**
247  * xmlParserError:
248  * @ctx:  an XML parser context
249  * @msg:  the message to display/transmit
250  * @...:  extra parameters for the message display
251  * 
252  * Display and format an error messages, gives file, line, position and
253  * extra parameters.
254  */
255 void
256 xmlParserError(void *ctx, const char *msg, ...)
257 {
258     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
259     xmlParserInputPtr input = NULL;
260     xmlParserInputPtr cur = NULL;
261     char * str;
262
263     if (ctxt != NULL) {
264         input = ctxt->input;
265         if ((input != NULL) && (input->filename == NULL) &&
266             (ctxt->inputNr > 1)) {
267             cur = input;
268             input = ctxt->inputTab[ctxt->inputNr - 2];
269         }
270         xmlParserPrintFileInfo(input);
271     }
272
273     xmlGenericError(xmlGenericErrorContext, "error: ");
274     XML_GET_VAR_STR(msg, str);
275     xmlGenericError(xmlGenericErrorContext, "%s", str);
276     if (str != NULL)
277         xmlFree(str);
278
279     if (ctxt != NULL) {
280         xmlParserPrintFileContext(input);
281         if (cur != NULL) {
282             xmlParserPrintFileInfo(cur);
283             xmlGenericError(xmlGenericErrorContext, "\n");
284             xmlParserPrintFileContext(cur);
285         }
286     }
287 }
288
289 /**
290  * xmlParserWarning:
291  * @ctx:  an XML parser context
292  * @msg:  the message to display/transmit
293  * @...:  extra parameters for the message display
294  * 
295  * Display and format a warning messages, gives file, line, position and
296  * extra parameters.
297  */
298 void
299 xmlParserWarning(void *ctx, const char *msg, ...)
300 {
301     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
302     xmlParserInputPtr input = NULL;
303     xmlParserInputPtr cur = NULL;
304     char * str;
305
306     if (ctxt != NULL) {
307         input = ctxt->input;
308         if ((input != NULL) && (input->filename == NULL) &&
309             (ctxt->inputNr > 1)) {
310             cur = input;
311             input = ctxt->inputTab[ctxt->inputNr - 2];
312         }
313         xmlParserPrintFileInfo(input);
314     }
315         
316     xmlGenericError(xmlGenericErrorContext, "warning: ");
317     XML_GET_VAR_STR(msg, str);
318     xmlGenericError(xmlGenericErrorContext, "%s", str);
319     if (str != NULL)
320         xmlFree(str);
321
322     if (ctxt != NULL) {
323         xmlParserPrintFileContext(input);
324         if (cur != NULL) {
325             xmlParserPrintFileInfo(cur);
326             xmlGenericError(xmlGenericErrorContext, "\n");
327             xmlParserPrintFileContext(cur);
328         }
329     }
330 }
331
332 /************************************************************************
333  *                                                                      *
334  *                      Handling of validation errors                   *
335  *                                                                      *
336  ************************************************************************/
337
338 /**
339  * xmlParserValidityError:
340  * @ctx:  an XML parser context
341  * @msg:  the message to display/transmit
342  * @...:  extra parameters for the message display
343  * 
344  * Display and format an validity error messages, gives file,
345  * line, position and extra parameters.
346  */
347 void
348 xmlParserValidityError(void *ctx, const char *msg, ...)
349 {
350     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
351     xmlParserInputPtr input = NULL;
352     char * str;
353     int len = xmlStrlen((const xmlChar *) msg);
354     static int had_info = 0;
355
356     if ((len > 1) && (msg[len - 2] != ':')) {
357         if (ctxt != NULL) {
358             input = ctxt->input;
359             if ((input->filename == NULL) && (ctxt->inputNr > 1))
360                 input = ctxt->inputTab[ctxt->inputNr - 2];
361                 
362             if (had_info == 0) {
363                 xmlParserPrintFileInfo(input);
364             }
365         }
366         xmlGenericError(xmlGenericErrorContext, "validity error: ");
367         had_info = 0;
368     } else {
369         had_info = 1;
370     }
371
372     XML_GET_VAR_STR(msg, str);
373     xmlGenericError(xmlGenericErrorContext, "%s", str);
374     if (str != NULL)
375         xmlFree(str);
376
377     if ((ctxt != NULL) && (input != NULL)) {
378         xmlParserPrintFileContext(input);
379     }
380 }
381
382 /**
383  * xmlParserValidityWarning:
384  * @ctx:  an XML parser context
385  * @msg:  the message to display/transmit
386  * @...:  extra parameters for the message display
387  * 
388  * Display and format a validity warning messages, gives file, line,
389  * position and extra parameters.
390  */
391 void
392 xmlParserValidityWarning(void *ctx, const char *msg, ...)
393 {
394     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
395     xmlParserInputPtr input = NULL;
396     char * str;
397     int len = xmlStrlen((const xmlChar *) msg);
398
399     if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
400         input = ctxt->input;
401         if ((input->filename == NULL) && (ctxt->inputNr > 1))
402             input = ctxt->inputTab[ctxt->inputNr - 2];
403
404         xmlParserPrintFileInfo(input);
405     }
406         
407     xmlGenericError(xmlGenericErrorContext, "validity warning: ");
408     XML_GET_VAR_STR(msg, str);
409     xmlGenericError(xmlGenericErrorContext, "%s", str);
410     if (str != NULL)
411         xmlFree(str);
412
413     if (ctxt != NULL) {
414         xmlParserPrintFileContext(input);
415     }
416 }
417
418