/** @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 COPYING
         1         2         3         4         5         6         7         8
    5678901234567890123456789012345678901234567890123456789012345678901234567890
*/
#ifndef __GNUG__
#error GNU C++ Compiler is required for automatical function trace
#endif
#include 
#include 
#include 
#include 
#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<