blob: 81d722d16d5e3d0859e58c533907b54a1b30cf45 [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
Bjorn Reese70a9da52001-04-21 16:57:29 +00009#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000010
Owen Taylor3473f882001-02-23 17:55:21 +000011#include <stdarg.h>
12#include <libxml/parser.h>
13#include <libxml/xmlerror.h>
Daniel Veillarde356c282001-03-10 12:32:04 +000014#include <libxml/xmlmemory.h>
Owen Taylor3473f882001-02-23 17:55:21 +000015
16/************************************************************************
17 * *
18 * Handling of out of context errors *
19 * *
20 ************************************************************************/
21
22/**
23 * xmlGenericErrorDefaultFunc:
24 * @ctx: an error context
25 * @msg: the message to display/transmit
26 * @...: extra parameters for the message display
27 *
28 * Default handler for out of context error messages.
29 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +000030static void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000031xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
Owen Taylor3473f882001-02-23 17:55:21 +000032 va_list args;
33
34 if (xmlGenericErrorContext == NULL)
35 xmlGenericErrorContext = (void *) stderr;
36
37 va_start(args, msg);
38 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
39 va_end(args);
40}
41
42xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
43void *xmlGenericErrorContext = NULL;
44
45
46/**
47 * xmlSetGenericErrorFunc:
48 * @ctx: the new error handling context
49 * @handler: the new handler function
50 *
51 * Function to reset the handler and the error context for out of
52 * context error messages.
53 * This simply means that @handler will be called for subsequent
54 * error messages while not parsing nor validating. And @ctx will
55 * be passed as first argument to @handler
56 * One can simply force messages to be emitted to another FILE * than
57 * stderr by setting @ctx to this file handle and @handler to NULL.
58 */
59void
60xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
61 xmlGenericErrorContext = ctx;
62 if (handler != NULL)
63 xmlGenericError = handler;
64 else
65 xmlGenericError = xmlGenericErrorDefaultFunc;
66}
67
68/************************************************************************
69 * *
70 * Handling of parsing errors *
71 * *
72 ************************************************************************/
73
74/**
75 * xmlParserPrintFileInfo:
76 * @input: an xmlParserInputPtr input
77 *
78 * Displays the associated file and line informations for the current input
79 */
80
81void
82xmlParserPrintFileInfo(xmlParserInputPtr input) {
83 if (input != NULL) {
84 if (input->filename)
85 xmlGenericError(xmlGenericErrorContext,
86 "%s:%d: ", input->filename,
87 input->line);
88 else
89 xmlGenericError(xmlGenericErrorContext,
90 "Entity: line %d: ", input->line);
91 }
92}
93
94/**
95 * xmlParserPrintFileContext:
96 * @input: an xmlParserInputPtr input
97 *
98 * Displays current context within the input content for error tracking
99 */
100
101void
102xmlParserPrintFileContext(xmlParserInputPtr input) {
103 const xmlChar *cur, *base;
104 int n;
Daniel Veillard2be30642001-03-27 00:32:28 +0000105 xmlChar content[81];
106 xmlChar *ctnt;
Owen Taylor3473f882001-02-23 17:55:21 +0000107
108 if (input == NULL) return;
109 cur = input->cur;
110 base = input->base;
Daniel Veillard2be30642001-03-27 00:32:28 +0000111 /* skip backwards over any end-of-lines */
Owen Taylor3473f882001-02-23 17:55:21 +0000112 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
113 cur--;
114 }
115 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000116 /* search backwards for beginning-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000117 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
118 cur--;
119 if ((*cur == '\n') || (*cur == '\r')) cur++;
Daniel Veillard2be30642001-03-27 00:32:28 +0000120 /* search forward for end-of-line maximum 80 characters */
Owen Taylor3473f882001-02-23 17:55:21 +0000121 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000122 ctnt = content;
Owen Taylor3473f882001-02-23 17:55:21 +0000123 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
Daniel Veillard2be30642001-03-27 00:32:28 +0000124 *ctnt++ = *cur++;
Owen Taylor3473f882001-02-23 17:55:21 +0000125 n++;
126 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000127 *ctnt = 0;
128 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
129 /* create blank line with problem pointer */
Owen Taylor3473f882001-02-23 17:55:21 +0000130 cur = input->cur;
Daniel Veillard2be30642001-03-27 00:32:28 +0000131 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
132 cur--;
133 }
Owen Taylor3473f882001-02-23 17:55:21 +0000134 n = 0;
Daniel Veillard2be30642001-03-27 00:32:28 +0000135 ctnt = content;
136 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
137 *ctnt++ = ' ';
138 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000139 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000140 *(--ctnt) = '^';
141 *(++ctnt) = 0;
142 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000143}
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
Daniel Veillard92ad2102001-03-27 12:47:33 +0000161 str = (char *) xmlMalloc(150);
Daniel Veillarde356c282001-03-10 12:32:04 +0000162 if (str == NULL)
163 return(NULL);
164
Daniel Veillard92ad2102001-03-27 12:47:33 +0000165 size = 150;
Daniel Veillarde356c282001-03-10 12:32:04 +0000166 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 chars = vsnprintf(str + length, left, msg, args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000172 /* If that worked, we're done. */
173 if ((chars > -1) && (chars < left ))
174 break;
175 /* Else try again with more space. */
176 if (chars > -1) /* glibc 2.1 */
177 size += chars + 1; /* precisely what is needed */
178 else /* glibc 2.0 */
179 size += 100;
180 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
181 xmlFree(str);
182 return(NULL);
183 }
184 str = larger;
185 }
186 return(str);
187}
188
189/**
Owen Taylor3473f882001-02-23 17:55:21 +0000190 * xmlParserError:
191 * @ctx: an XML parser context
192 * @msg: the message to display/transmit
193 * @...: extra parameters for the message display
194 *
195 * Display and format an error messages, gives file, line, position and
196 * extra parameters.
197 */
198void
199xmlParserError(void *ctx, const char *msg, ...)
200{
201 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
202 xmlParserInputPtr input = NULL;
203 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000204 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000205 va_list args;
206
207 if (ctxt != NULL) {
208 input = ctxt->input;
209 if ((input != NULL) && (input->filename == NULL) &&
210 (ctxt->inputNr > 1)) {
211 cur = input;
212 input = ctxt->inputTab[ctxt->inputNr - 2];
213 }
214 xmlParserPrintFileInfo(input);
215 }
216
217 xmlGenericError(xmlGenericErrorContext, "error: ");
218 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000219 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000220 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000221 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000222 if (str != NULL)
223 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000224
225 if (ctxt != NULL) {
226 xmlParserPrintFileContext(input);
227 if (cur != NULL) {
228 xmlParserPrintFileInfo(cur);
229 xmlGenericError(xmlGenericErrorContext, "\n");
230 xmlParserPrintFileContext(cur);
231 }
232 }
233}
234
235/**
236 * xmlParserWarning:
237 * @ctx: an XML parser context
238 * @msg: the message to display/transmit
239 * @...: extra parameters for the message display
240 *
241 * Display and format a warning messages, gives file, line, position and
242 * extra parameters.
243 */
244void
245xmlParserWarning(void *ctx, const char *msg, ...)
246{
247 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
248 xmlParserInputPtr input = NULL;
249 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000250 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000251 va_list args;
252
253 if (ctxt != NULL) {
254 input = ctxt->input;
255 if ((input != NULL) && (input->filename == NULL) &&
256 (ctxt->inputNr > 1)) {
257 cur = input;
258 input = ctxt->inputTab[ctxt->inputNr - 2];
259 }
260 xmlParserPrintFileInfo(input);
261 }
262
263 xmlGenericError(xmlGenericErrorContext, "warning: ");
264 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000265 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000266 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000267 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000268 if (str != NULL)
269 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000270
271 if (ctxt != NULL) {
272 xmlParserPrintFileContext(input);
273 if (cur != NULL) {
274 xmlParserPrintFileInfo(cur);
275 xmlGenericError(xmlGenericErrorContext, "\n");
276 xmlParserPrintFileContext(cur);
277 }
278 }
279}
280
281/************************************************************************
282 * *
283 * Handling of validation errors *
284 * *
285 ************************************************************************/
286
287/**
288 * xmlParserValidityError:
289 * @ctx: an XML parser context
290 * @msg: the message to display/transmit
291 * @...: extra parameters for the message display
292 *
293 * Display and format an validity error messages, gives file,
294 * line, position and extra parameters.
295 */
296void
297xmlParserValidityError(void *ctx, const char *msg, ...)
298{
299 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
300 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000301 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000302 va_list args;
303
304 if (ctxt != NULL) {
305 input = ctxt->input;
306 if ((input->filename == NULL) && (ctxt->inputNr > 1))
307 input = ctxt->inputTab[ctxt->inputNr - 2];
308
309 xmlParserPrintFileInfo(input);
310 }
311
312 xmlGenericError(xmlGenericErrorContext, "validity error: ");
313 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000314 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000315 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000316 xmlGenericError(xmlGenericErrorContext, str);
317 if (str != NULL)
318 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000319
320 if (ctxt != NULL) {
321 xmlParserPrintFileContext(input);
322 }
323}
324
325/**
326 * xmlParserValidityWarning:
327 * @ctx: an XML parser context
328 * @msg: the message to display/transmit
329 * @...: extra parameters for the message display
330 *
331 * Display and format a validity warning messages, gives file, line,
332 * position and extra parameters.
333 */
334void
335xmlParserValidityWarning(void *ctx, const char *msg, ...)
336{
337 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
338 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000339 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000340 va_list args;
341
342 if (ctxt != NULL) {
343 input = ctxt->input;
344 if ((input->filename == NULL) && (ctxt->inputNr > 1))
345 input = ctxt->inputTab[ctxt->inputNr - 2];
346
347 xmlParserPrintFileInfo(input);
348 }
349
350 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
351 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000352 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000353 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000354 xmlGenericError(xmlGenericErrorContext, str);
355 if (str != NULL)
356 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000357
358 if (ctxt != NULL) {
359 xmlParserPrintFileContext(input);
360 }
361}
362
363