1 /*
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.com>
7 */
8
9 #define IN_LIBXML
10 #include "libxml.h"
11
12 #include <string.h>
13 #include <stdarg.h>
14 #include <stdlib.h>
15 #include <libxml/parser.h>
16 #include <libxml/xmlerror.h>
17 #include <libxml/xmlmemory.h>
18
19 #include "private/error.h"
20 #include "private/globals.h"
21 #include "private/string.h"
22
23 /**
24 * xmlIsCatastrophicError:
25 * @level: error level
26 * @code: error code
27 *
28 * Returns true if an error is catastrophic.
29 */
30 int
xmlIsCatastrophicError(int level,int code)31 xmlIsCatastrophicError(int level, int code) {
32 int fatal = 0;
33
34 if (level != XML_ERR_FATAL)
35 return(0);
36
37 switch (code) {
38 case XML_ERR_NO_MEMORY:
39 /* case XML_ERR_RESOURCE_LIMIT: */
40 case XML_ERR_SYSTEM:
41 case XML_ERR_ARGUMENT:
42 case XML_ERR_INTERNAL_ERROR:
43 fatal = 1;
44 break;
45 default:
46 if ((code >= 1500) && (code <= 1599))
47 fatal = 1;
48 break;
49 }
50
51 return(fatal);
52 }
53
54 /************************************************************************
55 * *
56 * Error struct *
57 * *
58 ************************************************************************/
59
60 static int
xmlVSetError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,va_list ap)61 xmlVSetError(xmlError *err,
62 void *ctxt, xmlNodePtr node,
63 int domain, int code, xmlErrorLevel level,
64 const char *file, int line,
65 const char *str1, const char *str2, const char *str3,
66 int int1, int col,
67 const char *fmt, va_list ap)
68 {
69 char *message = NULL;
70 char *fileCopy = NULL;
71 char *str1Copy = NULL;
72 char *str2Copy = NULL;
73 char *str3Copy = NULL;
74
75 if (code == XML_ERR_OK) {
76 xmlResetError(err);
77 return(0);
78 }
79
80 /*
81 * Formatting the message
82 */
83 if (fmt == NULL) {
84 message = xmlMemStrdup("No error message provided");
85 } else {
86 xmlChar *tmp;
87 int res;
88
89 res = xmlStrVASPrintf(&tmp, MAX_ERR_MSG_SIZE, fmt, ap);
90 if (res < 0)
91 goto err_memory;
92 message = (char *) tmp;
93 }
94 if (message == NULL)
95 goto err_memory;
96
97 if (file != NULL) {
98 fileCopy = (char *) xmlStrdup((const xmlChar *) file);
99 if (fileCopy == NULL)
100 goto err_memory;
101 }
102 if (str1 != NULL) {
103 str1Copy = (char *) xmlStrdup((const xmlChar *) str1);
104 if (str1Copy == NULL)
105 goto err_memory;
106 }
107 if (str2 != NULL) {
108 str2Copy = (char *) xmlStrdup((const xmlChar *) str2);
109 if (str2Copy == NULL)
110 goto err_memory;
111 }
112 if (str3 != NULL) {
113 str3Copy = (char *) xmlStrdup((const xmlChar *) str3);
114 if (str3Copy == NULL)
115 goto err_memory;
116 }
117
118 xmlResetError(err);
119
120 err->domain = domain;
121 err->code = code;
122 err->message = message;
123 err->level = level;
124 err->file = fileCopy;
125 err->line = line;
126 err->str1 = str1Copy;
127 err->str2 = str2Copy;
128 err->str3 = str3Copy;
129 err->int1 = int1;
130 err->int2 = col;
131 err->node = node;
132 err->ctxt = ctxt;
133
134 return(0);
135
136 err_memory:
137 xmlFree(message);
138 xmlFree(fileCopy);
139 xmlFree(str1Copy);
140 xmlFree(str2Copy);
141 xmlFree(str3Copy);
142 return(-1);
143 }
144
145 static int LIBXML_ATTR_FORMAT(14,15)
xmlSetError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,...)146 xmlSetError(xmlError *err,
147 void *ctxt, xmlNodePtr node,
148 int domain, int code, xmlErrorLevel level,
149 const char *file, int line,
150 const char *str1, const char *str2, const char *str3,
151 int int1, int col,
152 const char *fmt, ...)
153 {
154 va_list ap;
155 int res;
156
157 va_start(ap, fmt);
158 res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
159 str1, str2, str3, int1, col, fmt, ap);
160 va_end(ap);
161
162 return(res);
163 }
164
165 static int
xmlVUpdateError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,va_list ap)166 xmlVUpdateError(xmlError *err,
167 void *ctxt, xmlNodePtr node,
168 int domain, int code, xmlErrorLevel level,
169 const char *file, int line,
170 const char *str1, const char *str2, const char *str3,
171 int int1, int col,
172 const char *fmt, va_list ap)
173 {
174 int res;
175
176 /*
177 * Find first element parent.
178 */
179 if (node != NULL) {
180 int i;
181
182 for (i = 0; i < 10; i++) {
183 if ((node->type == XML_ELEMENT_NODE) ||
184 (node->parent == NULL))
185 break;
186 node = node->parent;
187 }
188 }
189
190 /*
191 * Get file and line from node.
192 */
193 if (node != NULL) {
194 if ((file == NULL) && (node->doc != NULL))
195 file = (const char *) node->doc->URL;
196
197 if (line == 0) {
198 if (node->type == XML_ELEMENT_NODE)
199 line = node->line;
200 if ((line == 0) || (line == 65535))
201 line = xmlGetLineNo(node);
202 }
203 }
204
205 res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
206 str1, str2, str3, int1, col, fmt, ap);
207
208 return(res);
209 }
210
211 /************************************************************************
212 * *
213 * Handling of out of context errors *
214 * *
215 ************************************************************************/
216
217 /**
218 * xmlGenericErrorDefaultFunc:
219 * @ctx: an error context
220 * @msg: the message to display/transmit
221 * @...: extra parameters for the message display
222 *
223 * Default handler for out of context error messages.
224 */
225 void
xmlGenericErrorDefaultFunc(void * ctx ATTRIBUTE_UNUSED,const char * msg,...)226 xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
227 va_list args;
228
229 if (xmlGenericErrorContext == NULL)
230 xmlGenericErrorContext = (void *) stderr;
231
232 va_start(args, msg);
233 vfprintf((FILE *)xmlGenericErrorContext, msg, args);
234 va_end(args);
235 }
236
237 /**
238 * initGenericErrorDefaultFunc:
239 * @handler: the handler
240 *
241 * DEPRECATED: Use xmlSetGenericErrorFunc.
242 *
243 * Set or reset (if NULL) the default handler for generic errors
244 * to the builtin error function.
245 */
246 void
initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)247 initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
248 {
249 if (handler == NULL)
250 xmlGenericError = xmlGenericErrorDefaultFunc;
251 else
252 xmlGenericError = (*handler);
253 }
254
255 /**
256 * xmlSetGenericErrorFunc:
257 * @ctx: the new error handling context
258 * @handler: the new handler function
259 *
260 * DEPRECATED: See xmlSetStructuredErrorFunc for alternatives.
261 *
262 * Set the global "generic" handler and context for error messages.
263 * The generic error handler will only receive fragments of error
264 * messages which should be concatenated or printed to a stream.
265 *
266 * If handler is NULL, use the built-in default handler which prints
267 * to stderr.
268 *
269 * Since this is a global setting, it's a good idea to reset the
270 * error handler to its default value after collecting the errors
271 * you're interested in.
272 *
273 * For multi-threaded applications, this must be set separately for
274 * each thread.
275 */
276 void
xmlSetGenericErrorFunc(void * ctx,xmlGenericErrorFunc handler)277 xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
278 xmlGenericErrorContext = ctx;
279 if (handler != NULL)
280 xmlGenericError = handler;
281 else
282 xmlGenericError = xmlGenericErrorDefaultFunc;
283 }
284
285 /**
286 * xmlSetStructuredErrorFunc:
287 * @ctx: the new error handling context
288 * @handler: the new handler function
289 *
290 * DEPRECATED: Use a per-context error handler.
291 *
292 * It's recommended to use the per-context error handlers instead:
293 *
294 * - xmlCtxtSetErrorHandler (since 2.13.0)
295 * - xmlTextReaderSetStructuredErrorHandler
296 * - xmlXPathSetErrorHandler (since 2.13.0)
297 * - xmlXIncludeSetErrorHandler (since 2.13.0)
298 * - xmlSchemaSetParserStructuredErrors
299 * - xmlSchemaSetValidStructuredErrors
300 * - xmlRelaxNGSetParserStructuredErrors
301 * - xmlRelaxNGSetValidStructuredErrors
302 *
303 * Set the global "structured" handler and context for error messages.
304 * If handler is NULL, the error handler is deactivated.
305 *
306 * The structured error handler takes precedence over "generic"
307 * handlers, even per-context generic handlers.
308 *
309 * Since this is a global setting, it's a good idea to deactivate the
310 * error handler after collecting the errors you're interested in.
311 *
312 * For multi-threaded applications, this must be set separately for
313 * each thread.
314 */
315 void
xmlSetStructuredErrorFunc(void * ctx,xmlStructuredErrorFunc handler)316 xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
317 xmlStructuredErrorContext = ctx;
318 xmlStructuredError = handler;
319 }
320
321 /************************************************************************
322 * *
323 * Handling of parsing errors *
324 * *
325 ************************************************************************/
326
327 /**
328 * xmlParserPrintFileInfo:
329 * @input: an xmlParserInputPtr input
330 *
331 * DEPRECATED: Use xmlFormatError.
332 *
333 * Displays the associated file and line information for the current input
334 */
335
336 void
xmlParserPrintFileInfo(xmlParserInputPtr input)337 xmlParserPrintFileInfo(xmlParserInputPtr input) {
338 if (input != NULL) {
339 if (input->filename)
340 xmlGenericError(xmlGenericErrorContext,
341 "%s:%d: ", input->filename,
342 input->line);
343 else
344 xmlGenericError(xmlGenericErrorContext,
345 "Entity: line %d: ", input->line);
346 }
347 }
348
349 /**
350 * xmlParserPrintFileContextInternal:
351 * @input: an xmlParserInputPtr input
352 *
353 * Displays current context within the input content for error tracking
354 */
355
356 static void
xmlParserPrintFileContextInternal(xmlParserInputPtr input,xmlGenericErrorFunc channel,void * data)357 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
358 xmlGenericErrorFunc channel, void *data ) {
359 const xmlChar *cur, *base, *start;
360 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
361 xmlChar content[81]; /* space for 80 chars + line terminator */
362 xmlChar *ctnt;
363
364 if ((input == NULL) || (input->cur == NULL))
365 return;
366
367 cur = input->cur;
368 base = input->base;
369 /* skip backwards over any end-of-lines */
370 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
371 cur--;
372 }
373 n = 0;
374 /* search backwards for beginning-of-line (to max buff size) */
375 while ((n < sizeof(content) - 1) && (cur > base) &&
376 (*cur != '\n') && (*cur != '\r')) {
377 cur--;
378 n++;
379 }
380 if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) {
381 cur++;
382 } else {
383 /* skip over continuation bytes */
384 while ((cur < input->cur) && ((*cur & 0xC0) == 0x80))
385 cur++;
386 }
387 /* calculate the error position in terms of the current position */
388 col = input->cur - cur;
389 /* search forward for end-of-line (to max buff size) */
390 n = 0;
391 start = cur;
392 /* copy selected text to our buffer */
393 while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) {
394 int len = input->end - cur;
395 int c = xmlGetUTF8Char(cur, &len);
396
397 if ((c < 0) || (n + len > sizeof(content)-1))
398 break;
399 cur += len;
400 n += len;
401 }
402 memcpy(content, start, n);
403 content[n] = 0;
404 /* print out the selected text */
405 channel(data ,"%s\n", content);
406 /* create blank line with problem pointer */
407 n = 0;
408 ctnt = content;
409 /* (leave buffer space for pointer + line terminator) */
410 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
411 if (*(ctnt) != '\t')
412 *(ctnt) = ' ';
413 ctnt++;
414 }
415 *ctnt++ = '^';
416 *ctnt = 0;
417 channel(data ,"%s\n", content);
418 }
419
420 /**
421 * xmlParserPrintFileContext:
422 * @input: an xmlParserInputPtr input
423 *
424 * DEPRECATED: Use xmlFormatError.
425 *
426 * Displays current context within the input content for error tracking
427 */
428 void
xmlParserPrintFileContext(xmlParserInputPtr input)429 xmlParserPrintFileContext(xmlParserInputPtr input) {
430 xmlParserPrintFileContextInternal(input, xmlGenericError,
431 xmlGenericErrorContext);
432 }
433
434 /**
435 * xmlFormatError:
436 * @err: the error
437 * @channel: callback
438 * @data: user data for callback
439 *
440 * Report a formatted error to a printf-like callback.
441 *
442 * This can result in a verbose multi-line report including additional
443 * information from the parser context.
444 *
445 * Available since 2.13.0.
446 */
447 void
xmlFormatError(const xmlError * err,xmlGenericErrorFunc channel,void * data)448 xmlFormatError(const xmlError *err, xmlGenericErrorFunc channel, void *data)
449 {
450 const char *message;
451 const char *file;
452 int line;
453 int code;
454 int domain;
455 const xmlChar *name = NULL;
456 xmlNodePtr node;
457 xmlErrorLevel level;
458 xmlParserCtxtPtr ctxt = NULL;
459 xmlParserInputPtr input = NULL;
460 xmlParserInputPtr cur = NULL;
461
462 if ((err == NULL) || (channel == NULL))
463 return;
464
465 message = err->message;
466 file = err->file;
467 line = err->line;
468 code = err->code;
469 domain = err->domain;
470 level = err->level;
471 node = err->node;
472
473 if (code == XML_ERR_OK)
474 return;
475
476 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
477 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
478 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
479 ctxt = err->ctxt;
480 }
481
482 if ((node != NULL) && (node->type == XML_ELEMENT_NODE) &&
483 (domain != XML_FROM_SCHEMASV))
484 name = node->name;
485
486 /*
487 * Maintain the compatibility with the legacy error handling
488 */
489 if ((ctxt != NULL) && (ctxt->input != NULL)) {
490 input = ctxt->input;
491 if ((input->filename == NULL) &&
492 (ctxt->inputNr > 1)) {
493 cur = input;
494 input = ctxt->inputTab[ctxt->inputNr - 2];
495 }
496 if (input->filename)
497 channel(data, "%s:%d: ", input->filename, input->line);
498 else if ((line != 0) && (domain == XML_FROM_PARSER))
499 channel(data, "Entity: line %d: ", input->line);
500 } else {
501 if (file != NULL)
502 channel(data, "%s:%d: ", file, line);
503 else if ((line != 0) &&
504 ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
505 (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
506 (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
507 channel(data, "Entity: line %d: ", line);
508 }
509 if (name != NULL) {
510 channel(data, "element %s: ", name);
511 }
512 switch (domain) {
513 case XML_FROM_PARSER:
514 channel(data, "parser ");
515 break;
516 case XML_FROM_NAMESPACE:
517 channel(data, "namespace ");
518 break;
519 case XML_FROM_DTD:
520 case XML_FROM_VALID:
521 channel(data, "validity ");
522 break;
523 case XML_FROM_HTML:
524 channel(data, "HTML parser ");
525 break;
526 case XML_FROM_MEMORY:
527 channel(data, "memory ");
528 break;
529 case XML_FROM_OUTPUT:
530 channel(data, "output ");
531 break;
532 case XML_FROM_IO:
533 channel(data, "I/O ");
534 break;
535 case XML_FROM_XINCLUDE:
536 channel(data, "XInclude ");
537 break;
538 case XML_FROM_XPATH:
539 channel(data, "XPath ");
540 break;
541 case XML_FROM_XPOINTER:
542 channel(data, "parser ");
543 break;
544 case XML_FROM_REGEXP:
545 channel(data, "regexp ");
546 break;
547 case XML_FROM_MODULE:
548 channel(data, "module ");
549 break;
550 case XML_FROM_SCHEMASV:
551 channel(data, "Schemas validity ");
552 break;
553 case XML_FROM_SCHEMASP:
554 channel(data, "Schemas parser ");
555 break;
556 case XML_FROM_RELAXNGP:
557 channel(data, "Relax-NG parser ");
558 break;
559 case XML_FROM_RELAXNGV:
560 channel(data, "Relax-NG validity ");
561 break;
562 case XML_FROM_CATALOG:
563 channel(data, "Catalog ");
564 break;
565 case XML_FROM_C14N:
566 channel(data, "C14N ");
567 break;
568 case XML_FROM_XSLT:
569 channel(data, "XSLT ");
570 break;
571 case XML_FROM_I18N:
572 channel(data, "encoding ");
573 break;
574 case XML_FROM_SCHEMATRONV:
575 channel(data, "schematron ");
576 break;
577 case XML_FROM_BUFFER:
578 channel(data, "internal buffer ");
579 break;
580 case XML_FROM_URI:
581 channel(data, "URI ");
582 break;
583 default:
584 break;
585 }
586 switch (level) {
587 case XML_ERR_NONE:
588 channel(data, ": ");
589 break;
590 case XML_ERR_WARNING:
591 channel(data, "warning : ");
592 break;
593 case XML_ERR_ERROR:
594 channel(data, "error : ");
595 break;
596 case XML_ERR_FATAL:
597 channel(data, "error : ");
598 break;
599 }
600 if (message != NULL) {
601 int len;
602 len = xmlStrlen((const xmlChar *) message);
603 if ((len > 0) && (message[len - 1] != '\n'))
604 channel(data, "%s\n", message);
605 else
606 channel(data, "%s", message);
607 } else {
608 channel(data, "%s\n", "No error message provided");
609 }
610
611 if (ctxt != NULL) {
612 if ((input != NULL) &&
613 ((input->buf == NULL) || (input->buf->encoder == NULL)) &&
614 (code == XML_ERR_INVALID_ENCODING) &&
615 (input->cur < input->end)) {
616 int i;
617
618 channel(data, "Bytes:");
619 for (i = 0; i < 4; i++) {
620 if (input->cur + i >= input->end)
621 break;
622 channel(data, " 0x%02X", input->cur[i]);
623 }
624 channel(data, "\n");
625 }
626
627 xmlParserPrintFileContextInternal(input, channel, data);
628
629 if (cur != NULL) {
630 if (cur->filename)
631 channel(data, "%s:%d: \n", cur->filename, cur->line);
632 else if ((line != 0) && (domain == XML_FROM_PARSER))
633 channel(data, "Entity: line %d: \n", cur->line);
634 xmlParserPrintFileContextInternal(cur, channel, data);
635 }
636 }
637 if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
638 (err->int1 < 100) &&
639 (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
640 xmlChar buf[150];
641 int i;
642
643 channel(data, "%s\n", err->str1);
644 for (i=0;i < err->int1;i++)
645 buf[i] = ' ';
646 buf[i++] = '^';
647 buf[i] = 0;
648 channel(data, "%s\n", buf);
649 }
650 }
651
652 /**
653 * xmlRaiseMemoryError:
654 * @schannel: the structured callback channel
655 * @channel: the old callback channel
656 * @data: the callback data
657 * @domain: the domain for the error
658 * @error: optional error struct to be filled
659 *
660 * Update the global and optional error structure, then forward the
661 * error to an error handler.
662 *
663 * This function doesn't make memory allocations which are likely
664 * to fail after an OOM error.
665 */
666 void
xmlRaiseMemoryError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,int domain,xmlError * error)667 xmlRaiseMemoryError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel,
668 void *data, int domain, xmlError *error)
669 {
670 xmlError *lastError = xmlGetLastErrorInternal();
671
672 xmlResetLastError();
673 lastError->domain = domain;
674 lastError->code = XML_ERR_NO_MEMORY;
675 lastError->level = XML_ERR_FATAL;
676
677 if (error != NULL) {
678 xmlResetError(error);
679 error->domain = domain;
680 error->code = XML_ERR_NO_MEMORY;
681 error->level = XML_ERR_FATAL;
682 }
683
684 if (schannel != NULL) {
685 schannel(data, lastError);
686 } else if (xmlStructuredError != NULL) {
687 xmlStructuredError(xmlStructuredErrorContext, lastError);
688 } else if (channel != NULL) {
689 channel(data, "libxml2: out of memory\n");
690 }
691 }
692
693 /**
694 * xmlVRaiseError:
695 * @schannel: the structured callback channel
696 * @channel: the old callback channel
697 * @data: the callback data
698 * @ctx: the parser context or NULL
699 * @node: the current node or NULL
700 * @domain: the domain for the error
701 * @code: the code for the error
702 * @level: the xmlErrorLevel for the error
703 * @file: the file source of the error (or NULL)
704 * @line: the line of the error or 0 if N/A
705 * @str1: extra string info
706 * @str2: extra string info
707 * @str3: extra string info
708 * @int1: extra int info
709 * @col: column number of the error or 0 if N/A
710 * @msg: the message to display/transmit
711 * @ap: extra parameters for the message display
712 *
713 * Update the appropriate global or contextual error structure,
714 * then forward the error message down the parser or generic
715 * error callback handler
716 *
717 * Returns 0 on success, -1 if a memory allocation failed.
718 */
719 int
xmlVRaiseError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,void * ctx,xmlNode * node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * msg,va_list ap)720 xmlVRaiseError(xmlStructuredErrorFunc schannel,
721 xmlGenericErrorFunc channel, void *data, void *ctx,
722 xmlNode *node, int domain, int code, xmlErrorLevel level,
723 const char *file, int line, const char *str1,
724 const char *str2, const char *str3, int int1, int col,
725 const char *msg, va_list ap)
726 {
727 xmlParserCtxtPtr ctxt = NULL;
728 /* xmlLastError is a macro retrieving the per-thread global. */
729 xmlErrorPtr lastError = xmlGetLastErrorInternal();
730 xmlErrorPtr to = lastError;
731
732 if (code == XML_ERR_OK)
733 return(0);
734 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
735 if (code == XML_ERR_INTERNAL_ERROR)
736 xmlAbort("Unexpected error: %d\n", code);
737 #endif
738 if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
739 return(0);
740
741 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
742 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
743 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
744 ctxt = (xmlParserCtxtPtr) ctx;
745
746 if (ctxt != NULL)
747 to = &ctxt->lastError;
748 }
749
750 if (xmlVUpdateError(to, ctxt, node, domain, code, level, file, line,
751 str1, str2, str3, int1, col, msg, ap))
752 return(-1);
753
754 if (to != lastError) {
755 if (xmlCopyError(to, lastError) < 0)
756 return(-1);
757 }
758
759 if (schannel != NULL) {
760 schannel(data, to);
761 } else if (xmlStructuredError != NULL) {
762 xmlStructuredError(xmlStructuredErrorContext, to);
763 } else if (channel != NULL) {
764 /* Don't invoke legacy error handlers */
765 if ((channel == xmlGenericErrorDefaultFunc) ||
766 (channel == xmlParserError) ||
767 (channel == xmlParserWarning) ||
768 (channel == xmlParserValidityError) ||
769 (channel == xmlParserValidityWarning))
770 xmlFormatError(to, xmlGenericError, xmlGenericErrorContext);
771 else
772 channel(data, "%s", to->message);
773 }
774
775 return(0);
776 }
777
778 /**
779 * xmlRaiseError:
780 * @schannel: the structured callback channel
781 * @channel: the old callback channel
782 * @data: the callback data
783 * @ctx: the parser context or NULL
784 * @node: the node or NULL
785 * @domain: the domain for the error
786 * @code: the code for the error
787 * @level: the xmlErrorLevel for the error
788 * @file: the file source of the error (or NULL)
789 * @line: the line of the error or 0 if N/A
790 * @str1: extra string info
791 * @str2: extra string info
792 * @str3: extra string info
793 * @int1: extra int info
794 * @col: column number of the error or 0 if N/A
795 * @msg: the message to display/transmit
796 * @...: extra parameters for the message display
797 *
798 * Update the appropriate global or contextual error structure,
799 * then forward the error message down the parser or generic
800 * error callback handler
801 *
802 * Returns 0 on success, -1 if a memory allocation failed.
803 */
804 int
xmlRaiseError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,void * ctx,xmlNode * node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * msg,...)805 xmlRaiseError(xmlStructuredErrorFunc schannel,
806 xmlGenericErrorFunc channel, void *data, void *ctx,
807 xmlNode *node, int domain, int code, xmlErrorLevel level,
808 const char *file, int line, const char *str1,
809 const char *str2, const char *str3, int int1, int col,
810 const char *msg, ...)
811 {
812 va_list ap;
813 int res;
814
815 va_start(ap, msg);
816 res = xmlVRaiseError(schannel, channel, data, ctx, node, domain, code,
817 level, file, line, str1, str2, str3, int1, col, msg,
818 ap);
819 va_end(ap);
820
821 return(res);
822 }
823
824 static void
xmlVFormatLegacyError(void * ctx,const char * level,const char * fmt,va_list ap)825 xmlVFormatLegacyError(void *ctx, const char *level,
826 const char *fmt, va_list ap) {
827 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
828 xmlParserInputPtr input = NULL;
829 xmlParserInputPtr cur = NULL;
830 xmlChar *str = NULL;
831
832 if (ctxt != NULL) {
833 input = ctxt->input;
834 if ((input != NULL) && (input->filename == NULL) &&
835 (ctxt->inputNr > 1)) {
836 cur = input;
837 input = ctxt->inputTab[ctxt->inputNr - 2];
838 }
839 xmlParserPrintFileInfo(input);
840 }
841
842 xmlGenericError(xmlGenericErrorContext, "%s: ", level);
843
844 xmlStrVASPrintf(&str, MAX_ERR_MSG_SIZE, fmt, ap);
845 if (str != NULL) {
846 xmlGenericError(xmlGenericErrorContext, "%s", (char *) str);
847 xmlFree(str);
848 }
849
850 if (ctxt != NULL) {
851 xmlParserPrintFileContext(input);
852 if (cur != NULL) {
853 xmlParserPrintFileInfo(cur);
854 xmlGenericError(xmlGenericErrorContext, "\n");
855 xmlParserPrintFileContext(cur);
856 }
857 }
858 }
859
860 /**
861 * xmlParserError:
862 * @ctx: an XML parser context
863 * @msg: the message to display/transmit
864 * @...: extra parameters for the message display
865 *
866 * Display and format an error messages, gives file, line, position and
867 * extra parameters.
868 */
869 void
xmlParserError(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)870 xmlParserError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
871 {
872 va_list ap;
873
874 va_start(ap, msg);
875 xmlVFormatLegacyError(ctx, "error", msg, ap);
876 va_end(ap);
877 }
878
879 /**
880 * xmlParserWarning:
881 * @ctx: an XML parser context
882 * @msg: the message to display/transmit
883 * @...: extra parameters for the message display
884 *
885 * Display and format a warning messages, gives file, line, position and
886 * extra parameters.
887 */
888 void
xmlParserWarning(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)889 xmlParserWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
890 {
891 va_list ap;
892
893 va_start(ap, msg);
894 xmlVFormatLegacyError(ctx, "warning", msg, ap);
895 va_end(ap);
896 }
897
898 /**
899 * xmlParserValidityError:
900 * @ctx: an XML parser context
901 * @msg: the message to display/transmit
902 * @...: extra parameters for the message display
903 *
904 * Display and format an validity error messages, gives file,
905 * line, position and extra parameters.
906 */
907 void
xmlParserValidityError(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)908 xmlParserValidityError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
909 {
910 va_list ap;
911
912 va_start(ap, msg);
913 xmlVFormatLegacyError(ctx, "validity error", msg, ap);
914 va_end(ap);
915 }
916
917 /**
918 * xmlParserValidityWarning:
919 * @ctx: an XML parser context
920 * @msg: the message to display/transmit
921 * @...: extra parameters for the message display
922 *
923 * Display and format a validity warning messages, gives file, line,
924 * position and extra parameters.
925 */
926 void
xmlParserValidityWarning(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)927 xmlParserValidityWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
928 {
929 va_list ap;
930
931 va_start(ap, msg);
932 xmlVFormatLegacyError(ctx, "validity warning", msg, ap);
933 va_end(ap);
934 }
935
936
937 /************************************************************************
938 * *
939 * Extended Error Handling *
940 * *
941 ************************************************************************/
942
943 /**
944 * xmlGetLastError:
945 *
946 * Get the last global error registered. This is per thread if compiled
947 * with thread support.
948 *
949 * Returns a pointer to the error
950 */
951 const xmlError *
xmlGetLastError(void)952 xmlGetLastError(void)
953 {
954 const xmlError *error = xmlGetLastErrorInternal();
955
956 if (error->code == XML_ERR_OK)
957 return(NULL);
958 return(error);
959 }
960
961 /**
962 * xmlResetError:
963 * @err: pointer to the error.
964 *
965 * Cleanup the error.
966 */
967 void
xmlResetError(xmlErrorPtr err)968 xmlResetError(xmlErrorPtr err)
969 {
970 if (err == NULL)
971 return;
972 if (err->code == XML_ERR_OK)
973 return;
974 if (err->message != NULL)
975 xmlFree(err->message);
976 if (err->file != NULL)
977 xmlFree(err->file);
978 if (err->str1 != NULL)
979 xmlFree(err->str1);
980 if (err->str2 != NULL)
981 xmlFree(err->str2);
982 if (err->str3 != NULL)
983 xmlFree(err->str3);
984 memset(err, 0, sizeof(xmlError));
985 err->code = XML_ERR_OK;
986 }
987
988 /**
989 * xmlResetLastError:
990 *
991 * Cleanup the last global error registered. For parsing error
992 * this does not change the well-formedness result.
993 */
994 void
xmlResetLastError(void)995 xmlResetLastError(void)
996 {
997 xmlError *error = xmlGetLastErrorInternal();
998
999 if (error->code != XML_ERR_OK)
1000 xmlResetError(error);
1001 }
1002
1003 /**
1004 * xmlCopyError:
1005 * @from: a source error
1006 * @to: a target error
1007 *
1008 * Save the original error to the new place.
1009 *
1010 * Returns 0 in case of success and -1 in case of error.
1011 */
1012 int
xmlCopyError(const xmlError * from,xmlErrorPtr to)1013 xmlCopyError(const xmlError *from, xmlErrorPtr to) {
1014 const char *fmt = NULL;
1015
1016 if ((from == NULL) || (to == NULL))
1017 return(-1);
1018
1019 if (from->message != NULL)
1020 fmt = "%s";
1021
1022 return(xmlSetError(to, from->ctxt, from->node,
1023 from->domain, from->code, from->level,
1024 from->file, from->line,
1025 from->str1, from->str2, from->str3,
1026 from->int1, from->int2,
1027 fmt, from->message));
1028 }
1029
1030 /**
1031 * xmlErrString:
1032 * @code: an xmlParserErrors code
1033 *
1034 * Returns an error message for a code.
1035 */
1036 const char *
xmlErrString(xmlParserErrors code)1037 xmlErrString(xmlParserErrors code) {
1038 const char *errmsg;
1039
1040 switch (code) {
1041 case XML_ERR_INVALID_HEX_CHARREF:
1042 errmsg = "CharRef: invalid hexadecimal value";
1043 break;
1044 case XML_ERR_INVALID_DEC_CHARREF:
1045 errmsg = "CharRef: invalid decimal value";
1046 break;
1047 case XML_ERR_INVALID_CHARREF:
1048 errmsg = "CharRef: invalid value";
1049 break;
1050 case XML_ERR_INTERNAL_ERROR:
1051 errmsg = "internal error";
1052 break;
1053 case XML_ERR_PEREF_AT_EOF:
1054 errmsg = "PEReference at end of document";
1055 break;
1056 case XML_ERR_PEREF_IN_PROLOG:
1057 errmsg = "PEReference in prolog";
1058 break;
1059 case XML_ERR_PEREF_IN_EPILOG:
1060 errmsg = "PEReference in epilog";
1061 break;
1062 case XML_ERR_PEREF_NO_NAME:
1063 errmsg = "PEReference: no name";
1064 break;
1065 case XML_ERR_PEREF_SEMICOL_MISSING:
1066 errmsg = "PEReference: expecting ';'";
1067 break;
1068 case XML_ERR_ENTITY_LOOP:
1069 errmsg = "Detected an entity reference loop";
1070 break;
1071 case XML_ERR_ENTITY_NOT_STARTED:
1072 errmsg = "EntityValue: \" or ' expected";
1073 break;
1074 case XML_ERR_ENTITY_PE_INTERNAL:
1075 errmsg = "PEReferences forbidden in internal subset";
1076 break;
1077 case XML_ERR_ENTITY_NOT_FINISHED:
1078 errmsg = "EntityValue: \" or ' expected";
1079 break;
1080 case XML_ERR_ATTRIBUTE_NOT_STARTED:
1081 errmsg = "AttValue: \" or ' expected";
1082 break;
1083 case XML_ERR_LT_IN_ATTRIBUTE:
1084 errmsg = "Unescaped '<' not allowed in attributes values";
1085 break;
1086 case XML_ERR_LITERAL_NOT_STARTED:
1087 errmsg = "SystemLiteral \" or ' expected";
1088 break;
1089 case XML_ERR_LITERAL_NOT_FINISHED:
1090 errmsg = "Unfinished System or Public ID \" or ' expected";
1091 break;
1092 case XML_ERR_MISPLACED_CDATA_END:
1093 errmsg = "Sequence ']]>' not allowed in content";
1094 break;
1095 case XML_ERR_URI_REQUIRED:
1096 errmsg = "SYSTEM or PUBLIC, the URI is missing";
1097 break;
1098 case XML_ERR_PUBID_REQUIRED:
1099 errmsg = "PUBLIC, the Public Identifier is missing";
1100 break;
1101 case XML_ERR_HYPHEN_IN_COMMENT:
1102 errmsg = "Comment must not contain '--' (double-hyphen)";
1103 break;
1104 case XML_ERR_PI_NOT_STARTED:
1105 errmsg = "xmlParsePI : no target name";
1106 break;
1107 case XML_ERR_RESERVED_XML_NAME:
1108 errmsg = "Invalid PI name";
1109 break;
1110 case XML_ERR_NOTATION_NOT_STARTED:
1111 errmsg = "NOTATION: Name expected here";
1112 break;
1113 case XML_ERR_NOTATION_NOT_FINISHED:
1114 errmsg = "'>' required to close NOTATION declaration";
1115 break;
1116 case XML_ERR_VALUE_REQUIRED:
1117 errmsg = "Entity value required";
1118 break;
1119 case XML_ERR_URI_FRAGMENT:
1120 errmsg = "Fragment not allowed";
1121 break;
1122 case XML_ERR_ATTLIST_NOT_STARTED:
1123 errmsg = "'(' required to start ATTLIST enumeration";
1124 break;
1125 case XML_ERR_NMTOKEN_REQUIRED:
1126 errmsg = "NmToken expected in ATTLIST enumeration";
1127 break;
1128 case XML_ERR_ATTLIST_NOT_FINISHED:
1129 errmsg = "')' required to finish ATTLIST enumeration";
1130 break;
1131 case XML_ERR_MIXED_NOT_STARTED:
1132 errmsg = "MixedContentDecl : '|' or ')*' expected";
1133 break;
1134 case XML_ERR_PCDATA_REQUIRED:
1135 errmsg = "MixedContentDecl : '#PCDATA' expected";
1136 break;
1137 case XML_ERR_ELEMCONTENT_NOT_STARTED:
1138 errmsg = "ContentDecl : Name or '(' expected";
1139 break;
1140 case XML_ERR_ELEMCONTENT_NOT_FINISHED:
1141 errmsg = "ContentDecl : ',' '|' or ')' expected";
1142 break;
1143 case XML_ERR_PEREF_IN_INT_SUBSET:
1144 errmsg =
1145 "PEReference: forbidden within markup decl in internal subset";
1146 break;
1147 case XML_ERR_GT_REQUIRED:
1148 errmsg = "expected '>'";
1149 break;
1150 case XML_ERR_CONDSEC_INVALID:
1151 errmsg = "XML conditional section '[' expected";
1152 break;
1153 case XML_ERR_INT_SUBSET_NOT_FINISHED:
1154 errmsg = "Content error in the internal subset";
1155 break;
1156 case XML_ERR_EXT_SUBSET_NOT_FINISHED:
1157 errmsg = "Content error in the external subset";
1158 break;
1159 case XML_ERR_CONDSEC_INVALID_KEYWORD:
1160 errmsg =
1161 "conditional section INCLUDE or IGNORE keyword expected";
1162 break;
1163 case XML_ERR_CONDSEC_NOT_FINISHED:
1164 errmsg = "XML conditional section not closed";
1165 break;
1166 case XML_ERR_XMLDECL_NOT_STARTED:
1167 errmsg = "Text declaration '<?xml' required";
1168 break;
1169 case XML_ERR_XMLDECL_NOT_FINISHED:
1170 errmsg = "parsing XML declaration: '?>' expected";
1171 break;
1172 case XML_ERR_EXT_ENTITY_STANDALONE:
1173 errmsg = "external parsed entities cannot be standalone";
1174 break;
1175 case XML_ERR_ENTITYREF_SEMICOL_MISSING:
1176 errmsg = "EntityRef: expecting ';'";
1177 break;
1178 case XML_ERR_DOCTYPE_NOT_FINISHED:
1179 errmsg = "DOCTYPE improperly terminated";
1180 break;
1181 case XML_ERR_LTSLASH_REQUIRED:
1182 errmsg = "EndTag: '</' not found";
1183 break;
1184 case XML_ERR_EQUAL_REQUIRED:
1185 errmsg = "expected '='";
1186 break;
1187 case XML_ERR_STRING_NOT_CLOSED:
1188 errmsg = "String not closed expecting \" or '";
1189 break;
1190 case XML_ERR_STRING_NOT_STARTED:
1191 errmsg = "String not started expecting ' or \"";
1192 break;
1193 case XML_ERR_ENCODING_NAME:
1194 errmsg = "Invalid XML encoding name";
1195 break;
1196 case XML_ERR_STANDALONE_VALUE:
1197 errmsg = "standalone accepts only 'yes' or 'no'";
1198 break;
1199 case XML_ERR_DOCUMENT_EMPTY:
1200 errmsg = "Document is empty";
1201 break;
1202 case XML_ERR_DOCUMENT_END:
1203 errmsg = "Extra content at the end of the document";
1204 break;
1205 case XML_ERR_NOT_WELL_BALANCED:
1206 errmsg = "chunk is not well balanced";
1207 break;
1208 case XML_ERR_EXTRA_CONTENT:
1209 errmsg = "extra content at the end of well balanced chunk";
1210 break;
1211 case XML_ERR_VERSION_MISSING:
1212 errmsg = "Malformed declaration expecting version";
1213 break;
1214 case XML_ERR_NAME_TOO_LONG:
1215 errmsg = "Name too long";
1216 break;
1217 case XML_ERR_INVALID_ENCODING:
1218 errmsg = "Invalid bytes in character encoding";
1219 break;
1220 case XML_ERR_RESOURCE_LIMIT:
1221 errmsg = "Resource limit exceeded";
1222 break;
1223 case XML_ERR_ARGUMENT:
1224 errmsg = "Invalid argument";
1225 break;
1226 case XML_ERR_SYSTEM:
1227 errmsg = "Out of system resources";
1228 break;
1229 case XML_ERR_REDECL_PREDEF_ENTITY:
1230 errmsg = "Invalid redeclaration of predefined entity";
1231 break;
1232 case XML_ERR_UNSUPPORTED_ENCODING:
1233 errmsg = "Unsupported encoding";
1234 break;
1235 case XML_ERR_INVALID_CHAR:
1236 errmsg = "Invalid character";
1237 break;
1238
1239 case XML_IO_UNKNOWN:
1240 errmsg = "Unknown IO error"; break;
1241 case XML_IO_EACCES:
1242 errmsg = "Permission denied"; break;
1243 case XML_IO_EAGAIN:
1244 errmsg = "Resource temporarily unavailable"; break;
1245 case XML_IO_EBADF:
1246 errmsg = "Bad file descriptor"; break;
1247 case XML_IO_EBADMSG:
1248 errmsg = "Bad message"; break;
1249 case XML_IO_EBUSY:
1250 errmsg = "Resource busy"; break;
1251 case XML_IO_ECANCELED:
1252 errmsg = "Operation canceled"; break;
1253 case XML_IO_ECHILD:
1254 errmsg = "No child processes"; break;
1255 case XML_IO_EDEADLK:
1256 errmsg = "Resource deadlock avoided"; break;
1257 case XML_IO_EDOM:
1258 errmsg = "Domain error"; break;
1259 case XML_IO_EEXIST:
1260 errmsg = "File exists"; break;
1261 case XML_IO_EFAULT:
1262 errmsg = "Bad address"; break;
1263 case XML_IO_EFBIG:
1264 errmsg = "File too large"; break;
1265 case XML_IO_EINPROGRESS:
1266 errmsg = "Operation in progress"; break;
1267 case XML_IO_EINTR:
1268 errmsg = "Interrupted function call"; break;
1269 case XML_IO_EINVAL:
1270 errmsg = "Invalid argument"; break;
1271 case XML_IO_EIO:
1272 errmsg = "Input/output error"; break;
1273 case XML_IO_EISDIR:
1274 errmsg = "Is a directory"; break;
1275 case XML_IO_EMFILE:
1276 errmsg = "Too many open files"; break;
1277 case XML_IO_EMLINK:
1278 errmsg = "Too many links"; break;
1279 case XML_IO_EMSGSIZE:
1280 errmsg = "Inappropriate message buffer length"; break;
1281 case XML_IO_ENAMETOOLONG:
1282 errmsg = "Filename too long"; break;
1283 case XML_IO_ENFILE:
1284 errmsg = "Too many open files in system"; break;
1285 case XML_IO_ENODEV:
1286 errmsg = "No such device"; break;
1287 case XML_IO_ENOENT:
1288 errmsg = "No such file or directory"; break;
1289 case XML_IO_ENOEXEC:
1290 errmsg = "Exec format error"; break;
1291 case XML_IO_ENOLCK:
1292 errmsg = "No locks available"; break;
1293 case XML_IO_ENOMEM:
1294 errmsg = "Not enough space"; break;
1295 case XML_IO_ENOSPC:
1296 errmsg = "No space left on device"; break;
1297 case XML_IO_ENOSYS:
1298 errmsg = "Function not implemented"; break;
1299 case XML_IO_ENOTDIR:
1300 errmsg = "Not a directory"; break;
1301 case XML_IO_ENOTEMPTY:
1302 errmsg = "Directory not empty"; break;
1303 case XML_IO_ENOTSUP:
1304 errmsg = "Not supported"; break;
1305 case XML_IO_ENOTTY:
1306 errmsg = "Inappropriate I/O control operation"; break;
1307 case XML_IO_ENXIO:
1308 errmsg = "No such device or address"; break;
1309 case XML_IO_EPERM:
1310 errmsg = "Operation not permitted"; break;
1311 case XML_IO_EPIPE:
1312 errmsg = "Broken pipe"; break;
1313 case XML_IO_ERANGE:
1314 errmsg = "Result too large"; break;
1315 case XML_IO_EROFS:
1316 errmsg = "Read-only file system"; break;
1317 case XML_IO_ESPIPE:
1318 errmsg = "Invalid seek"; break;
1319 case XML_IO_ESRCH:
1320 errmsg = "No such process"; break;
1321 case XML_IO_ETIMEDOUT:
1322 errmsg = "Operation timed out"; break;
1323 case XML_IO_EXDEV:
1324 errmsg = "Improper link"; break;
1325 case XML_IO_NETWORK_ATTEMPT:
1326 errmsg = "Attempt to load network entity"; break;
1327 case XML_IO_ENCODER:
1328 errmsg = "encoder error"; break;
1329 case XML_IO_FLUSH:
1330 errmsg = "flush error"; break;
1331 case XML_IO_WRITE:
1332 errmsg = "write error"; break;
1333 case XML_IO_NO_INPUT:
1334 errmsg = "no input"; break;
1335 case XML_IO_BUFFER_FULL:
1336 errmsg = "buffer full"; break;
1337 case XML_IO_LOAD_ERROR:
1338 errmsg = "loading error"; break;
1339 case XML_IO_ENOTSOCK:
1340 errmsg = "not a socket"; break;
1341 case XML_IO_EISCONN:
1342 errmsg = "already connected"; break;
1343 case XML_IO_ECONNREFUSED:
1344 errmsg = "connection refused"; break;
1345 case XML_IO_ENETUNREACH:
1346 errmsg = "unreachable network"; break;
1347 case XML_IO_EADDRINUSE:
1348 errmsg = "address in use"; break;
1349 case XML_IO_EALREADY:
1350 errmsg = "already in use"; break;
1351 case XML_IO_EAFNOSUPPORT:
1352 errmsg = "unknown address family"; break;
1353 case XML_IO_UNSUPPORTED_PROTOCOL:
1354 errmsg = "unsupported protocol"; break;
1355
1356 default:
1357 errmsg = "Unregistered error message";
1358 }
1359
1360 return(errmsg);
1361 }
1362
1363 /**
1364 * xmlVPrintErrorMessage:
1365 * @fmt: printf format string
1366 * @ap: arguments
1367 *
1368 * Prints to stderr.
1369 */
1370 void
xmlVPrintErrorMessage(const char * fmt,va_list ap)1371 xmlVPrintErrorMessage(const char *fmt, va_list ap) {
1372 vfprintf(stderr, fmt, ap);
1373 }
1374
1375 /**
1376 * xmlPrintErrorMessage:
1377 * @fmt: printf format string
1378 * @...: arguments
1379 *
1380 * Prints to stderr.
1381 */
1382 void
xmlPrintErrorMessage(const char * fmt,...)1383 xmlPrintErrorMessage(const char *fmt, ...) {
1384 va_list ap;
1385
1386 va_start(ap, fmt);
1387 xmlVPrintErrorMessage(fmt, ap);
1388 va_end(ap);
1389 }
1390
1391 /**
1392 * xmlAbort:
1393 * @fmt: printf format string
1394 * @...: arguments
1395 *
1396 * Print message to stderr and abort.
1397 */
1398 void
xmlAbort(const char * fmt,...)1399 xmlAbort(const char *fmt, ...) {
1400 va_list ap;
1401
1402 va_start(ap, fmt);
1403 xmlVPrintErrorMessage(fmt, ap);
1404 va_end(ap);
1405
1406 abort();
1407 }
1408