blob: 52354503094321c24fd41c4b07ef64de981c8b61 [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
72xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
73void *xmlGenericErrorContext = NULL;
74
75
76/**
77 * xmlSetGenericErrorFunc:
78 * @ctx: the new error handling context
79 * @handler: the new handler function
80 *
81 * Function to reset the handler and the error context for out of
82 * context error messages.
83 * This simply means that @handler will be called for subsequent
84 * error messages while not parsing nor validating. And @ctx will
85 * be passed as first argument to @handler
86 * One can simply force messages to be emitted to another FILE * than
87 * stderr by setting @ctx to this file handle and @handler to NULL.
88 */
89void
90xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
91 xmlGenericErrorContext = ctx;
92 if (handler != NULL)
93 xmlGenericError = handler;
94 else
95 xmlGenericError = xmlGenericErrorDefaultFunc;
96}
97
98/************************************************************************
99 * *
100 * Handling of parsing errors *
101 * *
102 ************************************************************************/
103
104/**
105 * xmlParserPrintFileInfo:
106 * @input: an xmlParserInputPtr input
107 *
108 * Displays the associated file and line informations for the current input
109 */
110
111void
112xmlParserPrintFileInfo(xmlParserInputPtr input) {
113 if (input != NULL) {
114 if (input->filename)
115 xmlGenericError(xmlGenericErrorContext,
116 "%s:%d: ", input->filename,
117 input->line);
118 else
119 xmlGenericError(xmlGenericErrorContext,
120 "Entity: line %d: ", input->line);
121 }
122}
123
124/**
125 * xmlParserPrintFileContext:
126 * @input: an xmlParserInputPtr input
127 *
128 * Displays current context within the input content for error tracking
129 */
130
131void
132xmlParserPrintFileContext(xmlParserInputPtr input) {
133 const xmlChar *cur, *base;
134 int n;
Daniel Veillard2be30642001-03-27 00:32:28 +0000135 xmlChar content[81];
136 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000137
138 if (input == NULL) return;
139 cur = input->cur;
140 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000141 /* skip backwards over any end-of-lines */
Owen Taylor3473f882001-02-23 17:55:21 +0000142 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
143 cur--;
144 }
145 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000146 /* search backwards for beginning-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000147 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
148 cur--;
149 if ((*cur == '\n') || (*cur == '\r')) cur++;
Daniel Veillard2be30642001-03-27 00:32:28 +0000150 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000151 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000152 ctnt = content;
Owen Taylor3473f882001-02-23 17:55:21 +0000153 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
Daniel Veillard2be30642001-03-27 00:32:28 +0000154 *ctnt++ = *cur++;
Owen Taylor3473f882001-02-23 17:55:21 +0000155 n++;
156 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000157 *ctnt = 0;
158 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
159 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000160 cur = input->cur;
Daniel Veillard2be30642001-03-27 00:32:28 +0000161 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
162 cur--;
163 }
Owen Taylor3473f882001-02-23 17:55:21 +0000164 n = 0;
Daniel Veillard7533cc82001-04-24 15:52:00 +0000165 ctnt = content;
Daniel Veillard2be30642001-03-27 00:32:28 +0000166 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
167 *ctnt++ = ' ';
168 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000169 }
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000170 if (ctnt > content) {
171 *(--ctnt) = '^';
172 *(++ctnt) = 0;
173 } else {
174 *ctnt = '^';
175 *(++ctnt) = 0;
176 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000177 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000178}
179
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000180#if 0
Owen Taylor3473f882001-02-23 17:55:21 +0000181/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000182 * xmlGetVarStr:
183 * @msg: the message format
184 * @args: a va_list argument list
185 *
186 * SGS contribution
187 * Get an arbitrary-sized string for an error argument
188 * The caller must free() the returned string
189 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000190static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000191xmlGetVarStr(const char * msg, va_list args) {
192 int size;
193 int length;
194 int chars, left;
195 char *str, *larger;
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000196 va_list ap;
Daniel Veillarde356c282001-03-10 12:32:04 +0000197
Daniel Veillard92ad2102001-03-27 12:47:33 +0000198 str = (char *) xmlMalloc(150);
Daniel Veillarde356c282001-03-10 12:32:04 +0000199 if (str == NULL)
200 return(NULL);
201
Daniel Veillard92ad2102001-03-27 12:47:33 +0000202 size = 150;
Daniel Veillarde356c282001-03-10 12:32:04 +0000203 length = 0;
204
Daniel Veillard7d42b542001-03-20 13:22:46 +0000205 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000206 left = size - length;
207 /* Try to print in the allocated space. */
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000208 va_start(msg, ap);
209 chars = vsnprintf(str + length, left, msg, ap);
210 va_end(ap);
Daniel Veillarde356c282001-03-10 12:32:04 +0000211 /* If that worked, we're done. */
212 if ((chars > -1) && (chars < left ))
213 break;
214 /* Else try again with more space. */
215 if (chars > -1) /* glibc 2.1 */
216 size += chars + 1; /* precisely what is needed */
217 else /* glibc 2.0 */
218 size += 100;
219 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
220 xmlFree(str);
221 return(NULL);
222 }
223 str = larger;
224 }
225 return(str);
226}
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000227#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000228
229/**
Owen Taylor3473f882001-02-23 17:55:21 +0000230 * xmlParserError:
231 * @ctx: an XML parser context
232 * @msg: the message to display/transmit
233 * @...: extra parameters for the message display
234 *
235 * Display and format an error messages, gives file, line, position and
236 * extra parameters.
237 */
238void
239xmlParserError(void *ctx, const char *msg, ...)
240{
241 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
242 xmlParserInputPtr input = NULL;
243 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000244 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000245
246 if (ctxt != NULL) {
247 input = ctxt->input;
248 if ((input != NULL) && (input->filename == NULL) &&
249 (ctxt->inputNr > 1)) {
250 cur = input;
251 input = ctxt->inputTab[ctxt->inputNr - 2];
252 }
253 xmlParserPrintFileInfo(input);
254 }
255
256 xmlGenericError(xmlGenericErrorContext, "error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000257 XML_GET_VAR_STR(msg, str);
Daniel Veillarde356c282001-03-10 12:32:04 +0000258 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000259 if (str != NULL)
260 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000261
262 if (ctxt != NULL) {
263 xmlParserPrintFileContext(input);
264 if (cur != NULL) {
265 xmlParserPrintFileInfo(cur);
266 xmlGenericError(xmlGenericErrorContext, "\n");
267 xmlParserPrintFileContext(cur);
268 }
269 }
270}
271
272/**
273 * xmlParserWarning:
274 * @ctx: an XML parser context
275 * @msg: the message to display/transmit
276 * @...: extra parameters for the message display
277 *
278 * Display and format a warning messages, gives file, line, position and
279 * extra parameters.
280 */
281void
282xmlParserWarning(void *ctx, const char *msg, ...)
283{
284 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
285 xmlParserInputPtr input = NULL;
286 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000287 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000288
289 if (ctxt != NULL) {
290 input = ctxt->input;
291 if ((input != NULL) && (input->filename == NULL) &&
292 (ctxt->inputNr > 1)) {
293 cur = input;
294 input = ctxt->inputTab[ctxt->inputNr - 2];
295 }
296 xmlParserPrintFileInfo(input);
297 }
298
299 xmlGenericError(xmlGenericErrorContext, "warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000300 XML_GET_VAR_STR(msg, str);
Daniel Veillarde356c282001-03-10 12:32:04 +0000301 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000302 if (str != NULL)
303 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000304
305 if (ctxt != NULL) {
306 xmlParserPrintFileContext(input);
307 if (cur != NULL) {
308 xmlParserPrintFileInfo(cur);
309 xmlGenericError(xmlGenericErrorContext, "\n");
310 xmlParserPrintFileContext(cur);
311 }
312 }
313}
314
315/************************************************************************
316 * *
317 * Handling of validation errors *
318 * *
319 ************************************************************************/
320
321/**
322 * xmlParserValidityError:
323 * @ctx: an XML parser context
324 * @msg: the message to display/transmit
325 * @...: extra parameters for the message display
326 *
327 * Display and format an validity error messages, gives file,
328 * line, position and extra parameters.
329 */
330void
331xmlParserValidityError(void *ctx, const char *msg, ...)
332{
333 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
334 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000335 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000336
337 if (ctxt != NULL) {
338 input = ctxt->input;
339 if ((input->filename == NULL) && (ctxt->inputNr > 1))
340 input = ctxt->inputTab[ctxt->inputNr - 2];
341
342 xmlParserPrintFileInfo(input);
343 }
344
345 xmlGenericError(xmlGenericErrorContext, "validity error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000346 XML_GET_VAR_STR(msg, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000347 xmlGenericError(xmlGenericErrorContext, str);
348 if (str != NULL)
349 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000350
351 if (ctxt != NULL) {
352 xmlParserPrintFileContext(input);
353 }
354}
355
356/**
357 * xmlParserValidityWarning:
358 * @ctx: an XML parser context
359 * @msg: the message to display/transmit
360 * @...: extra parameters for the message display
361 *
362 * Display and format a validity warning messages, gives file, line,
363 * position and extra parameters.
364 */
365void
366xmlParserValidityWarning(void *ctx, const char *msg, ...)
367{
368 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
369 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000370 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000371
372 if (ctxt != NULL) {
373 input = ctxt->input;
374 if ((input->filename == NULL) && (ctxt->inputNr > 1))
375 input = ctxt->inputTab[ctxt->inputNr - 2];
376
377 xmlParserPrintFileInfo(input);
378 }
379
380 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000381 XML_GET_VAR_STR(msg, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000382 xmlGenericError(xmlGenericErrorContext, str);
383 if (str != NULL)
384 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000385
386 if (ctxt != NULL) {
387 xmlParserPrintFileContext(input);
388 }
389}
390
391