LCOV - code coverage report
Current view: directory - port - cpl_error.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 183 84 45.9 %
Date: 2010-01-09 Functions: 15 12 80.0 %

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_error.cpp 17293 2009-06-26 14:55:34Z warmerdam $
       3                 :  *
       4                 :  * Name:     cpl_error.cpp
       5                 :  * Project:  CPL - Common Portability Library
       6                 :  * Purpose:  Error handling functions.
       7                 :  * Author:   Daniel Morissette, danmo@videotron.ca
       8                 :  *
       9                 :  **********************************************************************
      10                 :  * Copyright (c) 1998, Daniel Morissette
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  * 
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  * 
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      23                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "cpl_error.h"
      32                 : #include "cpl_vsi.h"
      33                 : #include "cpl_conv.h"
      34                 : #include "cpl_multiproc.h"
      35                 : 
      36                 : #if defined(WIN32CE)
      37                 : #  include "cpl_wince.h"
      38                 : #  include <wce_stdlib.h>
      39                 : #endif
      40                 :  
      41                 : #define TIMESTAMP_DEBUG
      42                 : 
      43                 : CPL_CVSID("$Id: cpl_error.cpp 17293 2009-06-26 14:55:34Z warmerdam $");
      44                 : 
      45                 : static void *hErrorMutex = NULL;
      46                 : static CPLErrorHandler pfnErrorHandler = CPLDefaultErrorHandler;
      47                 : 
      48                 : #if !defined(HAVE_VSNPRINTF)
      49                 : #  define DEFAULT_LAST_ERR_MSG_SIZE 20000
      50                 : #else
      51                 : #  define DEFAULT_LAST_ERR_MSG_SIZE 500
      52                 : #endif
      53                 : 
      54                 : typedef struct errHandler
      55                 : {
      56                 :     struct errHandler   *psNext;
      57                 :     CPLErrorHandler     pfnHandler;
      58                 : } CPLErrorHandlerNode;
      59                 : 
      60                 : typedef struct {
      61                 :     int     nLastErrNo;
      62                 :     CPLErr  eLastErrType;
      63                 :     CPLErrorHandlerNode *psHandlerStack;
      64                 :     int     nLastErrMsgMax;
      65                 :     char    szLastErrMsg[DEFAULT_LAST_ERR_MSG_SIZE];
      66                 : } CPLErrorContext;
      67                 : 
      68                 : /************************************************************************/
      69                 : /*                         CPLGetErrorContext()                         */
      70                 : /************************************************************************/
      71                 : 
      72         1361956 : static CPLErrorContext *CPLGetErrorContext()
      73                 : 
      74                 : {
      75                 :     CPLErrorContext *psCtx = 
      76         1361956 :         (CPLErrorContext *) CPLGetTLS( CTLS_ERRORCONTEXT );
      77                 : 
      78         1361956 :     if( psCtx == NULL )
      79                 :     {
      80             369 :         psCtx = (CPLErrorContext *) CPLCalloc(sizeof(CPLErrorContext),1);
      81             369 :         psCtx->eLastErrType = CE_None;
      82             369 :         psCtx->nLastErrMsgMax = sizeof(psCtx->szLastErrMsg);
      83             369 :         CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
      84                 :     }
      85                 : 
      86         1361956 :     return psCtx;
      87                 : }
      88                 : 
      89                 : 
      90                 : /**********************************************************************
      91                 :  *                          CPLError()
      92                 :  **********************************************************************/
      93                 : 
      94                 : /**
      95                 :  * Report an error.
      96                 :  *
      97                 :  * This function reports an error in a manner that can be hooked
      98                 :  * and reported appropriate by different applications.
      99                 :  *
     100                 :  * The effect of this function can be altered by applications by installing
     101                 :  * a custom error handling using CPLSetErrorHandler().
     102                 :  *
     103                 :  * The eErrClass argument can have the value CE_Warning indicating that the
     104                 :  * message is an informational warning, CE_Failure indicating that the
     105                 :  * action failed, but that normal recover mechanisms will be used or
     106                 :  * CE_Fatal meaning that a fatal error has occured, and that CPLError()
     107                 :  * should not return.  
     108                 :  *
     109                 :  * The default behaviour of CPLError() is to report errors to stderr,
     110                 :  * and to abort() after reporting a CE_Fatal error.  It is expected that
     111                 :  * some applications will want to supress error reporting, and will want to
     112                 :  * install a C++ exception, or longjmp() approach to no local fatal error
     113                 :  * recovery.
     114                 :  *
     115                 :  * Regardless of how application error handlers or the default error
     116                 :  * handler choose to handle an error, the error number, and message will
     117                 :  * be stored for recovery with CPLGetLastErrorNo() and CPLGetLastErrorMsg().
     118                 :  *
     119                 :  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
     120                 :  * @param err_no the error number (CPLE_*) from cpl_error.h.
     121                 :  * @param fmt a printf() style format string.  Any additional arguments
     122                 :  * will be treated as arguments to fill in this format in a manner
     123                 :  * similar to printf().
     124                 :  */
     125                 : 
     126           14758 : void    CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)
     127                 : {
     128                 :     va_list args;
     129                 : 
     130                 :     /* Expand the error message 
     131                 :      */
     132           14758 :     va_start(args, fmt);
     133           14758 :     CPLErrorV( eErrClass, err_no, fmt, args );
     134           14758 :     va_end(args);
     135           14758 : }
     136                 : 
     137                 : /************************************************************************/
     138                 : /*                             CPLErrorV()                              */
     139                 : /************************************************************************/
     140                 : 
     141           14758 : void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
     142                 : {
     143           14758 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     144                 : 
     145                 : /* -------------------------------------------------------------------- */
     146                 : /*      Expand the error message                                        */
     147                 : /* -------------------------------------------------------------------- */
     148                 : #if defined(HAVE_VSNPRINTF)
     149                 :     {
     150                 :         int nPR;
     151                 :         va_list wrk_args;
     152                 : 
     153                 : #ifdef va_copy
     154           14758 :         va_copy( wrk_args, args );
     155                 : #else
     156                 :         wrk_args = args;
     157                 : #endif
     158                 : 
     159                 : /* -------------------------------------------------------------------- */
     160                 : /*      If CPL_ACCUM_ERROR_MSG=ON accumulate the error messages,        */
     161                 : /*      rather than just replacing the last error message.              */
     162                 : /* -------------------------------------------------------------------- */
     163           14758 :         int nPreviousSize = 0;
     164           14758 :         if ( psCtx->psHandlerStack != NULL &&
     165                 :              EQUAL(CPLGetConfigOption( "CPL_ACCUM_ERROR_MSG", "" ), "ON"))
     166                 :         {
     167               0 :             nPreviousSize = strlen(psCtx->szLastErrMsg);
     168               0 :             if (nPreviousSize)
     169                 :             {
     170               0 :                 if (nPreviousSize + 1 + 1 >= psCtx->nLastErrMsgMax)
     171                 :                 {
     172               0 :                     psCtx->nLastErrMsgMax *= 3;
     173                 :                     psCtx = (CPLErrorContext *) 
     174               0 :                         CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
     175               0 :                     CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
     176                 :                 }
     177               0 :                 psCtx->szLastErrMsg[nPreviousSize] = '\n';
     178               0 :                 psCtx->szLastErrMsg[nPreviousSize+1] = '0';
     179               0 :                 nPreviousSize ++;
     180                 :             }
     181                 :         }
     182                 : 
     183           29516 :         while( ((nPR = vsnprintf( psCtx->szLastErrMsg+nPreviousSize, 
     184                 :                                  psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1
     185                 :                 || nPR >= psCtx->nLastErrMsgMax-nPreviousSize-1)
     186                 :                && psCtx->nLastErrMsgMax < 1000000 )
     187                 :         {
     188                 : #ifdef va_copy
     189               0 :             va_end( wrk_args );
     190               0 :             va_copy( wrk_args, args );
     191                 : #else
     192                 :             wrk_args = args;
     193                 : #endif
     194               0 :             psCtx->nLastErrMsgMax *= 3;
     195                 :             psCtx = (CPLErrorContext *) 
     196               0 :                 CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
     197               0 :             CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
     198                 :         }
     199                 : 
     200           14758 :         va_end( wrk_args );
     201                 :     }
     202                 : #else
     203                 :     vsprintf( psCtx->szLastErrMsg, fmt, args);
     204                 : #endif
     205                 : 
     206                 : /* -------------------------------------------------------------------- */
     207                 : /*      If the user provided his own error handling function, then      */
     208                 : /*      call it, otherwise print the error to stderr and return.        */
     209                 : /* -------------------------------------------------------------------- */
     210           14758 :     psCtx->nLastErrNo = err_no;
     211           14758 :     psCtx->eLastErrType = eErrClass;
     212                 : 
     213           14758 :     if( CPLGetConfigOption("CPL_LOG_ERRORS",NULL) != NULL )
     214               0 :         CPLDebug( "CPLError", "%s", psCtx->szLastErrMsg );
     215                 : 
     216                 : /* -------------------------------------------------------------------- */
     217                 : /*      Invoke the current error handler.                               */
     218                 : /* -------------------------------------------------------------------- */
     219           14758 :     if( psCtx->psHandlerStack != NULL )
     220                 :     {
     221                 :         psCtx->psHandlerStack->pfnHandler(eErrClass, err_no, 
     222           14707 :                                           psCtx->szLastErrMsg);
     223                 :     }
     224                 :     else
     225                 :     {
     226              51 :         CPLMutexHolderD( &hErrorMutex );
     227              51 :         if( pfnErrorHandler != NULL )
     228              51 :             pfnErrorHandler(eErrClass, err_no, psCtx->szLastErrMsg);
     229                 :     }
     230                 : 
     231           14758 :     if( eErrClass == CE_Fatal )
     232               0 :         abort();
     233           14758 : }
     234                 : 
     235                 : /************************************************************************/
     236                 : /*                              CPLDebug()                              */
     237                 : /************************************************************************/
     238                 : 
     239                 : /**
     240                 :  * Display a debugging message.
     241                 :  *
     242                 :  * The category argument is used in conjunction with the CPL_DEBUG
     243                 :  * environment variable to establish if the message should be displayed.
     244                 :  * If the CPL_DEBUG environment variable is not set, no debug messages
     245                 :  * are emitted (use CPLError(CE_Warning,...) to ensure messages are displayed).
     246                 :  * If CPL_DEBUG is set, but is an empty string or the word "ON" then all
     247                 :  * debug messages are shown.  Otherwise only messages whose category appears
     248                 :  * somewhere within the CPL_DEBUG value are displayed (as determinted by
     249                 :  * strstr()).
     250                 :  *
     251                 :  * Categories are usually an identifier for the subsystem producing the
     252                 :  * error.  For instance "GDAL" might be used for the GDAL core, and "TIFF"
     253                 :  * for messages from the TIFF translator.  
     254                 :  *
     255                 :  * @param pszCategory name of the debugging message category.
     256                 :  * @param pszFormat printf() style format string for message to display.
     257                 :  *        Remaining arguments are assumed to be for format.
     258                 :  */ 
     259                 : 
     260           32888 : void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
     261                 : 
     262                 : {
     263           32888 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     264                 :     char        *pszMessage;
     265                 :     va_list     args;
     266           32888 :     const char  *pszDebug = CPLGetConfigOption("CPL_DEBUG",NULL);
     267                 : 
     268                 : #define ERROR_MAX 25000
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Does this message pass our current criteria?                    */
     272                 : /* -------------------------------------------------------------------- */
     273           32888 :     if( pszDebug == NULL )
     274           32888 :         return;
     275                 : 
     276               0 :     if( !EQUAL(pszDebug,"ON") && !EQUAL(pszDebug,"") )
     277                 :     {
     278               0 :         size_t  i, nLen = strlen(pszCategory);
     279                 : 
     280               0 :         for( i = 0; pszDebug[i] != '\0'; i++ )
     281                 :         {
     282               0 :             if( EQUALN(pszCategory,pszDebug+i,nLen) )
     283               0 :                 break;
     284                 :         }
     285                 : 
     286               0 :         if( pszDebug[i] == '\0' )
     287               0 :             return;
     288                 :     }
     289                 : 
     290                 : /* -------------------------------------------------------------------- */
     291                 : /*    Allocate a block for the error.                                   */
     292                 : /* -------------------------------------------------------------------- */
     293               0 :     pszMessage = (char *) VSIMalloc( ERROR_MAX );
     294               0 :     if( pszMessage == NULL )
     295               0 :         return;
     296                 :         
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Dal -- always log a timestamp as the first part of the line     */
     299                 : /*      to ensure one is looking at what one should be looking at!      */
     300                 : /* -------------------------------------------------------------------- */
     301                 : 
     302               0 :     pszMessage[0] = '\0';
     303                 : #ifdef TIMESTAMP_DEBUG
     304               0 :     if( CPLGetConfigOption( "CPL_TIMESTAMP", NULL ) != NULL )
     305                 :     {
     306               0 :         strcpy( pszMessage, VSICTime( VSITime(NULL) ) );
     307                 :         
     308                 :         // On windows anyway, ctime puts a \n at the end, but I'm not 
     309                 :         // convinced this is standard behaviour, so we'll get rid of it
     310                 :         // carefully
     311                 : 
     312               0 :         if (pszMessage[strlen(pszMessage) -1 ] == '\n')
     313                 :         {
     314               0 :             pszMessage[strlen(pszMessage) - 1] = 0; // blow it out
     315                 :         }
     316               0 :         strcat( pszMessage, ": " );
     317                 :     }
     318                 : #endif
     319                 : 
     320                 : /* -------------------------------------------------------------------- */
     321                 : /*      Add the category.                                               */
     322                 : /* -------------------------------------------------------------------- */
     323               0 :     strcat( pszMessage, pszCategory );
     324               0 :     strcat( pszMessage, ": " );
     325                 :     
     326                 : /* -------------------------------------------------------------------- */
     327                 : /*      Format the application provided portion of the debug message.   */
     328                 : /* -------------------------------------------------------------------- */
     329               0 :     va_start(args, pszFormat);
     330                 : #if defined(HAVE_VSNPRINTF)
     331                 :     vsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage), 
     332               0 :               pszFormat, args);
     333                 : #else
     334                 :     vsprintf(pszMessage+strlen(pszMessage), pszFormat, args);
     335                 : #endif
     336               0 :     va_end(args);
     337                 : 
     338                 : /* -------------------------------------------------------------------- */
     339                 : /*      Invoke the current error handler.                               */
     340                 : /* -------------------------------------------------------------------- */
     341               0 :     if( psCtx->psHandlerStack != NULL )
     342                 :     {
     343               0 :         psCtx->psHandlerStack->pfnHandler( CE_Debug, CPLE_None, pszMessage );
     344                 :     }
     345                 :     else
     346                 :     {
     347               0 :         CPLMutexHolderD( &hErrorMutex );
     348               0 :         if( pfnErrorHandler != NULL )
     349               0 :             pfnErrorHandler( CE_Debug, CPLE_None, pszMessage );
     350                 :     }
     351                 : 
     352               0 :     VSIFree( pszMessage );
     353                 : }
     354                 : 
     355                 : /**********************************************************************
     356                 :  *                          CPLErrorReset()
     357                 :  **********************************************************************/
     358                 : 
     359                 : /**
     360                 :  * Erase any traces of previous errors.
     361                 :  *
     362                 :  * This is normally used to ensure that an error which has been recovered
     363                 :  * from does not appear to be still in play with high level functions.
     364                 :  */
     365                 : 
     366          346902 : void CPL_STDCALL CPLErrorReset()
     367                 : {
     368          346902 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     369                 : 
     370          346902 :     psCtx->nLastErrNo = CPLE_None;
     371          346902 :     psCtx->szLastErrMsg[0] = '\0';
     372          346902 :     psCtx->eLastErrType = CE_None;
     373          346902 : }
     374                 : 
     375                 : 
     376                 : /**********************************************************************
     377                 :  *                          CPLGetLastErrorNo()
     378                 :  **********************************************************************/
     379                 : 
     380                 : /**
     381                 :  * Fetch the last error number.
     382                 :  *
     383                 :  * This is the error number, not the error class.
     384                 :  *
     385                 :  * @return the error number of the last error to occur, or CPLE_None (0)
     386                 :  * if there are no posted errors.
     387                 :  */
     388                 : 
     389          626251 : int CPL_STDCALL CPLGetLastErrorNo()
     390                 : {
     391          626251 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     392                 : 
     393          626251 :     return psCtx->nLastErrNo;
     394                 : }
     395                 : 
     396                 : /**********************************************************************
     397                 :  *                          CPLGetLastErrorType()
     398                 :  **********************************************************************/
     399                 : 
     400                 : /**
     401                 :  * Fetch the last error type.
     402                 :  *
     403                 :  * This is the error class, not the error number.
     404                 :  *
     405                 :  * @return the error number of the last error to occur, or CE_None (0)
     406                 :  * if there are no posted errors.
     407                 :  */
     408                 : 
     409          335559 : CPLErr CPL_STDCALL CPLGetLastErrorType()
     410                 : {
     411          335559 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     412                 : 
     413          335559 :     return psCtx->eLastErrType;
     414                 : }
     415                 : 
     416                 : /**********************************************************************
     417                 :  *                          CPLGetLastErrorMsg()
     418                 :  **********************************************************************/
     419                 : 
     420                 : /**
     421                 :  * Get the last error message.
     422                 :  *
     423                 :  * Fetches the last error message posted with CPLError(), that hasn't
     424                 :  * been cleared by CPLErrorReset().  The returned pointer is to an internal
     425                 :  * string that should not be altered or freed.
     426                 :  *
     427                 :  * @return the last error message, or NULL if there is no posted error
     428                 :  * message.
     429                 :  */
     430                 : 
     431              41 : const char* CPL_STDCALL CPLGetLastErrorMsg()
     432                 : {
     433              41 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     434                 : 
     435              41 :     return psCtx->szLastErrMsg;
     436                 : }
     437                 : 
     438                 : /************************************************************************/
     439                 : /*                       CPLDefaultErrorHandler()                       */
     440                 : /************************************************************************/
     441                 : 
     442              51 : void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, int nError, 
     443                 :                              const char * pszErrorMsg )
     444                 : 
     445                 : {
     446                 :     static int       bLogInit = FALSE;
     447              51 :     static FILE *    fpLog = stderr;
     448                 :     static int       nCount = 0;
     449                 :     static int       nMaxErrors = -1;
     450                 : 
     451              51 :     if (eErrClass != CE_Debug)
     452                 :     {
     453              51 :         if( nMaxErrors == -1 )
     454                 :         {
     455                 :             nMaxErrors = 
     456               4 :                 atoi(CPLGetConfigOption( "CPL_MAX_ERROR_REPORTS", "1000" ));
     457                 :         }
     458                 : 
     459              51 :         nCount++;
     460              51 :         if (nCount > nMaxErrors && nMaxErrors > 0 )
     461               0 :             return;
     462                 :     }
     463                 : 
     464              51 :     if( !bLogInit )
     465                 :     {
     466               4 :         bLogInit = TRUE;
     467                 : 
     468               4 :         fpLog = stderr;
     469               4 :         if( CPLGetConfigOption( "CPL_LOG", NULL ) != NULL )
     470                 :         {
     471               0 :             fpLog = fopen( CPLGetConfigOption("CPL_LOG",""), "wt" );
     472               0 :             if( fpLog == NULL )
     473               0 :                 fpLog = stderr;
     474                 :         }
     475                 :     }
     476                 : 
     477              51 :     if( eErrClass == CE_Debug )
     478               0 :         fprintf( fpLog, "%s\n", pszErrorMsg );
     479              51 :     else if( eErrClass == CE_Warning )
     480              34 :         fprintf( fpLog, "Warning %d: %s\n", nError, pszErrorMsg );
     481                 :     else
     482              17 :         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
     483                 : 
     484              51 :     if (eErrClass != CE_Debug 
     485                 :         && nMaxErrors > 0 
     486                 :         && nCount == nMaxErrors )
     487                 :     {
     488                 :         fprintf( fpLog, 
     489                 :                  "More than %d errors or warnings have been reported. "
     490                 :                  "No more will be reported from now.\n", 
     491               0 :                  nMaxErrors );
     492                 :     }
     493                 : 
     494              51 :     fflush( fpLog );
     495                 : }
     496                 : 
     497                 : /************************************************************************/
     498                 : /*                        CPLQuietErrorHandler()                        */
     499                 : /************************************************************************/
     500                 : 
     501           14707 : void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , int nError, 
     502                 :                            const char * pszErrorMsg )
     503                 : 
     504                 : {
     505           14707 :     if( eErrClass == CE_Debug )
     506               0 :         CPLDefaultErrorHandler( eErrClass, nError, pszErrorMsg );
     507           14707 : }
     508                 : 
     509                 : /************************************************************************/
     510                 : /*                       CPLLoggingErrorHandler()                       */
     511                 : /************************************************************************/
     512                 : 
     513               0 : void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, int nError, 
     514                 :                              const char * pszErrorMsg )
     515                 : 
     516                 : {
     517                 :     static int       bLogInit = FALSE;
     518               0 :     static FILE *    fpLog = stderr;
     519                 : 
     520               0 :     if( !bLogInit )
     521                 :     {
     522               0 :         const char *cpl_log = NULL;
     523                 : 
     524               0 :         CPLSetConfigOption( "CPL_TIMESTAMP", "ON" );
     525                 : 
     526               0 :         bLogInit = TRUE;
     527                 : 
     528               0 :         cpl_log = CPLGetConfigOption("CPL_LOG", NULL );
     529                 : 
     530               0 :         fpLog = stderr;
     531               0 :         if( cpl_log != NULL && EQUAL(cpl_log,"OFF") )
     532                 :         {
     533               0 :             fpLog = NULL;
     534                 :         }
     535               0 :         else if( cpl_log != NULL )
     536                 :         {
     537                 :             char*     pszPath;
     538               0 :             int       i = 0;
     539                 : 
     540               0 :             pszPath = (char*)CPLMalloc(strlen(cpl_log) + 20);
     541               0 :             strcpy(pszPath, cpl_log);
     542                 : 
     543               0 :             while( (fpLog = fopen( pszPath, "rt" )) != NULL ) 
     544                 :             {
     545               0 :                 fclose( fpLog );
     546                 : 
     547                 :                 /* generate sequenced log file names, inserting # before ext.*/
     548               0 :                 if (strrchr(cpl_log, '.') == NULL)
     549                 :                 {
     550                 :                     sprintf( pszPath, "%s_%d%s", cpl_log, i++,
     551               0 :                              ".log" );
     552                 :                 }
     553                 :                 else
     554                 :                 {
     555               0 :                     size_t pos = 0;
     556               0 :                     char *cpl_log_base = strdup(cpl_log);
     557               0 :                     pos = strcspn(cpl_log_base, ".");
     558               0 :                     if (pos > 0)
     559                 :                     {
     560               0 :                         cpl_log_base[pos] = '\0';
     561                 :                     }
     562                 :                     sprintf( pszPath, "%s_%d%s", cpl_log_base,
     563               0 :                              i++, ".log" );
     564               0 :                     free(cpl_log_base);
     565                 :                 }
     566                 :             }
     567                 : 
     568               0 :             fpLog = fopen( pszPath, "wt" );
     569               0 :             CPLFree(pszPath);
     570                 :         }
     571                 :     }
     572                 : 
     573               0 :     if( fpLog == NULL )
     574               0 :         return;
     575                 : 
     576               0 :     if( eErrClass == CE_Debug )
     577               0 :         fprintf( fpLog, "%s\n", pszErrorMsg );
     578               0 :     else if( eErrClass == CE_Warning )
     579               0 :         fprintf( fpLog, "Warning %d: %s\n", nError, pszErrorMsg );
     580                 :     else
     581               0 :         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
     582                 : 
     583               0 :     fflush( fpLog );
     584                 : }
     585                 : 
     586                 : /**********************************************************************
     587                 :  *                          CPLSetErrorHandler()
     588                 :  **********************************************************************/
     589                 : 
     590                 : /**
     591                 :  * Install custom error handler.
     592                 :  *
     593                 :  * Allow the library's user to specify his own error handler function.
     594                 :  * A valid error handler is a C function with the following prototype:
     595                 :  *
     596                 :  * <pre>
     597                 :  *     void MyErrorHandler(CPLErr eErrClass, int err_no, const char *msg)
     598                 :  * </pre>
     599                 :  *
     600                 :  * Pass NULL to come back to the default behavior.  The default behaviour
     601                 :  * (CPLDefaultErrorHandler()) is to write the message to stderr. 
     602                 :  *
     603                 :  * The msg will be a partially formatted error message not containing the
     604                 :  * "ERROR %d:" portion emitted by the default handler.  Message formatting
     605                 :  * is handled by CPLError() before calling the handler.  If the error
     606                 :  * handler function is passed a CE_Fatal class error and returns, then
     607                 :  * CPLError() will call abort(). Applications wanting to interrupt this
     608                 :  * fatal behaviour will have to use longjmp(), or a C++ exception to
     609                 :  * indirectly exit the function.
     610                 :  *
     611                 :  * Another standard error handler is CPLQuietErrorHandler() which doesn't
     612                 :  * make any attempt to report the passed error or warning messages but
     613                 :  * will process debug messages via CPLDefaultErrorHandler.
     614                 :  *
     615                 :  * Note that error handlers set with CPLSetErrorHandler() apply to all
     616                 :  * threads in an application, while error handlers set with CPLPushErrorHandler
     617                 :  * are thread-local.  However, any error handlers pushed with 
     618                 :  * CPLPushErrorHandler (and not removed with CPLPopErrorHandler) take 
     619                 :  * precidence over the global error handlers set with CPLSetErrorHandler(). 
     620                 :  * Generally speaking CPLSetErrorHandler() would be used to set a desired
     621                 :  * global error handler, while CPLPushErrorHandler() would be used to install
     622                 :  * a temporary local error handler, such as CPLQuietErrorHandler() to suppress
     623                 :  * error reporting in a limited segment of code. 
     624                 :  *
     625                 :  * @param pfnErrorHandlerNew new error handler function.
     626                 :  * @return returns the previously installed error handler.
     627                 :  */ 
     628                 : 
     629                 : CPLErrorHandler CPL_STDCALL 
     630               0 : CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
     631                 : {
     632               0 :     CPLErrorHandler     pfnOldHandler = pfnErrorHandler;
     633               0 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     634                 : 
     635               0 :     if( psCtx->psHandlerStack != NULL )
     636                 :     {
     637                 :         CPLDebug( "CPL", 
     638                 :                   "CPLSetErrorHandler() called with an error handler on\n"
     639               0 :                   "the local stack.  New error handler will not be used immediately.\n" );
     640                 :     }
     641                 : 
     642                 : 
     643                 :     {
     644               0 :         CPLMutexHolderD( &hErrorMutex );
     645                 : 
     646               0 :         pfnOldHandler = pfnErrorHandler;
     647                 :         
     648               0 :         if( pfnErrorHandler == NULL )
     649               0 :             pfnErrorHandler = CPLDefaultErrorHandler;
     650                 :         else
     651               0 :             pfnErrorHandler = pfnErrorHandlerNew;
     652                 :     }
     653                 : 
     654               0 :     return pfnOldHandler;
     655                 : }
     656                 : 
     657                 : /************************************************************************/
     658                 : /*                        CPLPushErrorHandler()                         */
     659                 : /************************************************************************/
     660                 : 
     661                 : /**
     662                 :  * Push a new CPLError handler.
     663                 :  *
     664                 :  * This pushes a new error handler on the thread-local error handler
     665                 :  * stack.  This handler will be used untill removed with CPLPopErrorHandler().
     666                 :  *
     667                 :  * The CPLSetErrorHandler() docs have further information on how 
     668                 :  * CPLError handlers work.
     669                 :  *
     670                 :  * @param pfnErrorHandlerNew new error handler function.
     671                 :  */
     672                 : 
     673            2783 : void CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
     674                 : 
     675                 : {
     676            2783 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     677                 :     CPLErrorHandlerNode         *psNode;
     678                 : 
     679            2783 :     psNode = (CPLErrorHandlerNode *) VSIMalloc(sizeof(CPLErrorHandlerNode));
     680            2783 :     psNode->psNext = psCtx->psHandlerStack;
     681            2783 :     psNode->pfnHandler = pfnErrorHandlerNew;
     682                 : 
     683            2783 :     psCtx->psHandlerStack = psNode;
     684            2783 : }
     685                 : 
     686                 : /************************************************************************/
     687                 : /*                         CPLPopErrorHandler()                         */
     688                 : /************************************************************************/
     689                 : 
     690                 : /**
     691                 :  * Pop error handler off stack.
     692                 :  *
     693                 :  * Discards the current error handler on the error handler stack, and restores 
     694                 :  * the one in use before the last CPLPushErrorHandler() call.  This method
     695                 :  * has no effect if there are no error handlers on the current threads error
     696                 :  * handler stack. 
     697                 :  */ 
     698                 : 
     699            2774 : void CPL_STDCALL CPLPopErrorHandler()
     700                 : 
     701                 : {
     702            2774 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     703                 : 
     704            2774 :     if( psCtx->psHandlerStack != NULL )
     705                 :     {
     706            2774 :         CPLErrorHandlerNode     *psNode = psCtx->psHandlerStack;
     707                 : 
     708            2774 :         psCtx->psHandlerStack = psNode->psNext;
     709            2774 :         VSIFree( psNode );
     710                 :     }
     711            2774 : }
     712                 : 
     713                 : /************************************************************************/
     714                 : /*                             _CPLAssert()                             */
     715                 : /*                                                                      */
     716                 : /*      This function is called only when an assertion fails.           */
     717                 : /************************************************************************/
     718                 : 
     719                 : /**
     720                 :  * Report failure of a logical assertion.
     721                 :  *
     722                 :  * Applications would normally use the CPLAssert() macro which expands
     723                 :  * into code calling _CPLAssert() only if the condition fails.  _CPLAssert()
     724                 :  * will generate a CE_Fatal error call to CPLError(), indicating the file
     725                 :  * name, and line number of the failed assertion, as well as containing
     726                 :  * the assertion itself.
     727                 :  *
     728                 :  * There is no reason for application code to call _CPLAssert() directly.
     729                 :  */
     730                 : 
     731               0 : void CPL_STDCALL _CPLAssert( const char * pszExpression, const char * pszFile,
     732                 :                  int iLine )
     733                 : 
     734                 : {
     735                 :     CPLError( CE_Fatal, CPLE_AssertionFailed,
     736                 :               "Assertion `%s' failed\n"
     737                 :               "in file `%s', line %d\n",
     738               0 :               pszExpression, pszFile, iLine );
     739               0 : }
     740                 : 

Generated by: LCOV version 1.7