/** @file
    $Id$
    $Date$
    $Author$
    @copy © Marc Wäckerlin
    @license LGPL, see file COPYING
*/
#include 
#include 
#include 
#include 
#ifndef _T
#define _T
#endif
namespace mrw {
  /** @addtogroup AutoTrace
      @section trclog4cxx Trace using the log4cxx Library
      If you link to the library @c libmrwexclog4cxx using a linker
      option such as: @c -lmrwexclog4cxx, then an unexpected and a
      terminate handler are registered, that trace a fatal error using
      the log4cxx library. You don't need to change a single line in
      your code!
      The log4cxx library is located at:
       - http://logging.apache.org/log4cxx
      @note The configurator is not installed automatically. If you
      want to trace e.g. on the console, you have to call @c
      log4cxx::BasicConfigurator::configure(); as first statement in
      your @c main(). @see @ref AutoInitLog4cxx if you also want to
      automatically configure @c log4cxx.
  */
  //@{
  /** @brief unexpected handler, that traces using log4cxx
      The unexpected handler is installed automatically when you link
      to @c -lmrwexclog4cxx. The implementation of this unexpected
      handler is as follows:
      @code
  void unexpected_log4cxx() {
    log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace")));
    logger->fatal("Unexpected Exception", __FILE__, __LINE__);
    StackTrace::createSymtable();
    std::string st((std::string)StackTrace());
    try {
      throw;
    } catch (const mrw::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:+\n"+x.stacktrace());
    } catch (const std::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:\n"+st);
    } catch (...) {
      logger->fatal(std::string("Reason: **** not available ****")
                   +"\nStack:\n"+st);
    }
    throw std::bad_exception();
  }
      @endcode
  */
  void unexpected_log4cxx() {
    log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace")));
    logger->fatal("Unexpected Exception", __FILE__, __LINE__);
    StackTrace::createSymtable();
    std::string st((std::string)StackTrace());
    try {
      throw;
    } catch (const mrw::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:\n"+x.stacktrace());
    } catch (const std::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:\n"+st);
    } catch (...) {
      logger->fatal(std::string("Reason: **** not available ****")
                   +"\nStack:\n"+st);
    }
    throw std::bad_exception();
  }
  /** @brief terminate handler, that traces using log4cxx
      The terminate handler is installed automatically when you link
      to @c -lmrwexclog4cxx. The implementation of this terminate
      handler is as follows:
      @code
  void terminate_log4cxx() {
    log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace")));
    logger->fatal("Uncaught Exception", __FILE__, __LINE__);
    StackTrace::createSymtable();
    std::string st((std::string)StackTrace());
    try {
      throw;
      exit(0);
    } catch (const mrw::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:+\n"+x.stacktrace());
    } catch (const std::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:\n"+st);
    } catch (...) {
      logger->fatal(std::string("Reason: **** not available ****")
                    +"\nStack:\n"+st);
    }
    exit(1);
  }
      @endcode
  */
  void terminate_log4cxx() {
    log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace")));
    logger->fatal("Uncaught Exception", __FILE__, __LINE__);
    StackTrace::createSymtable();
    std::string st((std::string)StackTrace());
    try {
      throw;
    } catch (const mrw::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:\n"+x.stacktrace());
    } catch (const std::exception& x) {
      logger->fatal(std::string("Reason:\n")+x.what()
                    +"\nStack:\n"+st);
    } catch (...) {
      logger->fatal(std::string("Reason: **** not available ****")
                    +"\nStack:\n"+st);
    }
    exit(1);
  }
  //@}
  class AutoStackTrace {
    public:
    AutoStackTrace() {
      std::set_unexpected(&mrw::unexpected_log4cxx);
      std::set_terminate(&mrw::terminate_log4cxx);
    }
  };
  // initialize stack traces (load symbols)
  static AutoStackTrace _autoStackTrace;
}