blob: 25066ea109b35438b4845a9caaedc7c736c912fe [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 */
35void
36xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...) {
37 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;
110
111 if (input == NULL) return;
112 cur = input->cur;
113 base = input->base;
114 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
115 cur--;
116 }
117 n = 0;
118 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
119 cur--;
120 if ((*cur == '\n') || (*cur == '\r')) cur++;
121 base = cur;
122 n = 0;
123 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
124 xmlGenericError(xmlGenericErrorContext,
125 "%c", (unsigned char) *cur++);
126 n++;
127 }
128 xmlGenericError(xmlGenericErrorContext, "\n");
129 cur = input->cur;
130 while ((*cur == '\n') || (*cur == '\r'))
131 cur--;
132 n = 0;
133 while ((cur != base) && (n++ < 80)) {
134 xmlGenericError(xmlGenericErrorContext, " ");
135 base++;
136 }
137 xmlGenericError(xmlGenericErrorContext,"^\n");
138}
139
140/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000141 * xmlGetVarStr:
142 * @msg: the message format
143 * @args: a va_list argument list
144 *
145 * SGS contribution
146 * Get an arbitrary-sized string for an error argument
147 * The caller must free() the returned string
148 */
149char *
150xmlGetVarStr(const char * msg, va_list args) {
151 int size;
152 int length;
153 int chars, left;
154 char *str, *larger;
155
156 str = (char *) xmlMalloc(100);
157 if (str == NULL)
158 return(NULL);
159
160 size = 100;
161 length = 0;
162
Daniel Veillard7d42b542001-03-20 13:22:46 +0000163 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000164 left = size - length;
165 /* Try to print in the allocated space. */
Daniel Veillarda5f013b2001-03-22 12:44:45 +0000166#ifdef HAVE_VSNPRINTF
167 chars = vsnprintf(str + length, left, msg, args);
168#else
169 chars = vsprintf(str + length, msg, args);
170#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000171 /* If that worked, we're done. */
172 if ((chars > -1) && (chars < left ))
173 break;
174 /* Else try again with more space. */
175 if (chars > -1) /* glibc 2.1 */
176 size += chars + 1; /* precisely what is needed */
177 else /* glibc 2.0 */
178 size += 100;
179 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
180 xmlFree(str);
181 return(NULL);
182 }
183 str = larger;
184 }
185 return(str);
186}
187
188/**
Owen Taylor3473f882001-02-23 17:55:21 +0000189 * xmlParserError:
190 * @ctx: an XML parser context
191 * @msg: the message to display/transmit
192 * @...: extra parameters for the message display
193 *
194 * Display and format an error messages, gives file, line, position and
195 * extra parameters.
196 */
197void
198xmlParserError(void *ctx, const char *msg, ...)
199{
200 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
201 xmlParserInputPtr input = NULL;
202 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000203 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000204 va_list args;
205
206 if (ctxt != NULL) {
207 input = ctxt->input;
208 if ((input != NULL) && (input->filename == NULL) &&
209 (ctxt->inputNr > 1)) {
210 cur = input;
211 input = ctxt->inputTab[ctxt->inputNr - 2];
212 }
213 xmlParserPrintFileInfo(input);
214 }
215
216 xmlGenericError(xmlGenericErrorContext, "error: ");
217 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000218 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000219 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000220 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000221 if (str != NULL)
222 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000223
224 if (ctxt != NULL) {
225 xmlParserPrintFileContext(input);
226 if (cur != NULL) {
227 xmlParserPrintFileInfo(cur);
228 xmlGenericError(xmlGenericErrorContext, "\n");
229 xmlParserPrintFileContext(cur);
230 }
231 }
232}
233
234/**
235 * xmlParserWarning:
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 a warning messages, gives file, line, position and
241 * extra parameters.
242 */
243void
244xmlParserWarning(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 va_list args;
251
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, "warning: ");
263 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000264 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000265 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000266 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000267 if (str != NULL)
268 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000269
270 if (ctxt != NULL) {
271 xmlParserPrintFileContext(input);
272 if (cur != NULL) {
273 xmlParserPrintFileInfo(cur);
274 xmlGenericError(xmlGenericErrorContext, "\n");
275 xmlParserPrintFileContext(cur);
276 }
277 }
278}
279
280/************************************************************************
281 * *
282 * Handling of validation errors *
283 * *
284 ************************************************************************/
285
286/**
287 * xmlParserValidityError:
288 * @ctx: an XML parser context
289 * @msg: the message to display/transmit
290 * @...: extra parameters for the message display
291 *
292 * Display and format an validity error messages, gives file,
293 * line, position and extra parameters.
294 */
295void
296xmlParserValidityError(void *ctx, const char *msg, ...)
297{
298 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
299 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000300 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000301 va_list args;
302
303 if (ctxt != NULL) {
304 input = ctxt->input;
305 if ((input->filename == NULL) && (ctxt->inputNr > 1))
306 input = ctxt->inputTab[ctxt->inputNr - 2];
307
308 xmlParserPrintFileInfo(input);
309 }
310
311 xmlGenericError(xmlGenericErrorContext, "validity error: ");
312 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000313 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000314 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000315 xmlGenericError(xmlGenericErrorContext, str);
316 if (str != NULL)
317 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000318
319 if (ctxt != NULL) {
320 xmlParserPrintFileContext(input);
321 }
322}
323
324/**
325 * xmlParserValidityWarning:
326 * @ctx: an XML parser context
327 * @msg: the message to display/transmit
328 * @...: extra parameters for the message display
329 *
330 * Display and format a validity warning messages, gives file, line,
331 * position and extra parameters.
332 */
333void
334xmlParserValidityWarning(void *ctx, const char *msg, ...)
335{
336 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
337 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000338 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000339 va_list args;
340
341 if (ctxt != NULL) {
342 input = ctxt->input;
343 if ((input->filename == NULL) && (ctxt->inputNr > 1))
344 input = ctxt->inputTab[ctxt->inputNr - 2];
345
346 xmlParserPrintFileInfo(input);
347 }
348
349 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
350 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000351 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000352 va_end(args);
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