134 lines
3.7 KiB
C++
134 lines
3.7 KiB
C++
/** @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) \
|
|
&& defined(_REENTRANT) && !defined(_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 (...) {}
|
|
}
|