blob: 15d6246f40a93e7e8c25e1a3cf5054dad5c7d082 [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 Veillardd0463562001-10-13 09:15:48 +000077void
78initGenericErrorDefaultFunc(xmlGenericErrorFunc *handler)
79{
80 if (handler == NULL)
81 xmlGenericError = xmlGenericErrorDefaultFunc;
82 else
83 (*handler) = xmlGenericErrorDefaultFunc;
84}
Owen Taylor3473f882001-02-23 17:55:21 +000085
86/**
87 * xmlSetGenericErrorFunc:
88 * @ctx: the new error handling context
89 * @handler: the new handler function
90 *
91 * Function to reset the handler and the error context for out of
92 * context error messages.
93 * This simply means that @handler will be called for subsequent
94 * error messages while not parsing nor validating. And @ctx will
95 * be passed as first argument to @handler
96 * One can simply force messages to be emitted to another FILE * than
97 * stderr by setting @ctx to this file handle and @handler to NULL.
98 */
99void
100xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
101 xmlGenericErrorContext = ctx;
102 if (handler != NULL)
103 xmlGenericError = handler;
104 else
105 xmlGenericError = xmlGenericErrorDefaultFunc;
106}
107
108/************************************************************************
109 * *
110 * Handling of parsing errors *
111 * *
112 ************************************************************************/
113
114/**
115 * xmlParserPrintFileInfo:
116 * @input: an xmlParserInputPtr input
117 *
118 * Displays the associated file and line informations for the current input
119 */
120
121void
122xmlParserPrintFileInfo(xmlParserInputPtr input) {
123 if (input != NULL) {
124 if (input->filename)
125 xmlGenericError(xmlGenericErrorContext,
126 "%s:%d: ", input->filename,
127 input->line);
128 else
129 xmlGenericError(xmlGenericErrorContext,
130 "Entity: line %d: ", input->line);
131 }
132}
133
134/**
135 * xmlParserPrintFileContext:
136 * @input: an xmlParserInputPtr input
137 *
138 * Displays current context within the input content for error tracking
139 */
140
141void
142xmlParserPrintFileContext(xmlParserInputPtr input) {
143 const xmlChar *cur, *base;
144 int n;
Daniel Veillard2be30642001-03-27 00:32:28 +0000145 xmlChar content[81];
146 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000147
148 if (input == NULL) return;
149 cur = input->cur;
150 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000151 /* skip backwards over any end-of-lines */
Owen Taylor3473f882001-02-23 17:55:21 +0000152 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
153 cur--;
154 }
155 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000156 /* search backwards for beginning-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000157 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
158 cur--;
159 if ((*cur == '\n') || (*cur == '\r')) cur++;
Daniel Veillard2be30642001-03-27 00:32:28 +0000160 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000161 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000162 ctnt = content;
Owen Taylor3473f882001-02-23 17:55:21 +0000163 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
Daniel Veillard2be30642001-03-27 00:32:28 +0000164 *ctnt++ = *cur++;
Owen Taylor3473f882001-02-23 17:55:21 +0000165 n++;
166 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000167 *ctnt = 0;
168 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
169 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000170 cur = input->cur;
Daniel Veillard2be30642001-03-27 00:32:28 +0000171 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
172 cur--;
173 }
Owen Taylor3473f882001-02-23 17:55:21 +0000174 n = 0;
Daniel Veillard7533cc82001-04-24 15:52:00 +0000175 ctnt = content;
Daniel Veillard2be30642001-03-27 00:32:28 +0000176 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
177 *ctnt++ = ' ';
178 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000179 }
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000180 if (ctnt > content) {
181 *(--ctnt) = '^';
182 *(++ctnt) = 0;
183 } else {
184 *ctnt = '^';
185 *(++ctnt) = 0;
186 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000187 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000188}
189
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000190#if 0
Owen Taylor3473f882001-02-23 17:55:21 +0000191/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000192 * xmlGetVarStr:
193 * @msg: the message format
194 * @args: a va_list argument list
195 *
196 * SGS contribution
197 * Get an arbitrary-sized string for an error argument
198 * The caller must free() the returned string
199 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000200static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000201xmlGetVarStr(const char * msg, va_list args) {
202 int size;
203 int length;
204 int chars, left;
205 char *str, *larger;
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000206 va_list ap;
Daniel Veillarde356c282001-03-10 12:32:04 +0000207
Daniel Veillard92ad2102001-03-27 12:47:33 +0000208 str = (char *) xmlMalloc(150);
Daniel Veillarde356c282001-03-10 12:32:04 +0000209 if (str == NULL)
210 return(NULL);
211
Daniel Veillard92ad2102001-03-27 12:47:33 +0000212 size = 150;
Daniel Veillarde356c282001-03-10 12:32:04 +0000213 length = 0;
214
Daniel Veillard7d42b542001-03-20 13:22:46 +0000215 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000216 left = size - length;
217 /* Try to print in the allocated space. */
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000218 va_start(msg, ap);
219 chars = vsnprintf(str + length, left, msg, ap);
220 va_end(ap);
Daniel Veillarde356c282001-03-10 12:32:04 +0000221 /* If that worked, we're done. */
222 if ((chars > -1) && (chars < left ))
223 break;
224 /* Else try again with more space. */
225 if (chars > -1) /* glibc 2.1 */
226 size += chars + 1; /* precisely what is needed */
227 else /* glibc 2.0 */
228 size += 100;
229 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
230 xmlFree(str);
231 return(NULL);
232 }
233 str = larger;
234 }
235 return(str);
236}
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000237#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000238
239/**
Owen Taylor3473f882001-02-23 17:55:21 +0000240 * xmlParserError:
241 * @ctx: an XML parser context
242 * @msg: the message to display/transmit
243 * @...: extra parameters for the message display
244 *
245 * Display and format an error messages, gives file, line, position and
246 * extra parameters.
247 */
248void
249xmlParserError(void *ctx, const char *msg, ...)
250{
251 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
252 xmlParserInputPtr input = NULL;
253 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000254 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000255
256 if (ctxt != NULL) {
257 input = ctxt->input;
258 if ((input != NULL) && (input->filename == NULL) &&
259 (ctxt->inputNr > 1)) {
260 cur = input;
261 input = ctxt->inputTab[ctxt->inputNr - 2];
262 }
263 xmlParserPrintFileInfo(input);
264 }
265
266 xmlGenericError(xmlGenericErrorContext, "error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000267 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000268 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000269 if (str != NULL)
270 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000271
272 if (ctxt != NULL) {
273 xmlParserPrintFileContext(input);
274 if (cur != NULL) {
275 xmlParserPrintFileInfo(cur);
276 xmlGenericError(xmlGenericErrorContext, "\n");
277 xmlParserPrintFileContext(cur);
278 }
279 }
280}
281
282/**
283 * xmlParserWarning:
284 * @ctx: an XML parser context
285 * @msg: the message to display/transmit
286 * @...: extra parameters for the message display
287 *
288 * Display and format a warning messages, gives file, line, position and
289 * extra parameters.
290 */
291void
292xmlParserWarning(void *ctx, const char *msg, ...)
293{
294 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
295 xmlParserInputPtr input = NULL;
296 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000297 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000298
299 if (ctxt != NULL) {
300 input = ctxt->input;
301 if ((input != NULL) && (input->filename == NULL) &&
302 (ctxt->inputNr > 1)) {
303 cur = input;
304 input = ctxt->inputTab[ctxt->inputNr - 2];
305 }
306 xmlParserPrintFileInfo(input);
307 }
308
309 xmlGenericError(xmlGenericErrorContext, "warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000310 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000311 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000312 if (str != NULL)
313 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000314
315 if (ctxt != NULL) {
316 xmlParserPrintFileContext(input);
317 if (cur != NULL) {
318 xmlParserPrintFileInfo(cur);
319 xmlGenericError(xmlGenericErrorContext, "\n");
320 xmlParserPrintFileContext(cur);
321 }
322 }
323}
324
325/************************************************************************
326 * *
327 * Handling of validation errors *
328 * *
329 ************************************************************************/
330
331/**
332 * xmlParserValidityError:
333 * @ctx: an XML parser context
334 * @msg: the message to display/transmit
335 * @...: extra parameters for the message display
336 *
337 * Display and format an validity error messages, gives file,
338 * line, position and extra parameters.
339 */
340void
341xmlParserValidityError(void *ctx, const char *msg, ...)
342{
343 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
344 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000345 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000346
347 if (ctxt != NULL) {
348 input = ctxt->input;
349 if ((input->filename == NULL) && (ctxt->inputNr > 1))
350 input = ctxt->inputTab[ctxt->inputNr - 2];
351
352 xmlParserPrintFileInfo(input);
353 }
354
355 xmlGenericError(xmlGenericErrorContext, "validity error: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000356 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000357 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000358 if (str != NULL)
359 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000360
361 if (ctxt != NULL) {
362 xmlParserPrintFileContext(input);
363 }
364}
365
366/**
367 * xmlParserValidityWarning:
368 * @ctx: an XML parser context
369 * @msg: the message to display/transmit
370 * @...: extra parameters for the message display
371 *
372 * Display and format a validity warning messages, gives file, line,
373 * position and extra parameters.
374 */
375void
376xmlParserValidityWarning(void *ctx, const char *msg, ...)
377{
378 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
379 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000380 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000381
382 if (ctxt != NULL) {
383 input = ctxt->input;
384 if ((input->filename == NULL) && (ctxt->inputNr > 1))
385 input = ctxt->inputTab[ctxt->inputNr - 2];
386
387 xmlParserPrintFileInfo(input);
388 }
389
390 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
Daniel Veillard1c43dbf2001-06-05 17:12:52 +0000391 XML_GET_VAR_STR(msg, str);
Daniel Veillard635ef722001-10-29 11:48:19 +0000392 xmlGenericError(xmlGenericErrorContext, "%s", str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000393 if (str != NULL)
394 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000395
396 if (ctxt != NULL) {
397 xmlParserPrintFileContext(input);
398 }
399}
400
401