2 * error.c: module displaying/handling XML parser errors
4 * See Copyright for the status of this software.
6 * Daniel Veillard <daniel@veillard.com>
13 #include <libxml/parser.h>
14 #include <libxml/xmlerror.h>
15 #include <libxml/xmlmemory.h>
16 #include <libxml/globals.h>
18 void xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED,
22 #define XML_GET_VAR_STR(msg, str) { \
28 str = (char *) xmlMalloc(150); \
36 chars = vsnprintf(str, size, msg, ap); \
38 if ((chars > -1) && (chars < size)) \
44 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
52 /************************************************************************
54 * Handling of out of context errors *
56 ************************************************************************/
59 * xmlGenericErrorDefaultFunc:
60 * @ctx: an error context
61 * @msg: the message to display/transmit
62 * @...: extra parameters for the message display
64 * Default handler for out of context error messages.
67 xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
70 if (xmlGenericErrorContext == NULL)
71 xmlGenericErrorContext = (void *) stderr;
74 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
79 * initGenericErrorDefaultFunc:
80 * @handler: the handler
82 * Set or reset (if NULL) the default handler for generic errors
83 * to the builtin error function.
86 initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
89 xmlGenericError = xmlGenericErrorDefaultFunc;
91 (*handler) = xmlGenericErrorDefaultFunc;
95 * xmlSetGenericErrorFunc:
96 * @ctx: the new error handling context
97 * @handler: the new handler function
99 * Function to reset the handler and the error context for out of
100 * context error messages.
101 * This simply means that @handler will be called for subsequent
102 * error messages while not parsing nor validating. And @ctx will
103 * be passed as first argument to @handler
104 * One can simply force messages to be emitted to another FILE * than
105 * stderr by setting @ctx to this file handle and @handler to NULL.
108 xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
109 xmlGenericErrorContext = ctx;
111 xmlGenericError = handler;
113 xmlGenericError = xmlGenericErrorDefaultFunc;
116 /************************************************************************
118 * Handling of parsing errors *
120 ************************************************************************/
123 * xmlParserPrintFileInfo:
124 * @input: an xmlParserInputPtr input
126 * Displays the associated file and line informations for the current input
130 xmlParserPrintFileInfo(xmlParserInputPtr input) {
133 xmlGenericError(xmlGenericErrorContext,
134 "%s:%d: ", input->filename,
137 xmlGenericError(xmlGenericErrorContext,
138 "Entity: line %d: ", input->line);
143 * xmlParserPrintFileContext:
144 * @input: an xmlParserInputPtr input
146 * Displays current context within the input content for error tracking
150 xmlParserPrintFileContext(xmlParserInputPtr input) {
151 const xmlChar *cur, *base;
152 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
153 xmlChar content[81]; /* space for 80 chars + line terminator */
156 if (input == NULL) return;
159 /* skip backwards over any end-of-lines */
160 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
164 /* search backwards for beginning-of-line (to max buff size) */
165 while ((n++ < (sizeof(content)-1)) && (cur > base) &&
166 (*(cur) != '\n') && (*(cur) != '\r'))
168 if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
169 /* calculate the error position in terms of the current position */
170 col = input->cur - cur;
171 /* search forward for end-of-line (to max buff size) */
174 /* copy selected text to our buffer */
175 while ((*cur != 0) && (*(cur) != '\n') &&
176 (*(cur) != '\r') && (n < sizeof(content)-1)) {
181 /* print out the selected text */
182 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
183 /* create blank line with problem pointer */
186 /* (leave buffer space for pointer + line terminator) */
187 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
194 xmlGenericError(xmlGenericErrorContext,"%s\n", content);
200 * @msg: the message format
201 * @args: a va_list argument list
204 * Get an arbitrary-sized string for an error argument
205 * The caller must free() the returned string
208 xmlGetVarStr(const char * msg, va_list args) {
215 str = (char *) xmlMalloc(150);
223 left = size - length;
224 /* Try to print in the allocated space. */
226 chars = vsnprintf(str + length, left, msg, ap);
228 /* If that worked, we're done. */
229 if ((chars > -1) && (chars < left ))
231 /* Else try again with more space. */
232 if (chars > -1) /* glibc 2.1 */
233 size += chars + 1; /* precisely what is needed */
236 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
248 * @ctx: an XML parser context
249 * @msg: the message to display/transmit
250 * @...: extra parameters for the message display
252 * Display and format an error messages, gives file, line, position and
256 xmlParserError(void *ctx, const char *msg, ...)
258 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
259 xmlParserInputPtr input = NULL;
260 xmlParserInputPtr cur = NULL;
265 if ((input != NULL) && (input->filename == NULL) &&
266 (ctxt->inputNr > 1)) {
268 input = ctxt->inputTab[ctxt->inputNr - 2];
270 xmlParserPrintFileInfo(input);
273 xmlGenericError(xmlGenericErrorContext, "error: ");
274 XML_GET_VAR_STR(msg, str);
275 xmlGenericError(xmlGenericErrorContext, "%s", str);
280 xmlParserPrintFileContext(input);
282 xmlParserPrintFileInfo(cur);
283 xmlGenericError(xmlGenericErrorContext, "\n");
284 xmlParserPrintFileContext(cur);
291 * @ctx: an XML parser context
292 * @msg: the message to display/transmit
293 * @...: extra parameters for the message display
295 * Display and format a warning messages, gives file, line, position and
299 xmlParserWarning(void *ctx, const char *msg, ...)
301 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
302 xmlParserInputPtr input = NULL;
303 xmlParserInputPtr cur = NULL;
308 if ((input != NULL) && (input->filename == NULL) &&
309 (ctxt->inputNr > 1)) {
311 input = ctxt->inputTab[ctxt->inputNr - 2];
313 xmlParserPrintFileInfo(input);
316 xmlGenericError(xmlGenericErrorContext, "warning: ");
317 XML_GET_VAR_STR(msg, str);
318 xmlGenericError(xmlGenericErrorContext, "%s", str);
323 xmlParserPrintFileContext(input);
325 xmlParserPrintFileInfo(cur);
326 xmlGenericError(xmlGenericErrorContext, "\n");
327 xmlParserPrintFileContext(cur);
332 /************************************************************************
334 * Handling of validation errors *
336 ************************************************************************/
339 * xmlParserValidityError:
340 * @ctx: an XML parser context
341 * @msg: the message to display/transmit
342 * @...: extra parameters for the message display
344 * Display and format an validity error messages, gives file,
345 * line, position and extra parameters.
348 xmlParserValidityError(void *ctx, const char *msg, ...)
350 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
351 xmlParserInputPtr input = NULL;
353 int len = xmlStrlen((const xmlChar *) msg);
354 static int had_info = 0;
356 if ((len > 1) && (msg[len - 2] != ':')) {
359 if ((input->filename == NULL) && (ctxt->inputNr > 1))
360 input = ctxt->inputTab[ctxt->inputNr - 2];
363 xmlParserPrintFileInfo(input);
366 xmlGenericError(xmlGenericErrorContext, "validity error: ");
372 XML_GET_VAR_STR(msg, str);
373 xmlGenericError(xmlGenericErrorContext, "%s", str);
377 if ((ctxt != NULL) && (input != NULL)) {
378 xmlParserPrintFileContext(input);
383 * xmlParserValidityWarning:
384 * @ctx: an XML parser context
385 * @msg: the message to display/transmit
386 * @...: extra parameters for the message display
388 * Display and format a validity warning messages, gives file, line,
389 * position and extra parameters.
392 xmlParserValidityWarning(void *ctx, const char *msg, ...)
394 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
395 xmlParserInputPtr input = NULL;
397 int len = xmlStrlen((const xmlChar *) msg);
399 if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
401 if ((input->filename == NULL) && (ctxt->inputNr > 1))
402 input = ctxt->inputTab[ctxt->inputNr - 2];
404 xmlParserPrintFileInfo(input);
407 xmlGenericError(xmlGenericErrorContext, "validity warning: ");
408 XML_GET_VAR_STR(msg, str);
409 xmlGenericError(xmlGenericErrorContext, "%s", str);
414 xmlParserPrintFileContext(input);