blob: b8aaf1bece3e41520af7bb78b63e879330c32cd6 [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 *
6 * Daniel Veillard <Daniel.Veillard@w3.org>
7 */
8
9#ifdef WIN32
10#include "win32config.h"
11#else
12#include "config.h"
13#endif
14
15#include <stdio.h>
16#include <stdarg.h>
17#include <libxml/parser.h>
18#include <libxml/xmlerror.h>
Daniel Veillarde356c282001-03-10 12:32:04 +000019#include <libxml/xmlmemory.h>
Owen Taylor3473f882001-02-23 17:55:21 +000020
21/************************************************************************
22 * *
23 * Handling of out of context errors *
24 * *
25 ************************************************************************/
26
27/**
28 * xmlGenericErrorDefaultFunc:
29 * @ctx: an error context
30 * @msg: the message to display/transmit
31 * @...: extra parameters for the message display
32 *
33 * Default handler for out of context error messages.
34 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +000035static void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000036xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000037 va_list args;
38
39 if (xmlGenericErrorContext == NULL)
40 xmlGenericErrorContext = (void *) stderr;
41
42 va_start(args, msg);
43 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
44 va_end(args);
45}
46
47xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
48void *xmlGenericErrorContext = NULL;
49
50
51/**
52 * xmlSetGenericErrorFunc:
53 * @ctx: the new error handling context
54 * @handler: the new handler function
55 *
56 * Function to reset the handler and the error context for out of
57 * context error messages.
58 * This simply means that @handler will be called for subsequent
59 * error messages while not parsing nor validating. And @ctx will
60 * be passed as first argument to @handler
61 * One can simply force messages to be emitted to another FILE * than
62 * stderr by setting @ctx to this file handle and @handler to NULL.
63 */
64void
65xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
66 xmlGenericErrorContext = ctx;
67 if (handler != NULL)
68 xmlGenericError = handler;
69 else
70 xmlGenericError = xmlGenericErrorDefaultFunc;
71}
72
73/************************************************************************
74 * *
75 * Handling of parsing errors *
76 * *
77 ************************************************************************/
78
79/**
80 * xmlParserPrintFileInfo:
81 * @input: an xmlParserInputPtr input
82 *
83 * Displays the associated file and line informations for the current input
84 */
85
86void
87xmlParserPrintFileInfo(xmlParserInputPtr input) {
88 if (input != NULL) {
89 if (input->filename)
90 xmlGenericError(xmlGenericErrorContext,
91 "%s:%d: ", input->filename,
92 input->line);
93 else
94 xmlGenericError(xmlGenericErrorContext,
95 "Entity: line %d: ", input->line);
96 }
97}
98
99/**
100 * xmlParserPrintFileContext:
101 * @input: an xmlParserInputPtr input
102 *
103 * Displays current context within the input content for error tracking
104 */
105
106void
107xmlParserPrintFileContext(xmlParserInputPtr input) {
108 const xmlChar *cur, *base;
109 int n;
Daniel Veillard2be30642001-03-27 00:32:28 +0000110 xmlChar content[81];
111 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000112
113 if (input == NULL) return;
114 cur = input->cur;
115 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000116 /* skip backwards over any end-of-lines */
Owen Taylor3473f882001-02-23 17:55:21 +0000117 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
118 cur--;
119 }
120 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000121 /* search backwards for beginning-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000122 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
123 cur--;
124 if ((*cur == '\n') || (*cur == '\r')) cur++;
Daniel Veillard2be30642001-03-27 00:32:28 +0000125 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000126 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000127 ctnt = content;
Owen Taylor3473f882001-02-23 17:55:21 +0000128 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
Daniel Veillard2be30642001-03-27 00:32:28 +0000129 *ctnt++ = *cur++;
Owen Taylor3473f882001-02-23 17:55:21 +0000130 n++;
131 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000132 *ctnt = 0;
133 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
134 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000135 cur = input->cur;
Daniel Veillard2be30642001-03-27 00:32:28 +0000136 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
137 cur--;
138 }
Owen Taylor3473f882001-02-23 17:55:21 +0000139 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000140 ctnt = content;
141 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
142 *ctnt++ = ' ';
143 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000144 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000145 *(--ctnt) = '^';
146 *(++ctnt) = 0;
147 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000148}
149
150/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000151 * xmlGetVarStr:
152 * @msg: the message format
153 * @args: a va_list argument list
154 *
155 * SGS contribution
156 * Get an arbitrary-sized string for an error argument
157 * The caller must free() the returned string
158 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000159static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000160xmlGetVarStr(const char * msg, va_list args) {
161 int size;
162 int length;
163 int chars, left;
164 char *str, *larger;
165
166 str = (char *) xmlMalloc(100);
167 if (str == NULL)
168 return(NULL);
169
170 size = 100;
171 length = 0;
172
Daniel Veillard7d42b542001-03-20 13:22:46 +0000173 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000174 left = size - length;
175 /* Try to print in the allocated space. */
Daniel Veillarda5f013b2001-03-22 12:44:45 +0000176#ifdef HAVE_VSNPRINTF
177 chars = vsnprintf(str + length, left, msg, args);
178#else
179 chars = vsprintf(str + length, msg, args);
180#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000181 /* If that worked, we're done. */
182 if ((chars > -1) && (chars < left ))
183 break;
184 /* Else try again with more space. */
185 if (chars > -1) /* glibc 2.1 */
186 size += chars + 1; /* precisely what is needed */
187 else /* glibc 2.0 */
188 size += 100;
189 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
190 xmlFree(str);
191 return(NULL);
192 }
193 str = larger;
194 }
195 return(str);
196}
197
198/**
Owen Taylor3473f882001-02-23 17:55:21 +0000199 * xmlParserError:
200 * @ctx: an XML parser context
201 * @msg: the message to display/transmit
202 * @...: extra parameters for the message display
203 *
204 * Display and format an error messages, gives file, line, position and
205 * extra parameters.
206 */
207void
208xmlParserError(void *ctx, const char *msg, ...)
209{
210 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
211 xmlParserInputPtr input = NULL;
212 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000213 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000214 va_list args;
215
216 if (ctxt != NULL) {
217 input = ctxt->input;
218 if ((input != NULL) && (input->filename == NULL) &&
219 (ctxt->inputNr > 1)) {
220 cur = input;
221 input = ctxt->inputTab[ctxt->inputNr - 2];
222 }
223 xmlParserPrintFileInfo(input);
224 }
225
226 xmlGenericError(xmlGenericErrorContext, "error: ");
227 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000228 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000229 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000230 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000231 if (str != NULL)
232 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000233
234 if (ctxt != NULL) {
235 xmlParserPrintFileContext(input);
236 if (cur != NULL) {
237 xmlParserPrintFileInfo(cur);
238 xmlGenericError(xmlGenericErrorContext, "\n");
239 xmlParserPrintFileContext(cur);
240 }
241 }
242}
243
244/**
245 * xmlParserWarning:
246 * @ctx: an XML parser context
247 * @msg: the message to display/transmit
248 * @...: extra parameters for the message display
249 *
250 * Display and format a warning messages, gives file, line, position and
251 * extra parameters.
252 */
253void
254xmlParserWarning(void *ctx, const char *msg, ...)
255{
256 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
257 xmlParserInputPtr input = NULL;
258 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000259 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000260 va_list args;
261
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, "warning: ");
273 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000274 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000275 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000276 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000277 if (str != NULL)
278 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000279
280 if (ctxt != NULL) {
281 xmlParserPrintFileContext(input);
282 if (cur != NULL) {
283 xmlParserPrintFileInfo(cur);
284 xmlGenericError(xmlGenericErrorContext, "\n");
285 xmlParserPrintFileContext(cur);
286 }
287 }
288}
289
290/************************************************************************
291 * *
292 * Handling of validation errors *
293 * *
294 ************************************************************************/
295
296/**
297 * xmlParserValidityError:
298 * @ctx: an XML parser context
299 * @msg: the message to display/transmit
300 * @...: extra parameters for the message display
301 *
302 * Display and format an validity error messages, gives file,
303 * line, position and extra parameters.
304 */
305void
306xmlParserValidityError(void *ctx, const char *msg, ...)
307{
308 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
309 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000310 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000311 va_list args;
312
313 if (ctxt != NULL) {
314 input = ctxt->input;
315 if ((input->filename == NULL) && (ctxt->inputNr > 1))
316 input = ctxt->inputTab[ctxt->inputNr - 2];
317
318 xmlParserPrintFileInfo(input);
319 }
320
321 xmlGenericError(xmlGenericErrorContext, "validity error: ");
322 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000323 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000324 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000325 xmlGenericError(xmlGenericErrorContext, str);
326 if (str != NULL)
327 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000328
329 if (ctxt != NULL) {
330 xmlParserPrintFileContext(input);
331 }
332}
333
334/**
335 * xmlParserValidityWarning:
336 * @ctx: an XML parser context
337 * @msg: the message to display/transmit
338 * @...: extra parameters for the message display
339 *
340 * Display and format a validity warning messages, gives file, line,
341 * position and extra parameters.
342 */
343void
344xmlParserValidityWarning(void *ctx, const char *msg, ...)
345{
346 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
347 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000348 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000349 va_list args;
350
351 if (ctxt != NULL) {
352 input = ctxt->input;
353 if ((input->filename == NULL) && (ctxt->inputNr > 1))
354 input = ctxt->inputTab[ctxt->inputNr - 2];
355
356 xmlParserPrintFileInfo(input);
357 }
358
359 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
360 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000361 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000362 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000363 xmlGenericError(xmlGenericErrorContext, str);
364 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