blob: d663689830099a5e03bd2f309bd4920d4b2370a7 [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>
Owen Taylor3473f882001-02-23 17:55:21 +000015
Daniel Veillard1c43dbf2001-06-05 17:12:52 +000016#define XML_GET_VAR_STR(msg, str) { \
17 int size; \
18 int chars; \
19 char *larger; \
20 va_list ap; \
21 \
22 str = (char *) xmlMalloc(150); \
23 if (str == NULL) \
24 return; \
25 \
26 size = 150; \
27 \
28 while (1) { \
29 va_start(ap, msg); \
30 chars = vsnprintf(str, size, msg, ap); \
31 va_end(ap); \
32 if ((chars > -1) && (chars < size)) \
33 break; \
34 if (chars > -1) \
35 size += chars + 1; \
36 else \
37 size += 100; \
38 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
39 xmlFree(str); \
40 return; \
41 } \
42 str = larger; \
43 } \
44}
Bjorn Reese570ff082001-06-05 12:45:55 +000045
Owen Taylor3473f882001-02-23 17:55:21 +000046/************************************************************************
47 * *
48 * Handling of out of context errors *
49 * *
50 ************************************************************************/
51
52/**
53 * xmlGenericErrorDefaultFunc:
54 * @ctx: an error context
55 * @msg: the message to display/transmit
56 * @...: extra parameters for the message display
57 *
58 * Default handler for out of context error messages.
59 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +000060static void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000061xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000062 va_list args;
63
64 if (xmlGenericErrorContext == NULL)
65 xmlGenericErrorContext = (void *) stderr;
66
67 va_start(args, msg);
68 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
69 va_end(args);
70}
71
Daniel Veillardd0463562001-10-13 09:15:48 +000072void
73initGenericErrorDefaultFunc(xmlGenericErrorFunc *handler)
74{
75 if (handler == NULL)
76 xmlGenericError = xmlGenericErrorDefaultFunc;
77 else
78 (*handler) = xmlGenericErrorDefaultFunc;
79}
Owen Taylor3473f882001-02-23 17:55:21 +000080
81/**
82 * xmlSetGenericErrorFunc:
83 * @ctx: the new error handling context
84 * @handler: the new handler function
85 *
86 * Function to reset the handler and the error context for out of
87 * context error messages.
88 * This simply means that @handler will be called for subsequent
89 * error messages while not parsing nor validating. And @ctx will
90 * be passed as first argument to @handler
91 * One can simply force messages to be emitted to another FILE * than
92 * stderr by setting @ctx to this file handle and @handler to NULL.
93 */
94void
95xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
96 xmlGenericErrorContext = ctx;
97 if (handler != NULL)
98 xmlGenericError = handler;
99 else
100 xmlGenericError = xmlGenericErrorDefaultFunc;
101}
102
103/************************************************************************
104 * *
105 * Handling of parsing errors *
106 * *
107 ************************************************************************/
108
109/**
110 * xmlParserPrintFileInfo:
111 * @input: an xmlParserInputPtr input
112 *
113 * Displays the associated file and line informations for the current input
114 */
115
116void
117xmlParserPrintFileInfo(xmlParserInputPtr input) {
118 if (input != NULL) {
119 if (input->filename)
120 xmlGenericError(xmlGenericErrorContext,
121 "%s:%d: ", input->filename,
122 input->line);
123 else
124 xmlGenericError(xmlGenericErrorContext,
125 "Entity: line %d: ", input->line);
126 }
127}
128
129/**
130 * xmlParserPrintFileContext:
131 * @input: an xmlParserInputPtr input
132 *
133 * Displays current context within the input content for error tracking
134 */
135
136void
137xmlParserPrintFileContext(xmlParserInputPtr input) {
138 const xmlChar *cur, *base;
139 int n;
Daniel Veillard2be30642001-03-27 00:32:28 +0000140 xmlChar content[81];
141 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000142
143 if (input == NULL) return;
144 cur = input->cur;
145 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000146 /* skip backwards over any end-of-lines */
Owen Taylor3473f882001-02-23 17:55:21 +0000147 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
148 cur--;
149 }
150 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000151 /* search backwards for beginning-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000152 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
153 cur--;
154 if ((*cur == '\n') || (*cur == '\r')) cur++;
Daniel Veillard2be30642001-03-27 00:32:28 +0000155 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000156 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000157 ctnt = content;
Owen Taylor3473f882001-02-23 17:55:21 +0000158 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
Daniel Veillard2be30642001-03-27 00:32:28 +0000159 *ctnt++ = *cur++;
Owen Taylor3473f882001-02-23 17:55:21 +0000160 n++;
161 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000162 *ctnt = 0;
163 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
164 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000165 cur = input->cur;
Daniel Veillard2be30642001-03-27 00:32:28 +0000166 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
167 cur--;
168 }
Owen Taylor3473f882001-02-23 17:55:21 +0000169 n = 0;
Daniel Veillard7533cc82001-04-24 15:52:00 +0000170 ctnt = content;
Daniel Veillard2be30642001-03-27 00:32:28 +0000171 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
172 *ctnt++ = ' ';
173 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000174 }
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000175 if (ctnt > content) {
176 *(--ctnt) = '^';
177 *(++ctnt) = 0;
178 } else {
179 *ctnt = '^';
180 *(++ctnt) = 0;
181 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000182 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000183}
184
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000185#if 0
Owen Taylor3473f882001-02-23 17:55:21 +0000186/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000187 * xmlGetVarStr:
188 * @msg: the message format
189 * @args: a va_list argument list
190 *
191 * SGS contribution
192 * Get an arbitrary-sized string for an error argument
193 * The caller must free() the returned string
194 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000195static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000196xmlGetVarStr(const char * msg, va_list args) {
197 int size;
198 int length;
199 int chars, left;
200 char *str, *larger;
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000201 va_list ap;
Daniel Veillarde356c282001-03-10 12:32:04 +0000202
Daniel Veillard92ad2102001-03-27 12:47:33 +0000203 str = (char *) xmlMalloc(150);
Daniel Veillarde356c282001-03-10 12:32:04 +0000204 if (str == NULL)
205 return(NULL);
206
Daniel Veillard92ad2102001-03-27 12:47:33 +0000207 size = 150;
Daniel Veillarde356c282001-03-10 12:32:04 +0000208 length = 0;
209
Daniel Veillard7d42b542001-03-20 13:22:46 +0000210 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000211 left = size - length;
212 /* Try to print in the allocated space. */
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000213 va_start(msg, ap);
214 chars = vsnprintf(str + length, left, msg, ap);
215 va_end(ap);
Daniel Veillarde356c282001-03-10 12:32:04 +0000216 /* If that worked, we're done. */
217 if ((chars > -1) && (chars < left ))
218 break;
219 /* Else try again with more space. */
220 if (chars > -1) /* glibc 2.1 */
221 size += chars + 1; /* precisely what is needed */
222 else /* glibc 2.0 */
223 size += 100;
224 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
225 xmlFree(str);
226 return(NULL);
227 }
228 str = larger;
229 }
230 return(str);
231}
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000232#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000233
234/**
Owen Taylor3473f882001-02-23 17:55:21 +0000235 * xmlParserError:
236 * @ctx: an XML parser context
237 * @msg: the message to display/transmit
238 * @...: extra parameters for the message display
239 *
240 * Display and format an error messages, gives file, line, position and
241 * extra parameters.
242 */
243void
244xmlParserError(void *ctx, const char *msg, ...)
245{
246 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
247 xmlParserInputPtr input = NULL;
248 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000249 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000250
251 if (ctxt != NULL) {
252 input = ctxt->input;
253 if ((input != NULL) && (input->filename == NULL) &&
254 (ctxt->inputNr > 1)) {
255 cur = input;
256 input = ctxt->inputTab[ctxt->inputNr - 2];
257 }
258 xmlParserPrintFileInfo(input);
259 }
260
261 xmlGenericError(xmlGenericErrorContext, "error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000262 XML_GET_VAR_STR(msg, str);
Daniel Veillarde356c282001-03-10 12:32:04 +0000263 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000264 if (str != NULL)
265 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000266
267 if (ctxt != NULL) {
268 xmlParserPrintFileContext(input);
269 if (cur != NULL) {
270 xmlParserPrintFileInfo(cur);
271 xmlGenericError(xmlGenericErrorContext, "\n");
272 xmlParserPrintFileContext(cur);
273 }
274 }
275}
276
277/**
278 * xmlParserWarning:
279 * @ctx: an XML parser context
280 * @msg: the message to display/transmit
281 * @...: extra parameters for the message display
282 *
283 * Display and format a warning messages, gives file, line, position and
284 * extra parameters.
285 */
286void
287xmlParserWarning(void *ctx, const char *msg, ...)
288{
289 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
290 xmlParserInputPtr input = NULL;
291 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000292 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000293
294 if (ctxt != NULL) {
295 input = ctxt->input;
296 if ((input != NULL) && (input->filename == NULL) &&
297 (ctxt->inputNr > 1)) {
298 cur = input;
299 input = ctxt->inputTab[ctxt->inputNr - 2];
300 }
301 xmlParserPrintFileInfo(input);
302 }
303
304 xmlGenericError(xmlGenericErrorContext, "warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000305 XML_GET_VAR_STR(msg, str);
Daniel Veillarde356c282001-03-10 12:32:04 +0000306 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000307 if (str != NULL)
308 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000309
310 if (ctxt != NULL) {
311 xmlParserPrintFileContext(input);
312 if (cur != NULL) {
313 xmlParserPrintFileInfo(cur);
314 xmlGenericError(xmlGenericErrorContext, "\n");
315 xmlParserPrintFileContext(cur);
316 }
317 }
318}
319
320/************************************************************************
321 * *
322 * Handling of validation errors *
323 * *
324 ************************************************************************/
325
326/**
327 * xmlParserValidityError:
328 * @ctx: an XML parser context
329 * @msg: the message to display/transmit
330 * @...: extra parameters for the message display
331 *
332 * Display and format an validity error messages, gives file,
333 * line, position and extra parameters.
334 */
335void
336xmlParserValidityError(void *ctx, const char *msg, ...)
337{
338 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
339 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000340 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000341
342 if (ctxt != NULL) {
343 input = ctxt->input;
344 if ((input->filename == NULL) && (ctxt->inputNr > 1))
345 input = ctxt->inputTab[ctxt->inputNr - 2];
346
347 xmlParserPrintFileInfo(input);
348 }
349
350 xmlGenericError(xmlGenericErrorContext, "validity error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000351 XML_GET_VAR_STR(msg, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000352 xmlGenericError(xmlGenericErrorContext, str);
353 if (str != NULL)
354 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000355
356 if (ctxt != NULL) {
357 xmlParserPrintFileContext(input);
358 }
359}
360
361/**
362 * xmlParserValidityWarning:
363 * @ctx: an XML parser context
364 * @msg: the message to display/transmit
365 * @...: extra parameters for the message display
366 *
367 * Display and format a validity warning messages, gives file, line,
368 * position and extra parameters.
369 */
370void
371xmlParserValidityWarning(void *ctx, const char *msg, ...)
372{
373 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
374 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000375 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000376
377 if (ctxt != NULL) {
378 input = ctxt->input;
379 if ((input->filename == NULL) && (ctxt->inputNr > 1))
380 input = ctxt->inputTab[ctxt->inputNr - 2];
381
382 xmlParserPrintFileInfo(input);
383 }
384
385 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000386 XML_GET_VAR_STR(msg, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000387 xmlGenericError(xmlGenericErrorContext, str);
388 if (str != NULL)
389 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000390
391 if (ctxt != NULL) {
392 xmlParserPrintFileContext(input);
393 }
394}
395
396