Initial revision
[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     int n;
153     xmlChar  content[81];
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 maximum 80 characters */
165     while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
166         cur--;
167     if ((*cur == '\n') || (*cur == '\r')) cur++;
168         /* search forward for end-of-line maximum 80 characters */
169     n = 0;
170     ctnt = content;
171     while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
172                 *ctnt++ = *cur++;
173         n++;
174     }
175     *ctnt = 0;
176     xmlGenericError(xmlGenericErrorContext,"%s\n", content);
177     /* create blank line with problem pointer */
178     cur = input->cur;
179     while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
180                 cur--;
181         }
182     n = 0;
183     ctnt = content;
184     while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
185         *ctnt++ = ' ';
186         cur--;
187     }
188     if (ctnt > content) {
189         *(--ctnt) = '^';
190         *(++ctnt) = 0;
191     } else {
192         *ctnt = '^';
193         *(++ctnt) = 0;
194     }
195     xmlGenericError(xmlGenericErrorContext,"%s\n", content);
196 }
197
198 #if 0
199 /**
200  * xmlGetVarStr:
201  * @msg:  the message format
202  * @args:  a va_list argument list
203  *
204  * SGS contribution
205  * Get an arbitrary-sized string for an error argument
206  * The caller must free() the returned string
207  */
208 static char *
209 xmlGetVarStr(const char * msg, va_list args) {
210     int       size;
211     int       length;
212     int       chars, left;
213     char      *str, *larger;
214     va_list   ap;
215
216     str = (char *) xmlMalloc(150);
217     if (str == NULL)
218       return(NULL);
219
220     size = 150;
221     length = 0;
222
223     while (1) {
224         left = size - length;
225                     /* Try to print in the allocated space. */
226         va_start(msg, ap);
227         chars = vsnprintf(str + length, left, msg, ap);
228         va_end(ap);
229                           /* If that worked, we're done. */
230         if ((chars > -1) && (chars < left ))
231             break;
232                           /* Else try again with more space. */
233         if (chars > -1)         /* glibc 2.1 */
234             size += chars + 1;  /* precisely what is needed */
235         else                    /* glibc 2.0 */
236             size += 100;
237         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
238             xmlFree(str);
239             return(NULL);
240         }
241         str = larger;
242     }
243     return(str);
244 }
245 #endif
246
247 /**
248  * xmlParserError:
249  * @ctx:  an XML parser context
250  * @msg:  the message to display/transmit
251  * @...:  extra parameters for the message display
252  * 
253  * Display and format an error messages, gives file, line, position and
254  * extra parameters.
255  */
256 void
257 xmlParserError(void *ctx, const char *msg, ...)
258 {
259     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
260     xmlParserInputPtr input = NULL;
261     xmlParserInputPtr cur = NULL;
262     char * str;
263
264     if (ctxt != NULL) {
265         input = ctxt->input;
266         if ((input != NULL) && (input->filename == NULL) &&
267             (ctxt->inputNr > 1)) {
268             cur = input;
269             input = ctxt->inputTab[ctxt->inputNr - 2];
270         }
271         xmlParserPrintFileInfo(input);
272     }
273
274     xmlGenericError(xmlGenericErrorContext, "error: ");
275     XML_GET_VAR_STR(msg, str);
276     xmlGenericError(xmlGenericErrorContext, "%s", str);
277     if (str != NULL)
278         xmlFree(str);
279
280     if (ctxt != NULL) {
281         xmlParserPrintFileContext(input);
282         if (cur != NULL) {
283             xmlParserPrintFileInfo(cur);
284             xmlGenericError(xmlGenericErrorContext, "\n");
285             xmlParserPrintFileContext(cur);
286         }
287     }
288 }
289
290 /**
291  * xmlParserWarning:
292  * @ctx:  an XML parser context
293  * @msg:  the message to display/transmit
294  * @...:  extra parameters for the message display
295  * 
296  * Display and format a warning messages, gives file, line, position and
297  * extra parameters.
298  */
299 void
300 xmlParserWarning(void *ctx, const char *msg, ...)
301 {
302     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
303     xmlParserInputPtr input = NULL;
304     xmlParserInputPtr cur = NULL;
305     char * str;
306
307     if (ctxt != NULL) {
308         input = ctxt->input;
309         if ((input != NULL) && (input->filename == NULL) &&
310             (ctxt->inputNr > 1)) {
311             cur = input;
312             input = ctxt->inputTab[ctxt->inputNr - 2];
313         }
314         xmlParserPrintFileInfo(input);
315     }
316         
317     xmlGenericError(xmlGenericErrorContext, "warning: ");
318     XML_GET_VAR_STR(msg, str);
319     xmlGenericError(xmlGenericErrorContext, "%s", str);
320     if (str != NULL)
321         xmlFree(str);
322
323     if (ctxt != NULL) {
324         xmlParserPrintFileContext(input);
325         if (cur != NULL) {
326             xmlParserPrintFileInfo(cur);
327             xmlGenericError(xmlGenericErrorContext, "\n");
328             xmlParserPrintFileContext(cur);
329         }
330     }
331 }
332
333 /************************************************************************
334  *                                                                      *
335  *                      Handling of validation errors                   *
336  *                                                                      *
337  ************************************************************************/
338
339 /**
340  * xmlParserValidityError:
341  * @ctx:  an XML parser context
342  * @msg:  the message to display/transmit
343  * @...:  extra parameters for the message display
344  * 
345  * Display and format an validity error messages, gives file,
346  * line, position and extra parameters.
347  */
348 void
349 xmlParserValidityError(void *ctx, const char *msg, ...)
350 {
351     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
352     xmlParserInputPtr input = NULL;
353     char * str;
354     int len = xmlStrlen((const xmlChar *) msg);
355     static int had_info = 0;
356     int need_context = 0;
357
358     if ((len > 1) && (msg[len - 2] != ':')) {
359         if (ctxt != NULL) {
360             input = ctxt->input;
361             if ((input->filename == NULL) && (ctxt->inputNr > 1))
362                 input = ctxt->inputTab[ctxt->inputNr - 2];
363                 
364             if (had_info == 0) {
365                 xmlParserPrintFileInfo(input);
366             }
367         }
368         xmlGenericError(xmlGenericErrorContext, "validity error: ");
369         need_context = 1;
370         had_info = 0;
371     } else {
372         had_info = 1;
373     }
374
375     XML_GET_VAR_STR(msg, str);
376     xmlGenericError(xmlGenericErrorContext, "%s", str);
377     if (str != NULL)
378         xmlFree(str);
379
380     if ((ctxt != NULL) && (input != NULL)) {
381         xmlParserPrintFileContext(input);
382     }
383 }
384
385 /**
386  * xmlParserValidityWarning:
387  * @ctx:  an XML parser context
388  * @msg:  the message to display/transmit
389  * @...:  extra parameters for the message display
390  * 
391  * Display and format a validity warning messages, gives file, line,
392  * position and extra parameters.
393  */
394 void
395 xmlParserValidityWarning(void *ctx, const char *msg, ...)
396 {
397     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
398     xmlParserInputPtr input = NULL;
399     char * str;
400     int len = xmlStrlen((const xmlChar *) msg);
401
402     if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
403         input = ctxt->input;
404         if ((input->filename == NULL) && (ctxt->inputNr > 1))
405             input = ctxt->inputTab[ctxt->inputNr - 2];
406
407         xmlParserPrintFileInfo(input);
408     }
409         
410     xmlGenericError(xmlGenericErrorContext, "validity warning: ");
411     XML_GET_VAR_STR(msg, str);
412     xmlGenericError(xmlGenericErrorContext, "%s", str);
413     if (str != NULL)
414         xmlFree(str);
415
416     if (ctxt != NULL) {
417         xmlParserPrintFileContext(input);
418     }
419 }
420
421