Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

cpl_error.cpp

00001 /**********************************************************************
00002  * $Id: cpl_error_cpp-source.html,v 1.5 2000/11/06 04:49:01 warmerda Exp $
00003  *
00004  * Name:     cpl_error.cpp
00005  * Project:  CPL - Common Portability Library
00006  * Purpose:  Error handling functions.
00007  * Author:   Daniel Morissette, danmo@videotron.ca
00008  *
00009  **********************************************************************
00010  * Copyright (c) 1998, Daniel Morissette
00011  *
00012  * Permission is hereby granted, free of charge, to any person obtaining a
00013  * copy of this software and associated documentation files (the "Software"),
00014  * to deal in the Software without restriction, including without limitation
00015  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00016  * and/or sell copies of the Software, and to permit persons to whom the
00017  * Software is furnished to do so, subject to the following conditions:
00018  * 
00019  * The above copyright notice and this permission notice shall be included
00020  * in all copies or substantial portions of the Software.
00021  * 
00022  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00025  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00027  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
00028  * DEALINGS IN THE SOFTWARE.
00029  **********************************************************************
00030  *
00031  * $Log: cpl_error_cpp-source.html,v $
00031  * Revision 1.5  2000/11/06 04:49:01  warmerda
00031  * *** empty log message ***
00031  *
00032  * Revision 1.13  2000/03/31 14:37:48  warmerda
00033  * only use vsnprintf where available
00034  *
00035  * Revision 1.12  2000/03/31 14:11:55  warmerda
00036  * added CPLErrorV
00037  *
00038  * Revision 1.11  2000/01/10 17:35:45  warmerda
00039  * added push down stack of error handlers
00040  *
00041  * Revision 1.10  1999/11/23 04:16:56  danmo
00042  * Fixed var. initialization that failed to compile as C
00043  *
00044  * Revision 1.9  1999/09/03 17:03:45  warmerda
00045  * Completed partial help line.
00046  *
00047  * Revision 1.8  1999/07/23 14:27:47  warmerda
00048  * CPLSetErrorHandler returns old handler
00049  *
00050  * Revision 1.7  1999/06/27 16:50:52  warmerda
00051  * added support for CPL_DEBUG and CPL_LOG variables
00052  *
00053  * Revision 1.6  1999/06/26 02:46:11  warmerda
00054  * Fixed initialization of debug messages.
00055  *
00056  * Revision 1.5  1999/05/20 14:59:05  warmerda
00057  * added CPLDebug()
00058  *
00059  * Revision 1.4  1999/05/20 02:54:38  warmerda
00060  * Added API documentation
00061  *
00062  * Revision 1.3  1998/12/15 19:02:27  warmerda
00063  * Avoid use of errno as a variable
00064  *
00065  * Revision 1.2  1998/12/06 02:52:52  warmerda
00066  * Implement assert support
00067  *
00068  * Revision 1.1  1998/12/03 18:26:02  warmerda
00069  * New
00070  *
00071  **********************************************************************/
00072 
00073 #include "cpl_error.h"
00074 #include "cpl_vsi.h"
00075 
00076 /* static buffer to store the last error message.  We'll assume that error
00077  * messages cannot be longer than 2000 chars... which is quite reasonable
00078  * (that's 25 lines of 80 chars!!!)
00079  */
00080 static char gszCPLLastErrMsg[2000] = "";
00081 static int  gnCPLLastErrNo = 0;
00082 
00083 static CPLErrorHandler gpfnCPLErrorHandler = CPLDefaultErrorHandler;
00084 
00085 typedef struct errHandler
00086 {
00087     struct errHandler   *psNext;
00088     CPLErrorHandler     pfnHandler;
00089 } CPLErrorHandlerNode;
00090 
00091 static CPLErrorHandlerNode * psHandlerStack = NULL;
00092 
00093 /**********************************************************************
00094  *                          CPLError()
00095  **********************************************************************/
00096 
00129 void    CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)
00130 {
00131     va_list args;
00132 
00133     /* Expand the error message 
00134      */
00135     va_start(args, fmt);
00136     CPLErrorV( eErrClass, err_no, fmt, args );
00137     va_end(args);
00138 }
00139 
00140 /************************************************************************/
00141 /*                             CPLErrorV()                              */
00142 /************************************************************************/
00143 
00144 void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
00145 {
00146     /* Expand the error message 
00147      */
00148 #if defined(HAVE_VSNPRINTF)
00149     vsnprintf(gszCPLLastErrMsg, sizeof(gszCPLLastErrMsg), fmt, args);
00150 #else
00151     vsprintf(gszCPLLastErrMsg, fmt, args);
00152 #endif
00153 
00154     /* If the user provided his own error handling function, then call
00155      * it, otherwise print the error to stderr and return.
00156      */
00157     gnCPLLastErrNo = err_no;
00158 
00159     if( gpfnCPLErrorHandler )
00160         gpfnCPLErrorHandler(eErrClass, err_no, gszCPLLastErrMsg);
00161 
00162     if( eErrClass == CE_Fatal )
00163         abort();
00164 }
00165 
00166 /************************************************************************/
00167 /*                              CPLDebug()                              */
00168 /************************************************************************/
00169 
00191 void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
00192 
00193 {
00194     char        *pszMessage;
00195     va_list args;
00196     const char      *pszDebug = getenv("CPL_DEBUG");
00197 
00198 /* -------------------------------------------------------------------- */
00199 /*      Does this message pass our current criteria?                    */
00200 /* -------------------------------------------------------------------- */
00201     if( pszDebug == NULL )
00202         return;
00203 
00204     if( !EQUAL(pszDebug,"ON") && !EQUAL(pszDebug,"") )
00205     {
00206         int            i, nLen = strlen(pszCategory);
00207 
00208         for( i = 0; pszDebug[i] != '\0'; i++ )
00209         {
00210             if( EQUALN(pszCategory,pszDebug+i,nLen) )
00211                 break;
00212         }
00213 
00214         if( pszDebug[i] == '\0' )
00215             return;
00216     }
00217 
00218 /* -------------------------------------------------------------------- */
00219 /*      Format the error message                                        */
00220 /* -------------------------------------------------------------------- */
00221     pszMessage = (char *) VSIMalloc(25000);
00222     if( pszMessage == NULL )
00223         return;
00224         
00225     strcpy( pszMessage, pszCategory );
00226     strcat( pszMessage, ": " );
00227     
00228     va_start(args, pszFormat);
00229     vsprintf(pszMessage+strlen(pszMessage), pszFormat, args);
00230     va_end(args);
00231 
00232 /* -------------------------------------------------------------------- */
00233 /*      If the user provided his own error handling function, then call */
00234 /*      it, otherwise print the error to stderr and return.             */
00235 /* -------------------------------------------------------------------- */
00236     if( gpfnCPLErrorHandler )
00237         gpfnCPLErrorHandler(CE_Debug, CPLE_None, pszMessage);
00238 
00239     VSIFree( pszMessage );
00240 }
00241 
00242 /**********************************************************************
00243  *                          CPLErrorReset()
00244  **********************************************************************/
00245 
00253 void    CPLErrorReset()
00254 {
00255     gnCPLLastErrNo = CPLE_None;
00256     gszCPLLastErrMsg[0] = '\0';
00257 }
00258 
00259 
00260 /**********************************************************************
00261  *                          CPLGetLastErrorNo()
00262  **********************************************************************/
00263 
00273 int     CPLGetLastErrorNo()
00274 {
00275     return gnCPLLastErrNo;
00276 }
00277 
00278 /**********************************************************************
00279  *                          CPLGetLastErrorMsg()
00280  **********************************************************************/
00281 
00293 const char* CPLGetLastErrorMsg()
00294 {
00295     return gszCPLLastErrMsg;
00296 }
00297 
00298 /************************************************************************/
00299 /*                       CPLDefaultErrorHandler()                       */
00300 /************************************************************************/
00301 
00302 void CPLDefaultErrorHandler( CPLErr eErrClass, int nError, 
00303                              const char * pszErrorMsg )
00304 
00305 {
00306     static int       bLogInit = FALSE;
00307     static FILE *    fpLog;
00308     fpLog = stderr;
00309 
00310     if( !bLogInit )
00311     {
00312         bLogInit = TRUE;
00313 
00314         if( getenv( "CPL_LOG" ) != NULL )
00315         {
00316             fpLog = fopen( getenv("CPL_LOG"), "wt" );
00317             if( fpLog == NULL )
00318                 fpLog = stderr;
00319         }
00320     }
00321 
00322     if( eErrClass == CE_Debug )
00323         fprintf( fpLog, "%s\n", pszErrorMsg );
00324     else if( eErrClass == CE_Warning )
00325         fprintf( fpLog, "Warning %d: %s\n", nError, pszErrorMsg );
00326     else
00327         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
00328 
00329     fflush( fpLog );
00330 }
00331 
00332 /************************************************************************/
00333 /*                        CPLQuietErrorHandler()                        */
00334 /************************************************************************/
00335 
00336 void CPLQuietErrorHandler( CPLErr eErrClass , int nError, 
00337                            const char * pszErrorMsg )
00338 
00339 {
00340     if( eErrClass == CE_Debug )
00341         CPLDefaultErrorHandler( eErrClass, nError, pszErrorMsg );
00342 }
00343 
00344 /**********************************************************************
00345  *                          CPLSetErrorHandler()
00346  **********************************************************************/
00347 
00377 CPLErrorHandler CPLSetErrorHandler( CPLErrorHandler pfnErrorHandler )
00378 {
00379     CPLErrorHandler     pfnOldHandler = gpfnCPLErrorHandler;
00380     
00381     gpfnCPLErrorHandler = pfnErrorHandler;
00382 
00383     return pfnOldHandler;
00384 }
00385 
00386 
00387 
00388 /************************************************************************/
00389 /*                        CPLPushErrorHandler()                         */
00390 /************************************************************************/
00391 
00403 void CPLPushErrorHandler( CPLErrorHandler pfnErrorHandler )
00404 
00405 {
00406     CPLErrorHandlerNode         *psNode;
00407 
00408     psNode = (CPLErrorHandlerNode *) VSIMalloc(sizeof(CPLErrorHandlerNode));
00409     psNode->psNext = psHandlerStack;
00410     psNode->pfnHandler = gpfnCPLErrorHandler;
00411 
00412     psHandlerStack = psNode;
00413 
00414     CPLSetErrorHandler( pfnErrorHandler );
00415 }
00416 
00417 /************************************************************************/
00418 /*                         CPLPopErrorHandler()                         */
00419 /************************************************************************/
00420 
00428 void CPLPopErrorHandler()
00429 
00430 {
00431     if( psHandlerStack != NULL )
00432     {
00433         CPLErrorHandlerNode     *psNode = psHandlerStack;
00434 
00435         psHandlerStack = psNode->psNext;
00436         CPLSetErrorHandler( psNode->pfnHandler );
00437         VSIFree( psNode );
00438     }
00439 }
00440 
00441 /************************************************************************/
00442 /*                             _CPLAssert()                             */
00443 /*                                                                      */
00444 /*      This function is called only when an assertion fails.           */
00445 /************************************************************************/
00446 
00459 void _CPLAssert( const char * pszExpression, const char * pszFile,
00460                  int iLine )
00461 
00462 {
00463     CPLError( CE_Fatal, CPLE_AssertionFailed,
00464               "Assertion `%s' failed\n"
00465               "in file `%s', line %d\n",
00466               pszExpression, pszFile, iLine );
00467 }
00468 

doxygen1.2.3-20001105 Dimitri van Heesch, © 1997-2000