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.10 2002/04/16 13:11:47 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.10  2002/04/16 13:11:47  warmerda
00031  * updated
00031  *
00032  * Revision 1.21  2001/12/14 19:45:17  warmerda
00033  * Avoid use of errno in prototype.
00034  *
00035  * Revision 1.20  2001/11/27 17:01:06  warmerda
00036  * added timestamp to debug messages
00037  *
00038  * Revision 1.19  2001/11/15 16:11:08  warmerda
00039  * use vsnprintf() for debug calls if it is available
00040  *
00041  * Revision 1.18  2001/11/02 22:07:58  warmerda
00042  * added logging error handler
00043  *
00044  * Revision 1.17  2001/07/18 04:00:49  warmerda
00045  * added CPL_CVSID
00046  *
00047  * Revision 1.16  2001/02/15 16:30:57  warmerda
00048  * fixed initialization of fpLog
00049  *
00050  * Revision 1.15  2001/01/19 21:16:41  warmerda
00051  * expanded tabs
00052  *
00053  * Revision 1.14  2000/11/30 17:30:10  warmerda
00054  * added CPLGetLastErrorType
00055  *
00056  * Revision 1.13  2000/03/31 14:37:48  warmerda
00057  * only use vsnprintf where available
00058  *
00059  * Revision 1.12  2000/03/31 14:11:55  warmerda
00060  * added CPLErrorV
00061  *
00062  * Revision 1.11  2000/01/10 17:35:45  warmerda
00063  * added push down stack of error handlers
00064  *
00065  * Revision 1.10  1999/11/23 04:16:56  danmo
00066  * Fixed var. initialization that failed to compile as C
00067  *
00068  * Revision 1.9  1999/09/03 17:03:45  warmerda
00069  * Completed partial help line.
00070  *
00071  * Revision 1.8  1999/07/23 14:27:47  warmerda
00072  * CPLSetErrorHandler returns old handler
00073  *
00074  * Revision 1.7  1999/06/27 16:50:52  warmerda
00075  * added support for CPL_DEBUG and CPL_LOG variables
00076  *
00077  * Revision 1.6  1999/06/26 02:46:11  warmerda
00078  * Fixed initialization of debug messages.
00079  *
00080  * Revision 1.5  1999/05/20 14:59:05  warmerda
00081  * added CPLDebug()
00082  *
00083  * Revision 1.4  1999/05/20 02:54:38  warmerda
00084  * Added API documentation
00085  *
00086  * Revision 1.3  1998/12/15 19:02:27  warmerda
00087  * Avoid use of errno as a variable
00088  *
00089  * Revision 1.2  1998/12/06 02:52:52  warmerda
00090  * Implement assert support
00091  *
00092  * Revision 1.1  1998/12/03 18:26:02  warmerda
00093  * New
00094  *
00095  **********************************************************************/
00096 
00097 #include "cpl_error.h"
00098 #include "cpl_vsi.h"
00099 
00100 #define TIMESTAMP_DEBUG
00101 #ifdef TIMESTAMP_DEBUG
00102 #include <time.h>
00103 #endif
00104 
00105 CPL_CVSID("$Id: cpl_error_cpp-source.html,v 1.10 2002/04/16 13:11:47 warmerda Exp $");
00106 
00107 /* static buffer to store the last error message.  We'll assume that error
00108  * messages cannot be longer than 2000 chars... which is quite reasonable
00109  * (that's 25 lines of 80 chars!!!)
00110  */
00111 static char gszCPLLastErrMsg[2000] = "";
00112 static int  gnCPLLastErrNo = 0;
00113 static CPLErr geCPLLastErrType = CE_None;
00114 
00115 static CPLErrorHandler gpfnCPLErrorHandler = CPLDefaultErrorHandler;
00116 
00117 typedef struct errHandler
00118 {
00119     struct errHandler   *psNext;
00120     CPLErrorHandler     pfnHandler;
00121 } CPLErrorHandlerNode;
00122 
00123 static CPLErrorHandlerNode * psHandlerStack = NULL;
00124 
00125 /**********************************************************************
00126  *                          CPLError()
00127  **********************************************************************/
00128 
00161 void    CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)
00162 {
00163     va_list args;
00164 
00165     /* Expand the error message 
00166      */
00167     va_start(args, fmt);
00168     CPLErrorV( eErrClass, err_no, fmt, args );
00169     va_end(args);
00170 }
00171 
00172 /************************************************************************/
00173 /*                             CPLErrorV()                              */
00174 /************************************************************************/
00175 
00176 void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
00177 {
00178     /* Expand the error message 
00179      */
00180 #if defined(HAVE_VSNPRINTF)
00181     vsnprintf(gszCPLLastErrMsg, sizeof(gszCPLLastErrMsg), fmt, args);
00182 #else
00183     vsprintf(gszCPLLastErrMsg, fmt, args);
00184 #endif
00185 
00186     /* If the user provided his own error handling function, then call
00187      * it, otherwise print the error to stderr and return.
00188      */
00189     gnCPLLastErrNo = err_no;
00190     geCPLLastErrType = eErrClass;
00191 
00192     if( gpfnCPLErrorHandler )
00193         gpfnCPLErrorHandler(eErrClass, err_no, gszCPLLastErrMsg);
00194 
00195     if( eErrClass == CE_Fatal )
00196         abort();
00197 }
00198 
00199 /************************************************************************/
00200 /*                              CPLDebug()                              */
00201 /************************************************************************/
00202 
00224 void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
00225 
00226 {
00227     char        *pszMessage;
00228     va_list args;
00229     const char      *pszDebug = getenv("CPL_DEBUG");
00230 
00231 #define ERROR_MAX 25000
00232 
00233 /* -------------------------------------------------------------------- */
00234 /*      Does this message pass our current criteria?                    */
00235 /* -------------------------------------------------------------------- */
00236     if( pszDebug == NULL )
00237         return;
00238 
00239     if( !EQUAL(pszDebug,"ON") && !EQUAL(pszDebug,"") )
00240     {
00241         int            i, nLen = strlen(pszCategory);
00242 
00243         for( i = 0; pszDebug[i] != '\0'; i++ )
00244         {
00245             if( EQUALN(pszCategory,pszDebug+i,nLen) )
00246                 break;
00247         }
00248 
00249         if( pszDebug[i] == '\0' )
00250             return;
00251     }
00252 
00253 /* -------------------------------------------------------------------- */
00254 /*    Allocate a block for the error.                                   */
00255 /* -------------------------------------------------------------------- */
00256     pszMessage = (char *) VSIMalloc(ERROR_MAX);
00257     if( pszMessage == NULL )
00258         return;
00259         
00260 /* -------------------------------------------------------------------- */
00261 /*      Dal -- always log a timestamp as the first part of the line     */
00262 /*      to ensure one is looking at what one should be looking at!      */
00263 /* -------------------------------------------------------------------- */
00264 
00265 #ifdef TIMESTAMP_DEBUG
00266     {
00267         time_t ltime;
00268     
00269         time( &ltime );
00270         strcpy( pszMessage, ctime( &ltime ) );
00271         
00272         // On windows anyway, ctime puts a \n at the end, but I'm not 
00273         // convinced this is standard behaviour, so we'll get rid of it
00274         // carefully
00275 
00276         if (pszMessage[strlen(pszMessage) -1 ] == '\n')
00277         {
00278             pszMessage[strlen(pszMessage) - 1] = 0; // blow it out
00279         }
00280         strcat( pszMessage, ": " );
00281     }
00282 #else
00283     pszMessage[0] = '\0';
00284 #endif
00285 
00286 /* -------------------------------------------------------------------- */
00287 /*      Add the category.                                               */
00288 /* -------------------------------------------------------------------- */
00289     strcat( pszMessage, pszCategory );
00290     strcat( pszMessage, ": " );
00291     
00292 /* -------------------------------------------------------------------- */
00293 /*      Format the application provided portion of the debug message.   */
00294 /* -------------------------------------------------------------------- */
00295     va_start(args, pszFormat);
00296 #if defined(HAVE_VSNPRINTF)
00297     vsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage), 
00298               pszFormat, args);
00299 #else
00300     vsprintf(pszMessage+strlen(pszMessage), pszFormat, args);
00301 #endif
00302     va_end(args);
00303 
00304 /* -------------------------------------------------------------------- */
00305 /*      If the user provided his own error handling function, then call */
00306 /*      it, otherwise print the error to stderr and return.             */
00307 /* -------------------------------------------------------------------- */
00308     if( gpfnCPLErrorHandler )
00309         gpfnCPLErrorHandler(CE_Debug, CPLE_None, pszMessage);
00310 
00311     VSIFree( pszMessage );
00312 }
00313 
00314 /**********************************************************************
00315  *                          CPLErrorReset()
00316  **********************************************************************/
00317 
00325 void    CPLErrorReset()
00326 {
00327     gnCPLLastErrNo = CPLE_None;
00328     gszCPLLastErrMsg[0] = '\0';
00329     geCPLLastErrType = CE_None;
00330 }
00331 
00332 
00333 /**********************************************************************
00334  *                          CPLGetLastErrorNo()
00335  **********************************************************************/
00336 
00346 int     CPLGetLastErrorNo()
00347 {
00348     return gnCPLLastErrNo;
00349 }
00350 
00351 /**********************************************************************
00352  *                          CPLGetLastErrorType()
00353  **********************************************************************/
00354 
00364 CPLErr CPLGetLastErrorType()
00365 {
00366     return geCPLLastErrType;
00367 }
00368 
00369 /**********************************************************************
00370  *                          CPLGetLastErrorMsg()
00371  **********************************************************************/
00372 
00384 const char* CPLGetLastErrorMsg()
00385 {
00386     return gszCPLLastErrMsg;
00387 }
00388 
00389 /************************************************************************/
00390 /*                       CPLDefaultErrorHandler()                       */
00391 /************************************************************************/
00392 
00393 void CPLDefaultErrorHandler( CPLErr eErrClass, int nError, 
00394                              const char * pszErrorMsg )
00395 
00396 {
00397     static int       bLogInit = FALSE;
00398     static FILE *    fpLog = stderr;
00399 
00400     if( !bLogInit )
00401     {
00402         bLogInit = TRUE;
00403 
00404         fpLog = stderr;
00405         if( getenv( "CPL_LOG" ) != NULL )
00406         {
00407             fpLog = fopen( getenv("CPL_LOG"), "wt" );
00408             if( fpLog == NULL )
00409                 fpLog = stderr;
00410         }
00411     }
00412 
00413     if( eErrClass == CE_Debug )
00414         fprintf( fpLog, "%s\n", pszErrorMsg );
00415     else if( eErrClass == CE_Warning )
00416         fprintf( fpLog, "Warning %d: %s\n", nError, pszErrorMsg );
00417     else
00418         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
00419 
00420     fflush( fpLog );
00421 }
00422 
00423 /************************************************************************/
00424 /*                        CPLQuietErrorHandler()                        */
00425 /************************************************************************/
00426 
00427 void CPLQuietErrorHandler( CPLErr eErrClass , int nError, 
00428                            const char * pszErrorMsg )
00429 
00430 {
00431     if( eErrClass == CE_Debug )
00432         CPLDefaultErrorHandler( eErrClass, nError, pszErrorMsg );
00433 }
00434 
00435 /************************************************************************/
00436 /*                       CPLLoggingErrorHandler()                       */
00437 /************************************************************************/
00438 
00439 void CPLLoggingErrorHandler( CPLErr eErrClass, int nError, 
00440                              const char * pszErrorMsg )
00441 
00442 {
00443     static int       bLogInit = FALSE;
00444     static FILE *    fpLog = stderr;
00445 
00446     if( !bLogInit )
00447     {
00448         const char *cpl_log = NULL;
00449 
00450         bLogInit = TRUE;
00451 
00452         if( getenv("CPL_LOG") != NULL )
00453             cpl_log = getenv("CPL_LOG");
00454 
00455         fpLog = stderr;
00456         if( cpl_log != NULL && EQUAL(cpl_log,"OFF") )
00457         {
00458             fpLog = NULL;
00459         }
00460         else if( cpl_log != NULL )
00461         {
00462             char      path[5000];
00463             int       i = 0;
00464 
00465             strcpy( path, cpl_log );
00466 
00467             while( (fpLog = fopen( path, "rt" )) != NULL ) 
00468             {
00469                 fclose( fpLog );
00470 
00471                 sprintf( path, "%s_%d", cpl_log, i++ );
00472             }
00473 
00474             fpLog = fopen( path, "wt" );
00475         }
00476     }
00477 
00478     if( fpLog == NULL )
00479         return;
00480 
00481     if( eErrClass == CE_Debug )
00482         fprintf( fpLog, "%s\n", pszErrorMsg );
00483     else if( eErrClass == CE_Warning )
00484         fprintf( fpLog, "Warning %d: %s\n", nError, pszErrorMsg );
00485     else
00486         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
00487 
00488     fflush( fpLog );
00489 }
00490 
00491 /**********************************************************************
00492  *                          CPLSetErrorHandler()
00493  **********************************************************************/
00494 
00524 CPLErrorHandler CPLSetErrorHandler( CPLErrorHandler pfnErrorHandler )
00525 {
00526     CPLErrorHandler     pfnOldHandler = gpfnCPLErrorHandler;
00527     
00528     gpfnCPLErrorHandler = pfnErrorHandler;
00529 
00530     return pfnOldHandler;
00531 }
00532 
00533 
00534 
00535 /************************************************************************/
00536 /*                        CPLPushErrorHandler()                         */
00537 /************************************************************************/
00538 
00550 void CPLPushErrorHandler( CPLErrorHandler pfnErrorHandler )
00551 
00552 {
00553     CPLErrorHandlerNode         *psNode;
00554 
00555     psNode = (CPLErrorHandlerNode *) VSIMalloc(sizeof(CPLErrorHandlerNode));
00556     psNode->psNext = psHandlerStack;
00557     psNode->pfnHandler = gpfnCPLErrorHandler;
00558 
00559     psHandlerStack = psNode;
00560 
00561     CPLSetErrorHandler( pfnErrorHandler );
00562 }
00563 
00564 /************************************************************************/
00565 /*                         CPLPopErrorHandler()                         */
00566 /************************************************************************/
00567 
00575 void CPLPopErrorHandler()
00576 
00577 {
00578     if( psHandlerStack != NULL )
00579     {
00580         CPLErrorHandlerNode     *psNode = psHandlerStack;
00581 
00582         psHandlerStack = psNode->psNext;
00583         CPLSetErrorHandler( psNode->pfnHandler );
00584         VSIFree( psNode );
00585     }
00586 }
00587 
00588 /************************************************************************/
00589 /*                             _CPLAssert()                             */
00590 /*                                                                      */
00591 /*      This function is called only when an assertion fails.           */
00592 /************************************************************************/
00593 
00606 void _CPLAssert( const char * pszExpression, const char * pszFile,
00607                  int iLine )
00608 
00609 {
00610     CPLError( CE_Fatal, CPLE_AssertionFailed,
00611               "Assertion `%s' failed\n"
00612               "in file `%s', line %d\n",
00613               pszExpression, pszFile, iLine );
00614 }
00615 

Generated at Thu Mar 28 09:47:27 2002 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000