blob: 4477afed920ed696e09a6c3f41a4f2cab4d8631e [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 Veillard7533cc82001-04-24 15:52:00 +0000135 ctnt = content;
Daniel Veillard2be30642001-03-27 00:32:28 +0000136 while ((n++ < 79) && (cur > base) && (*cur != '\n') && (*cur != '\r')) {
137 *ctnt++ = ' ';
138 cur--;
Owen Taylor3473f882001-02-23 17:55:21 +0000139 }
Daniel Veillard5a7c3452001-04-26 09:16:13 +0000140 if (ctnt > content) {
141 *(--ctnt) = '^';
142 *(++ctnt) = 0;
143 } else {
144 *ctnt = '^';
145 *(++ctnt) = 0;
146 }
Daniel Veillard2be30642001-03-27 00:32:28 +0000147 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
Owen Taylor3473f882001-02-23 17:55:21 +0000148}
149
150/**
Daniel Veillarde356c282001-03-10 12:32:04 +0000151 * xmlGetVarStr:
152 * @msg: the message format
153 * @args: a va_list argument list
154 *
155 * SGS contribution
156 * Get an arbitrary-sized string for an error argument
157 * The caller must free() the returned string
158 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000159static char *
Daniel Veillarde356c282001-03-10 12:32:04 +0000160xmlGetVarStr(const char * msg, va_list args) {
161 int size;
162 int length;
163 int chars, left;
164 char *str, *larger;
165
Daniel Veillard92ad2102001-03-27 12:47:33 +0000166 str = (char *) xmlMalloc(150);
Daniel Veillarde356c282001-03-10 12:32:04 +0000167 if (str == NULL)
168 return(NULL);
169
Daniel Veillard92ad2102001-03-27 12:47:33 +0000170 size = 150;
Daniel Veillarde356c282001-03-10 12:32:04 +0000171 length = 0;
172
Daniel Veillard7d42b542001-03-20 13:22:46 +0000173 while (1) {
Daniel Veillarde356c282001-03-10 12:32:04 +0000174 left = size - length;
175 /* Try to print in the allocated space. */
Daniel Veillarda5f013b2001-03-22 12:44:45 +0000176 chars = vsnprintf(str + length, left, msg, args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000177 /* If that worked, we're done. */
178 if ((chars > -1) && (chars < left ))
179 break;
180 /* Else try again with more space. */
181 if (chars > -1) /* glibc 2.1 */
182 size += chars + 1; /* precisely what is needed */
183 else /* glibc 2.0 */
184 size += 100;
185 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
186 xmlFree(str);
187 return(NULL);
188 }
189 str = larger;
190 }
191 return(str);
192}
193
194/**
Owen Taylor3473f882001-02-23 17:55:21 +0000195 * xmlParserError:
196 * @ctx: an XML parser context
197 * @msg: the message to display/transmit
198 * @...: extra parameters for the message display
199 *
200 * Display and format an error messages, gives file, line, position and
201 * extra parameters.
202 */
203void
204xmlParserError(void *ctx, const char *msg, ...)
205{
206 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
207 xmlParserInputPtr input = NULL;
208 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000209 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000210 va_list args;
211
212 if (ctxt != NULL) {
213 input = ctxt->input;
214 if ((input != NULL) && (input->filename == NULL) &&
215 (ctxt->inputNr > 1)) {
216 cur = input;
217 input = ctxt->inputTab[ctxt->inputNr - 2];
218 }
219 xmlParserPrintFileInfo(input);
220 }
221
222 xmlGenericError(xmlGenericErrorContext, "error: ");
223 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000224 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000225 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000226 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000227 if (str != NULL)
228 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000229
230 if (ctxt != NULL) {
231 xmlParserPrintFileContext(input);
232 if (cur != NULL) {
233 xmlParserPrintFileInfo(cur);
234 xmlGenericError(xmlGenericErrorContext, "\n");
235 xmlParserPrintFileContext(cur);
236 }
237 }
238}
239
240/**
241 * xmlParserWarning:
242 * @ctx: an XML parser context
243 * @msg: the message to display/transmit
244 * @...: extra parameters for the message display
245 *
246 * Display and format a warning messages, gives file, line, position and
247 * extra parameters.
248 */
249void
250xmlParserWarning(void *ctx, const char *msg, ...)
251{
252 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
253 xmlParserInputPtr input = NULL;
254 xmlParserInputPtr cur = NULL;
Daniel Veillarde356c282001-03-10 12:32:04 +0000255 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000256 va_list args;
257
258 if (ctxt != NULL) {
259 input = ctxt->input;
260 if ((input != NULL) && (input->filename == NULL) &&
261 (ctxt->inputNr > 1)) {
262 cur = input;
263 input = ctxt->inputTab[ctxt->inputNr - 2];
264 }
265 xmlParserPrintFileInfo(input);
266 }
267
268 xmlGenericError(xmlGenericErrorContext, "warning: ");
269 va_start(args, msg);
Daniel Veillarde356c282001-03-10 12:32:04 +0000270 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000271 va_end(args);
Daniel Veillarde356c282001-03-10 12:32:04 +0000272 xmlGenericError(xmlGenericErrorContext, str);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000273 if (str != NULL)
274 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000275
276 if (ctxt != NULL) {
277 xmlParserPrintFileContext(input);
278 if (cur != NULL) {
279 xmlParserPrintFileInfo(cur);
280 xmlGenericError(xmlGenericErrorContext, "\n");
281 xmlParserPrintFileContext(cur);
282 }
283 }
284}
285
286/************************************************************************
287 * *
288 * Handling of validation errors *
289 * *
290 ************************************************************************/
291
292/**
293 * xmlParserValidityError:
294 * @ctx: an XML parser context
295 * @msg: the message to display/transmit
296 * @...: extra parameters for the message display
297 *
298 * Display and format an validity error messages, gives file,
299 * line, position and extra parameters.
300 */
301void
302xmlParserValidityError(void *ctx, const char *msg, ...)
303{
304 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
305 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000306 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000307 va_list args;
308
309 if (ctxt != NULL) {
310 input = ctxt->input;
311 if ((input->filename == NULL) && (ctxt->inputNr > 1))
312 input = ctxt->inputTab[ctxt->inputNr - 2];
313
314 xmlParserPrintFileInfo(input);
315 }
316
317 xmlGenericError(xmlGenericErrorContext, "validity error: ");
318 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000319 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000320 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000321 xmlGenericError(xmlGenericErrorContext, str);
322 if (str != NULL)
323 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000324
325 if (ctxt != NULL) {
326 xmlParserPrintFileContext(input);
327 }
328}
329
330/**
331 * xmlParserValidityWarning:
332 * @ctx: an XML parser context
333 * @msg: the message to display/transmit
334 * @...: extra parameters for the message display
335 *
336 * Display and format a validity warning messages, gives file, line,
337 * position and extra parameters.
338 */
339void
340xmlParserValidityWarning(void *ctx, const char *msg, ...)
341{
342 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
343 xmlParserInputPtr input = NULL;
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000344 char * str;
Owen Taylor3473f882001-02-23 17:55:21 +0000345 va_list args;
346
347 if (ctxt != NULL) {
348 input = ctxt->input;
349 if ((input->filename == NULL) && (ctxt->inputNr > 1))
350 input = ctxt->inputTab[ctxt->inputNr - 2];
351
352 xmlParserPrintFileInfo(input);
353 }
354
355 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
356 va_start(args, msg);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000357 str = xmlGetVarStr(msg, args);
Owen Taylor3473f882001-02-23 17:55:21 +0000358 va_end(args);
Daniel Veillard9e7160d2001-03-18 23:17:47 +0000359 xmlGenericError(xmlGenericErrorContext, str);
360 if (str != NULL)
361 xmlFree(str);
Owen Taylor3473f882001-02-23 17:55:21 +0000362
363 if (ctxt != NULL) {
364 xmlParserPrintFileContext(input);
365 }
366}
367
368