blob: 26747382e66f3b0049c1bb511f13db7f74150a28 [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);
217 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000218
219 if (ctxt != NULL) {
220 xmlParserPrintFileContext(input);
221 if (cur != NULL) {
222 xmlParserPrintFileInfo(cur);
223 xmlGenericError(xmlGenericErrorContext, "\n");
224 xmlParserPrintFileContext(cur);
225 }
226 }
227}
228
229/**
230 * xmlParserWarning:
231 * @ctx: an XML parser context
232 * @msg: the message to display/transmit
233 * @...: extra parameters for the message display
234 *
235 * Display and format a warning messages, gives file, line, position and
236 * extra parameters.
237 */
238void
239xmlParserWarning(void *ctx, const char *msg, ...)
240{
241 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
242 xmlParserInputPtr input = NULL;
243 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000244 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000245 va_list args;
246
247 if (ctxt != NULL) {
248 input = ctxt->input;
249 if ((input != NULL) && (input->filename == NULL) &&
250 (ctxt->inputNr > 1)) {
251 cur = input;
252 input = ctxt->inputTab[ctxt->inputNr - 2];
253 }
254 xmlParserPrintFileInfo(input);
255 }
256
257 xmlGenericError(xmlGenericErrorContext, "warning: ");
258 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000259 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000260 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000261 xmlGenericError(xmlGenericErrorContext, str);
262 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000263
264 if (ctxt != NULL) {
265 xmlParserPrintFileContext(input);
266 if (cur != NULL) {
267 xmlParserPrintFileInfo(cur);
268 xmlGenericError(xmlGenericErrorContext, "\n");
269 xmlParserPrintFileContext(cur);
270 }
271 }
272}
273
274/************************************************************************
275 * *
276 * Handling of validation errors *
277 * *
278 ************************************************************************/
279
280/**
281 * xmlParserValidityError:
282 * @ctx: an XML parser context
283 * @msg: the message to display/transmit
284 * @...: extra parameters for the message display
285 *
286 * Display and format an validity error messages, gives file,
287 * line, position and extra parameters.
288 */
289void
290xmlParserValidityError(void *ctx, const char *msg, ...)
291{
292 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
293 xmlParserInputPtr input = NULL;
294 va_list args;
295
296 if (ctxt != NULL) {
297 input = ctxt->input;
298 if ((input->filename == NULL) && (ctxt->inputNr > 1))
299 input = ctxt->inputTab[ctxt->inputNr - 2];
300
301 xmlParserPrintFileInfo(input);
302 }
303
304 xmlGenericError(xmlGenericErrorContext, "validity error: ");
305 va_start(args, msg);
306 vfprintf(xmlGenericErrorContext, msg, args);
307 va_end(args);
308
309 if (ctxt != NULL) {
310 xmlParserPrintFileContext(input);
311 }
312}
313
314/**
315 * xmlParserValidityWarning:
316 * @ctx: an XML parser context
317 * @msg: the message to display/transmit
318 * @...: extra parameters for the message display
319 *
320 * Display and format a validity warning messages, gives file, line,
321 * position and extra parameters.
322 */
323void
324xmlParserValidityWarning(void *ctx, const char *msg, ...)
325{
326 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
327 xmlParserInputPtr input = NULL;
328 va_list args;
329
330 if (ctxt != NULL) {
331 input = ctxt->input;
332 if ((input->filename == NULL) && (ctxt->inputNr > 1))
333 input = ctxt->inputTab[ctxt->inputNr - 2];
334
335 xmlParserPrintFileInfo(input);
336 }
337
338 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
339 va_start(args, msg);
340 vfprintf(xmlGenericErrorContext, msg, args);
341 va_end(args);
342
343 if (ctxt != NULL) {
344 xmlParserPrintFileContext(input);
345 }
346}
347
348