LCOV - code coverage report
Current view: directory - port - cpl_error.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 212 121 57.1 %
Date: 2012-04-28 Functions: 20 16 80.0 %

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_error.cpp 23348 2011-11-06 16:22:05Z rouault $
       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 23348 2011-11-06 16:22:05Z rouault $");
      44                 : 
      45                 : static void *hErrorMutex = NULL;
      46                 : static void *pErrorHandlerUserData = NULL; 
      47                 : static CPLErrorHandler pfnErrorHandler = CPLDefaultErrorHandler;
      48                 : 
      49                 : #if !defined(HAVE_VSNPRINTF)
      50                 : #  define DEFAULT_LAST_ERR_MSG_SIZE 20000
      51                 : #else
      52                 : #  define DEFAULT_LAST_ERR_MSG_SIZE 500
      53                 : #endif
      54                 : 
      55                 : typedef struct errHandler
      56                 : {
      57                 :     struct errHandler   *psNext;
      58                 :     void                *pUserData;
      59                 :     CPLErrorHandler     pfnHandler;
      60                 : } CPLErrorHandlerNode;
      61                 : 
      62                 : typedef struct {
      63                 :     int     nLastErrNo;
      64                 :     CPLErr  eLastErrType;
      65                 :     CPLErrorHandlerNode *psHandlerStack;
      66                 :     int     nLastErrMsgMax;
      67                 :     int     nFailureIntoWarning;
      68                 :     char    szLastErrMsg[DEFAULT_LAST_ERR_MSG_SIZE];
      69                 :     /* Do not add anything here. szLastErrMsg must be the last field. See CPLRealloc() below */
      70                 : } CPLErrorContext;
      71                 : 
      72                 : /************************************************************************/
      73                 : /*                         CPLGetErrorContext()                         */
      74                 : /************************************************************************/
      75                 : 
      76         4051300 : static CPLErrorContext *CPLGetErrorContext()
      77                 : 
      78                 : {
      79                 :     CPLErrorContext *psCtx = 
      80         4051300 :         (CPLErrorContext *) CPLGetTLS( CTLS_ERRORCONTEXT );
      81                 : 
      82         4051300 :     if( psCtx == NULL )
      83                 :     {
      84            1307 :         psCtx = (CPLErrorContext *) CPLCalloc(sizeof(CPLErrorContext),1);
      85            1307 :         psCtx->eLastErrType = CE_None;
      86            1307 :         psCtx->nLastErrMsgMax = sizeof(psCtx->szLastErrMsg);
      87            1307 :         CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
      88                 :     }
      89                 : 
      90         4051300 :     return psCtx;
      91                 : }
      92                 : 
      93                 : /************************************************************************/
      94                 : /*                         CPLGetErrorHandlerUserData()                 */
      95                 : /************************************************************************/
      96                 : 
      97                 : /**
      98                 :  * Fetch the user data for the error context
      99                 :  *
     100                 :  * Fetches the user data for the current error context.  You can 
     101                 :  * set the user data for the error context when you add your handler by 
     102                 :  * issuing CPLSetErrorHandlerEx() and CPLPushErrorHandlerEx().  Note that 
     103                 :  * user data is primarily intended for providing context within error handlers
     104                 :  * themselves, but they could potentially be abused in other useful ways with the usual 
     105                 :  * caveat emptor understanding.
     106                 :  *
     107                 :  * @return the user data pointer for the error context
     108                 :  */
     109                 : 
     110               0 : void* CPL_STDCALL CPLGetErrorHandlerUserData(void)
     111                 : {
     112               0 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     113               0 :     return (void*) psCtx->psHandlerStack ? psCtx->psHandlerStack->pUserData : pErrorHandlerUserData;
     114                 : }
     115                 : 
     116                 : /**********************************************************************
     117                 :  *                          CPLError()
     118                 :  **********************************************************************/
     119                 : 
     120                 : /**
     121                 :  * Report an error.
     122                 :  *
     123                 :  * This function reports an error in a manner that can be hooked
     124                 :  * and reported appropriate by different applications.
     125                 :  *
     126                 :  * The effect of this function can be altered by applications by installing
     127                 :  * a custom error handling using CPLSetErrorHandler().
     128                 :  *
     129                 :  * The eErrClass argument can have the value CE_Warning indicating that the
     130                 :  * message is an informational warning, CE_Failure indicating that the
     131                 :  * action failed, but that normal recover mechanisms will be used or
     132                 :  * CE_Fatal meaning that a fatal error has occured, and that CPLError()
     133                 :  * should not return.  
     134                 :  *
     135                 :  * The default behaviour of CPLError() is to report errors to stderr,
     136                 :  * and to abort() after reporting a CE_Fatal error.  It is expected that
     137                 :  * some applications will want to supress error reporting, and will want to
     138                 :  * install a C++ exception, or longjmp() approach to no local fatal error
     139                 :  * recovery.
     140                 :  *
     141                 :  * Regardless of how application error handlers or the default error
     142                 :  * handler choose to handle an error, the error number, and message will
     143                 :  * be stored for recovery with CPLGetLastErrorNo() and CPLGetLastErrorMsg().
     144                 :  *
     145                 :  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
     146                 :  * @param err_no the error number (CPLE_*) from cpl_error.h.
     147                 :  * @param fmt a printf() style format string.  Any additional arguments
     148                 :  * will be treated as arguments to fill in this format in a manner
     149                 :  * similar to printf().
     150                 :  */
     151                 : 
     152            8894 : void    CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)
     153                 : {
     154                 :     va_list args;
     155                 : 
     156                 :     /* Expand the error message 
     157                 :      */
     158            8894 :     va_start(args, fmt);
     159            8894 :     CPLErrorV( eErrClass, err_no, fmt, args );
     160            8894 :     va_end(args);
     161            8894 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                             CPLErrorV()                              */
     165                 : /************************************************************************/
     166                 : 
     167           35368 : void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
     168                 : {
     169           35368 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     170                 : 
     171           35368 :     if (psCtx->nFailureIntoWarning > 0 && eErrClass == CE_Failure)
     172               0 :         eErrClass = CE_Warning;
     173                 : 
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      Expand the error message                                        */
     176                 : /* -------------------------------------------------------------------- */
     177                 : #if defined(HAVE_VSNPRINTF)
     178                 :     {
     179                 :         int nPR;
     180                 :         va_list wrk_args;
     181                 : 
     182                 : #ifdef va_copy
     183           35368 :         va_copy( wrk_args, args );
     184                 : #else
     185                 :         wrk_args = args;
     186                 : #endif
     187                 : 
     188                 : /* -------------------------------------------------------------------- */
     189                 : /*      If CPL_ACCUM_ERROR_MSG=ON accumulate the error messages,        */
     190                 : /*      rather than just replacing the last error message.              */
     191                 : /* -------------------------------------------------------------------- */
     192           35368 :         int nPreviousSize = 0;
     193           35368 :         if ( psCtx->psHandlerStack != NULL &&
     194                 :              EQUAL(CPLGetConfigOption( "CPL_ACCUM_ERROR_MSG", "" ), "ON"))
     195                 :         {
     196               0 :             nPreviousSize = strlen(psCtx->szLastErrMsg);
     197               0 :             if (nPreviousSize)
     198                 :             {
     199               0 :                 if (nPreviousSize + 1 + 1 >= psCtx->nLastErrMsgMax)
     200                 :                 {
     201               0 :                     psCtx->nLastErrMsgMax *= 3;
     202                 :                     psCtx = (CPLErrorContext *) 
     203               0 :                         CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
     204               0 :                     CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
     205                 :                 }
     206               0 :                 psCtx->szLastErrMsg[nPreviousSize] = '\n';
     207               0 :                 psCtx->szLastErrMsg[nPreviousSize+1] = '0';
     208               0 :                 nPreviousSize ++;
     209                 :             }
     210                 :         }
     211                 : 
     212           70736 :         while( ((nPR = vsnprintf( psCtx->szLastErrMsg+nPreviousSize, 
     213                 :                                  psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1
     214                 :                 || nPR >= psCtx->nLastErrMsgMax-nPreviousSize-1)
     215                 :                && psCtx->nLastErrMsgMax < 1000000 )
     216                 :         {
     217                 : #ifdef va_copy
     218               0 :             va_end( wrk_args );
     219               0 :             va_copy( wrk_args, args );
     220                 : #else
     221                 :             wrk_args = args;
     222                 : #endif
     223               0 :             psCtx->nLastErrMsgMax *= 3;
     224                 :             psCtx = (CPLErrorContext *) 
     225               0 :                 CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
     226               0 :             CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
     227                 :         }
     228                 : 
     229           35368 :         va_end( wrk_args );
     230                 :     }
     231                 : #else
     232                 :     vsprintf( psCtx->szLastErrMsg, fmt, args);
     233                 : #endif
     234                 : 
     235                 : /* -------------------------------------------------------------------- */
     236                 : /*      If the user provided his own error handling function, then      */
     237                 : /*      call it, otherwise print the error to stderr and return.        */
     238                 : /* -------------------------------------------------------------------- */
     239           35368 :     psCtx->nLastErrNo = err_no;
     240           35368 :     psCtx->eLastErrType = eErrClass;
     241                 : 
     242           35368 :     if( CPLGetConfigOption("CPL_LOG_ERRORS",NULL) != NULL )
     243               0 :         CPLDebug( "CPLError", "%s", psCtx->szLastErrMsg );
     244                 : 
     245                 : /* -------------------------------------------------------------------- */
     246                 : /*      Invoke the current error handler.                               */
     247                 : /* -------------------------------------------------------------------- */
     248           35368 :     if( psCtx->psHandlerStack != NULL )
     249                 :     {
     250                 :         psCtx->psHandlerStack->pfnHandler(eErrClass, err_no, 
     251           34868 :                                           psCtx->szLastErrMsg);
     252                 :     }
     253                 :     else
     254                 :     {
     255             500 :         CPLMutexHolderD( &hErrorMutex );
     256             500 :         if( pfnErrorHandler != NULL )
     257             500 :             pfnErrorHandler(eErrClass, err_no, psCtx->szLastErrMsg);
     258                 :     }
     259                 : 
     260           35368 :     if( eErrClass == CE_Fatal )
     261               0 :         abort();
     262           35368 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                         CPLEmergencyError()                          */
     266                 : /************************************************************************/
     267                 : 
     268                 : /**
     269                 :  * Fatal error when things are bad. 
     270                 :  *
     271                 :  * This function should be called in an emergency situation where
     272                 :  * it is unlikely that a regular error report would work.  This would 
     273                 :  * include in the case of heap exhaustion for even small allocations, 
     274                 :  * or any failure in the process of reporting an error (such as TLS 
     275                 :  * allocations). 
     276                 :  *
     277                 :  * This function should never return.  After the error message has been
     278                 :  * reported as best possible, the application will abort() similarly to how
     279                 :  * CPLError() aborts on CE_Fatal class errors.
     280                 :  *
     281                 :  * @param pszMessage the error message to report.
     282                 :  */
     283                 : 
     284               0 : void CPLEmergencyError( const char *pszMessage )
     285                 : {
     286               0 :     CPLErrorContext *psCtx = NULL;
     287                 :     static int bInEmergencyError = FALSE;
     288                 : 
     289               0 :     if( !bInEmergencyError )
     290                 :     {
     291               0 :         bInEmergencyError = TRUE;
     292               0 :         psCtx = (CPLErrorContext *) CPLGetTLS( CTLS_ERRORCONTEXT );
     293                 :     }
     294                 : 
     295               0 :     if( psCtx != NULL && psCtx->psHandlerStack != NULL )
     296                 :     {
     297                 :         psCtx->psHandlerStack->pfnHandler( CE_Fatal, CPLE_AppDefined, 
     298               0 :                                            pszMessage );
     299                 :     }
     300               0 :     else if( pfnErrorHandler != NULL )
     301                 :     {
     302               0 :         pfnErrorHandler( CE_Fatal, CPLE_AppDefined, pszMessage );
     303                 :     }
     304                 :     else
     305                 :     {
     306               0 :         fprintf( stderr, "FATAL: %s\n", pszMessage );
     307                 :     }
     308                 : 
     309               0 :     abort();
     310                 : }
     311                 : 
     312                 : /************************************************************************/
     313                 : /*                              CPLDebug()                              */
     314                 : /************************************************************************/
     315                 : 
     316                 : /**
     317                 :  * Display a debugging message.
     318                 :  *
     319                 :  * The category argument is used in conjunction with the CPL_DEBUG
     320                 :  * environment variable to establish if the message should be displayed.
     321                 :  * If the CPL_DEBUG environment variable is not set, no debug messages
     322                 :  * are emitted (use CPLError(CE_Warning,...) to ensure messages are displayed).
     323                 :  * If CPL_DEBUG is set, but is an empty string or the word "ON" then all
     324                 :  * debug messages are shown.  Otherwise only messages whose category appears
     325                 :  * somewhere within the CPL_DEBUG value are displayed (as determinted by
     326                 :  * strstr()).
     327                 :  *
     328                 :  * Categories are usually an identifier for the subsystem producing the
     329                 :  * error.  For instance "GDAL" might be used for the GDAL core, and "TIFF"
     330                 :  * for messages from the TIFF translator.  
     331                 :  *
     332                 :  * @param pszCategory name of the debugging message category.
     333                 :  * @param pszFormat printf() style format string for message to display.
     334                 :  *        Remaining arguments are assumed to be for format.
     335                 :  */ 
     336                 : 
     337          252708 : void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
     338                 : 
     339                 : {
     340          252708 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     341                 :     char        *pszMessage;
     342                 :     va_list     args;
     343          252708 :     const char  *pszDebug = CPLGetConfigOption("CPL_DEBUG",NULL);
     344                 : 
     345                 : #define ERROR_MAX 25000
     346                 : 
     347                 : /* -------------------------------------------------------------------- */
     348                 : /*      Does this message pass our current criteria?                    */
     349                 : /* -------------------------------------------------------------------- */
     350          252708 :     if( pszDebug == NULL )
     351          252706 :         return;
     352                 : 
     353               2 :     if( !EQUAL(pszDebug,"ON") && !EQUAL(pszDebug,"") )
     354                 :     {
     355               0 :         size_t  i, nLen = strlen(pszCategory);
     356                 : 
     357               0 :         for( i = 0; pszDebug[i] != '\0'; i++ )
     358                 :         {
     359               0 :             if( EQUALN(pszCategory,pszDebug+i,nLen) )
     360               0 :                 break;
     361                 :         }
     362                 : 
     363               0 :         if( pszDebug[i] == '\0' )
     364               0 :             return;
     365                 :     }
     366                 : 
     367                 : /* -------------------------------------------------------------------- */
     368                 : /*    Allocate a block for the error.                                   */
     369                 : /* -------------------------------------------------------------------- */
     370               2 :     pszMessage = (char *) VSIMalloc( ERROR_MAX );
     371               2 :     if( pszMessage == NULL )
     372               0 :         return;
     373                 :         
     374                 : /* -------------------------------------------------------------------- */
     375                 : /*      Dal -- always log a timestamp as the first part of the line     */
     376                 : /*      to ensure one is looking at what one should be looking at!      */
     377                 : /* -------------------------------------------------------------------- */
     378                 : 
     379               2 :     pszMessage[0] = '\0';
     380                 : #ifdef TIMESTAMP_DEBUG
     381               2 :     if( CPLGetConfigOption( "CPL_TIMESTAMP", NULL ) != NULL )
     382                 :     {
     383               0 :         strcpy( pszMessage, VSICTime( VSITime(NULL) ) );
     384                 :         
     385                 :         // On windows anyway, ctime puts a \n at the end, but I'm not 
     386                 :         // convinced this is standard behaviour, so we'll get rid of it
     387                 :         // carefully
     388                 : 
     389               0 :         if (pszMessage[strlen(pszMessage) -1 ] == '\n')
     390                 :         {
     391               0 :             pszMessage[strlen(pszMessage) - 1] = 0; // blow it out
     392                 :         }
     393               0 :         strcat( pszMessage, ": " );
     394                 :     }
     395                 : #endif
     396                 : 
     397                 : /* -------------------------------------------------------------------- */
     398                 : /*      Add the category.                                               */
     399                 : /* -------------------------------------------------------------------- */
     400               2 :     strcat( pszMessage, pszCategory );
     401               2 :     strcat( pszMessage, ": " );
     402                 :     
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Format the application provided portion of the debug message.   */
     405                 : /* -------------------------------------------------------------------- */
     406               2 :     va_start(args, pszFormat);
     407                 : #if defined(HAVE_VSNPRINTF)
     408                 :     vsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage), 
     409               2 :               pszFormat, args);
     410                 : #else
     411                 :     vsprintf(pszMessage+strlen(pszMessage), pszFormat, args);
     412                 : #endif
     413               2 :     va_end(args);
     414                 : 
     415                 : /* -------------------------------------------------------------------- */
     416                 : /*      Invoke the current error handler.                               */
     417                 : /* -------------------------------------------------------------------- */
     418               2 :     if( psCtx->psHandlerStack != NULL )
     419                 :     {
     420               2 :         psCtx->psHandlerStack->pfnHandler( CE_Debug, CPLE_None, pszMessage );
     421                 :     }
     422                 :     else
     423                 :     {
     424               0 :         CPLMutexHolderD( &hErrorMutex );
     425               0 :         if( pfnErrorHandler != NULL )
     426               0 :             pfnErrorHandler( CE_Debug, CPLE_None, pszMessage );
     427                 :     }
     428                 : 
     429               2 :     VSIFree( pszMessage );
     430                 : }
     431                 : 
     432                 : /**********************************************************************
     433                 :  *                          CPLErrorReset()
     434                 :  **********************************************************************/
     435                 : 
     436                 : /**
     437                 :  * Erase any traces of previous errors.
     438                 :  *
     439                 :  * This is normally used to ensure that an error which has been recovered
     440                 :  * from does not appear to be still in play with high level functions.
     441                 :  */
     442                 : 
     443         1301998 : void CPL_STDCALL CPLErrorReset()
     444                 : {
     445         1301998 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     446                 : 
     447         1301998 :     psCtx->nLastErrNo = CPLE_None;
     448         1301998 :     psCtx->szLastErrMsg[0] = '\0';
     449         1301998 :     psCtx->eLastErrType = CE_None;
     450         1301998 : }
     451                 : 
     452                 : 
     453                 : /**********************************************************************
     454                 :  *                          CPLGetLastErrorNo()
     455                 :  **********************************************************************/
     456                 : 
     457                 : /**
     458                 :  * Fetch the last error number.
     459                 :  *
     460                 :  * Fetches the last error number posted with CPLError(), that hasn't
     461                 :  * been cleared by CPLErrorReset().  This is the error number, not the error class.
     462                 :  *
     463                 :  * @return the error number of the last error to occur, or CPLE_None (0)
     464                 :  * if there are no posted errors.
     465                 :  */
     466                 : 
     467         1678136 : int CPL_STDCALL CPLGetLastErrorNo()
     468                 : {
     469         1678136 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     470                 : 
     471         1678136 :     return psCtx->nLastErrNo;
     472                 : }
     473                 : 
     474                 : /**********************************************************************
     475                 :  *                          CPLGetLastErrorType()
     476                 :  **********************************************************************/
     477                 : 
     478                 : /**
     479                 :  * Fetch the last error type.
     480                 :  *
     481                 :  * Fetches the last error type posted with CPLError(), that hasn't
     482                 :  * been cleared by CPLErrorReset().  This is the error class, not the error number.
     483                 :  *
     484                 :  * @return the error type of the last error to occur, or CE_None (0)
     485                 :  * if there are no posted errors.
     486                 :  */
     487                 : 
     488          737854 : CPLErr CPL_STDCALL CPLGetLastErrorType()
     489                 : {
     490          737854 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     491                 : 
     492          737854 :     return psCtx->eLastErrType;
     493                 : }
     494                 : 
     495                 : /**********************************************************************
     496                 :  *                          CPLGetLastErrorMsg()
     497                 :  **********************************************************************/
     498                 : 
     499                 : /**
     500                 :  * Get the last error message.
     501                 :  *
     502                 :  * Fetches the last error message posted with CPLError(), that hasn't
     503                 :  * been cleared by CPLErrorReset().  The returned pointer is to an internal
     504                 :  * string that should not be altered or freed.
     505                 :  *
     506                 :  * @return the last error message, or NULL if there is no posted error
     507                 :  * message.
     508                 :  */
     509                 : 
     510             402 : const char* CPL_STDCALL CPLGetLastErrorMsg()
     511                 : {
     512             402 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     513                 : 
     514             402 :     return psCtx->szLastErrMsg;
     515                 : }
     516                 : 
     517                 : /************************************************************************/
     518                 : /*                       CPLDefaultErrorHandler()                       */
     519                 : /************************************************************************/
     520                 : 
     521             484 : void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, int nError, 
     522                 :                              const char * pszErrorMsg )
     523                 : 
     524                 : {
     525                 :     static int       bLogInit = FALSE;
     526             484 :     static FILE *    fpLog = stderr;
     527                 :     static int       nCount = 0;
     528                 :     static int       nMaxErrors = -1;
     529                 : 
     530             484 :     if (eErrClass != CE_Debug)
     531                 :     {
     532             482 :         if( nMaxErrors == -1 )
     533                 :         {
     534                 :             nMaxErrors = 
     535             153 :                 atoi(CPLGetConfigOption( "CPL_MAX_ERROR_REPORTS", "1000" ));
     536                 :         }
     537                 : 
     538             482 :         nCount++;
     539             482 :         if (nCount > nMaxErrors && nMaxErrors > 0 )
     540               0 :             return;
     541                 :     }
     542                 : 
     543             484 :     if( !bLogInit )
     544                 :     {
     545             153 :         bLogInit = TRUE;
     546                 : 
     547             153 :         fpLog = stderr;
     548             153 :         if( CPLGetConfigOption( "CPL_LOG", NULL ) != NULL )
     549                 :         {
     550               0 :             fpLog = fopen( CPLGetConfigOption("CPL_LOG",""), "wt" );
     551               0 :             if( fpLog == NULL )
     552               0 :                 fpLog = stderr;
     553                 :         }
     554                 :     }
     555                 : 
     556             484 :     if( eErrClass == CE_Debug )
     557               2 :         fprintf( fpLog, "%s\n", pszErrorMsg );
     558             482 :     else if( eErrClass == CE_Warning )
     559             266 :         fprintf( fpLog, "Warning %d: %s\n", nError, pszErrorMsg );
     560                 :     else
     561             216 :         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
     562                 : 
     563             484 :     if (eErrClass != CE_Debug 
     564                 :         && nMaxErrors > 0 
     565                 :         && nCount == nMaxErrors )
     566                 :     {
     567                 :         fprintf( fpLog, 
     568                 :                  "More than %d errors or warnings have been reported. "
     569                 :                  "No more will be reported from now.\n", 
     570               0 :                  nMaxErrors );
     571                 :     }
     572                 : 
     573             484 :     fflush( fpLog );
     574                 : }
     575                 : 
     576                 : /************************************************************************/
     577                 : /*                        CPLQuietErrorHandler()                        */
     578                 : /************************************************************************/
     579                 : 
     580           34886 : void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , int nError, 
     581                 :                            const char * pszErrorMsg )
     582                 : 
     583                 : {
     584           34886 :     if( eErrClass == CE_Debug )
     585               2 :         CPLDefaultErrorHandler( eErrClass, nError, pszErrorMsg );
     586           34886 : }
     587                 : 
     588                 : /************************************************************************/
     589                 : /*                       CPLLoggingErrorHandler()                       */
     590                 : /************************************************************************/
     591                 : 
     592               0 : void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, int nError, 
     593                 :                              const char * pszErrorMsg )
     594                 : 
     595                 : {
     596                 :     static int       bLogInit = FALSE;
     597               0 :     static FILE *    fpLog = stderr;
     598                 : 
     599               0 :     if( !bLogInit )
     600                 :     {
     601               0 :         const char *cpl_log = NULL;
     602                 : 
     603               0 :         CPLSetConfigOption( "CPL_TIMESTAMP", "ON" );
     604                 : 
     605               0 :         bLogInit = TRUE;
     606                 : 
     607               0 :         cpl_log = CPLGetConfigOption("CPL_LOG", NULL );
     608                 : 
     609               0 :         fpLog = stderr;
     610               0 :         if( cpl_log != NULL && EQUAL(cpl_log,"OFF") )
     611                 :         {
     612               0 :             fpLog = NULL;
     613                 :         }
     614               0 :         else if( cpl_log != NULL )
     615                 :         {
     616                 :             char*     pszPath;
     617               0 :             int       i = 0;
     618                 : 
     619               0 :             pszPath = (char*)CPLMalloc(strlen(cpl_log) + 20);
     620               0 :             strcpy(pszPath, cpl_log);
     621                 : 
     622               0 :             while( (fpLog = fopen( pszPath, "rt" )) != NULL ) 
     623                 :             {
     624               0 :                 fclose( fpLog );
     625                 : 
     626                 :                 /* generate sequenced log file names, inserting # before ext.*/
     627               0 :                 if (strrchr(cpl_log, '.') == NULL)
     628                 :                 {
     629                 :                     sprintf( pszPath, "%s_%d%s", cpl_log, i++,
     630               0 :                              ".log" );
     631                 :                 }
     632                 :                 else
     633                 :                 {
     634               0 :                     size_t pos = 0;
     635               0 :                     char *cpl_log_base = strdup(cpl_log);
     636               0 :                     pos = strcspn(cpl_log_base, ".");
     637               0 :                     if (pos > 0)
     638                 :                     {
     639               0 :                         cpl_log_base[pos] = '\0';
     640                 :                     }
     641                 :                     sprintf( pszPath, "%s_%d%s", cpl_log_base,
     642               0 :                              i++, ".log" );
     643               0 :                     free(cpl_log_base);
     644                 :                 }
     645                 :             }
     646                 : 
     647               0 :             fpLog = fopen( pszPath, "wt" );
     648               0 :             CPLFree(pszPath);
     649                 :         }
     650                 :     }
     651                 : 
     652               0 :     if( fpLog == NULL )
     653               0 :         return;
     654                 : 
     655               0 :     if( eErrClass == CE_Debug )
     656               0 :         fprintf( fpLog, "%s\n", pszErrorMsg );
     657               0 :     else if( eErrClass == CE_Warning )
     658               0 :         fprintf( fpLog, "Warning %d: %s\n", nError, pszErrorMsg );
     659                 :     else
     660               0 :         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
     661                 : 
     662               0 :     fflush( fpLog );
     663                 : }
     664                 : 
     665                 : /**********************************************************************
     666                 :  *                      CPLTurnFailureIntoWarning()                   *
     667                 :  **********************************************************************/
     668                 : 
     669              40 : void CPLTurnFailureIntoWarning(int bOn )
     670                 : {
     671              40 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     672              40 :     psCtx->nFailureIntoWarning += (bOn) ? 1 : -1;
     673              40 :     if (psCtx->nFailureIntoWarning < 0)
     674                 :     {
     675               0 :         CPLDebug("CPL", "Wrong nesting of CPLTurnFailureIntoWarning(TRUE) / CPLTurnFailureIntoWarning(FALSE)");
     676                 :     }
     677              40 : }
     678                 : 
     679                 : /**********************************************************************
     680                 :  *                          CPLSetErrorHandlerEx()                    *
     681                 :  **********************************************************************/
     682                 : 
     683                 : /**
     684                 :  * Install custom error handle with user's data. This method is 
     685                 :  * essentially CPLSetErrorHandler with an added pointer to pUserData.  
     686                 :  * The pUserData is not returned in the CPLErrorHandler, however, and 
     687                 :  * must be fetched via CPLGetLastErrorUserData
     688                 :  *
     689                 :  * @param pfnErrorHandlerNew new error handler function.
     690                 :  * @param pUserData User data to carry along with the error context.
     691                 :  * @return returns the previously installed error handler.
     692                 :  */ 
     693                 : 
     694                 : CPLErrorHandler CPL_STDCALL 
     695              68 : CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, 
     696                 :                       void* pUserData )
     697                 : {
     698              68 :     CPLErrorHandler     pfnOldHandler = pfnErrorHandler;
     699              68 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     700                 : 
     701              68 :     if( psCtx->psHandlerStack != NULL )
     702                 :     {
     703                 :         CPLDebug( "CPL", 
     704                 :                   "CPLSetErrorHandler() called with an error handler on\n"
     705               0 :                   "the local stack.  New error handler will not be used immediately.\n" );
     706                 :     }
     707                 : 
     708                 : 
     709                 :     {
     710              68 :         CPLMutexHolderD( &hErrorMutex );
     711                 : 
     712              68 :         pfnOldHandler = pfnErrorHandler;
     713                 :         
     714              68 :         if( pfnErrorHandler == NULL )
     715               0 :             pfnErrorHandler = CPLDefaultErrorHandler;
     716                 :         else
     717              68 :             pfnErrorHandler = pfnErrorHandlerNew;
     718                 :             
     719              68 :         pErrorHandlerUserData = pUserData;
     720                 :     }
     721                 : 
     722              68 :     return pfnOldHandler;
     723                 : }
     724                 : 
     725                 : 
     726                 : /**********************************************************************
     727                 :  *                          CPLSetErrorHandler()                      *
     728                 :  **********************************************************************/
     729                 : 
     730                 : /**
     731                 :  * Install custom error handler.
     732                 :  *
     733                 :  * Allow the library's user to specify his own error handler function.
     734                 :  * A valid error handler is a C function with the following prototype:
     735                 :  *
     736                 :  * <pre>
     737                 :  *     void MyErrorHandler(CPLErr eErrClass, int err_no, const char *msg)
     738                 :  * </pre>
     739                 :  *
     740                 :  * Pass NULL to come back to the default behavior.  The default behaviour
     741                 :  * (CPLDefaultErrorHandler()) is to write the message to stderr. 
     742                 :  *
     743                 :  * The msg will be a partially formatted error message not containing the
     744                 :  * "ERROR %d:" portion emitted by the default handler.  Message formatting
     745                 :  * is handled by CPLError() before calling the handler.  If the error
     746                 :  * handler function is passed a CE_Fatal class error and returns, then
     747                 :  * CPLError() will call abort(). Applications wanting to interrupt this
     748                 :  * fatal behaviour will have to use longjmp(), or a C++ exception to
     749                 :  * indirectly exit the function.
     750                 :  *
     751                 :  * Another standard error handler is CPLQuietErrorHandler() which doesn't
     752                 :  * make any attempt to report the passed error or warning messages but
     753                 :  * will process debug messages via CPLDefaultErrorHandler.
     754                 :  *
     755                 :  * Note that error handlers set with CPLSetErrorHandler() apply to all
     756                 :  * threads in an application, while error handlers set with CPLPushErrorHandler
     757                 :  * are thread-local.  However, any error handlers pushed with 
     758                 :  * CPLPushErrorHandler (and not removed with CPLPopErrorHandler) take 
     759                 :  * precidence over the global error handlers set with CPLSetErrorHandler(). 
     760                 :  * Generally speaking CPLSetErrorHandler() would be used to set a desired
     761                 :  * global error handler, while CPLPushErrorHandler() would be used to install
     762                 :  * a temporary local error handler, such as CPLQuietErrorHandler() to suppress
     763                 :  * error reporting in a limited segment of code. 
     764                 :  *
     765                 :  * @param pfnErrorHandlerNew new error handler function.
     766                 :  * @return returns the previously installed error handler.
     767                 :  */ 
     768                 : CPLErrorHandler CPL_STDCALL 
     769              68 : CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
     770                 : {
     771              68 :     return CPLSetErrorHandlerEx(pfnErrorHandlerNew, NULL);
     772                 : }
     773                 : 
     774                 : /************************************************************************/
     775                 : /*                        CPLPushErrorHandler()                         */
     776                 : /************************************************************************/
     777                 : 
     778                 : /**
     779                 :  * Push a new CPLError handler.
     780                 :  *
     781                 :  * This pushes a new error handler on the thread-local error handler
     782                 :  * stack.  This handler will be used until removed with CPLPopErrorHandler().
     783                 :  *
     784                 :  * The CPLSetErrorHandler() docs have further information on how 
     785                 :  * CPLError handlers work.
     786                 :  *
     787                 :  * @param pfnErrorHandlerNew new error handler function.
     788                 :  */
     789                 : 
     790           22361 : void CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
     791                 : 
     792                 : {
     793           22361 :     CPLPushErrorHandlerEx(pfnErrorHandlerNew, NULL);
     794           22361 : }
     795                 : 
     796                 : 
     797                 : /************************************************************************/
     798                 : /*                        CPLPushErrorHandlerEx()                       */
     799                 : /************************************************************************/
     800                 : 
     801                 : /**
     802                 :  * Push a new CPLError handler with user data on the error context.
     803                 :  *
     804                 :  * This pushes a new error handler on the thread-local error handler
     805                 :  * stack.  This handler will be used until removed with CPLPopErrorHandler(). 
     806                 :  * Obtain the user data back by using CPLGetErrorContext().
     807                 :  *
     808                 :  * The CPLSetErrorHandler() docs have further information on how 
     809                 :  * CPLError handlers work.
     810                 :  *
     811                 :  * @param pfnErrorHandlerNew new error handler function.
     812                 :  * @param pUserData User data to put on the error context. 
     813                 :  */
     814           22361 : void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, 
     815                 :                                         void* pUserData )
     816                 : 
     817                 : {
     818           22361 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     819                 :     CPLErrorHandlerNode         *psNode;
     820                 : 
     821           22361 :     psNode = (CPLErrorHandlerNode *) VSIMalloc(sizeof(CPLErrorHandlerNode));
     822           22361 :     psNode->psNext = psCtx->psHandlerStack;
     823           22361 :     psNode->pfnHandler = pfnErrorHandlerNew;
     824           22361 :     psNode->pUserData = pUserData;
     825           22361 :     psCtx->psHandlerStack = psNode;
     826           22361 : }
     827                 : 
     828                 : /************************************************************************/
     829                 : /*                         CPLPopErrorHandler()                         */
     830                 : /************************************************************************/
     831                 : 
     832                 : /**
     833                 :  * Pop error handler off stack.
     834                 :  *
     835                 :  * Discards the current error handler on the error handler stack, and restores 
     836                 :  * the one in use before the last CPLPushErrorHandler() call.  This method
     837                 :  * has no effect if there are no error handlers on the current threads error
     838                 :  * handler stack. 
     839                 :  */ 
     840                 : 
     841           22365 : void CPL_STDCALL CPLPopErrorHandler()
     842                 : 
     843                 : {
     844           22365 :     CPLErrorContext *psCtx = CPLGetErrorContext();
     845                 : 
     846           22365 :     if( psCtx->psHandlerStack != NULL )
     847                 :     {
     848           22361 :         CPLErrorHandlerNode     *psNode = psCtx->psHandlerStack;
     849                 : 
     850           22361 :         psCtx->psHandlerStack = psNode->psNext;
     851           22361 :         VSIFree( psNode );
     852                 :     }
     853           22365 : }
     854                 : 
     855                 : /************************************************************************/
     856                 : /*                             _CPLAssert()                             */
     857                 : /*                                                                      */
     858                 : /*      This function is called only when an assertion fails.           */
     859                 : /************************************************************************/
     860                 : 
     861                 : /**
     862                 :  * Report failure of a logical assertion.
     863                 :  *
     864                 :  * Applications would normally use the CPLAssert() macro which expands
     865                 :  * into code calling _CPLAssert() only if the condition fails.  _CPLAssert()
     866                 :  * will generate a CE_Fatal error call to CPLError(), indicating the file
     867                 :  * name, and line number of the failed assertion, as well as containing
     868                 :  * the assertion itself.
     869                 :  *
     870                 :  * There is no reason for application code to call _CPLAssert() directly.
     871                 :  */
     872                 : 
     873               0 : void CPL_STDCALL _CPLAssert( const char * pszExpression, const char * pszFile,
     874                 :                  int iLine )
     875                 : 
     876                 : {
     877                 :     CPLError( CE_Fatal, CPLE_AssertionFailed,
     878                 :               "Assertion `%s' failed\n"
     879                 :               "in file `%s', line %d\n",
     880               0 :               pszExpression, pszFile, iLine );
     881               0 : }
     882                 : 

Generated by: LCOV version 1.7