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

rlog.h

00001 /*****************************************************************************
00002  * Author:   Valient Gough <vgough@pobox.com>
00003  *
00004  *****************************************************************************
00005  * Copyright (c) 2002-2004, Valient Gough
00006  *
00007  * This library is free software; you can distribute it and/or modify it under
00008  * the terms of the GNU Lesser General Public License (LGPL), as published by
00009  * the Free Software Foundation; either version 2.1 of the License, or (at your
00010  * option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE.  See the LGPL in the file COPYING for more
00015  * details.
00016  *
00017  */
00018                                                                                                 
00019 
00020 #ifndef _rlog_incl_
00021 #define _rlog_incl_
00022 
00036 #ifndef RLOG_COMPONENT
00037 #warning RLOG_COMPONENT not defined - setting to UNKNOWN
00038 #define RLOG_COMPONENT "[unknown]"
00039 #endif
00040 
00041 /*
00042     Defined by configure if our compiler allows us to specify printf attributes
00043     on a function pointer..  Newer versions of GCC allow this, but older ones
00044     do not..
00045 */
00046 #define HAVE_PRINTF_FP 1
00047 
00048 /*
00049     We use __printf__ attribute to allow gcc to inspect printf style arguments
00050     and give warnings if the rDebug(), rWarning(), etc macros are misused.
00051 
00052     We use __builtin_expect on GCC 2.96 and above to allow optimization of
00053     publication activation check.  We tell the compiler that the branch is
00054     unlikely to occur, allowing GCC to push unecessary code out of the main
00055     path.
00056 */
00057 #ifdef __GNUC__
00058 
00059 # define PRINTF(FMT,X) __attribute__ (( __format__ ( __printf__, FMT, X)))
00060 # define HAVE_PRINTF_ATTR 1
00061 
00062 # if !defined( __builtin_expect )
00063 #  define __builtin_expect(x,expected_value) (x)
00064 # endif
00065 
00066 # define   likely(x)  __builtin_expect((x),1)
00067 # define unlikely(x)  __builtin_expect((x),0)
00068 
00069 #else
00070 
00071 // Not using the gcc compiler, make the macros do nothing..  They are
00072 // documented as the last instance of the macros..
00073 
00081 # define PRINTF(FMT,X)
00082 # define HAVE_PRINTF_ATTR 0
00083 
00085 # define   likely(x)  (x)
00086 
00092 # define unlikely(x)  (x)
00093 
00094 #endif
00095 
00096 #if HAVE_PRINTF_FP
00097 # define PRINTF_FP(FMT,X) PRINTF(FMT,X)
00098 #else
00099 # define PRINTF_FP(FMT,X)
00100 #endif
00101 
00102 #define CONCAT2(A,B) A##B
00103 #define CONCAT(A,B) CONCAT2(A,B)
00104 #define STR(X) #X
00105 
00106 // Use somewhat unique names (doesn't matter if they aren't as they are used in
00107 // a private context, so the compiler will make them unique if it must)
00108 #define LOGID CONCAT(_rL_, __LINE__)
00109 
00110 // may be useful for checking from configuration files
00111 #define CURRENT_RLOG_VERSION 20040219
00112 extern "C" int RLogVersion();
00113 
00114 namespace rlog
00115 {
00116 
00117     class RLogChannel;
00118     class RLogPublisher;
00119 
00123     enum LogLevel
00124     {
00125         Log_Undef    =0, 
00126         Log_Critical,    
00127         Log_Error,       
00128         Log_Warning,     
00129         Log_Notice,      
00130         Log_Info,        
00131         Log_Debug        
00132     };
00133 
00144     void RLogInit(int &argc, char **argv);
00145 
00146 
00147     // Get channel with a particular component name
00148     RLogChannel *GetComponentChannel(const char *component, 
00149                                      const char *path, 
00150                                      LogLevel level = Log_Undef);
00151 
00152     // the global channel receives messages for all components
00153     RLogChannel *GetGlobalChannel( const char *path,
00154                                    LogLevel level = Log_Undef);
00155 
00199 #define DEF_CHANNEL(path,level) RLOG_CHANNEL_IMPL(RLOG_COMPONENT, path, level)
00200 #define RLOG_CHANNEL(path) RLOG_CHANNEL_IMPL(RLOG_COMPONENT, path, Log_Undef)
00201 #define RLOG_CHANNEL_IMPL(COMPONENT,path,level) \
00202     rlog::GetComponentChannel(STR(COMPONENT),path,level)
00203 
00204     /*
00205         Pre-defined channels, 
00206         "debug", "warning", and "error".
00207 
00208         You can of course defined sub-channels based on the predefined types,
00209         such as "debug/level1", or whatever.
00210     */
00211     extern RLogChannel *_RLDebugChannel;
00212     extern RLogChannel *_RLWarningChannel;
00213     extern RLogChannel *_RLErrorChannel;
00214 
00227     struct PublishLoc
00228     {
00229         // If the compiler supports printf attribute specification on function
00230         // pointers, we'll use it here so that the compiler knows to check for
00231         // proper printf formatting.  If it doesn't support it, then we'll
00232         // force the check by inserting a bogus inline function..
00234         void (*publish)(PublishLoc *, RLogChannel *, const char *format, ... )
00235             PRINTF_FP(3,4);
00236         RLogPublisher *pub;
00237         const char *component;
00238         const char *fileName;
00239         const char *functionName;
00240         int lineNum;
00241         RLogChannel *channel;
00242     };
00243 
00250     void RLog_Register(PublishLoc *loc, RLogChannel *, 
00251                        const char *format, ... ) PRINTF(3,4);
00252 
00258     void rAssertFailed( const char *component, const char *file, 
00259                         const char *function, int line, 
00260                         const char *conditionStr );
00261 
00262     // if we don't have printf attributes on function pointers, but we do have
00263     // printf attributes, then make a bogus check function..
00264 #if !HAVE_PRINTF_FP && HAVE_PRINTF_ATTR
00265     void __checkArgs(const char *, ... ) PRINTF(1,2);
00266 
00267     inline void __checkArgs(const char *, ...)
00268     { }
00269 #endif
00270 }
00271 
00277 #define _rMessageDef(ID, COMPONENT) \
00278   static rlog::PublishLoc ID ={&rlog::RLog_Register, 0, STR(COMPONENT), \
00279       __FILE__, __FUNCTION__, __LINE__, 0};
00280 
00285 #if HAVE_PRINTF_FP || !HAVE_PRINTF_ATTR
00286 #define _rMessageCall(ID, CHANNEL, ...) \
00287   if(unlikely(ID.publish!=0)) (*ID.publish)( &ID, CHANNEL, ##__VA_ARGS__ );
00288 #else
00289 #define _rMessageCall(ID, CHANNEL, ...) \
00290   if(unlikely(ID.publish!=0))  \
00291   { \
00292     (*ID.publish)( &ID, CHANNEL, ##__VA_ARGS__ ); \
00293     rlog::__checkArgs( __VA_ARGS__ ); \
00294   }
00295 #endif
00296 
00306 #define _rMessage(ID, CHANNEL, ... ) \
00307   do { _rMessageDef(ID, RLOG_COMPONENT) \
00308        _rMessageCall(ID, CHANNEL, ##__VA_ARGS__ ) } while(0)
00309 
00333 #define rDebug(...) \
00334   _rMessage( LOGID, rlog::_RLDebugChannel, ##__VA_ARGS__ )
00335 
00353 #define rWarning(...) \
00354   _rMessage( LOGID, rlog::_RLWarningChannel, ##__VA_ARGS__ )
00355 
00371 #define rError(...) \
00372   _rMessage( LOGID, rlog::_RLErrorChannel, ##__VA_ARGS__ )
00373 
00391 #define rLog(channel, ...) \
00392   _rMessage( LOGID, channel, ##__VA_ARGS__ )
00393 
00394 #define _rAssertFailed(COMPONENT, COND) \
00395     rlog::rAssertFailed(STR(COMPONENT),__FILE__,__FUNCTION__,__LINE__, COND)
00396 
00407 #define rAssert( cond ) \
00408     do { \
00409         if( unlikely((cond) == false) ) \
00410         { rError( "Assert failed: " STR(cond) ); \
00411           _rAssertFailed(RLOG_COMPONENT, STR(cond)); \
00412         } \
00413     } while(0)
00414 
00422 #define rAssertSilent( cond ) \
00423     do { \
00424         if( unlikely((cond) == false) ) \
00425         { _rAssertFailed(RLOG_COMPONENT, STR(cond)); } \
00426     } while(0)
00427 
00428 
00429 #define _ERROR_IMPL(COMPONENT, MSG) \
00430     rlog::Error( STR(COMPONENT), __FILE__, __FUNCTION__, __LINE__, MSG )
00431 
00432 #define ERROR( MSG ) _ERROR_IMPL( RLOG_COMPONENT, MSG )
00433     
00434 
00438 #endif
00439 

Generated on Sun Mar 14 14:49:50 2004 for rlog by doxygen 1.3.2