blob: 14d91f316b8ef74708e17eb836b9fca91f266643 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * error.c: module displaying/handling XML parser errors
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00006 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00007 */
8
Daniel Veillard34ce8be2002-03-18 19:37:11 +00009#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000010#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000011
Owen Taylor3473f882001-02-23 17:55:21 +000012#include <stdarg.h>
13#include <libxml/parser.h>
14#include <libxml/xmlerror.h>
Daniel Veillarde356c282001-03-10 12:32:04 +000015#include <libxml/xmlmemory.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000016#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000017
Daniel Veillard635ef722001-10-29 11:48:19 +000018void xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED,
19 const char *msg,
20 ...);
21
Daniel Veillard1c43dbf2001-06-05 17:12:52 +000022#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}
Bjorn Reese570ff082001-06-05 12:45:55 +000051
Owen Taylor3473f882001-02-23 17:55:21 +000052/************************************************************************
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 */
Daniel Veillard635ef722001-10-29 11:48:19 +000066void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000067xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000068 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
Daniel Veillard9d06d302002-01-22 18:15:52 +000078/**
79 * initGenericErrorDefaultFunc:
80 * @handler: the handler
81 *
82 * Set or reset (if NULL) the default handler for generic errors
83 */
Daniel Veillardd0463562001-10-13 09:15:48 +000084void
Daniel Veillarddb5850a2002-01-18 11:49:26 +000085initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
Daniel Veillardd0463562001-10-13 09:15:48 +000086{
Daniel Veillarddb5850a2002-01-18 11:49:26 +000087 if (handler == NULL)
88 xmlGenericError = xmlGenericErrorDefaultFunc;
89 else
90 (*handler) = xmlGenericErrorDefaultFunc;
Daniel Veillardd0463562001-10-13 09:15:48 +000091}
Owen Taylor3473f882001-02-23 17:55:21 +000092
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 */
106void
107xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
108 xmlGenericErrorContext = ctx;
109 if (handler != NULL)
110 xmlGenericError = handler;
111 else
112 xmlGenericError = xmlGenericErrorDefaultFunc;
113}
114
115/************************************************************************
116 * *
117 * Handling of parsing errors *
118 * *
119 ************************************************************************/
120
121/**
122 * xmlParserPrintFileInfo:
123 * @input: an xmlParserInputPtr input
124 *
125 * Displays the associated file and line informations for the current input
126 */
127
128void
129xmlParserPrintFileInfo(xmlParserInputPtr input) {
130 if (input != NULL) {
131 if (input->filename)
132 xmlGenericError(xmlGenericErrorContext,
133 "%s:%d: ", input->filename,
134 input->line);
135 else
136 xmlGenericError(xmlGenericErrorContext,
137 "Entity: line %d: ", input->line);
138 }
139}
140
141/**
142 * xmlParserPrintFileContext:
143 * @input: an xmlParserInputPtr input
144 *
145 * Displays current context within the input content for error tracking
146 */
147
148void
Daniel Veillard561b7f82002-03-20 21:55:57 +0000149xmlParserPrintFileContext(xmlParserInputPtr input) {
150 const xmlChar *cur, *base;
Owen Taylor3473f882001-02-23 17:55:21 +0000151 int n;
Daniel Veillard561b7f82002-03-20 21:55:57 +0000152 xmlChar content[81];
Daniel Veillard2be30642001-03-27 00:32:28 +0000153 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000154
Daniel Veillard561b7f82002-03-20 21:55:57 +0000155 if (input == NULL) return;
Owen Taylor3473f882001-02-23 17:55:21 +0000156 cur = input->cur;
157 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000158 /* skip backwards over any end-of-lines */
Daniel Veillard561b7f82002-03-20 21:55:57 +0000159 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
160 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000161 }
162 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000163 /* search backwards for beginning-of-line maximum 80 characters */
Daniel Veillard561b7f82002-03-20 21:55:57 +0000164 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
Owen Taylor3473f882001-02-23 17:55:21 +0000165 cur--;
Daniel Veillard561b7f82002-03-20 21:55:57 +0000166 if ((*cur == '\n') || (*cur == '\r')) cur++;
167 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000168 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000169 ctnt = content;
Daniel Veillard561b7f82002-03-20 21:55:57 +0000170 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
171 *ctnt++ = *cur++;
172 n++;
Owen Taylor3473f882001-02-23 17:55:21 +0000173 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000174 *ctnt = 0;
Daniel Veillard561b7f82002-03-20 21:55:57 +0000175 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Daniel Veillard2be30642001-03-27 00:32:28 +0000176 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000177 cur = input->cur;
Daniel Veillard561b7f82002-03-20 21:55:57 +0000178 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
179 cur--;
180 }
Owen Taylor3473f882001-02-23 17:55:21 +0000181 n = 0;
Daniel Veillard7533cc82001-04-24 15:52:00 +0000182 ctnt = content;
Daniel Veillard561b7f82002-03-20 21:55:57 +0000183 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
184 *ctnt++ = ' ';
185 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000186 }
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000187 if (ctnt > content) {
Daniel Veillard561b7f82002-03-20 21:55:57 +0000188 *(--ctnt) = '^';
189 *(++ctnt) = 0;
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000190 } else {
Daniel Veillard561b7f82002-03-20 21:55:57 +0000191 *ctnt = '^';
192 *(++ctnt) = 0;
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000193 }
Daniel Veillard561b7f82002-03-20 21:55:57 +0000194 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000195}
196
Daniel Veillard561b7f82002-03-20 21:55:57 +0000197#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 */
207static char *
208xmlGetVarStr(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
Daniel Veillarde356c282001-03-10 12:32:04 +0000246/**
Owen Taylor3473f882001-02-23 17:55:21 +0000247 * 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 */
255void
256xmlParserError(void *ctx, const char *msg, ...)
257{
258 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
259 xmlParserInputPtr input = NULL;
260 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000261 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000262
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: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000274 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000275 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000276 if (str != NULL)
277 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000278
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 */
298void
299xmlParserWarning(void *ctx, const char *msg, ...)
300{
301 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
302 xmlParserInputPtr input = NULL;
303 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000304 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000305
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: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000317 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000318 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000319 if (str != NULL)
320 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000321
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 */
347void
348xmlParserValidityError(void *ctx, const char *msg, ...)
349{
350 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
351 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000352 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000353
354 if (ctxt != NULL) {
355 input = ctxt->input;
356 if ((input->filename == NULL) && (ctxt->inputNr > 1))
357 input = ctxt->inputTab[ctxt->inputNr - 2];
358
359 xmlParserPrintFileInfo(input);
360 }
361
362 xmlGenericError(xmlGenericErrorContext, "validity error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000363 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000364 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000365 if (str != NULL)
366 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000367
368 if (ctxt != NULL) {
369 xmlParserPrintFileContext(input);
370 }
371}
372
373/**
374 * xmlParserValidityWarning:
375 * @ctx: an XML parser context
376 * @msg: the message to display/transmit
377 * @...: extra parameters for the message display
378 *
379 * Display and format a validity warning messages, gives file, line,
380 * position and extra parameters.
381 */
382void
383xmlParserValidityWarning(void *ctx, const char *msg, ...)
384{
385 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
386 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000387 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000388
389 if (ctxt != NULL) {
390 input = ctxt->input;
391 if ((input->filename == NULL) && (ctxt->inputNr > 1))
392 input = ctxt->inputTab[ctxt->inputNr - 2];
393
394 xmlParserPrintFileInfo(input);
395 }
396
397 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000398 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000399 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000400 if (str != NULL)
401 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000402
403 if (ctxt != NULL) {
404 xmlParserPrintFileContext(input);
405 }
406}
407
408