/** @file
$ Id $
$ Date $
$ Author $
@ copy & copy ; Marc W & auml ; ckerlin
@ license LGPL , see file < a href = " license.html " > COPYING < / a >
$ Log $
Revision 1.2 2004 / 08 / 28 16 : 21 : 25 marc
mrw - c + + - 0.92 ( mrw )
- new file : version . cpp
- new file header for all sources
- work around warning in mrw : : auto < T >
- possibility to compile without log4cxx
- work around bugs in demangle . h and libiberty . h
- corrections in documentation
- added simple tracing mechanism
- more warnings
- small corrections in Auto < > : : Free and a new test for it
- possibility to compile without stack trace
*/
# ifndef __MRW_SIMPLETRACE_HPP__
# define __MRW_SIMPLETRACE_HPP__
# include <iostream>
# include <iomanip>
# include <string>
/** @defgroup SimpleTrace Simple Tracing (for temporary debugging)
@ pre # include < mrw / simpletrace . hpp >
Here is a simple tracing to @ c std : : cout mechanism for temporary
debugging and simple testing purposes . Might be useful when
experimenting and exploring new C + + language constructs . Please
note that you can only trace in methods and functions that start
with @ c METHOD respectively @ c FUNCTION .
Please note that you should not use this simple mechanism for real
projects , only for your experiments ! For your work , use
< a href = " http://logging.apache.org/log4cxx " > log4cxx < / a > !
The trace of the following code :
@ code
# include <mrw/simpletrace.hpp>
void fn ( int i = 0 ) {
FUNCTION ; // trace entry and exit
if ( ! i ) TRACE ( " Hello World, this is a nice text! " ) ;
if ( i < 4 ) fn ( + + i ) ;
}
class A {
public :
A ( ) {
NO_TRACE ; // don't trace in constructor
method ( ) ; // not traced
}
void method ( ) {
METHOD ; // trace entry and exit
CALL ( fn ( ) ) ; // trace before call
fn ( ) ;
}
} ;
int main ( int , char * * ) {
FUNCTION ;
CALL ( A ( ) . method ( ) ) ;
A ( ) . method ( ) ;
TRACE ( " No more trace: " ) ;
TRACE_OFF ;
A ( ) . method ( ) ;
TRACE_ON ;
TRACE ( " Back again " ) ;
return 0 ;
}
@ endcode
Produces this output :
@ verbatim
tmp . cpp : 20 0 : \ main
tmp . cpp : 21 0 : - > A ( ) . method ( )
tmp . cpp : 14 0xbffff10f : \ method
tmp . cpp : 15 0xbffff10f : - > fn ( )
tmp . cpp : 3 0 : \ fn
tmp . cpp : 4 0 : * * * * Hello World , this is a nice text ! * * * *
tmp . cpp : 3 0 : \ fn
tmp . cpp : 3 0 : \ fn
tmp . cpp : 3 0 : \ fn
tmp . cpp : 3 0 : \ fn
tmp . cpp : 3 0 : / fn
tmp . cpp : 3 0 : / fn
tmp . cpp : 3 0 : / fn
tmp . cpp : 3 0 : / fn
tmp . cpp : 3 0 : / fn
tmp . cpp : 14 0xbffff10f : / method
tmp . cpp : 23 0 : * * * * No more trace : * * * *
tmp . cpp : 27 0 : * * * * Back again * * * *
tmp . cpp : 20 0 : / main
@ endverbatim
*/
//@{
# ifndef __GNUG__
/// Declare method entrance, place as first line in method.
# define METHOD(name) mrw::FnTrace fnTrace(this, #name, __FILE__, __LINE__)
/// Declare function entrance, place as first line in function.
# define FUNCTION(name) mrw::FnTrace fnTrace(0, #name, __FILE__, __LINE__)
# else
/// Declare method entrance, place as first line in method.
/// GNU g++ knows the method name.
# define METHOD mrw::FnTrace fnTrace(this, __FUNCTION__, __FILE__, __LINE__)
/// Declare function entrance, place as first line in function.
/// GNU g++ knows the method name.
# define FUNCTION mrw::FnTrace fnTrace(0, __FUNCTION__, __FILE__, __LINE__)
# endif
/// Document the call of another method (before you call it).
# define CALL(name) fnTrace.call(#name, __FILE__, __LINE__)
/// Trace an arbitrary text.
# define TRACE(text) fnTrace.trace(text, __FILE__, __LINE__)
/// Turn all tracing off (from here on).
# define TRACE_OFF mrw::FnTrace::off()
/// Turn all tracing off (from here on).
# define TRACE_ON mrw::FnTrace::on()
/// Don't trace in this scope (from here on).
# define NO_TRACE mrw::NoTrace noTrace;
namespace mrw {
class FnTrace {
public :
FnTrace ( const void * addr , const std : : string & name ,
const std : : string & file , unsigned long line ) throw ( ) :
_addr ( addr ) , _name ( name ) , _file ( file ) , _line ( line ) {
if ( _off = = 0 )
std : : cout < < std : : setw ( 15 ) < < _file < < ' : ' < < std : : setiosflags ( std : : ios : : left )
< < std : : setw ( 5 ) < < _line < < std : : resetiosflags ( std : : ios : : left ) < < ' '
< < std : : hex < < std : : setw ( 15 ) < < _addr < < " : " < < std : : dec
< < std : : setw ( 2 + _level ) < < std : : setfill ( ' ' ) < < " \\ "
< < _name < < std : : endl ;
+ + _level ;
}
~ FnTrace ( ) throw ( ) {
- - _level ;
if ( _off = = 0 )
std : : cout < < std : : setw ( 15 ) < < _file < < ' : ' < < std : : setiosflags ( std : : ios : : left )
< < std : : setw ( 5 ) < < _line < < std : : resetiosflags ( std : : ios : : left ) < < ' '
< < std : : hex < < std : : setw ( 15 ) < < _addr < < " : " < < std : : dec
< < std : : setw ( 2 + _level ) < < std : : setfill ( ' ' ) < < " / " < < _name
< < std : : endl ;
}
void call ( const std : : string & name ,
const std : : string & file , unsigned long line ) throw ( ) {
if ( _off = = 0 )
std : : cout < < std : : setw ( 15 ) < < file < < ' : ' < < std : : setiosflags ( std : : ios : : left )
< < std : : setw ( 5 ) < < line < < std : : resetiosflags ( std : : ios : : left ) < < ' '
< < std : : hex < < std : : setw ( 15 ) < < _addr < < " : " < < std : : dec
< < std : : setw ( 4 + _level ) < < std : : setfill ( ' ' ) < < " -> " < < name
< < std : : endl ;
}
void trace ( const std : : string & text ,
const std : : string & file , unsigned long line ) throw ( ) {
if ( _off = = 0 )
std : : cout < < std : : setw ( 15 ) < < file < < ' : ' < < std : : setiosflags ( std : : ios : : left )
< < std : : setw ( 5 ) < < line < < std : : resetiosflags ( std : : ios : : left ) < < ' '
< < std : : hex < < std : : setw ( 15 ) < < _addr < < " : " < < std : : dec
< < std : : setw ( 4 + _level ) < < std : : setfill ( ' ' ) < < " **** " < < text
< < " **** " < < std : : endl ;
}
static void off ( ) throw ( ) {
+ + _off ;
}
static void on ( ) throw ( ) {
if ( _off > 0 ) - - _off ;
}
private :
const void * _addr ;
const std : : string _name ;
const std : : string _file ;
unsigned long _line ;
static unsigned int _level ;
static unsigned int _off ;
} ;
unsigned int FnTrace : : _level ( 0 ) ;
unsigned int FnTrace : : _off ( 0 ) ;
class NoTrace {
public :
NoTrace ( ) throw ( ) { TRACE_OFF ; }
~ NoTrace ( ) throw ( ) { TRACE_ON ; }
} ;
}
//@}
# endif