blob: cf1c1a544604cccaecf110d0be52bc6ebc011139 [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
Daniel Veillard56a4cb82001-03-24 17:00:36 +000021#ifdef __GNUC__
22#define UNUSED __attribute__((__unused__))
23#else
24#define UNUSED
25#endif
Owen Taylor3473f882001-02-23 17:55:21 +000026/************************************************************************
27 * *
28 * Handling of out of context errors *
29 * *
30 ************************************************************************/
31
32/**
33 * xmlGenericErrorDefaultFunc:
34 * @ctx: an error context
35 * @msg: the message to display/transmit
36 * @...: extra parameters for the message display
37 *
38 * Default handler for out of context error messages.
39 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +000040static void
41xmlGenericErrorDefaultFunc(void *ctx UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000042 va_list args;
43
44 if (xmlGenericErrorContext == NULL)
45 xmlGenericErrorContext = (void *) stderr;
46
47 va_start(args, msg);
48 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
49 va_end(args);
50}
51
52xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
53void *xmlGenericErrorContext = NULL;
54
55
56/**
57 * xmlSetGenericErrorFunc:
58 * @ctx: the new error handling context
59 * @handler: the new handler function
60 *
61 * Function to reset the handler and the error context for out of
62 * context error messages.
63 * This simply means that @handler will be called for subsequent
64 * error messages while not parsing nor validating. And @ctx will
65 * be passed as first argument to @handler
66 * One can simply force messages to be emitted to another FILE * than
67 * stderr by setting @ctx to this file handle and @handler to NULL.
68 */
69void
70xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
71 xmlGenericErrorContext = ctx;
72 if (handler != NULL)
73 xmlGenericError = handler;
74 else
75 xmlGenericError = xmlGenericErrorDefaultFunc;
76}
77
78/************************************************************************
79 * *
80 * Handling of parsing errors *
81 * *
82 ************************************************************************/
83
84/**
85 * xmlParserPrintFileInfo:
86 * @input: an xmlParserInputPtr input
87 *
88 * Displays the associated file and line informations for the current input
89 */
90
91void
92xmlParserPrintFileInfo(xmlParserInputPtr input) {
93 if (input != NULL) {
94 if (input->filename)
95 xmlGenericError(xmlGenericErrorContext,
96 "%s:%d: ", input->filename,
97 input->line);
98 else
99 xmlGenericError(xmlGenericErrorContext,
100 "Entity: line %d: ", input->line);
101 }
102}
103
104/**
105 * xmlParserPrintFileContext:
106 * @input: an xmlParserInputPtr input
107 *
108 * Displays current context within the input content for error tracking
109 */
110
111void
112xmlParserPrintFileContext(xmlParserInputPtr input) {
113 const xmlChar *cur, *base;
114 int n;
115
116 if (input == NULL) return;
117 cur = input->cur;
118 base = input->base;
119 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
120 cur--;
121 }
122 n = 0;
123 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
124 cur--;
125 if ((*cur == '\n') || (*cur == '\r')) cur++;
126 base = cur;
127 n = 0;
128 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
129 xmlGenericError(xmlGenericErrorContext,
130 "%c", (unsigned char) *cur++);
131 n++;
132 }
133 xmlGenericError(xmlGenericErrorContext, "\n");
134 cur = input->cur;
135 while ((*cur == '\n') || (*cur == '\r'))
136 cur--;
137 n = 0;
138 while ((cur != base) && (n++ < 80)) {
139 xmlGenericError(xmlGenericErrorContext, " ");
140 base++;
141 }
142 xmlGenericError(xmlGenericErrorContext,"^\n");
143}
144
145/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000146 * xmlGetVarStr:
147 * @msg: the message format
148 * @args: a va_list argument list
149 *
150 * SGS contribution
151 * Get an arbitrary-sized string for an error argument
152 * The caller must free() the returned string
153 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000154static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000155xmlGetVarStr(const char * msg, va_list args) {
156 int size;
157 int length;
158 int chars, left;
159 char *str, *larger;
160
161 str = (char *) xmlMalloc(100);
162 if (str == NULL)
163 return(NULL);
164
165 size = 100;
166 length = 0;
167
Daniel Veillard7d42b542001-03-20 13:22:46 +0000168 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000169 left = size - length;
170 /* Try to print in the allocated space. */
Daniel Veillarda5f013b2001-03-22 12:44:45 +0000171#ifdef HAVE_VSNPRINTF
172 chars = vsnprintf(str + length, left, msg, args);
173#else
174 chars = vsprintf(str + length, msg, args);
175#endif
Daniel Veillarde356c282001-03-10 12:32:04 +0000176 /* If that worked, we're done. */
177 if ((chars > -1) && (chars < left ))
178 break;
179 /* Else try again with more space. */
180 if (chars > -1) /* glibc 2.1 */
181 size += chars + 1; /* precisely what is needed */
182 else /* glibc 2.0 */
183 size += 100;
184 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
185 xmlFree(str);
186 return(NULL);
187 }
188 str = larger;
189 }
190 return(str);
191}
192
193/**
Owen Taylor3473f882001-02-23 17:55:21 +0000194 * xmlParserError:
195 * @ctx: an XML parser context
196 * @msg: the message to display/transmit
197 * @...: extra parameters for the message display
198 *
199 * Display and format an error messages, gives file, line, position and
200 * extra parameters.
201 */
202void
203xmlParserError(void *ctx, const char *msg, ...)
204{
205 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
206 xmlParserInputPtr input = NULL;
207 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000208 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000209 va_list args;
210
211 if (ctxt != NULL) {
212 input = ctxt->input;
213 if ((input != NULL) && (input->filename == NULL) &&
214 (ctxt->inputNr > 1)) {
215 cur = input;
216 input = ctxt->inputTab[ctxt->inputNr - 2];
217 }
218 xmlParserPrintFileInfo(input);
219 }
220
221 xmlGenericError(xmlGenericErrorContext, "error: ");
222 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000223 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000224 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000225 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000226 if (str != NULL)
227 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000228
229 if (ctxt != NULL) {
230 xmlParserPrintFileContext(input);
231 if (cur != NULL) {
232 xmlParserPrintFileInfo(cur);
233 xmlGenericError(xmlGenericErrorContext, "\n");
234 xmlParserPrintFileContext(cur);
235 }
236 }
237}
238
239/**
240 * xmlParserWarning:
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 a warning messages, gives file, line, position and
246 * extra parameters.
247 */
248void
249xmlParserWarning(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 va_list args;
256
257 if (ctxt != NULL) {
258 input = ctxt->input;
259 if ((input != NULL) && (input->filename == NULL) &&
260 (ctxt->inputNr > 1)) {
261 cur = input;
262 input = ctxt->inputTab[ctxt->inputNr - 2];
263 }
264 xmlParserPrintFileInfo(input);
265 }
266
267 xmlGenericError(xmlGenericErrorContext, "warning: ");
268 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000269 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000270 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000271 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000272 if (str != NULL)
273 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000274
275 if (ctxt != NULL) {
276 xmlParserPrintFileContext(input);
277 if (cur != NULL) {
278 xmlParserPrintFileInfo(cur);
279 xmlGenericError(xmlGenericErrorContext, "\n");
280 xmlParserPrintFileContext(cur);
281 }
282 }
283}
284
285/************************************************************************
286 * *
287 * Handling of validation errors *
288 * *
289 ************************************************************************/
290
291/**
292 * xmlParserValidityError:
293 * @ctx: an XML parser context
294 * @msg: the message to display/transmit
295 * @...: extra parameters for the message display
296 *
297 * Display and format an validity error messages, gives file,
298 * line, position and extra parameters.
299 */
300void
301xmlParserValidityError(void *ctx, const char *msg, ...)
302{
303 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
304 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000305 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000306 va_list args;
307
308 if (ctxt != NULL) {
309 input = ctxt->input;
310 if ((input->filename == NULL) && (ctxt->inputNr > 1))
311 input = ctxt->inputTab[ctxt->inputNr - 2];
312
313 xmlParserPrintFileInfo(input);
314 }
315
316 xmlGenericError(xmlGenericErrorContext, "validity error: ");
317 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000318 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000319 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000320 xmlGenericError(xmlGenericErrorContext, str);
321 if (str != NULL)
322 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000323
324 if (ctxt != NULL) {
325 xmlParserPrintFileContext(input);
326 }
327}
328
329/**
330 * xmlParserValidityWarning:
331 * @ctx: an XML parser context
332 * @msg: the message to display/transmit
333 * @...: extra parameters for the message display
334 *
335 * Display and format a validity warning messages, gives file, line,
336 * position and extra parameters.
337 */
338void
339xmlParserValidityWarning(void *ctx, const char *msg, ...)
340{
341 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
342 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000343 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000344 va_list args;
345
346 if (ctxt != NULL) {
347 input = ctxt->input;
348 if ((input->filename == NULL) && (ctxt->inputNr > 1))
349 input = ctxt->inputTab[ctxt->inputNr - 2];
350
351 xmlParserPrintFileInfo(input);
352 }
353
354 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
355 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000356 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000357 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000358 xmlGenericError(xmlGenericErrorContext, str);
359 if (str != NULL)
360 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000361
362 if (ctxt != NULL) {
363 xmlParserPrintFileContext(input);
364 }
365}
366
367