LTP GCOV extension - code coverage report
Current view: directory - port - cpl_error.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 191
Code covered: 47.1 % Executed lines: 90

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

Generated by: LTP GCOV extension version 1.5