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