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.
133 lines
3.7 KiB
133 lines
3.7 KiB
18 years ago
|
/** @file
|
||
|
|
||
|
$Id: autofunctiontracelog4cxx.cpp,v 1.3 2005/04/14 19:12:18 marc Exp $
|
||
|
|
||
|
$Date: 2005/04/14 19:12:18 $
|
||
|
$Author: marc $
|
||
|
|
||
|
@copy © Marc Wäckerlin
|
||
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
||
|
|
||
|
1 2 3 4 5 6 7 8
|
||
|
5678901234567890123456789012345678901234567890123456789012345678901234567890
|
||
|
*/
|
||
|
|
||
|
#ifndef __GNUG__
|
||
|
#error GNU C++ Compiler is required for automatical function trace
|
||
|
#endif
|
||
|
|
||
|
#include <mrw/string.hpp>
|
||
|
#include <mrw/stacktrace.hpp>
|
||
|
#include <iostream>
|
||
|
#include <iomanip>
|
||
|
|
||
|
#if (__GNUC__==3 && __GNUC_MINOR__<4 || __GNUC__<3) && _REENTRANT && !_MT
|
||
|
#define _MT
|
||
|
#endif
|
||
|
|
||
|
// these are special built in functions of GNU Compiler Collection
|
||
|
extern "C" void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));
|
||
|
extern "C" void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function));
|
||
|
|
||
|
namespace mrw {
|
||
|
|
||
|
// workaround doxygen problem:
|
||
|
// - the C++ compiler compiles the following code
|
||
|
// - doxygen ignores it
|
||
|
#ifndef LET_DOXYGEN_IGNORE_THIS // no matching class member found for
|
||
|
// int mrw::ThreadInfo::level()
|
||
|
struct ThreadInfo {
|
||
|
int level;
|
||
|
bool recurse;
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
#ifdef _MT
|
||
|
static __thread ThreadInfo info = {0, false};
|
||
|
#else
|
||
|
static ThreadInfo info = {0, false};
|
||
|
#endif
|
||
|
|
||
|
static bool mainPassed(false);
|
||
|
|
||
|
class Lock {
|
||
|
public:
|
||
|
Lock() __attribute__((no_instrument_function));
|
||
|
~Lock() __attribute__((no_instrument_function));
|
||
|
};
|
||
|
// workaround doxygen problem:
|
||
|
// - the C++ compiler compiles the following code
|
||
|
// - doxygen ignores it
|
||
|
#ifndef LET_DOXYGEN_IGNORE_THIS // doxygen can't match with __attribute__ above
|
||
|
Lock::Lock() {
|
||
|
info.recurse = true;
|
||
|
}
|
||
|
Lock::~Lock() {
|
||
|
info.recurse = false;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
extern "C" int main(int, char**);
|
||
|
|
||
|
/** @addtogroup FunctionTrace */
|
||
|
//@{
|
||
|
|
||
|
/** @defgroup AutoFunctionTraceStdlog Automatic Function Trace to standard out for GNU g++
|
||
|
|
||
|
Same as @ref AutoFunctionTrace, but traces to @c stdlog.
|
||
|
|
||
|
If you link to the library @c libmrwautofunctiontracestdlog using
|
||
|
a linker option such as: @c -lmrwautofunctiontracestdlog and you
|
||
|
must enable the GNU Compiler Collection specific function trace
|
||
|
feature with compile and link option @c -finstrument-functions
|
||
|
then you get an automatical function trace, that traces to @c
|
||
|
stdlog. You don't need to change a single line in your code!
|
||
|
|
||
|
*/
|
||
|
//@{
|
||
|
|
||
|
//@}
|
||
|
|
||
|
//@}
|
||
|
|
||
|
extern "C" void __cyg_profile_func_enter(void *this_fn, void*) {
|
||
|
if (!mrw::mainPassed)
|
||
|
if (this_fn == (void*)&::main) // not ANSI C++ conform...
|
||
|
mrw::mainPassed=true;
|
||
|
else
|
||
|
return;
|
||
|
try {
|
||
|
if (mrw::info.recurse) return;
|
||
|
mrw::Lock lock;
|
||
|
{
|
||
|
static bool init(mrw::StackTrace::createSymtable());
|
||
|
if (!init) return;
|
||
|
mrw::StackTrace::CodePos pos(mrw::StackTrace::translate(this_fn));
|
||
|
std::clog<<std::setw(2+mrw::info.level++)<<std::setfill(' ')
|
||
|
<<"\\ "<<pos.function<<" ("<<pos.file<<':'<<pos.line<<')'
|
||
|
<<std::endl;
|
||
|
}
|
||
|
} catch (...) {}
|
||
|
}
|
||
|
|
||
|
extern "C" void __cyg_profile_func_exit(void *this_fn, void*) {
|
||
|
if (!mrw::mainPassed)
|
||
|
return;
|
||
|
else
|
||
|
if (this_fn == (void*)&::main) { // not ANSI C++ conform...
|
||
|
mrw::mainPassed=false;
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
if (mrw::info.recurse || mrw::info.level==0) return;
|
||
|
mrw::Lock lock;
|
||
|
{
|
||
|
mrw::StackTrace::CodePos pos(mrw::StackTrace::translate(this_fn));
|
||
|
std::clog<<std::setw(2+--mrw::info.level)<<std::setfill(' ')
|
||
|
<<"/ "<<pos.function<<" ("<<pos.file<<':'<<pos.line<<')'
|
||
|
<<std::endl;
|
||
|
}
|
||
|
} catch (...) {}
|
||
|
}
|