blob: 0ba84cfa52aa385c7976bffd0593163d5fc29579 [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 Veillard1c43dbf2001-06-05 17:12:52 +000017#define XML_GET_VAR_STR(msg, str) { \
18 int size; \
19 int chars; \
20 char *larger; \
21 va_list ap; \
22 \
23 str = (char *) xmlMalloc(150); \
24 if (str == NULL) \
25 return; \
26 \
27 size = 150; \
28 \
29 while (1) { \
30 va_start(ap, msg); \
31 chars = vsnprintf(str, size, msg, ap); \
32 va_end(ap); \
33 if ((chars > -1) && (chars < size)) \
34 break; \
35 if (chars > -1) \
36 size += chars + 1; \
37 else \
38 size += 100; \
39 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
40 xmlFree(str); \
41 return; \
42 } \
43 str = larger; \
44 } \
45}
Bjorn Reese570ff082001-06-05 12:45:55 +000046
Owen Taylor3473f882001-02-23 17:55:21 +000047/************************************************************************
48 * *
49 * Handling of out of context errors *
50 * *
51 ************************************************************************/
52
53/**
54 * xmlGenericErrorDefaultFunc:
55 * @ctx: an error context
56 * @msg: the message to display/transmit
57 * @...: extra parameters for the message display
58 *
59 * Default handler for out of context error messages.
60 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +000061static void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000062xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000063 va_list args;
64
65 if (xmlGenericErrorContext == NULL)
66 xmlGenericErrorContext = (void *) stderr;
67
68 va_start(args, msg);
69 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
70 va_end(args);
71}
72
Daniel Veillardd0463562001-10-13 09:15:48 +000073void
74initGenericErrorDefaultFunc(xmlGenericErrorFunc *handler)
75{
76 if (handler == NULL)
77 xmlGenericError = xmlGenericErrorDefaultFunc;
78 else
79 (*handler) = xmlGenericErrorDefaultFunc;
80}
Owen Taylor3473f882001-02-23 17:55:21 +000081
82/**
83 * xmlSetGenericErrorFunc:
84 * @ctx: the new error handling context
85 * @handler: the new handler function
86 *
87 * Function to reset the handler and the error context for out of
88 * context error messages.
89 * This simply means that @handler will be called for subsequent
90 * error messages while not parsing nor validating. And @ctx will
91 * be passed as first argument to @handler
92 * One can simply force messages to be emitted to another FILE * than
93 * stderr by setting @ctx to this file handle and @handler to NULL.
94 */
95void
96xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
97 xmlGenericErrorContext = ctx;
98 if (handler != NULL)
99 xmlGenericError = handler;
100 else
101 xmlGenericError = xmlGenericErrorDefaultFunc;
102}
103
104/************************************************************************
105 * *
106 * Handling of parsing errors *
107 * *
108 ************************************************************************/
109
110/**
111 * xmlParserPrintFileInfo:
112 * @input: an xmlParserInputPtr input
113 *
114 * Displays the associated file and line informations for the current input
115 */
116
117void
118xmlParserPrintFileInfo(xmlParserInputPtr input) {
119 if (input != NULL) {
120 if (input->filename)
121 xmlGenericError(xmlGenericErrorContext,
122 "%s:%d: ", input->filename,
123 input->line);
124 else
125 xmlGenericError(xmlGenericErrorContext,
126 "Entity: line %d: ", input->line);
127 }
128}
129
130/**
131 * xmlParserPrintFileContext:
132 * @input: an xmlParserInputPtr input
133 *
134 * Displays current context within the input content for error tracking
135 */
136
137void
138xmlParserPrintFileContext(xmlParserInputPtr input) {
139 const xmlChar *cur, *base;
140 int n;
Daniel Veillard2be30642001-03-27 00:32:28 +0000141 xmlChar content[81];
142 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000143
144 if (input == NULL) return;
145 cur = input->cur;
146 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000147 /* skip backwards over any end-of-lines */
Owen Taylor3473f882001-02-23 17:55:21 +0000148 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
149 cur--;
150 }
151 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000152 /* search backwards for beginning-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000153 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
154 cur--;
155 if ((*cur == '\n') || (*cur == '\r')) cur++;
Daniel Veillard2be30642001-03-27 00:32:28 +0000156 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000157 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000158 ctnt = content;
Owen Taylor3473f882001-02-23 17:55:21 +0000159 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
Daniel Veillard2be30642001-03-27 00:32:28 +0000160 *ctnt++ = *cur++;
Owen Taylor3473f882001-02-23 17:55:21 +0000161 n++;
162 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000163 *ctnt = 0;
164 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
165 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000166 cur = input->cur;
Daniel Veillard2be30642001-03-27 00:32:28 +0000167 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
168 cur--;
169 }
Owen Taylor3473f882001-02-23 17:55:21 +0000170 n = 0;
Daniel Veillard7533cc82001-04-24 15:52:00 +0000171 ctnt = content;
Daniel Veillard2be30642001-03-27 00:32:28 +0000172 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
173 *ctnt++ = ' ';
174 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000175 }
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000176 if (ctnt > content) {
177 *(--ctnt) = '^';
178 *(++ctnt) = 0;
179 } else {
180 *ctnt = '^';
181 *(++ctnt) = 0;
182 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000183 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000184}
185
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000186#if 0
Owen Taylor3473f882001-02-23 17:55:21 +0000187/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000188 * xmlGetVarStr:
189 * @msg: the message format
190 * @args: a va_list argument list
191 *
192 * SGS contribution
193 * Get an arbitrary-sized string for an error argument
194 * The caller must free() the returned string
195 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000196static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000197xmlGetVarStr(const char * msg, va_list args) {
198 int size;
199 int length;
200 int chars, left;
201 char *str, *larger;
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000202 va_list ap;
Daniel Veillarde356c282001-03-10 12:32:04 +0000203
Daniel Veillard92ad2102001-03-27 12:47:33 +0000204 str = (char *) xmlMalloc(150);
Daniel Veillarde356c282001-03-10 12:32:04 +0000205 if (str == NULL)
206 return(NULL);
207
Daniel Veillard92ad2102001-03-27 12:47:33 +0000208 size = 150;
Daniel Veillarde356c282001-03-10 12:32:04 +0000209 length = 0;
210
Daniel Veillard7d42b542001-03-20 13:22:46 +0000211 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000212 left = size - length;
213 /* Try to print in the allocated space. */
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000214 va_start(msg, ap);
215 chars = vsnprintf(str + length, left, msg, ap);
216 va_end(ap);
Daniel Veillarde356c282001-03-10 12:32:04 +0000217 /* If that worked, we're done. */
218 if ((chars > -1) && (chars < left ))
219 break;
220 /* Else try again with more space. */
221 if (chars > -1) /* glibc 2.1 */
222 size += chars + 1; /* precisely what is needed */
223 else /* glibc 2.0 */
224 size += 100;
225 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
226 xmlFree(str);
227 return(NULL);
228 }
229 str = larger;
230 }
231 return(str);
232}
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000233#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000234
235/**
Owen Taylor3473f882001-02-23 17:55:21 +0000236 * xmlParserError:
237 * @ctx: an XML parser context
238 * @msg: the message to display/transmit
239 * @...: extra parameters for the message display
240 *
241 * Display and format an error messages, gives file, line, position and
242 * extra parameters.
243 */
244void
245xmlParserError(void *ctx, const char *msg, ...)
246{
247 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
248 xmlParserInputPtr input = NULL;
249 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000250 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000251
252 if (ctxt != NULL) {
253 input = ctxt->input;
254 if ((input != NULL) && (input->filename == NULL) &&
255 (ctxt->inputNr > 1)) {
256 cur = input;
257 input = ctxt->inputTab[ctxt->inputNr - 2];
258 }
259 xmlParserPrintFileInfo(input);
260 }
261
262 xmlGenericError(xmlGenericErrorContext, "error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000263 XML_GET_VAR_STR(msg, str);
Daniel Veillarde356c282001-03-10 12:32:04 +0000264 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000265 if (str != NULL)
266 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000267
268 if (ctxt != NULL) {
269 xmlParserPrintFileContext(input);
270 if (cur != NULL) {
271 xmlParserPrintFileInfo(cur);
272 xmlGenericError(xmlGenericErrorContext, "\n");
273 xmlParserPrintFileContext(cur);
274 }
275 }
276}
277
278/**
279 * xmlParserWarning:
280 * @ctx: an XML parser context
281 * @msg: the message to display/transmit
282 * @...: extra parameters for the message display
283 *
284 * Display and format a warning messages, gives file, line, position and
285 * extra parameters.
286 */
287void
288xmlParserWarning(void *ctx, const char *msg, ...)
289{
290 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
291 xmlParserInputPtr input = NULL;
292 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000293 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000294
295 if (ctxt != NULL) {
296 input = ctxt->input;
297 if ((input != NULL) && (input->filename == NULL) &&
298 (ctxt->inputNr > 1)) {
299 cur = input;
300 input = ctxt->inputTab[ctxt->inputNr - 2];
301 }
302 xmlParserPrintFileInfo(input);
303 }
304
305 xmlGenericError(xmlGenericErrorContext, "warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000306 XML_GET_VAR_STR(msg, str);
Daniel Veillarde356c282001-03-10 12:32:04 +0000307 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000308 if (str != NULL)
309 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000310
311 if (ctxt != NULL) {
312 xmlParserPrintFileContext(input);
313 if (cur != NULL) {
314 xmlParserPrintFileInfo(cur);
315 xmlGenericError(xmlGenericErrorContext, "\n");
316 xmlParserPrintFileContext(cur);
317 }
318 }
319}
320
321/************************************************************************
322 * *
323 * Handling of validation errors *
324 * *
325 ************************************************************************/
326
327/**
328 * xmlParserValidityError:
329 * @ctx: an XML parser context
330 * @msg: the message to display/transmit
331 * @...: extra parameters for the message display
332 *
333 * Display and format an validity error messages, gives file,
334 * line, position and extra parameters.
335 */
336void
337xmlParserValidityError(void *ctx, const char *msg, ...)
338{
339 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
340 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000341 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000342
343 if (ctxt != NULL) {
344 input = ctxt->input;
345 if ((input->filename == NULL) && (ctxt->inputNr > 1))
346 input = ctxt->inputTab[ctxt->inputNr - 2];
347
348 xmlParserPrintFileInfo(input);
349 }
350
351 xmlGenericError(xmlGenericErrorContext, "validity error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000352 XML_GET_VAR_STR(msg, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000353 xmlGenericError(xmlGenericErrorContext, str);
354 if (str != NULL)
355 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000356
357 if (ctxt != NULL) {
358 xmlParserPrintFileContext(input);
359 }
360}
361
362/**
363 * xmlParserValidityWarning:
364 * @ctx: an XML parser context
365 * @msg: the message to display/transmit
366 * @...: extra parameters for the message display
367 *
368 * Display and format a validity warning messages, gives file, line,
369 * position and extra parameters.
370 */
371void
372xmlParserValidityWarning(void *ctx, const char *msg, ...)
373{
374 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
375 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000376 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000377
378 if (ctxt != NULL) {
379 input = ctxt->input;
380 if ((input->filename == NULL) && (ctxt->inputNr > 1))
381 input = ctxt->inputTab[ctxt->inputNr - 2];
382
383 xmlParserPrintFileInfo(input);
384 }
385
386 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000387 XML_GET_VAR_STR(msg, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000388 xmlGenericError(xmlGenericErrorContext, str);
389 if (str != NULL)
390 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000391
392 if (ctxt != NULL) {
393 xmlParserPrintFileContext(input);
394 }
395}
396
397