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.

134 lines
3.7 KiB

/** @file
$Id: autofunctiontracelog4cxx.cxx,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.hxx>
#include <mrw/stacktrace.hxx>
#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 (...) {}
}