blob: a30530e03c586da90a870a5e774386c4535a94ee [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
163 while (1) { // From the man page for vsnprintf ....
164 left = size - length;
165 /* Try to print in the allocated space. */
166 chars = vsnprintf(str + length, left, msg, args);
167 /* If that worked, we're done. */
168 if ((chars > -1) && (chars < left ))
169 break;
170 /* Else try again with more space. */
171 if (chars > -1) /* glibc 2.1 */
172 size += chars + 1; /* precisely what is needed */
173 else /* glibc 2.0 */
174 size += 100;
175 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
176 xmlFree(str);
177 return(NULL);
178 }
179 str = larger;
180 }
181 return(str);
182}
183
184/**
Owen Taylor3473f882001-02-23 17:55:21 +0000185 * xmlParserError:
186 * @ctx: an XML parser context
187 * @msg: the message to display/transmit
188 * @...: extra parameters for the message display
189 *
190 * Display and format an error messages, gives file, line, position and
191 * extra parameters.
192 */
193void
194xmlParserError(void *ctx, const char *msg, ...)
195{
196 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
197 xmlParserInputPtr input = NULL;
198 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000199 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000200 va_list args;
201
202 if (ctxt != NULL) {
203 input = ctxt->input;
204 if ((input != NULL) && (input->filename == NULL) &&
205 (ctxt->inputNr > 1)) {
206 cur = input;
207 input = ctxt->inputTab[ctxt->inputNr - 2];
208 }
209 xmlParserPrintFileInfo(input);
210 }
211
212 xmlGenericError(xmlGenericErrorContext, "error: ");
213 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000214 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000215 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000216 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000217 if (str != NULL)
218 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000219
220 if (ctxt != NULL) {
221 xmlParserPrintFileContext(input);
222 if (cur != NULL) {
223 xmlParserPrintFileInfo(cur);
224 xmlGenericError(xmlGenericErrorContext, "\n");
225 xmlParserPrintFileContext(cur);
226 }
227 }
228}
229
230/**
231 * xmlParserWarning:
232 * @ctx: an XML parser context
233 * @msg: the message to display/transmit
234 * @...: extra parameters for the message display
235 *
236 * Display and format a warning messages, gives file, line, position and
237 * extra parameters.
238 */
239void
240xmlParserWarning(void *ctx, const char *msg, ...)
241{
242 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
243 xmlParserInputPtr input = NULL;
244 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000245 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000246 va_list args;
247
248 if (ctxt != NULL) {
249 input = ctxt->input;
250 if ((input != NULL) && (input->filename == NULL) &&
251 (ctxt->inputNr > 1)) {
252 cur = input;
253 input = ctxt->inputTab[ctxt->inputNr - 2];
254 }
255 xmlParserPrintFileInfo(input);
256 }
257
258 xmlGenericError(xmlGenericErrorContext, "warning: ");
259 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000260 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000261 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000262 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000263 if (str != NULL)
264 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000265
266 if (ctxt != NULL) {
267 xmlParserPrintFileContext(input);
268 if (cur != NULL) {
269 xmlParserPrintFileInfo(cur);
270 xmlGenericError(xmlGenericErrorContext, "\n");
271 xmlParserPrintFileContext(cur);
272 }
273 }
274}
275
276/************************************************************************
277 * *
278 * Handling of validation errors *
279 * *
280 ************************************************************************/
281
282/**
283 * xmlParserValidityError:
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 an validity error messages, gives file,
289 * line, position and extra parameters.
290 */
291void
292xmlParserValidityError(void *ctx, const char *msg, ...)
293{
294 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
295 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000296 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000297 va_list args;
298
299 if (ctxt != NULL) {
300 input = ctxt->input;
301 if ((input->filename == NULL) && (ctxt->inputNr > 1))
302 input = ctxt->inputTab[ctxt->inputNr - 2];
303
304 xmlParserPrintFileInfo(input);
305 }
306
307 xmlGenericError(xmlGenericErrorContext, "validity error: ");
308 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000309 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000310 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000311 xmlGenericError(xmlGenericErrorContext, str);
312 if (str != NULL)
313 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000314
315 if (ctxt != NULL) {
316 xmlParserPrintFileContext(input);
317 }
318}
319
320/**
321 * xmlParserValidityWarning:
322 * @ctx: an XML parser context
323 * @msg: the message to display/transmit
324 * @...: extra parameters for the message display
325 *
326 * Display and format a validity warning messages, gives file, line,
327 * position and extra parameters.
328 */
329void
330xmlParserValidityWarning(void *ctx, const char *msg, ...)
331{
332 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
333 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000334 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000335 va_list args;
336
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 warning: ");
346 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000347 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000348 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000349 xmlGenericError(xmlGenericErrorContext, str);
350 if (str != NULL)
351 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000352
353 if (ctxt != NULL) {
354 xmlParserPrintFileContext(input);
355 }
356}
357
358