blob: f27494e4c38246ca5c1ff88a47965deb29b8bb37 [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
Bjorn Reese70a9da52001-04-21 16:57:29 +00009#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000010
Owen Taylor3473f882001-02-23 17:55:21 +000011#include <stdarg.h>
12#include <libxml/parser.h>
13#include <libxml/xmlerror.h>
Daniel Veillarde356c282001-03-10 12:32:04 +000014#include <libxml/xmlmemory.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000015#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000016
Daniel Veillard635ef722001-10-29 11:48:19 +000017void xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED,
18 const char *msg,
19 ...);
20
Daniel Veillard1c43dbf2001-06-05 17:12:52 +000021#define XML_GET_VAR_STR(msg, str) { \
22 int size; \
23 int chars; \
24 char *larger; \
25 va_list ap; \
26 \
27 str = (char *) xmlMalloc(150); \
28 if (str == NULL) \
29 return; \
30 \
31 size = 150; \
32 \
33 while (1) { \
34 va_start(ap, msg); \
35 chars = vsnprintf(str, size, msg, ap); \
36 va_end(ap); \
37 if ((chars > -1) && (chars < size)) \
38 break; \
39 if (chars > -1) \
40 size += chars + 1; \
41 else \
42 size += 100; \
43 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
44 xmlFree(str); \
45 return; \
46 } \
47 str = larger; \
48 } \
49}
Bjorn Reese570ff082001-06-05 12:45:55 +000050
Owen Taylor3473f882001-02-23 17:55:21 +000051/************************************************************************
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 */
Daniel Veillard635ef722001-10-29 11:48:19 +000065void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000066xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000067 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
Daniel Veillard9d06d302002-01-22 18:15:52 +000077/**
78 * initGenericErrorDefaultFunc:
79 * @handler: the handler
80 *
81 * Set or reset (if NULL) the default handler for generic errors
82 */
Daniel Veillardd0463562001-10-13 09:15:48 +000083void
Daniel Veillarddb5850a2002-01-18 11:49:26 +000084initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
Daniel Veillardd0463562001-10-13 09:15:48 +000085{
Daniel Veillarddb5850a2002-01-18 11:49:26 +000086 if (handler == NULL)
87 xmlGenericError = xmlGenericErrorDefaultFunc;
88 else
89 (*handler) = xmlGenericErrorDefaultFunc;
Daniel Veillardd0463562001-10-13 09:15:48 +000090}
Owen Taylor3473f882001-02-23 17:55:21 +000091
92/**
93 * xmlSetGenericErrorFunc:
94 * @ctx: the new error handling context
95 * @handler: the new handler function
96 *
97 * Function to reset the handler and the error context for out of
98 * context error messages.
99 * This simply means that @handler will be called for subsequent
100 * error messages while not parsing nor validating. And @ctx will
101 * be passed as first argument to @handler
102 * One can simply force messages to be emitted to another FILE * than
103 * stderr by setting @ctx to this file handle and @handler to NULL.
104 */
105void
106xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
107 xmlGenericErrorContext = ctx;
108 if (handler != NULL)
109 xmlGenericError = handler;
110 else
111 xmlGenericError = xmlGenericErrorDefaultFunc;
112}
113
114/************************************************************************
115 * *
116 * Handling of parsing errors *
117 * *
118 ************************************************************************/
119
120/**
121 * xmlParserPrintFileInfo:
122 * @input: an xmlParserInputPtr input
123 *
124 * Displays the associated file and line informations for the current input
125 */
126
127void
128xmlParserPrintFileInfo(xmlParserInputPtr input) {
129 if (input != NULL) {
130 if (input->filename)
131 xmlGenericError(xmlGenericErrorContext,
132 "%s:%d: ", input->filename,
133 input->line);
134 else
135 xmlGenericError(xmlGenericErrorContext,
136 "Entity: line %d: ", input->line);
137 }
138}
139
140/**
141 * xmlParserPrintFileContext:
142 * @input: an xmlParserInputPtr input
143 *
144 * Displays current context within the input content for error tracking
145 */
146
147void
148xmlParserPrintFileContext(xmlParserInputPtr input) {
149 const xmlChar *cur, *base;
150 int n;
Daniel Veillard2be30642001-03-27 00:32:28 +0000151 xmlChar content[81];
152 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000153
154 if (input == NULL) return;
155 cur = input->cur;
156 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000157 /* skip backwards over any end-of-lines */
Owen Taylor3473f882001-02-23 17:55:21 +0000158 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
159 cur--;
160 }
161 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000162 /* search backwards for beginning-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000163 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
164 cur--;
165 if ((*cur == '\n') || (*cur == '\r')) cur++;
Daniel Veillard2be30642001-03-27 00:32:28 +0000166 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000167 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000168 ctnt = content;
Owen Taylor3473f882001-02-23 17:55:21 +0000169 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
Daniel Veillard2be30642001-03-27 00:32:28 +0000170 *ctnt++ = *cur++;
Owen Taylor3473f882001-02-23 17:55:21 +0000171 n++;
172 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000173 *ctnt = 0;
174 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
175 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000176 cur = input->cur;
Daniel Veillard2be30642001-03-27 00:32:28 +0000177 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
178 cur--;
179 }
Owen Taylor3473f882001-02-23 17:55:21 +0000180 n = 0;
Daniel Veillard7533cc82001-04-24 15:52:00 +0000181 ctnt = content;
Daniel Veillard2be30642001-03-27 00:32:28 +0000182 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
183 *ctnt++ = ' ';
184 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000185 }
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000186 if (ctnt > content) {
187 *(--ctnt) = '^';
188 *(++ctnt) = 0;
189 } else {
190 *ctnt = '^';
191 *(++ctnt) = 0;
192 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000193 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000194}
195
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000196#if 0
Owen Taylor3473f882001-02-23 17:55:21 +0000197/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000198 * xmlGetVarStr:
199 * @msg: the message format
200 * @args: a va_list argument list
201 *
202 * SGS contribution
203 * Get an arbitrary-sized string for an error argument
204 * The caller must free() the returned string
205 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000206static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000207xmlGetVarStr(const char * msg, va_list args) {
208 int size;
209 int length;
210 int chars, left;
211 char *str, *larger;
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000212 va_list ap;
Daniel Veillarde356c282001-03-10 12:32:04 +0000213
Daniel Veillard92ad2102001-03-27 12:47:33 +0000214 str = (char *) xmlMalloc(150);
Daniel Veillarde356c282001-03-10 12:32:04 +0000215 if (str == NULL)
216 return(NULL);
217
Daniel Veillard92ad2102001-03-27 12:47:33 +0000218 size = 150;
Daniel Veillarde356c282001-03-10 12:32:04 +0000219 length = 0;
220
Daniel Veillard7d42b542001-03-20 13:22:46 +0000221 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000222 left = size - length;
223 /* Try to print in the allocated space. */
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000224 va_start(msg, ap);
225 chars = vsnprintf(str + length, left, msg, ap);
226 va_end(ap);
Daniel Veillarde356c282001-03-10 12:32:04 +0000227 /* If that worked, we're done. */
228 if ((chars > -1) && (chars < left ))
229 break;
230 /* Else try again with more space. */
231 if (chars > -1) /* glibc 2.1 */
232 size += chars + 1; /* precisely what is needed */
233 else /* glibc 2.0 */
234 size += 100;
235 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
236 xmlFree(str);
237 return(NULL);
238 }
239 str = larger;
240 }
241 return(str);
242}
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000243#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000244
245/**
Owen Taylor3473f882001-02-23 17:55:21 +0000246 * xmlParserError:
247 * @ctx: an XML parser context
248 * @msg: the message to display/transmit
249 * @...: extra parameters for the message display
250 *
251 * Display and format an error messages, gives file, line, position and
252 * extra parameters.
253 */
254void
255xmlParserError(void *ctx, const char *msg, ...)
256{
257 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
258 xmlParserInputPtr input = NULL;
259 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000260 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000261
262 if (ctxt != NULL) {
263 input = ctxt->input;
264 if ((input != NULL) && (input->filename == NULL) &&
265 (ctxt->inputNr > 1)) {
266 cur = input;
267 input = ctxt->inputTab[ctxt->inputNr - 2];
268 }
269 xmlParserPrintFileInfo(input);
270 }
271
272 xmlGenericError(xmlGenericErrorContext, "error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000273 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000274 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000275 if (str != NULL)
276 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000277
278 if (ctxt != NULL) {
279 xmlParserPrintFileContext(input);
280 if (cur != NULL) {
281 xmlParserPrintFileInfo(cur);
282 xmlGenericError(xmlGenericErrorContext, "\n");
283 xmlParserPrintFileContext(cur);
284 }
285 }
286}
287
288/**
289 * xmlParserWarning:
290 * @ctx: an XML parser context
291 * @msg: the message to display/transmit
292 * @...: extra parameters for the message display
293 *
294 * Display and format a warning messages, gives file, line, position and
295 * extra parameters.
296 */
297void
298xmlParserWarning(void *ctx, const char *msg, ...)
299{
300 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
301 xmlParserInputPtr input = NULL;
302 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000303 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000304
305 if (ctxt != NULL) {
306 input = ctxt->input;
307 if ((input != NULL) && (input->filename == NULL) &&
308 (ctxt->inputNr > 1)) {
309 cur = input;
310 input = ctxt->inputTab[ctxt->inputNr - 2];
311 }
312 xmlParserPrintFileInfo(input);
313 }
314
315 xmlGenericError(xmlGenericErrorContext, "warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000316 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000317 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000318 if (str != NULL)
319 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000320
321 if (ctxt != NULL) {
322 xmlParserPrintFileContext(input);
323 if (cur != NULL) {
324 xmlParserPrintFileInfo(cur);
325 xmlGenericError(xmlGenericErrorContext, "\n");
326 xmlParserPrintFileContext(cur);
327 }
328 }
329}
330
331/************************************************************************
332 * *
333 * Handling of validation errors *
334 * *
335 ************************************************************************/
336
337/**
338 * xmlParserValidityError:
339 * @ctx: an XML parser context
340 * @msg: the message to display/transmit
341 * @...: extra parameters for the message display
342 *
343 * Display and format an validity error messages, gives file,
344 * line, position and extra parameters.
345 */
346void
347xmlParserValidityError(void *ctx, const char *msg, ...)
348{
349 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
350 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000351 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000352
353 if (ctxt != NULL) {
354 input = ctxt->input;
355 if ((input->filename == NULL) && (ctxt->inputNr > 1))
356 input = ctxt->inputTab[ctxt->inputNr - 2];
357
358 xmlParserPrintFileInfo(input);
359 }
360
361 xmlGenericError(xmlGenericErrorContext, "validity error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000362 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000363 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000364 if (str != NULL)
365 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000366
367 if (ctxt != NULL) {
368 xmlParserPrintFileContext(input);
369 }
370}
371
372/**
373 * xmlParserValidityWarning:
374 * @ctx: an XML parser context
375 * @msg: the message to display/transmit
376 * @...: extra parameters for the message display
377 *
378 * Display and format a validity warning messages, gives file, line,
379 * position and extra parameters.
380 */
381void
382xmlParserValidityWarning(void *ctx, const char *msg, ...)
383{
384 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
385 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000386 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000387
388 if (ctxt != NULL) {
389 input = ctxt->input;
390 if ((input->filename == NULL) && (ctxt->inputNr > 1))
391 input = ctxt->inputTab[ctxt->inputNr - 2];
392
393 xmlParserPrintFileInfo(input);
394 }
395
396 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000397 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000398 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000399 if (str != NULL)
400 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000401
402 if (ctxt != NULL) {
403 xmlParserPrintFileContext(input);
404 }
405}
406
407