C++ Library containing a lot of needful things: Stack Trace, Command Line Parser, Resource Handling, Configuration Files, Unix Command Execution, Directories, Regular Expressions, Tokenizer, Function Trace, Standard Extensions.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

192 lines
6.5 KiB

/** @file
$Id$
$Date$
$Author$
@copy © Marc Wä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