Reactos
at master 1022 lines 28 kB view raw
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 <libxml/parser.h> 15#include <libxml/xmlerror.h> 16#include <libxml/xmlmemory.h> 17 18#include "private/error.h" 19 20#define XML_MAX_ERRORS 100 21 22#define XML_GET_VAR_STR(msg, str) { \ 23 int size, prev_size = -1; \ 24 int chars; \ 25 char *larger; \ 26 va_list ap; \ 27 \ 28 str = (char *) xmlMalloc(150); \ 29 if (str != NULL) { \ 30 \ 31 size = 150; \ 32 \ 33 while (size < 64000) { \ 34 va_start(ap, msg); \ 35 chars = vsnprintf(str, size, msg, ap); \ 36 va_end(ap); \ 37 if ((chars > -1) && (chars < size)) { \ 38 if (prev_size == chars) { \ 39 break; \ 40 } else { \ 41 prev_size = chars; \ 42 } \ 43 } \ 44 if (chars > -1) \ 45 size += chars + 1; \ 46 else \ 47 size += 100; \ 48 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\ 49 break; \ 50 } \ 51 str = larger; \ 52 }} \ 53} 54 55/************************************************************************ 56 * * 57 * Handling of out of context errors * 58 * * 59 ************************************************************************/ 60 61/** 62 * xmlGenericErrorDefaultFunc: 63 * @ctx: an error context 64 * @msg: the message to display/transmit 65 * @...: extra parameters for the message display 66 * 67 * Default handler for out of context error messages. 68 */ 69void 70xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { 71 va_list args; 72 73 if (xmlGenericErrorContext == NULL) 74 xmlGenericErrorContext = (void *) stderr; 75 76 va_start(args, msg); 77 vfprintf((FILE *)xmlGenericErrorContext, msg, args); 78 va_end(args); 79} 80 81/** 82 * initGenericErrorDefaultFunc: 83 * @handler: the handler 84 * 85 * DEPRECATED: Use xmlSetGenericErrorFunc. 86 * 87 * Set or reset (if NULL) the default handler for generic errors 88 * to the builtin error function. 89 */ 90void 91initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler) 92{ 93 if (handler == NULL) 94 xmlGenericError = xmlGenericErrorDefaultFunc; 95 else 96 xmlGenericError = (*handler); 97} 98 99/** 100 * xmlSetGenericErrorFunc: 101 * @ctx: the new error handling context 102 * @handler: the new handler function 103 * 104 * Function to reset the handler and the error context for out of 105 * context error messages. 106 * This simply means that @handler will be called for subsequent 107 * error messages while not parsing nor validating. And @ctx will 108 * be passed as first argument to @handler 109 * One can simply force messages to be emitted to another FILE * than 110 * stderr by setting @ctx to this file handle and @handler to NULL. 111 * For multi-threaded applications, this must be set separately for each thread. 112 */ 113void 114xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) { 115 xmlGenericErrorContext = ctx; 116 if (handler != NULL) 117 xmlGenericError = handler; 118 else 119 xmlGenericError = xmlGenericErrorDefaultFunc; 120} 121 122/** 123 * xmlSetStructuredErrorFunc: 124 * @ctx: the new error handling context 125 * @handler: the new handler function 126 * 127 * Function to reset the handler and the error context for out of 128 * context structured error messages. 129 * This simply means that @handler will be called for subsequent 130 * error messages while not parsing nor validating. And @ctx will 131 * be passed as first argument to @handler 132 * For multi-threaded applications, this must be set separately for each thread. 133 */ 134void 135xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) { 136 xmlStructuredErrorContext = ctx; 137 xmlStructuredError = handler; 138} 139 140/************************************************************************ 141 * * 142 * Handling of parsing errors * 143 * * 144 ************************************************************************/ 145 146/** 147 * xmlParserPrintFileInfo: 148 * @input: an xmlParserInputPtr input 149 * 150 * Displays the associated file and line information for the current input 151 */ 152 153void 154xmlParserPrintFileInfo(xmlParserInputPtr input) { 155 if (input != NULL) { 156 if (input->filename) 157 xmlGenericError(xmlGenericErrorContext, 158 "%s:%d: ", input->filename, 159 input->line); 160 else 161 xmlGenericError(xmlGenericErrorContext, 162 "Entity: line %d: ", input->line); 163 } 164} 165 166/** 167 * xmlParserPrintFileContextInternal: 168 * @input: an xmlParserInputPtr input 169 * 170 * Displays current context within the input content for error tracking 171 */ 172 173static void 174xmlParserPrintFileContextInternal(xmlParserInputPtr input , 175 xmlGenericErrorFunc channel, void *data ) { 176 const xmlChar *cur, *base, *start; 177 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ 178 xmlChar content[81]; /* space for 80 chars + line terminator */ 179 xmlChar *ctnt; 180 181 if ((input == NULL) || (input->cur == NULL)) 182 return; 183 184 cur = input->cur; 185 base = input->base; 186 /* skip backwards over any end-of-lines */ 187 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { 188 cur--; 189 } 190 n = 0; 191 /* search backwards for beginning-of-line (to max buff size) */ 192 while ((n < sizeof(content) - 1) && (cur > base) && 193 (*cur != '\n') && (*cur != '\r')) { 194 cur--; 195 n++; 196 } 197 if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) { 198 cur++; 199 } else { 200 /* skip over continuation bytes */ 201 while ((cur < input->cur) && ((*cur & 0xC0) == 0x80)) 202 cur++; 203 } 204 /* calculate the error position in terms of the current position */ 205 col = input->cur - cur; 206 /* search forward for end-of-line (to max buff size) */ 207 n = 0; 208 start = cur; 209 /* copy selected text to our buffer */ 210 while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) { 211 int len = input->end - cur; 212 int c = xmlGetUTF8Char(cur, &len); 213 214 if ((c < 0) || (n + len > sizeof(content)-1)) 215 break; 216 cur += len; 217 n += len; 218 } 219 memcpy(content, start, n); 220 content[n] = 0; 221 /* print out the selected text */ 222 channel(data ,"%s\n", content); 223 /* create blank line with problem pointer */ 224 n = 0; 225 ctnt = content; 226 /* (leave buffer space for pointer + line terminator) */ 227 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) { 228 if (*(ctnt) != '\t') 229 *(ctnt) = ' '; 230 ctnt++; 231 } 232 *ctnt++ = '^'; 233 *ctnt = 0; 234 channel(data ,"%s\n", content); 235} 236 237/** 238 * xmlParserPrintFileContext: 239 * @input: an xmlParserInputPtr input 240 * 241 * Displays current context within the input content for error tracking 242 */ 243void 244xmlParserPrintFileContext(xmlParserInputPtr input) { 245 xmlParserPrintFileContextInternal(input, xmlGenericError, 246 xmlGenericErrorContext); 247} 248 249/** 250 * xmlReportError: 251 * @err: the error 252 * @ctx: the parser context or NULL 253 * @str: the formatted error message 254 * 255 * Report an error with its context, replace the 4 old error/warning 256 * routines. 257 */ 258static void 259xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, 260 xmlGenericErrorFunc channel, void *data) 261{ 262 char *file = NULL; 263 int line = 0; 264 int code = -1; 265 int domain; 266 const xmlChar *name = NULL; 267 xmlNodePtr node; 268 xmlErrorLevel level; 269 xmlParserInputPtr input = NULL; 270 xmlParserInputPtr cur = NULL; 271 272 if (err == NULL) 273 return; 274 275 if (channel == NULL) { 276 channel = xmlGenericError; 277 data = xmlGenericErrorContext; 278 } 279 file = err->file; 280 line = err->line; 281 code = err->code; 282 domain = err->domain; 283 level = err->level; 284 node = err->node; 285 286 if (code == XML_ERR_OK) 287 return; 288 289 if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) 290 name = node->name; 291 292 /* 293 * Maintain the compatibility with the legacy error handling 294 */ 295 if (ctxt != NULL) { 296 input = ctxt->input; 297 if ((input != NULL) && (input->filename == NULL) && 298 (ctxt->inputNr > 1)) { 299 cur = input; 300 input = ctxt->inputTab[ctxt->inputNr - 2]; 301 } 302 if (input != NULL) { 303 if (input->filename) 304 channel(data, "%s:%d: ", input->filename, input->line); 305 else if ((line != 0) && (domain == XML_FROM_PARSER)) 306 channel(data, "Entity: line %d: ", input->line); 307 } 308 } else { 309 if (file != NULL) 310 channel(data, "%s:%d: ", file, line); 311 else if ((line != 0) && 312 ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)|| 313 (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) || 314 (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV))) 315 channel(data, "Entity: line %d: ", line); 316 } 317 if (name != NULL) { 318 channel(data, "element %s: ", name); 319 } 320 switch (domain) { 321 case XML_FROM_PARSER: 322 channel(data, "parser "); 323 break; 324 case XML_FROM_NAMESPACE: 325 channel(data, "namespace "); 326 break; 327 case XML_FROM_DTD: 328 case XML_FROM_VALID: 329 channel(data, "validity "); 330 break; 331 case XML_FROM_HTML: 332 channel(data, "HTML parser "); 333 break; 334 case XML_FROM_MEMORY: 335 channel(data, "memory "); 336 break; 337 case XML_FROM_OUTPUT: 338 channel(data, "output "); 339 break; 340 case XML_FROM_IO: 341 channel(data, "I/O "); 342 break; 343 case XML_FROM_XINCLUDE: 344 channel(data, "XInclude "); 345 break; 346 case XML_FROM_XPATH: 347 channel(data, "XPath "); 348 break; 349 case XML_FROM_XPOINTER: 350 channel(data, "parser "); 351 break; 352 case XML_FROM_REGEXP: 353 channel(data, "regexp "); 354 break; 355 case XML_FROM_MODULE: 356 channel(data, "module "); 357 break; 358 case XML_FROM_SCHEMASV: 359 channel(data, "Schemas validity "); 360 break; 361 case XML_FROM_SCHEMASP: 362 channel(data, "Schemas parser "); 363 break; 364 case XML_FROM_RELAXNGP: 365 channel(data, "Relax-NG parser "); 366 break; 367 case XML_FROM_RELAXNGV: 368 channel(data, "Relax-NG validity "); 369 break; 370 case XML_FROM_CATALOG: 371 channel(data, "Catalog "); 372 break; 373 case XML_FROM_C14N: 374 channel(data, "C14N "); 375 break; 376 case XML_FROM_XSLT: 377 channel(data, "XSLT "); 378 break; 379 case XML_FROM_I18N: 380 channel(data, "encoding "); 381 break; 382 case XML_FROM_SCHEMATRONV: 383 channel(data, "schematron "); 384 break; 385 case XML_FROM_BUFFER: 386 channel(data, "internal buffer "); 387 break; 388 case XML_FROM_URI: 389 channel(data, "URI "); 390 break; 391 default: 392 break; 393 } 394 switch (level) { 395 case XML_ERR_NONE: 396 channel(data, ": "); 397 break; 398 case XML_ERR_WARNING: 399 channel(data, "warning : "); 400 break; 401 case XML_ERR_ERROR: 402 channel(data, "error : "); 403 break; 404 case XML_ERR_FATAL: 405 channel(data, "error : "); 406 break; 407 } 408 if (str != NULL) { 409 int len; 410 len = xmlStrlen((const xmlChar *)str); 411 if ((len > 0) && (str[len - 1] != '\n')) 412 channel(data, "%s\n", str); 413 else 414 channel(data, "%s", str); 415 } else { 416 channel(data, "%s\n", "out of memory error"); 417 } 418 419 if (ctxt != NULL) { 420 xmlParserPrintFileContextInternal(input, channel, data); 421 if (cur != NULL) { 422 if (cur->filename) 423 channel(data, "%s:%d: \n", cur->filename, cur->line); 424 else if ((line != 0) && (domain == XML_FROM_PARSER)) 425 channel(data, "Entity: line %d: \n", cur->line); 426 xmlParserPrintFileContextInternal(cur, channel, data); 427 } 428 } 429 if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) && 430 (err->int1 < 100) && 431 (err->int1 < xmlStrlen((const xmlChar *)err->str1))) { 432 xmlChar buf[150]; 433 int i; 434 435 channel(data, "%s\n", err->str1); 436 for (i=0;i < err->int1;i++) 437 buf[i] = ' '; 438 buf[i++] = '^'; 439 buf[i] = 0; 440 channel(data, "%s\n", buf); 441 } 442} 443 444/** 445 * __xmlRaiseError: 446 * @schannel: the structured callback channel 447 * @channel: the old callback channel 448 * @data: the callback data 449 * @ctx: the parser context or NULL 450 * @ctx: the parser context or NULL 451 * @domain: the domain for the error 452 * @code: the code for the error 453 * @level: the xmlErrorLevel for the error 454 * @file: the file source of the error (or NULL) 455 * @line: the line of the error or 0 if N/A 456 * @str1: extra string info 457 * @str2: extra string info 458 * @str3: extra string info 459 * @int1: extra int info 460 * @col: column number of the error or 0 if N/A 461 * @msg: the message to display/transmit 462 * @...: extra parameters for the message display 463 * 464 * Update the appropriate global or contextual error structure, 465 * then forward the error message down the parser or generic 466 * error callback handler 467 */ 468void 469__xmlRaiseError(xmlStructuredErrorFunc schannel, 470 xmlGenericErrorFunc channel, void *data, void *ctx, 471 void *nod, int domain, int code, xmlErrorLevel level, 472 const char *file, int line, const char *str1, 473 const char *str2, const char *str3, int int1, int col, 474 const char *msg, ...) 475{ 476 xmlParserCtxtPtr ctxt = NULL; 477 xmlNodePtr node = (xmlNodePtr) nod; 478 char *str = NULL; 479 xmlParserInputPtr input = NULL; 480 xmlErrorPtr to = &xmlLastError; 481 xmlNodePtr baseptr = NULL; 482 483 if (code == XML_ERR_OK) 484 return; 485 if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING)) 486 return; 487 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || 488 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || 489 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { 490 ctxt = (xmlParserCtxtPtr) ctx; 491 492 if (ctxt != NULL) { 493 if (level == XML_ERR_WARNING) { 494 if (ctxt->nbWarnings >= XML_MAX_ERRORS) 495 return; 496 ctxt->nbWarnings += 1; 497 } else { 498 if (ctxt->nbErrors >= XML_MAX_ERRORS) 499 return; 500 ctxt->nbErrors += 1; 501 } 502 503 if ((schannel == NULL) && (ctxt->sax != NULL) && 504 (ctxt->sax->initialized == XML_SAX2_MAGIC) && 505 (ctxt->sax->serror != NULL)) { 506 schannel = ctxt->sax->serror; 507 data = ctxt->userData; 508 } 509 } 510 } 511 /* 512 * Check if structured error handler set 513 */ 514 if (schannel == NULL) { 515 schannel = xmlStructuredError; 516 /* 517 * if user has defined handler, change data ptr to user's choice 518 */ 519 if (schannel != NULL) 520 data = xmlStructuredErrorContext; 521 } 522 /* 523 * Formatting the message 524 */ 525 if (msg == NULL) { 526 str = (char *) xmlStrdup(BAD_CAST "No error message provided"); 527 } else { 528 XML_GET_VAR_STR(msg, str); 529 } 530 531 /* 532 * specific processing if a parser context is provided 533 */ 534 if (ctxt != NULL) { 535 if (file == NULL) { 536 input = ctxt->input; 537 if ((input != NULL) && (input->filename == NULL) && 538 (ctxt->inputNr > 1)) { 539 input = ctxt->inputTab[ctxt->inputNr - 2]; 540 } 541 if (input != NULL) { 542 file = input->filename; 543 line = input->line; 544 col = input->col; 545 } 546 } 547 to = &ctxt->lastError; 548 } else if ((node != NULL) && (file == NULL)) { 549 int i; 550 551 if ((node->doc != NULL) && (node->doc->URL != NULL)) { 552 baseptr = node; 553/* file = (const char *) node->doc->URL; */ 554 } 555 for (i = 0; 556 ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE)); 557 i++) 558 node = node->parent; 559 if ((baseptr == NULL) && (node != NULL) && 560 (node->doc != NULL) && (node->doc->URL != NULL)) 561 baseptr = node; 562 563 if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) 564 line = node->line; 565 if ((line == 0) || (line == 65535)) 566 line = xmlGetLineNo(node); 567 } 568 569 /* 570 * Save the information about the error 571 */ 572 xmlResetError(to); 573 to->domain = domain; 574 to->code = code; 575 to->message = str; 576 to->level = level; 577 if (file != NULL) 578 to->file = (char *) xmlStrdup((const xmlChar *) file); 579 else if (baseptr != NULL) { 580#ifdef LIBXML_XINCLUDE_ENABLED 581 /* 582 * We check if the error is within an XInclude section and, 583 * if so, attempt to print out the href of the XInclude instead 584 * of the usual "base" (doc->URL) for the node (bug 152623). 585 */ 586 xmlNodePtr prev = baseptr; 587 char *href = NULL; 588 int inclcount = 0; 589 while (prev != NULL) { 590 if (prev->prev == NULL) 591 prev = prev->parent; 592 else { 593 prev = prev->prev; 594 if (prev->type == XML_XINCLUDE_START) { 595 if (inclcount > 0) { 596 --inclcount; 597 } else { 598 href = (char *) xmlGetProp(prev, BAD_CAST "href"); 599 if (href != NULL) 600 break; 601 } 602 } else if (prev->type == XML_XINCLUDE_END) 603 inclcount++; 604 } 605 } 606 if (href != NULL) 607 to->file = href; 608 else 609#endif 610 to->file = (char *) xmlStrdup(baseptr->doc->URL); 611 if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) { 612 to->file = (char *) xmlStrdup(node->doc->URL); 613 } 614 } 615 to->line = line; 616 if (str1 != NULL) 617 to->str1 = (char *) xmlStrdup((const xmlChar *) str1); 618 if (str2 != NULL) 619 to->str2 = (char *) xmlStrdup((const xmlChar *) str2); 620 if (str3 != NULL) 621 to->str3 = (char *) xmlStrdup((const xmlChar *) str3); 622 to->int1 = int1; 623 to->int2 = col; 624 to->node = node; 625 to->ctxt = ctx; 626 627 if (to != &xmlLastError) 628 xmlCopyError(to,&xmlLastError); 629 630 if (schannel != NULL) { 631 schannel(data, to); 632 return; 633 } 634 635 /* 636 * Find the callback channel if channel param is NULL 637 */ 638 if ((ctxt != NULL) && (channel == NULL) && 639 (xmlStructuredError == NULL) && (ctxt->sax != NULL)) { 640 if (level == XML_ERR_WARNING) 641 channel = ctxt->sax->warning; 642 else 643 channel = ctxt->sax->error; 644 data = ctxt->userData; 645 } else if (channel == NULL) { 646 channel = xmlGenericError; 647 if (ctxt != NULL) { 648 data = ctxt; 649 } else { 650 data = xmlGenericErrorContext; 651 } 652 } 653 if (channel == NULL) 654 return; 655 656 if ((channel == xmlParserError) || 657 (channel == xmlParserWarning) || 658 (channel == xmlParserValidityError) || 659 (channel == xmlParserValidityWarning)) 660 xmlReportError(to, ctxt, str, NULL, NULL); 661 else if (((void(*)(void)) channel == (void(*)(void)) fprintf) || 662 (channel == xmlGenericErrorDefaultFunc)) 663 xmlReportError(to, ctxt, str, channel, data); 664 else 665 channel(data, "%s", str); 666} 667 668/** 669 * __xmlSimpleError: 670 * @domain: where the error comes from 671 * @code: the error code 672 * @node: the context node 673 * @extra: extra information 674 * 675 * Handle an out of memory condition 676 */ 677void 678__xmlSimpleError(int domain, int code, xmlNodePtr node, 679 const char *msg, const char *extra) 680{ 681 682 if (code == XML_ERR_NO_MEMORY) { 683 if (extra) 684 __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, 685 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, 686 NULL, NULL, 0, 0, 687 "Memory allocation failed : %s\n", extra); 688 else 689 __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, 690 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, 691 NULL, NULL, 0, 0, "Memory allocation failed\n"); 692 } else { 693 __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, 694 code, XML_ERR_ERROR, NULL, 0, extra, 695 NULL, NULL, 0, 0, msg, extra); 696 } 697} 698/** 699 * xmlParserError: 700 * @ctx: an XML parser context 701 * @msg: the message to display/transmit 702 * @...: extra parameters for the message display 703 * 704 * Display and format an error messages, gives file, line, position and 705 * extra parameters. 706 */ 707void 708xmlParserError(void *ctx, const char *msg, ...) 709{ 710 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 711 xmlParserInputPtr input = NULL; 712 xmlParserInputPtr cur = NULL; 713 char * str; 714 715 if (ctxt != NULL) { 716 input = ctxt->input; 717 if ((input != NULL) && (input->filename == NULL) && 718 (ctxt->inputNr > 1)) { 719 cur = input; 720 input = ctxt->inputTab[ctxt->inputNr - 2]; 721 } 722 xmlParserPrintFileInfo(input); 723 } 724 725 xmlGenericError(xmlGenericErrorContext, "error: "); 726 XML_GET_VAR_STR(msg, str); 727 xmlGenericError(xmlGenericErrorContext, "%s", str); 728 if (str != NULL) 729 xmlFree(str); 730 731 if (ctxt != NULL) { 732 xmlParserPrintFileContext(input); 733 if (cur != NULL) { 734 xmlParserPrintFileInfo(cur); 735 xmlGenericError(xmlGenericErrorContext, "\n"); 736 xmlParserPrintFileContext(cur); 737 } 738 } 739} 740 741/** 742 * xmlParserWarning: 743 * @ctx: an XML parser context 744 * @msg: the message to display/transmit 745 * @...: extra parameters for the message display 746 * 747 * Display and format a warning messages, gives file, line, position and 748 * extra parameters. 749 */ 750void 751xmlParserWarning(void *ctx, const char *msg, ...) 752{ 753 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 754 xmlParserInputPtr input = NULL; 755 xmlParserInputPtr cur = NULL; 756 char * str; 757 758 if (ctxt != NULL) { 759 input = ctxt->input; 760 if ((input != NULL) && (input->filename == NULL) && 761 (ctxt->inputNr > 1)) { 762 cur = input; 763 input = ctxt->inputTab[ctxt->inputNr - 2]; 764 } 765 xmlParserPrintFileInfo(input); 766 } 767 768 xmlGenericError(xmlGenericErrorContext, "warning: "); 769 XML_GET_VAR_STR(msg, str); 770 xmlGenericError(xmlGenericErrorContext, "%s", str); 771 if (str != NULL) 772 xmlFree(str); 773 774 if (ctxt != NULL) { 775 xmlParserPrintFileContext(input); 776 if (cur != NULL) { 777 xmlParserPrintFileInfo(cur); 778 xmlGenericError(xmlGenericErrorContext, "\n"); 779 xmlParserPrintFileContext(cur); 780 } 781 } 782} 783 784/************************************************************************ 785 * * 786 * Handling of validation errors * 787 * * 788 ************************************************************************/ 789 790/** 791 * xmlParserValidityError: 792 * @ctx: an XML parser context 793 * @msg: the message to display/transmit 794 * @...: extra parameters for the message display 795 * 796 * Display and format an validity error messages, gives file, 797 * line, position and extra parameters. 798 */ 799void 800xmlParserValidityError(void *ctx, const char *msg, ...) 801{ 802 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 803 xmlParserInputPtr input = NULL; 804 char * str; 805 int len = xmlStrlen((const xmlChar *) msg); 806 static int had_info = 0; 807 808 if ((len > 1) && (msg[len - 2] != ':')) { 809 if (ctxt != NULL) { 810 input = ctxt->input; 811 if ((input->filename == NULL) && (ctxt->inputNr > 1)) 812 input = ctxt->inputTab[ctxt->inputNr - 2]; 813 814 if (had_info == 0) { 815 xmlParserPrintFileInfo(input); 816 } 817 } 818 xmlGenericError(xmlGenericErrorContext, "validity error: "); 819 had_info = 0; 820 } else { 821 had_info = 1; 822 } 823 824 XML_GET_VAR_STR(msg, str); 825 xmlGenericError(xmlGenericErrorContext, "%s", str); 826 if (str != NULL) 827 xmlFree(str); 828 829 if ((ctxt != NULL) && (input != NULL)) { 830 xmlParserPrintFileContext(input); 831 } 832} 833 834/** 835 * xmlParserValidityWarning: 836 * @ctx: an XML parser context 837 * @msg: the message to display/transmit 838 * @...: extra parameters for the message display 839 * 840 * Display and format a validity warning messages, gives file, line, 841 * position and extra parameters. 842 */ 843void 844xmlParserValidityWarning(void *ctx, const char *msg, ...) 845{ 846 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 847 xmlParserInputPtr input = NULL; 848 char * str; 849 int len = xmlStrlen((const xmlChar *) msg); 850 851 if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) { 852 input = ctxt->input; 853 if ((input->filename == NULL) && (ctxt->inputNr > 1)) 854 input = ctxt->inputTab[ctxt->inputNr - 2]; 855 856 xmlParserPrintFileInfo(input); 857 } 858 859 xmlGenericError(xmlGenericErrorContext, "validity warning: "); 860 XML_GET_VAR_STR(msg, str); 861 xmlGenericError(xmlGenericErrorContext, "%s", str); 862 if (str != NULL) 863 xmlFree(str); 864 865 if (ctxt != NULL) { 866 xmlParserPrintFileContext(input); 867 } 868} 869 870 871/************************************************************************ 872 * * 873 * Extended Error Handling * 874 * * 875 ************************************************************************/ 876 877/** 878 * xmlGetLastError: 879 * 880 * Get the last global error registered. This is per thread if compiled 881 * with thread support. 882 * 883 * Returns a pointer to the error 884 */ 885const xmlError * 886xmlGetLastError(void) 887{ 888 if (xmlLastError.code == XML_ERR_OK) 889 return (NULL); 890 return (&xmlLastError); 891} 892 893/** 894 * xmlResetError: 895 * @err: pointer to the error. 896 * 897 * Cleanup the error. 898 */ 899void 900xmlResetError(xmlErrorPtr err) 901{ 902 if (err == NULL) 903 return; 904 if (err->code == XML_ERR_OK) 905 return; 906 if (err->message != NULL) 907 xmlFree(err->message); 908 if (err->file != NULL) 909 xmlFree(err->file); 910 if (err->str1 != NULL) 911 xmlFree(err->str1); 912 if (err->str2 != NULL) 913 xmlFree(err->str2); 914 if (err->str3 != NULL) 915 xmlFree(err->str3); 916 memset(err, 0, sizeof(xmlError)); 917 err->code = XML_ERR_OK; 918} 919 920/** 921 * xmlResetLastError: 922 * 923 * Cleanup the last global error registered. For parsing error 924 * this does not change the well-formedness result. 925 */ 926void 927xmlResetLastError(void) 928{ 929 if (xmlLastError.code == XML_ERR_OK) 930 return; 931 xmlResetError(&xmlLastError); 932} 933 934/** 935 * xmlCtxtGetLastError: 936 * @ctx: an XML parser context 937 * 938 * Get the last parsing error registered. 939 * 940 * Returns NULL if no error occurred or a pointer to the error 941 */ 942const xmlError * 943xmlCtxtGetLastError(void *ctx) 944{ 945 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 946 947 if (ctxt == NULL) 948 return (NULL); 949 if (ctxt->lastError.code == XML_ERR_OK) 950 return (NULL); 951 return (&ctxt->lastError); 952} 953 954/** 955 * xmlCtxtResetLastError: 956 * @ctx: an XML parser context 957 * 958 * Cleanup the last global error registered. For parsing error 959 * this does not change the well-formedness result. 960 */ 961void 962xmlCtxtResetLastError(void *ctx) 963{ 964 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 965 966 if (ctxt == NULL) 967 return; 968 ctxt->errNo = XML_ERR_OK; 969 if (ctxt->lastError.code == XML_ERR_OK) 970 return; 971 xmlResetError(&ctxt->lastError); 972} 973 974/** 975 * xmlCopyError: 976 * @from: a source error 977 * @to: a target error 978 * 979 * Save the original error to the new place. 980 * 981 * Returns 0 in case of success and -1 in case of error. 982 */ 983int 984xmlCopyError(const xmlError *from, xmlErrorPtr to) { 985 char *message, *file, *str1, *str2, *str3; 986 987 if ((from == NULL) || (to == NULL)) 988 return(-1); 989 990 message = (char *) xmlStrdup((xmlChar *) from->message); 991 file = (char *) xmlStrdup ((xmlChar *) from->file); 992 str1 = (char *) xmlStrdup ((xmlChar *) from->str1); 993 str2 = (char *) xmlStrdup ((xmlChar *) from->str2); 994 str3 = (char *) xmlStrdup ((xmlChar *) from->str3); 995 996 if (to->message != NULL) 997 xmlFree(to->message); 998 if (to->file != NULL) 999 xmlFree(to->file); 1000 if (to->str1 != NULL) 1001 xmlFree(to->str1); 1002 if (to->str2 != NULL) 1003 xmlFree(to->str2); 1004 if (to->str3 != NULL) 1005 xmlFree(to->str3); 1006 to->domain = from->domain; 1007 to->code = from->code; 1008 to->level = from->level; 1009 to->line = from->line; 1010 to->node = from->node; 1011 to->int1 = from->int1; 1012 to->int2 = from->int2; 1013 to->node = from->node; 1014 to->ctxt = from->ctxt; 1015 to->message = message; 1016 to->file = file; 1017 to->str1 = str1; 1018 to->str2 = str2; 1019 to->str3 = str3; 1020 1021 return 0; 1022}