File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / error.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:37:58 2012 UTC (12 years, 5 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>