From 4ca9363fd040cb0258aa6bbeef0863966618fbc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Sun, 5 Aug 2007 08:20:01 +0000 Subject: [PATCH] Release 3-2-0 with tag: REL_mrw-c++-3-2-0 --- ChangeLog | 17 ++ bootstrap.sh | 1 - configure.in | 37 ++- makefile.am | 28 ++- mrw/auto.hpp | 90 +++++++ mrw/autofunctiontracelog4cxx.cpp | 58 ++++- mrw/autostacktracelog4cxx.cpp | 140 +++++++++-- mrw/autostacktracestderr.cpp | 75 +++++- mrw/doxyfile.in | 6 +- mrw/errno.cpp | 38 +-- mrw/errno.hpp | 7 +- mrw/foot.html | 3 +- mrw/functiontrace.hpp | 73 +++--- mrw/functiontrace_test.cpp | 45 ++-- mrw/head.html | 4 - mrw/hintergrund.png | Bin 0 -> 36887 bytes mrw/log4cxxconfiguration.cpp | 135 ++++++---- mrw/makefile.am | 302 +++++++++++++---------- mrw/mrw.hpp.in | 96 ++++--- mrw/mrwautofunctiontracelog4cxx_test.cpp | 109 +++++--- mrw/stacktrace.cpp | 78 ++++-- mrw/stacktrace.hpp | 4 +- mrw/stacktrace_test.cpp | 5 +- mrw/string.hpp | 7 +- 24 files changed, 952 insertions(+), 406 deletions(-) create mode 100644 mrw/hintergrund.png diff --git a/ChangeLog b/ChangeLog index 8ec7657..c1c3638 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +* Sun Aug 5 2007 Marc Waeckerlin - mrw-c++-3.2.1 (mrw) + - Compatibility to UNICODE log4cxx 0.9.7 +* Fri Jul 7 2007 Marc Waeckerlin - mrw-c++-3.2.0 (mrw) + - Partly ported to SVN version of log4cxx + - Added valgrind support with --enable-valgrind + - Checked with valgrind and repaired defects: + - Mismatching delete in StackTrace +* Tue Jun 12 2007 Marc Waeckerlin - mrw-c++-3.1.1 (mrw) + - Don't catch abort() in autostacktraceXXX.cpp +* Thu May 31 2007 Marc Waeckerlin - mrw-c++-3.1.0 (mrw) + - Bug in string.hpp join: Only join with list of strings was possible. +* Fri May 25 2007 Marc Waeckerlin - mrw-c++-3.0.0 (mrw) + - Function- and method-trace have been renamed from FUNCTION and + METHOD to MRW_FUNCTION and MRW_METHOD due to naming conflicts with + Qt-Library. This breaks backward compatibility! +* Sat May 19 2007 Marc Waeckerlin - mrw-c++-2.3.4 (mrw) + - also tracing for signals in autostacktraceXXX (-lmrwexclog4cxx) * Sat Feb 04 2006 Marc Waeckerlin - mrw-c++-2.3.1 (mrw) - new rpm package mrw-c++-minimal without debug facilities no dependencies to boost, log4cxx and ltdl libraries diff --git a/bootstrap.sh b/bootstrap.sh index 2d637db..91e94a9 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -15,5 +15,4 @@ ## added file header ## -test -f makefile && make distclean aclocal && libtoolize --force && automake -a && autoconf diff --git a/configure.in b/configure.in index 7cc988c..580c9ae 100644 --- a/configure.in +++ b/configure.in @@ -13,11 +13,11 @@ # init AC_INIT([mrw/mrw.hpp.in]) +AC_CANONICAL_SYSTEM PACKAGENAME=mrw-c++ -m4_define(x_major, 2) -m4_define(x_minor, 3) +m4_define(x_major, 3) +m4_define(x_minor, 2) m4_define(x_least, 1) -AM_INIT_AUTOMAKE(@PACKAGENAME@, @MAJOR@.@MINOR@.@LEAST@, [marc@waeckerlin.org]) # copy M4 to shell MAJOR=x_major @@ -27,6 +27,8 @@ AC_SUBST(MAJOR) AC_SUBST(MINOR) AC_SUBST(LEAST) +AM_INIT_AUTOMAKE($PACKAGENAME, $MAJOR.$MINOR.$LEAST, [marc@waeckerlin.org]) + # libtool versioning LIB_MAJOR=m4_eval(x_major+x_minor) LIB_MINOR=x_least @@ -62,9 +64,17 @@ AC_CHECK_HEADER(sys/old_procfs.h, [AM_CPPFLAGS=-D__solaris__]) # libraries AC_CHECK_HEADER(log4cxx/logger.h, [have_log4cxx=yes]) AC_CHECK_HEADER(ltdl.h, [have_ltdl=yes]) +AC_CHECK_HEADER(regex.h, [have_regex=yes]) +AC_CHECK_HEADERS(unistd.h fcntl.h, [have_exec=yes]) +AC_CHECK_HEADER(dirent.h, [have_dir=yes]) # Arguments AM_MAINTAINER_MODE +AC_ARG_ENABLE(valgrind, + AS_HELP_STRING([--enable-valgrind], + [runs all checks with valgrind enabled]), + [have_valgrind="$enableval"], [have_valgrind="no"]) +AM_CONDITIONAL(HAVE_VALGRIND, test "$have_valgrind" = "yes") AC_ARG_ENABLE(threads, [ --disable-threads disable multithreading], [with_threads="$enableval"], [with_threads="yes"]) @@ -85,6 +95,18 @@ AC_ARG_ENABLE(dot, [ --disable-dot disable dot graphic tools for documentation], [have_dot="$enableval"]) test "$enableval" = "yes" && HAVE_DOT="YES" || HAVE_DOT="NO"; +AC_ARG_ENABLE(dir, + [ --disable-dir disable POSIX directory access], + [have_dir="$enableval"]) +AM_CONDITIONAL(HAVE_DIR, test "$have_dir" = "yes") +AC_ARG_ENABLE(exec, + [ --disable-exec disable UNIX fork and execute with pipes], + [have_exec="$enableval"]) +AM_CONDITIONAL(HAVE_EXEC, test "$have_exec" = "yes") +AC_ARG_ENABLE(regexp, + [ --disable-regexp disable use of regular expressions], + [have_regex="$enableval"]) +AM_CONDITIONAL(HAVE_REGEXP, test "$have_regex" = "yes") AC_ARG_ENABLE(log4cxx, [ --disable-log4cxx disable use of log4cxx library in automated stack trace], @@ -197,6 +219,15 @@ if test "$with_threads" = "no"; then AC_MSG_WARN([Multithreading support is disabled! - use --enable-threads to enable it - actually, there's only support for automated function trace]); fi +if test "$have_dir" != "yes"; then +AC_MSG_WARN([POSIX directory access is disabled! + - you need a UNIX/Posix environment if you want to use it]); fi +if test "$have_exec" != "yes"; then +AC_MSG_WARN([UNIX fork/exec with pipes will not be used! + - you need a UNIX/Posix environment if you want to use it]); fi +if test "$have_regex" != "yes"; then +AC_MSG_WARN([GNU regular expression library will not be used! + - if you want it, install it]); fi if test "$have_log4cxx" != "yes"; then AC_MSG_WARN([Library log4cxx will not be used! - if you want it, download it from: diff --git a/makefile.am b/makefile.am index 5bb41de..cda41b4 100644 --- a/makefile.am +++ b/makefile.am @@ -54,17 +54,25 @@ rpm: dist rpmbuild -ba --clean @PACKAGENAME@.spec rpmbuild -bb --clean @PACKAGENAME@-minimal.spec -webserver: rpm - ssh root@waeckerlin.org bash -c \ - '"rm -r /home/marc/mrw-c++; mkdir -p /home/marc/mrw-c++"' - scp doc/html/* \ - doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf \ - @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.tar.gz \ - ${RPMS} \ - log4cxx*.rpm \ - root@waeckerlin.org:/home/marc/mrw-c++/ +webserver: check distcheck rpm webserver.en webserver.de webserver.zh + - rm -rf ~/www/marc/data/doxygen/mrw-cpp + mkdir -p ~/www/marc/data/doxygen/mrw-cpp + cp doc/html/*.html ~/www/marc/data/doxygen/mrw-cpp/ + cp doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf \ + @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.tar.gz \ + ${RPMS} \ + log4cxx*.rpm \ + ~/www/marc/downloads/ + date +'%s 127.0.0.1 :computer:c_:mrw-c_:index mrw @PACKAGENAME@ version @MAJOR@.@MINOR@.@LEAST@' >> ~/www/marc/data/changes.log -maintainerclean-local: +webserver.%: + - rm -rf ~/www/marc/data/media/$(@:webserver.%=%)/computer/c_/mrw-c_ + mkdir -p ~/www/marc/data/media/$(@:webserver.%=%)/computer/c_/mrw-c_ + cp doc/html/*.png \ + doc/html/*.gif \ + ~/www/marc/data/media/$(@:webserver.%=%)/computer/c_/mrw-c_/ + +maintainer-clean-local: - find . -name '*~' | xargs rm - rm -r doc - rm -r autom4te.cache diff --git a/mrw/auto.hpp b/mrw/auto.hpp index c1eb014..f894e60 100644 --- a/mrw/auto.hpp +++ b/mrw/auto.hpp @@ -255,6 +255,96 @@ namespace mrw { T* _res; ///< the resource to be managed }; + /** @brief Automatically deletes an array pointer when destructed. + @pre \#include + + mrw::AutoPtrAry is a replacement for std::auto_ptr. Other than + mrw::AutoPtr it is for arrays, that means, it calls @c delete[] + instead of @c delete to free the memory. The problem with + standard std::auto_ptr is, that it cannot be stored in a + std::map and it does not call @c delete[]. + + @warning Use this class with prudence! Should I ever find out, + how to work around the std::auto_ptr / std::map problem, + then this class may become deprecated. + + @param T type of the pointer to manage + */ + template + class AutoPtrAry { + public: + /// @brief Construct from an allocated resource. + /// The resource is freed if necessary. + /// AutoPtrAry takes over ownership of the resource. + explicit AutoPtrAry(T* res = 0) + throw(std::bad_exception): _res(res) { + res = 0; + } + /// @brief Takeover ownership from another AutoPtrAry. + AutoPtrAry(AutoPtrAry& o) throw(std::bad_exception): + _res(o.release()) { + } + //! @brief Do not use this method! + //! This method had to be introduced for the @c std::map, where + //! @c operator[] first creates an empty element, then assigns it + //! the real value. Because that empty element is temporary, gcc can + //! not use @c AutoResource(AutoResource&) since release 4.0. + AutoPtrAry(const AutoPtrAry& o) throw(std::bad_exception): _res(0) { + assert(o._res==0); + if (o._res!=0) + _res = const_cast(o).release(); + } + /// @brief Free resource. Calls @c reset(). + ~AutoPtrAry() throw(std::bad_exception) {reset();} + /// @brief Assign new resource. Calls @c reset(). + /// The resource is freed if necessary. + AutoPtrAry& operator=(T* res) throw(std::bad_exception) { + return reset(res); + } + /// @brief Takeover ownership from another AutoResource. + /// Calls @c reset() from @c this and @c release() from @c other. + AutoPtrAry& operator=(AutoPtrAry& other) throw(std::bad_exception) { + return reset(other.release()); + } + /// @brief Get the resource. + operator T* const() const throw(std::bad_exception) { + return _res; + } + /// @brief find out, if a value is set + /// @return @c true: resource is valid + operator bool() const throw(std::bad_exception) { + return _res!=0; + } + /// @brief Access the AutoPtrAry like a normal pointer. + T*const operator->() {return _res;} + /// @brief Dereference the AutoPtrAry like a normal pointer. + T& operator*() {return *_res;} + /// @brief get the resetted resource for resetting it. + /// Calls @c reset and returns the cleaned resource. + /// The intention is, that you can safely assign it a new value + /// (e.g. in an expression). + T* getClean() throw(std::bad_exception) { + reset(); + return _res; + } + /// @brief Give away ownership of the resource. + /// @return old resource + T* release() throw(std::bad_exception) { + T* res(_res); _res=0; + return res; + } + /// @brief Assign a new resource. + /// The old resource of @c this is freed if necessary. + AutoPtrAry& reset(T* res = 0) + throw(std::bad_exception) { + delete[] _res; + _res = res; + return *this; + } + private: + T* _res; ///< the resource to be managed + }; + /** @brief Automatically closes a file when destructed. @pre \#include diff --git a/mrw/autofunctiontracelog4cxx.cpp b/mrw/autofunctiontracelog4cxx.cpp index db5568f..3f68437 100644 --- a/mrw/autofunctiontracelog4cxx.cpp +++ b/mrw/autofunctiontracelog4cxx.cpp @@ -31,6 +31,26 @@ 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)); + +// support for log4cxx 0.9.7 and for new CVS version +#ifndef LOG4CXX_LOCATION +# define MRW_LOG4CXX_LOCATION pos.file.c_str(), pos.line +#define MRW_LEVEL_DEBUG ::log4cxx::Level::DEBUG +#define MRW_LEVEL_INFO ::log4cxx::Level::INFO +#define MRW_LEVEL_WARN ::log4cxx::Level::WARN +#define MRW_LEVEL_ERROR ::log4cxx::Level::ERROR +#define MRW_LEVEL_FATAL ::log4cxx::Level::FATAL +#else +# define LOG4CXX_CVS +# define MRW_LOG4CXX_LOCATION \ + ::log4cxx::spi::LocationInfo(pos.file.c_str(), pos.function.c_str(), pos.line) +#define MRW_LEVEL_DEBUG ::log4cxx::Level::getDebug() +#define MRW_LEVEL_INFO ::log4cxx::Level::getInfo() +#define MRW_LEVEL_WARN ::log4cxx::Level::getWarn() +#define MRW_LEVEL_ERROR ::log4cxx::Level::getError() +#define MRW_LEVEL_FATAL ::log4cxx::Level::getFatal() +#endif + namespace mrw { struct ThreadInfo { @@ -176,14 +196,20 @@ extern "C" void __cyg_profile_func_enter(void *this_fn, void*) { (hierarchy.rfind(' ', std::min(hierarchy.find('<'), hierarchy.find("operator")))); if (p!=std::string::npos) hierarchy.erase(0, p+1); +// hierarchy.erase +// (hierarchy.find_first_not_of +// ("qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM1234567890_.")); + if (hierarchy=="") hierarchy = "global"; + std::string name("mrw.fn."+hierarchy); log4cxx::Logger* logger - (log4cxx::Logger::getLogger(_T("mrw.fn.")+hierarchy)); + (log4cxx::Logger::getLogger(log4cxx::String(name.begin(), name.end()))); if (logger->isDebugEnabled()) { - std::ostringstream ss; - ss<forcedLog(::log4cxx::Level::DEBUG, ss.str(), - pos.file.c_str(), pos.line); + std::basic_ostringstream ss; + ss<forcedLog(MRW_LEVEL_DEBUG, ss.str(), + MRW_LOG4CXX_LOCATION); } } } catch (...) {} @@ -206,19 +232,25 @@ extern "C" void __cyg_profile_func_exit(void *this_fn, void*) { for (std::string::size_type p(0); (p=hierarchy.find("::", p))!=std::string::npos; hierarchy.replace(p, 2, ".")); - hierarchy.erase(hierarchy.find('(')); + hierarchy.erase(hierarchy.rfind('(')); std::string::size_type p (hierarchy.rfind(' ', std::min(hierarchy.find('<'), hierarchy.find("operator")))); if (p!=std::string::npos) hierarchy.erase(0, p+1); +// hierarchy.erase +// (hierarchy.find_first_not_of +// ("qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM1234567890_.")); + if (hierarchy=="") hierarchy = "global"; + std::string name("mrw.fn."+hierarchy); log4cxx::Logger* logger - (log4cxx::Logger::getLogger(_T("mrw.fn.")+hierarchy)); + (log4cxx::Logger::getLogger(log4cxx::String(name.begin(), name.end()))); if (logger->isDebugEnabled()) { - std::ostringstream ss; - ss<forcedLog(::log4cxx::Level::DEBUG, ss.str(), - pos.file.c_str(), pos.line); + std::basic_ostringstream ss; + ss<forcedLog(MRW_LEVEL_DEBUG, ss.str(), + MRW_LOG4CXX_LOCATION); } } } catch (...) {} diff --git a/mrw/autostacktracelog4cxx.cpp b/mrw/autostacktracelog4cxx.cpp index 916f281..81ed123 100644 --- a/mrw/autostacktracelog4cxx.cpp +++ b/mrw/autostacktracelog4cxx.cpp @@ -11,11 +11,28 @@ */ #include #include +#include #include #include -#ifndef _T -#define _T + +// support for log4cxx 0.9.7 and for new CVS version +#ifndef LOG4CXX_LOCATION +# define MRW_LOG4CXX_LOCATION __FILE__, __LINE__ +#define MRW_LEVEL_DEBUG ::log4cxx::Level::DEBUG +#define MRW_LEVEL_INFO ::log4cxx::Level::INFO +#define MRW_LEVEL_WARN ::log4cxx::Level::WARN +#define MRW_LEVEL_ERROR ::log4cxx::Level::ERROR +#define MRW_LEVEL_FATAL ::log4cxx::Level::FATAL +#else +# define LOG4CXX_CVS +# define MRW_LOG4CXX_LOCATION \ + ::log4cxx::spi::LocationInfo(__FILE__, __FUNCTION__, __LINE__) +#define MRW_LEVEL_DEBUG ::log4cxx::Level::getDebug() +#define MRW_LEVEL_INFO ::log4cxx::Level::getInfo() +#define MRW_LEVEL_WARN ::log4cxx::Level::getWarn() +#define MRW_LEVEL_ERROR ::log4cxx::Level::getError() +#define MRW_LEVEL_FATAL ::log4cxx::Level::getFatal() #endif namespace mrw { @@ -27,8 +44,10 @@ namespace mrw { 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. Also for all know signals there's a signal + handler to trace the stack before termination (except in case of + a @c SIGTRAP, wehere the program is not terminated). You don't + need to change a single line in your code! The log4cxx library is located at: - http://logging.apache.org/log4cxx @@ -49,7 +68,7 @@ namespace mrw { @code void unexpected_log4cxx() { - log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); + log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("mrw.stacktrace")); logger->fatal("Unexpected Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); @@ -71,21 +90,27 @@ namespace mrw { */ void unexpected_log4cxx() { - log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); - logger->fatal("Unexpected Exception", __FILE__, __LINE__); + static const std::string name("mrw.stacktrace"); + log4cxx::LoggerPtr logger + (log4cxx::Logger::getLogger(log4cxx::String(name.begin(), name.end()))); + static const std::string txt("Unexpected Exception"); + logger->fatal(log4cxx::String(txt.begin(), txt.end()), MRW_LOG4CXX_LOCATION); 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()); + std::string txt(std::string("Reason:\n")+x.what() + +"\nStack:\n"+x.stacktrace()); + logger->fatal(log4cxx::String(txt.begin(), txt.end())); } catch (const std::exception& x) { - logger->fatal(std::string("Reason:\n")+x.what() - +"\nStack:\n"+st); + std::string txt(std::string("Reason:\n")+x.what() + +"\nStack:\n"+st); + logger->fatal(log4cxx::String(txt.begin(), txt.end())); } catch (...) { - logger->fatal(std::string("Reason: **** not available ****") - +"\nStack:\n"+st); + std::string txt(std::string("Reason: **** not available ****") + +"\nStack:\n"+st); + logger->fatal(log4cxx::String(txt.begin(), txt.end())); } throw std::bad_exception(); } @@ -98,7 +123,7 @@ namespace mrw { @code void terminate_log4cxx() { - log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); + log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("mrw.stacktrace")); logger->fatal("Uncaught Exception", __FILE__, __LINE__); StackTrace::createSymtable(); std::string st((std::string)StackTrace()); @@ -121,35 +146,104 @@ namespace mrw { */ void terminate_log4cxx() { - log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(_T("mrw.stacktrace"))); - logger->fatal("Uncaught Exception", __FILE__, __LINE__); + static const std::string name("mrw.stacktrace"); + log4cxx::LoggerPtr logger + (log4cxx::Logger::getLogger(log4cxx::String(name.begin(), name.end()))); + static const std::string txt("Uncaught Exception"); + logger->fatal(log4cxx::String(txt.begin(), txt.end()), MRW_LOG4CXX_LOCATION); 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()); + std::string txt(std::string("Reason:\n")+x.what() + +"\nStack:\n"+x.stacktrace()); + logger->fatal(log4cxx::String(txt.begin(), txt.end())); } catch (const std::exception& x) { - logger->fatal(std::string("Reason:\n")+x.what() - +"\nStack:\n"+st); + std::string txt(std::string("Reason:\n")+x.what() + +"\nStack:\n"+st); + logger->fatal(log4cxx::String(txt.begin(), txt.end())); } catch (...) { - logger->fatal(std::string("Reason: **** not available ****") - +"\nStack:\n"+st); + std::string txt(std::string("Reason: **** not available ****") + +"\nStack:\n"+st); + logger->fatal(log4cxx::String(txt.begin(), txt.end())); } exit(1); } + + /** @brief segmentation-fault handler, that traces using log4cxx - //@} + The segmentation-fault handler is installed automatically when you link + to @c -lmrwexclog4cxx. The implementation of this handler is as follows: + + @code + void signal_log4cxx(int sig) { + std::string txt; + bool abort(true); + switch sig { + case SIGFPE: txt="SIGFPE: Arithmetic error."; break; + case SIGILL: txt="SIGILL: Illegal instruction."; break; + case SIGSEGV: txt="SIGSEGV: Segmentation fault" + " (invalid access to valid memory)."; break; + case SIGBUS: txt="SIGBUS: Invalid pointer dereference" + " (access to an invalid memory address)."; break; + case SIGABRT: txt="SIGABRT: Funktion 'abort' was called."; break; + case SIGIOT: txt="SIGIOT: PDP-11 'iot' instruction"; break; + case SIGTRAP: txt="SIGTRAP: Breakpoint instruction."; abort=false; break; + case SIGEMT: txt="SIGEMT: Emulator trap."; break; + case SIGSYS: txt="SIGSYS: Bad system call."; break; + default: txt="Unknown Signal Nr. "+sig; break; + } + StackTrace::createSymtable(); + std::string st((std::string)StackTrace()); + log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("mrw.stacktrace")); + logger->fatal("Aborted by signal: "+txt+"\nStack:\n"+st); + if (abort) exit(1); + } + @endcode + + */ + void signal_log4cxx(int sig) { + std::string txt; + bool abort(true); + switch (sig) { + case SIGFPE: txt="SIGFPE: Arithmetic error."; break; + case SIGILL: txt="SIGILL: Illegal instruction."; break; + case SIGSEGV: txt="SIGSEGV: Segmentation fault" + " (invalid access to valid memory)."; break; + case SIGBUS: txt="SIGBUS: Invalid pointer dereference" + " (access to an invalid memory address)."; break; + case SIGABRT: txt="SIGABRT: Funktion 'abort' was called."; break; + case SIGTRAP: txt="SIGTRAP: Breakpoint instruction."; abort=false; break; + case SIGSYS: txt="SIGSYS: Bad system call."; break; + default: txt="Unknown Signal Nr. "+sig; break; + } + StackTrace::createSymtable(); + std::string st((std::string)StackTrace()); + static const std::string name("mrw.stacktrace"); + log4cxx::LoggerPtr logger + (log4cxx::Logger::getLogger(log4cxx::String(name.begin(), name.end()))); + std::string errtxt("Aborted by signal: "+txt+"\nStack:\n"+st); + logger->fatal(log4cxx::String(errtxt.begin(), errtxt.end())); + if (abort) exit(1); + } class AutoStackTrace { public: AutoStackTrace() { std::set_unexpected(&mrw::unexpected_log4cxx); std::set_terminate(&mrw::terminate_log4cxx); + std::signal(SIGFPE, &mrw::signal_log4cxx); + std::signal(SIGILL, &mrw::signal_log4cxx); + std::signal(SIGSEGV, &mrw::signal_log4cxx); + std::signal(SIGBUS, &mrw::signal_log4cxx); + std::signal(SIGTRAP, &mrw::signal_log4cxx); + std::signal(SIGSYS, &mrw::signal_log4cxx); } }; + //@} + // initialize stack traces (load symbols) static AutoStackTrace _autoStackTrace; diff --git a/mrw/autostacktracestderr.cpp b/mrw/autostacktracestderr.cpp index c41bcff..938a4e5 100644 --- a/mrw/autostacktracestderr.cpp +++ b/mrw/autostacktracestderr.cpp @@ -11,6 +11,7 @@ */ #include #include +#include #include #include @@ -48,8 +49,10 @@ namespace mrw { If you link to the library @c libmrwexcstderr using a linker option such as: @c -lmrwexcstderr, then an unexpected and a terminate handler are registered, that trace to the standard - error stream @c std::cerr. You don't need to change a single - line in your code! + error stream @c std::cerr. Also for all know signals there's a + signal handler to trace the stack before termination (except in + case of a @c SIGTRAP, wehere the program is not terminated). You + don't need to change a single line in your code! */ //@{ @@ -163,6 +166,67 @@ namespace mrw { exit(1); } + /** @brief segmentation-fault handler, that traces using stderr + + The segmentation-fault handler is installed automatically when you link + to @c -lmrwexcstderr. The implementation of this handler is as follows: + + @code + void signal_stderr(int sig) { + std::cerr<<"SIGNAL RECEIVED: -------------------------------"< #include +#include #include #include -#ifndef __GLIBC__ -#include -#endif -mrw::Errno::Errno() throw(): _errno(errno) {} +mrw::Errno::Errno() throw(): _errnoxxx(errno) {} mrw::Errno::operator std::string() const throw(std::bad_exception) { -#ifdef __GLIBC__ - char error[1024]; - return !strerror_r(_errno, error, 1024) ? - error : std::string("errno=")+_errno; -#else - return mrw::ifelse(strerror(_errno), (std::string("errno=")+_errno).c_str()); -#endif + return *this; } std::string mrw::Errno::string() const throw(std::bad_exception) { -#ifdef __GLIBC__ + char* pos(0); char error[1024]; - return !strerror_r(_errno, error, 1024) ? - error : std::string("errno=")+_errno; +#ifdef __GLIBC__ +# if defined __USE_XOPEN2K && !defined __USE_GNU + return strerror_r(errno=_errnoxxx, error, 1024)!=-1 + ? error+std::string(" errno=")+_errnoxxx + : std::string("errno=")+_errnoxxx; +# else + return (pos=strerror_r(errno=_errnoxxx, error, 1024)) + ? pos+std::string(" errno=")+_errnoxxx + : std::string("errno=")+_errnoxxx; +# endif #else - return mrw::ifelse(strerror(_errno), (std::string("errno=")+_errno).c_str()); +# if defined __USE_XOPEN2K && !defined __USE_GNU + return strerror_r(errno=_errnoxxx, error, 1024)!=-1 + ? error+std::string(" errno=")+_errnoxxx + : std::string("errno=")+_errnoxxx; +# else + return (pos=strerror(errno=_errnoxxx)) + ? error+std::string(" errno=")+_errnoxxx + : std::string("errno=")+_errnoxxx; +# endif #endif } diff --git a/mrw/errno.hpp b/mrw/errno.hpp index 12ab30e..23c1cb4 100644 --- a/mrw/errno.hpp +++ b/mrw/errno.hpp @@ -60,18 +60,19 @@ namespace mrw { /// returns the @c errno stored in the constructor operator int() const throw() { - return _errno; + return _errnoxxx; } /// returns the @c errno stored in the constructor int numerical() const throw() { - return _errno; + return _errnoxxx; } //.............................................................. variables private: - int _errno; + int _errnoxxx; // "xxx" for MinGW-compatibility (there's a + // function named _errno) }; diff --git a/mrw/foot.html b/mrw/foot.html index 67ab645..3f3b985 100644 --- a/mrw/foot.html +++ b/mrw/foot.html @@ -1,5 +1,4 @@ -
Last Change: $date
- +
Last Build: $date
diff --git a/mrw/functiontrace.hpp b/mrw/functiontrace.hpp index dac9cd7..aa8a612 100644 --- a/mrw/functiontrace.hpp +++ b/mrw/functiontrace.hpp @@ -34,10 +34,20 @@ // support for log4cxx 0.9.7 and for new CVS version #ifndef LOG4CXX_LOCATION # define MRW_LOG4CXX_LOCATION _file.c_str(), _line +#define MRW_LEVEL_DEBUG ::log4cxx::Level::DEBUG +#define MRW_LEVEL_INFO ::log4cxx::Level::INFO +#define MRW_LEVEL_WARN ::log4cxx::Level::WARN +#define MRW_LEVEL_ERROR ::log4cxx::Level::ERROR +#define MRW_LEVEL_FATAL ::log4cxx::Level::FATAL #else # define LOG4CXX_CVS # define MRW_LOG4CXX_LOCATION \ - ::log4cxx::spi::LocationInfo(_name.c_str(), _file.c_str(), _line) + ::log4cxx::spi::LocationInfo(_file.c_str(), _name.c_str(), _line) +#define MRW_LEVEL_DEBUG ::log4cxx::Level::getDebug() +#define MRW_LEVEL_INFO ::log4cxx::Level::getInfo() +#define MRW_LEVEL_WARN ::log4cxx::Level::getWarn() +#define MRW_LEVEL_ERROR ::log4cxx::Level::getError() +#define MRW_LEVEL_FATAL ::log4cxx::Level::getFatal() #endif namespace mrw { @@ -48,11 +58,11 @@ namespace mrw { /** @defgroup FunctionTrace Function Tracing (using log4cxx) @pre \#include - Place the macro @ref METHOD as first line of all methods you want to - trace, and macro @ref FUNCTION as first line of all functions to be + Place the macro @ref MRW_METHOD as first line of all methods you want to + trace, and macro @ref MRW_FUNCTION as first line of all functions to be traced. - There are alternative macros @ref METHOD2 and @ref FUNCTION2, + There are alternative macros @ref MRW_METHOD2 and @ref MRW_FUNCTION2, that allow you to also specify the logging hierarchy. The default for the hierarchy string is @c "mrw.fntrace". The logging level is always @c DEBUG and cannot be changed. @@ -71,7 +81,7 @@ namespace mrw { \#include \#include void fn(int i=0) { - FUNCTION("fn(int)"); // trace entry and exit + MRW_FUNCTION("fn(int)"); // trace entry and exit if (i<4) fn(++i); } class A { @@ -80,13 +90,13 @@ namespace mrw { method(); } void method() { - METHOD("A::method()"); // trace entry and exit + MRW_METHOD("A::method()"); // trace entry and exit fn(); } }; int main(int, char**) { log4cxx::BasicConfigurator::configure(); - FUNCTION("main(int, char**)"); + MRW_FUNCTION("main(int, char**)"); A().method(); return 0; } @@ -144,7 +154,7 @@ namespace mrw { namespace yyy { class Zzz { public: void doIt(int, char) { - METHOD("xxx::yyy::Zzz::doIt(int, char)"); + MRW_METHOD("xxx::yyy::Zzz::doIt(int, char)"); [...] } }; @@ -155,7 +165,7 @@ namespace mrw { @param name the full name of the method, including namespaces and class name */ -#define METHOD(name) mrw::FnTrace fnTrace(this, name, __FILE__, __LINE__) +#define MRW_METHOD(name) mrw::FnTrace fnTrace(this, name, __FILE__, __LINE__) /** @brief Declare function entrance, place as first line in functions. @@ -168,7 +178,7 @@ namespace mrw { namespace xxx { namespace yyy { void doIt(int, char) { - FUNCTION("xxx::yyy::doIt(int, char)"); + MRW_FUNCTION("xxx::yyy::doIt(int, char)"); [...] } } @@ -177,7 +187,7 @@ namespace mrw { @param name the full name of the function, including namespaces */ -#define FUNCTION(name) mrw::FnTrace fnTrace(name, __FILE__, __LINE__) +#define MRW_FUNCTION(name) mrw::FnTrace fnTrace(name, __FILE__, __LINE__) /** @brief Declare method entrance, place as first line in method. @@ -193,7 +203,7 @@ namespace mrw { namespace yyy { class Zzz { public: void doIt(int, char) { - METHOD2("xxx::yyy::Zzz::doIt(int, char)", "fn.xxx.yyy.Zzz"); + MRW_METHOD2("xxx::yyy::Zzz::doIt(int, char)", "fn.xxx.yyy.Zzz"); [...] } }; @@ -205,7 +215,7 @@ namespace mrw { and class name @param tracer the tracer hierarchy */ -#define METHOD2(name, tracer) \ +#define MRW_METHOD2(name, tracer) \ mrw::FnTrace fnTrace(this, name, __FILE__, __LINE__, tracer) /** @brief Declare function entrance, place as first line in functions. @@ -221,7 +231,7 @@ namespace mrw { namespace xxx { namespace yyy { void doIt(int, char) { - FUNCTION2("xxx::yyy::doIt(int, char)", "fn.xxx.yyy"); + MRW_FUNCTION2("xxx::yyy::doIt(int, char)", "fn.xxx.yyy"); [...] } } @@ -231,7 +241,7 @@ namespace mrw { @param name the full name of the function, including namespaces @param tracer the tracer hierarchy */ -#define FUNCTION2(name, tracer) \ +#define MRW_FUNCTION2(name, tracer) \ mrw::FnTrace fnTrace(name, __FILE__, __LINE__, tracer) class FnTrace { @@ -239,13 +249,15 @@ namespace mrw { FnTrace(const void* addr, const std::string& name, const std::string& file, unsigned long line, const std::string& tracer = "mrw.fntrace") throw(): - _addr(addr), _name(name), _file(file), _line(line), _tracer(tracer) { + _addr(addr), _name(name.begin(), name.end()), _file(file), _line(line), + _tracer(tracer.begin(), tracer.end()) { log4cxx::Logger* logger(log4cxx::Logger::getLogger(_tracer)); if (logger->isDebugEnabled()) { - std::stringstream oss; - oss<forcedLog(log4cxx::Level::DEBUG, oss.str(), + std::basic_stringstream oss; + oss<forcedLog(MRW_LEVEL_DEBUG, oss.str(), MRW_LOG4CXX_LOCATION); ++_level; } @@ -253,13 +265,15 @@ namespace mrw { FnTrace(const std::string& name, const std::string& file, unsigned long line, const std::string& tracer = "mrw.fntrace") throw(): - _addr(0), _name(name), _file(file), _line(line), _tracer(tracer) { + _addr(0), _name(name.begin(), name.end()), _file(file), _line(line), + _tracer(tracer.begin(), tracer.end()) { log4cxx::Logger* logger(log4cxx::Logger::getLogger(_tracer)); if (logger->isDebugEnabled()) { - std::stringstream oss; + std::basic_stringstream oss; oss<forcedLog(log4cxx::Level::DEBUG, oss.str(), + <forcedLog(MRW_LEVEL_DEBUG, oss.str(), MRW_LOG4CXX_LOCATION); ++_level; } @@ -268,22 +282,23 @@ namespace mrw { log4cxx::Logger* logger(log4cxx::Logger::getLogger(_tracer)); if (logger->isDebugEnabled()) { --_level; - std::stringstream oss; + std::basic_stringstream oss; if (_addr) oss<forcedLog(log4cxx::Level::DEBUG, oss.str(), + oss<forcedLog(MRW_LEVEL_DEBUG, oss.str(), MRW_LOG4CXX_LOCATION); } } private: const void* _addr; - const std::string _name; + const log4cxx::String _name; const std::string _file; unsigned long _line; - const std::string _tracer; + const log4cxx::String _tracer; /** @todo for multithreading, use thread specific storage */ static unsigned int _level; }; diff --git a/mrw/functiontrace_test.cpp b/mrw/functiontrace_test.cpp index a274306..646cc37 100644 --- a/mrw/functiontrace_test.cpp +++ b/mrw/functiontrace_test.cpp @@ -36,32 +36,32 @@ class A { public: A() { - METHOD("A::A()"); + MRW_METHOD("A::A()"); } ~A() { - METHOD("A::~A()"); + MRW_METHOD("A::~A()"); } void fn1() { - METHOD("A::fn1()"); + MRW_METHOD("A::fn1()"); fn2(); } void fn2() { - METHOD("A::fn2()"); + MRW_METHOD("A::fn2()"); fn3(); fn4(); } void fn3() { - METHOD("A::fn3()"); + MRW_METHOD("A::fn3()"); fn4(); } void fn4(bool flag=true) { - METHOD("A::fn4()"); + MRW_METHOD("A::fn4()"); if (flag) fn4(false); } }; void fn(A a) { - FUNCTION("fn(A)"); + MRW_FUNCTION("fn(A)"); a.fn1(); } @@ -70,16 +70,27 @@ class FunctionTraceTest: public CppUnit::TestFixture { void Init() { try {mrw::File::remove("functiontrace_test.log");} catch (...) {} log4cxx::helpers::Properties properties; - properties.setProperty("log4j.rootLogger", - "DEBUG, A1"); - properties.setProperty("log4j.appender.A1", - "org.apache.log4j.FileAppender"); - properties.setProperty("log4j.appender.A1.layout", - "org.apache.log4j.PatternLayout"); - properties.setProperty("log4j.appender.A1.layout.ConversionPattern", - "%F:%L - %m%n"); - properties.setProperty("log4j.appender.A1.filename", - "functiontrace_test.log"); + std::string name, cont; + properties.setProperty((name="log4j.rootLogger", + log4cxx::String(name.begin(), name.end())), + (cont="DEBUG, A1", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1", + log4cxx::String(name.begin(), name.end())), + (cont="org.apache.log4j.FileAppender", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1.layout", + log4cxx::String(name.begin(), name.end())), + (cont="org.apache.log4j.PatternLayout", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", + log4cxx::String(name.begin(), name.end())), + (cont="%F:%L - %m%n", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1.filename", + log4cxx::String(name.begin(), name.end())), + (cont="functiontrace_test.log", + log4cxx::String(cont.begin(), cont.end()))); log4cxx::PropertyConfigurator::configure(properties); } void Calls() { diff --git a/mrw/head.html b/mrw/head.html index 8ed296a..fc627cb 100644 --- a/mrw/head.html +++ b/mrw/head.html @@ -14,7 +14,3 @@ - - - -

$title

diff --git a/mrw/hintergrund.png b/mrw/hintergrund.png new file mode 100644 index 0000000000000000000000000000000000000000..17f0abc6db145b418406efea51ca83e1a8688952 GIT binary patch literal 36887 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 literal 0 HcmV?d00001 diff --git a/mrw/log4cxxconfiguration.cpp b/mrw/log4cxxconfiguration.cpp index 8dcd8a2..b7cf589 100644 --- a/mrw/log4cxxconfiguration.cpp +++ b/mrw/log4cxxconfiguration.cpp @@ -64,8 +64,9 @@ namespace mrw { -# /etc/mrwlog4cxx (global configuration) -# if no configuration file is found, use default configuration: @verbatim -log4j.rootLogger = DEBUG, A1 -log4j.logger.mrw.fn = DEBUG +log4j.rootLogger = WARN, A1 +log4j.logger.mrw.fntrace = OFF +log4j.logger.mrw.fn = OFF log4j.logger.mrw.fn.log4cxx = OFF log4j.logger.mrw.fn.boost = OFF log4j.logger.mrw.fn.Thread = OFF @@ -84,17 +85,17 @@ log4j.appender.A1.layout = org.apache.log4j.PatternLayout @endverbatim and for multi threaded programs in addition: @verbatim -log4j.appender.A1.layout.ConversionPattern = t-%-60c%m%n +log4j.appender.A1.layout.ConversionPattern = \%t-\%-40l - \%m\%n @endverbatim on the other hand, single threaded programs are formatted as: @verbatim -log4j.appender.A1.layout.ConversionPattern = 60c%m%n +log4j.appender.A1.layout.ConversionPattern = \%-40l - \%m\%n @endverbatim This results in the following behaviour: - trace to console - format as... - - @c "%t-%-60c%m%n" if threaded - - @c "%-60c%m%n" if not threaded + - @c "\%t-\%-40l - \%m\%n" if threaded + - @c "\%-40l - \%m\%n" if not threaded - enable all tracing to @c DEBUG - enable tracing of @ref AutoFunctionTrace - disable function trace for @c log4cxx @@ -122,50 +123,94 @@ log4j.appender.A1.layout.ConversionPattern = 60c%m%n else if (std::ifstream("/etc/mrwlog4cxx")) logconfigfile = "/etc/mrwlog4cxx"; if (logconfigfile.size()) { - log4cxx::PropertyConfigurator::configure(logconfigfile); + log4cxx::PropertyConfigurator::configure + (log4cxx::String(logconfigfile.begin(), logconfigfile.end())); return; } log4cxx::helpers::Properties properties; - properties.setProperty("log4j.rootLogger", - "DEBUG, A1"); - properties.setProperty("log4j.logger.mrw.fn", - "DEBUG"); - properties.setProperty("log4j.logger.mrw.fn.log4cxx", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.boost", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.Thread", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.QString", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.QShared", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.QWidget", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.QRect", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.qstrcmp", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.*.qt_cast", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.mrw", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.std", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.CppUnit", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.__gnu_cxx", - "OFF"); - properties.setProperty("log4j.appender.A1", - "org.apache.log4j.ConsoleAppender"); - properties.setProperty("log4j.appender.A1.layout", - "org.apache.log4j.PatternLayout"); + std::string name, cont; + properties.setProperty((name="log4j.rootLogger", + log4cxx::String(name.begin(), name.end())), + (cont="WARN, A1", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fntracea", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.log4cxx", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.boost", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.Thread", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.QString", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.QShared", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.QWidget", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.QRect", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.qstrcmp", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.*.qt_cast", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.mrw", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.std", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.CppUnit", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.__gnu_cxx", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1", + log4cxx::String(name.begin(), name.end())), + (cont="org.apache.log4j.ConsoleAppender", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1.layout", + log4cxx::String(name.begin(), name.end())), + (cont="org.apache.log4j.PatternLayout", + log4cxx::String(cont.begin(), cont.end()))); #ifdef _MT - properties.setProperty("log4j.appender.A1.layout.ConversionPattern", - "%t-%-60c%m%n"); + properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", + log4cxx::String(name.begin(), name.end())), + (cont="%t-%-40l - %m%n", + log4cxx::String(cont.begin(), cont.end()))); #else - properties.setProperty("log4j.appender.A1.layout.ConversionPattern", - "%-60c%m%n"); + properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", + log4cxx::String(name.begin(), name.end())), + (cont="%-40l - %m%n", + log4cxx::String(cont.begin(), cont.end()))); #endif log4cxx::PropertyConfigurator::configure(properties); } diff --git a/mrw/makefile.am b/mrw/makefile.am index 78de50e..dd4ace4 100644 --- a/mrw/makefile.am +++ b/mrw/makefile.am @@ -9,7 +9,7 @@ ## @license LGPL, see file COPYING ## -AM_CPPFLAGS += -I${top_srcdir} +AM_CPPFLAGS += -I$(top_srcdir) if HAVE_STACKTRACE AM_CPPFLAGS += -DHAVE_STACKTRACE @@ -17,13 +17,14 @@ endif CLEANFILES = doxygen.errors functiontrace_test.log \ mrwautofunctiontracelog4cxx_test.log \ - mrwautofunctiontracelog4cxx_test-mt.log -examplesdir = ${pkgdatadir}/examples -dist_examples_DATA = ${top_srcdir}/mrw/examples/* -htmldir = ${pkgdatadir}/doc/html -html_DATA = ${top_builddir}/doc/html/index.html -pdfdir = ${pkgdatadir}/doc/pdf -dist_pdf_DATA = ${top_builddir}/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf + mrwautofunctiontracelog4cxx_test-mt.log \ + $(VALTESTS) valgrind.log +examplesdir = $(pkgdatadir)/examples +dist_examples_DATA = $(top_srcdir)/mrw/examples/* +htmldir = $(pkgdatadir)/doc/html +html_DATA = $(top_builddir)/doc/html/index.html +pdfdir = $(pkgdatadir)/doc/pdf +dist_pdf_DATA = $(top_builddir)/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf lib_LTLIBRARIES = libmrw.la if HAVE_BOOST_THREAD @@ -45,14 +46,10 @@ endif endif endif if HAVE_LOG4CXX - lib_LTLIBRARIES += libmrwexclog4cxx.la \ - libmrwlog4cxxconfiguration.la -if HAVE_THREADS - lib_LTLIBRARIES += libmrwlog4cxxconfiguration-mt.la + lib_LTLIBRARIES += libmrwexclog4cxx.la if HAVE_BOOST_THREAD lib_LTLIBRARIES += libmrwexclog4cxx-mt.la endif -endif if AUTOFNTRACE lib_LTLIBRARIES += libmrwautofunctiontracelog4cxx.la if HAVE_THREADS @@ -63,18 +60,33 @@ endif endif endif endif +if HAVE_LOG4CXX + lib_LTLIBRARIES += libmrwlog4cxxconfiguration.la +if HAVE_THREADS + lib_LTLIBRARIES += libmrwlog4cxxconfiguration-mt.la +endif +endif libmrw_la_SOURCES = \ mrw.hpp version.cpp \ arg.cpp arg.hpp auto.hpp deque.hpp \ exception.cpp exception.hpp \ - exec.cpp exec.hpp list.hpp \ + list.hpp \ map.hpp multimap.hpp multiset.hpp \ set.hpp \ smartpointer.hpp stdext.cpp stdext.hpp \ - string.hpp unistd.hpp vector.hpp regexp.hpp regexp.cpp \ - tokenizer.hpp configfile.hpp configfile.cpp file.hpp \ + string.hpp unistd.hpp vector.hpp \ + tokenizer.hpp \ errno.hpp errno.cpp +if HAVE_DIR + libmrw_la_SOURCES += file.hpp configfile.hpp configfile.cpp +endif +if HAVE_REGEXP + libmrw_la_SOURCES += regexp.hpp regexp.cpp +endif +if HAVE_EXEC + libmrw_la_SOURCES += exec.cpp exec.hpp +endif if HAVE_LTDL libmrw_la_SOURCES += dynamiclibrary.hpp endif @@ -93,33 +105,32 @@ endif if HAVE_THREADS if HAVE_BOOST_THREAD - libmrw_mt_la_SOURCES = ${libmrw_la_SOURCES} + libmrw_mt_la_SOURCES = $(libmrw_la_SOURCES) libmrw_mt_la_CXXFLAGS = @THREADS@ - libmrw_mt_la_LDFLAGS = ${libmrw_la_LDFLAGS} -version-info @LIB_VERSION@ \ + libmrw_mt_la_LDFLAGS = $(libmrw_la_LDFLAGS) -version-info @LIB_VERSION@ \ @THREADS@ - libmrw_mt_la_LIBADD = ${libmrw_la_LIBADD} @BOOST_THREAD_LIB@ + libmrw_mt_la_LIBADD = $(libmrw_la_LIBADD) @BOOST_THREAD_LIB@ endif endif if HAVE_STACKTRACE libmrwexcstderr_la_SOURCES = autostacktracestderr.cpp version.cpp libmrwexcstderr_la_LDFLAGS = -version-info @LIB_VERSION@ - libmrwexcstderr_la_LIBADD = ${top_builddir}/mrw/libmrw.la + libmrwexcstderr_la_LIBADD = $(top_builddir)/mrw/libmrw.la if HAVE_THREADS if HAVE_BOOST_THREAD libmrwexcstderr_mt_la_SOURCES = autostacktracestderr.cpp version.cpp libmrwexcstderr_mt_la_CXXFLAGS = @THREADS@ libmrwexcstderr_mt_la_LDFLAGS = -version-info @LIB_VERSION@ @THREADS@ - libmrwexcstderr_mt_la_LIBADD = ${top_builddir}/mrw/libmrw-mt.la + libmrwexcstderr_mt_la_LIBADD = $(top_builddir)/mrw/libmrw-mt.la endif endif - if AUTOFNTRACE libmrwautofunctiontracestdlog_la_SOURCES = autofunctiontracestdlog.cpp \ version.cpp libmrwautofunctiontracestdlog_la_CXXFLAGS = -w libmrwautofunctiontracestdlog_la_LDFLAGS = -version-info @LIB_VERSION@ - libmrwautofunctiontracestdlog_la_LIBADD = ${top_builddir}/mrw/libmrw.la + libmrwautofunctiontracestdlog_la_LIBADD = $(top_builddir)/mrw/libmrw.la if HAVE_THREADS if HAVE_BOOST_THREAD libmrwautofunctiontracestdlog_mt_la_SOURCES = \ @@ -128,38 +139,28 @@ if HAVE_BOOST_THREAD libmrwautofunctiontracestdlog_mt_la_LDFLAGS = \ -version-info @LIB_VERSION@ @THREADS@ libmrwautofunctiontracestdlog_mt_la_LIBADD = \ - ${top_builddir}/mrw/libmrw-mt.la + $(top_builddir)/mrw/libmrw-mt.la endif endif endif if HAVE_LOG4CXX libmrwexclog4cxx_la_SOURCES = autostacktracelog4cxx.cpp version.cpp libmrwexclog4cxx_la_LDFLAGS = -version-info @LIB_VERSION@ - libmrwexclog4cxx_la_LIBADD = ${top_builddir}/mrw/libmrw.la -llog4cxx - libmrwlog4cxxconfiguration_la_SOURCES = log4cxxconfiguration.cpp version.cpp - libmrwlog4cxxconfiguration_la_LDFLAGS = -version-info @LIB_VERSION@ - libmrwlog4cxxconfiguration_la_LIBADD = -llog4cxx + libmrwexclog4cxx_la_LIBADD = $(top_builddir)/mrw/libmrw.la -llog4cxx if HAVE_THREADS if HAVE_BOOST_THREAD libmrwexclog4cxx_mt_la_SOURCES = autostacktracelog4cxx.cpp version.cpp libmrwexclog4cxx_mt_la_CXXFLAGS = @THREADS@ libmrwexclog4cxx_mt_la_LDFLAGS = -version-info @LIB_VERSION@ @THREADS@ - libmrwexclog4cxx_mt_la_LIBADD = ${top_builddir}/mrw/libmrw-mt.la -llog4cxx - libmrwlog4cxxconfiguration_mt_la_SOURCES = log4cxxconfiguration.cpp \ - version.cpp - libmrwlog4cxxconfiguration_mt_la_CXXFLAGS = @THREADS@ - libmrwlog4cxxconfiguration_mt_la_LDFLAGS = -version-info @LIB_VERSION@ \ - @THREADS@ - libmrwlog4cxxconfiguration_mt_la_LIBADD = -llog4cxx + libmrwexclog4cxx_mt_la_LIBADD = $(top_builddir)/mrw/libmrw-mt.la -llog4cxx endif endif - if AUTOFNTRACE libmrwautofunctiontracelog4cxx_la_SOURCES = autofunctiontracelog4cxx.cpp \ version.cpp libmrwautofunctiontracelog4cxx_la_CXXFLAGS = -w libmrwautofunctiontracelog4cxx_la_LDFLAGS = -version-info @LIB_VERSION@ - libmrwautofunctiontracelog4cxx_la_LIBADD = ${top_builddir}/mrw/libmrw.la -llog4cxx + libmrwautofunctiontracelog4cxx_la_LIBADD = $(top_builddir)/mrw/libmrw.la -llog4cxx if HAVE_THREADS if HAVE_BOOST_THREAD libmrwautofunctiontracelog4cxx_mt_la_SOURCES = \ @@ -168,159 +169,190 @@ if HAVE_BOOST_THREAD libmrwautofunctiontracelog4cxx_mt_la_LDFLAGS = \ -version-info @LIB_VERSION@ @THREADS@ libmrwautofunctiontracelog4cxx_mt_la_LIBADD = \ - ${top_builddir}/mrw/libmrw-mt.la -llog4cxx + $(top_builddir)/mrw/libmrw-mt.la -llog4cxx endif endif endif endif endif +if HAVE_LOG4CXX + libmrwlog4cxxconfiguration_la_SOURCES = log4cxxconfiguration.cpp version.cpp + libmrwlog4cxxconfiguration_la_LDFLAGS = -version-info @LIB_VERSION@ + libmrwlog4cxxconfiguration_la_LIBADD = -llog4cxx +if HAVE_THREADS + libmrwlog4cxxconfiguration_mt_la_SOURCES = log4cxxconfiguration.cpp \ + version.cpp + libmrwlog4cxxconfiguration_mt_la_CXXFLAGS = @THREADS@ + libmrwlog4cxxconfiguration_mt_la_LDFLAGS = -version-info @LIB_VERSION@ \ + @THREADS@ + libmrwlog4cxxconfiguration_mt_la_LIBADD = -llog4cxx +endif +endif -check_PROGRAMS = auto_test smartpointer_test exec_test stdext_test regexp_test \ - tokenizer_test configfile_test string_test +VALGRIND_CHECKS = auto_test smartpointer_test stdext_test \ + tokenizer_test string_test +NO_VALGRIND_CHECKS = +if HAVE_DIR + VALGRIND_CHECKS += configfile_test + dist_check_SCRIPTS = configfile_check.sh +endif +if HAVE_REGEXP + VALGRIND_CHECKS += regexp_test +endif +if HAVE_EXEC + VALGRIND_CHECKS += exec_test +endif if HAVE_LTDL -check_PROGRAMS += dynamiclibrary_test + VALGRIND_CHECKS += dynamiclibrary_test endif if HAVE_LOG4CXX - check_PROGRAMS += functiontrace_test + VALGRIND_CHECKS += functiontrace_test endif -dist_check_SCRIPTS = configfile_check.sh if HAVE_STACKTRACE - check_PROGRAMS += stacktrace_test mrwexcstderr_test + NO_VALGRIND_CHECKS += stacktrace_test + VALGRIND_CHECKS += mrwexcstderr_test if HAVE_LOG4CXX - check_PROGRAMS += mrwexclog4cxx_test + VALGRIND_CHECKS += mrwexclog4cxx_test if AUTOFNTRACE - check_PROGRAMS += mrwautofunctiontracelog4cxx_test + NO_VALGRIND_CHECKS += mrwautofunctiontracelog4cxx_test if HAVE_THREADS if HAVE_BOOST_THREAD - check_PROGRAMS += mrwautofunctiontracelog4cxx_test-mt + NO_VALGRIND_CHECKS += mrwautofunctiontracelog4cxx_test-mt endif endif endif endif endif + auto_test_SOURCES = auto_test.cpp version.cpp -auto_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 +auto_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 auto_test_CXXFLAGS = -g3 -O0 -auto_test_LDFLAGS = @CPPUNIT_LIBS@ -auto_test_LDADD = ${top_builddir}/mrw/libmrw.la +auto_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs +auto_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - auto_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la + auto_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la endif smartpointer_test_SOURCES = smartpointer_test.cpp version.cpp -smartpointer_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 +smartpointer_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 smartpointer_test_CXXFLAGS = -g3 -O0 -smartpointer_test_LDFLAGS = @CPPUNIT_LIBS@ -smartpointer_test_LDADD = ${top_builddir}/mrw/libmrw.la +smartpointer_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs +smartpointer_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - smartpointer_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la + smartpointer_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la endif +if HAVE_EXEC exec_test_SOURCES = exec_test.cpp version.cpp -exec_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 +exec_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 exec_test_CXXFLAGS = -g3 -O0 -exec_test_LDFLAGS = @CPPUNIT_LIBS@ -exec_test_LDADD = ${top_builddir}/mrw/libmrw.la +exec_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs +exec_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - exec_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la + exec_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la +endif endif stdext_test_SOURCES = stdext_test.cpp version.cpp -stdext_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 +stdext_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 stdext_test_CXXFLAGS = -g3 -O0 -stdext_test_LDFLAGS = @CPPUNIT_LIBS@ -stdext_test_LDADD = ${top_builddir}/mrw/libmrw.la +stdext_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs +stdext_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - stdext_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la + stdext_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la endif string_test_SOURCES = string_test.cpp version.cpp -string_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 +string_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 string_test_CXXFLAGS = -g3 -O0 -string_test_LDFLAGS = @CPPUNIT_LIBS@ -string_test_LDADD = ${top_builddir}/mrw/libmrw.la +string_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs +string_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - string_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la -endif -regexp_test_SOURCES = regexp_test.cpp version.cpp -regexp_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 -regexp_test_CXXFLAGS = -g3 -O0 -regexp_test_LDFLAGS = @CPPUNIT_LIBS@ -regexp_test_LDADD = ${top_builddir}/mrw/libmrw.la + string_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la +endif +if HAVE_REGEXP + regexp_test_SOURCES = regexp_test.cpp version.cpp + regexp_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 + regexp_test_CXXFLAGS = -g3 -O0 + regexp_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs + regexp_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - regexp_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la + regexp_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la +endif endif tokenizer_test_SOURCES = tokenizer_test.cpp version.cpp -tokenizer_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 +tokenizer_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 tokenizer_test_CXXFLAGS = -g3 -O0 -tokenizer_test_LDFLAGS = @CPPUNIT_LIBS@ -tokenizer_test_LDADD = ${top_builddir}/mrw/libmrw.la +tokenizer_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs +tokenizer_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - tokenizer_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la -endif -configfile_test_SOURCES = configfile_test.cpp version.cpp -configfile_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 -configfile_test_CXXFLAGS = -g3 -O0 -configfile_test_LDFLAGS = @CPPUNIT_LIBS@ -configfile_test_LDADD = ${top_builddir}/mrw/libmrw.la + tokenizer_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la +endif +if HAVE_DIR + configfile_test_SOURCES = configfile_test.cpp version.cpp + configfile_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 + configfile_test_CXXFLAGS = -g3 -O0 + configfile_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs + configfile_test_LDADD = $(top_builddir)/mrw/libmrw.la if HAVE_STACKTRACE - configfile_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la + configfile_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la +endif endif if HAVE_LTDL check_LTLIBRARIES = libdynamiclibrary_testlib.la libdynamiclibrary_testlib_la_SOURCES = dynamiclibrary_testlib.cpp libdynamiclibrary_testlib_la_LDFLAGS = -module -rpath /bullshit dynamiclibrary_test_SOURCES = dynamiclibrary_test.cpp version.cpp - dynamiclibrary_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 + dynamiclibrary_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 dynamiclibrary_test_CXXFLAGS = -g3 -O0 - dynamiclibrary_test_LDFLAGS = @CPPUNIT_LIBS@ - dynamiclibrary_test_LDADD = ${top_builddir}/mrw/libmrw.la -lltdl + dynamiclibrary_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs + dynamiclibrary_test_LDADD = $(top_builddir)/mrw/libmrw.la -lltdl endif if HAVE_LOG4CXX functiontrace_test_SOURCES = functiontrace_test.cpp version.cpp - functiontrace_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 + functiontrace_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 functiontrace_test_CXXFLAGS = -g3 -O0 - functiontrace_test_LDFLAGS = @CPPUNIT_LIBS@ - functiontrace_test_LDADD = ${top_builddir}/mrw/libmrw.la -llog4cxx + functiontrace_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs + functiontrace_test_LDADD = $(top_builddir)/mrw/libmrw.la -llog4cxx if HAVE_STACKTRACE - functiontrace_test_LDADD += ${top_builddir}/mrw/libmrwexcstderr.la + functiontrace_test_LDADD += $(top_builddir)/mrw/libmrwexcstderr.la endif endif if HAVE_STACKTRACE stacktrace_test_SOURCES = stacktrace_test.cpp version.cpp - stacktrace_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 + stacktrace_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 stacktrace_test_CXXFLAGS = -g3 -O0 - stacktrace_test_LDFLAGS = @CPPUNIT_LIBS@ - stacktrace_test_LDADD = ${top_builddir}/mrw/libmrw.la ${top_builddir}/mrw/libmrwexcstderr.la + stacktrace_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs + stacktrace_test_LDADD = $(top_builddir)/mrw/libmrw.la $(top_builddir)/mrw/libmrwexcstderr.la mrwexcstderr_test_SOURCES = mrwexcstderr_test.cpp version.cpp - mrwexcstderr_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 + mrwexcstderr_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 mrwexcstderr_test_CXXFLAGS = -g3 -O0 - mrwexcstderr_test_LDFLAGS = @CPPUNIT_LIBS@ - mrwexcstderr_test_LDADD = ${top_builddir}/mrw/libmrwexcstderr.la + mrwexcstderr_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs + mrwexcstderr_test_LDADD = $(top_builddir)/mrw/libmrwexcstderr.la if HAVE_LOG4CXX mrwexclog4cxx_test_SOURCES = mrwexclog4cxx_test.cpp version.cpp - mrwexclog4cxx_test_CPPFLAGS = -I${top_srcdir} @CPPUNIT_CFLAGS@ -g3 -O0 + mrwexclog4cxx_test_CPPFLAGS = -I$(top_srcdir) @CPPUNIT_CFLAGS@ -g3 -O0 mrwexclog4cxx_test_CXXFLAGS = -g3 -O0 - mrwexclog4cxx_test_LDFLAGS = @CPPUNIT_LIBS@ - mrwexclog4cxx_test_LDADD = ${top_builddir}/mrw/libmrwexclog4cxx.la -llog4cxx + mrwexclog4cxx_test_LDFLAGS = @CPPUNIT_LIBS@ -L.libs + mrwexclog4cxx_test_LDADD = $(top_builddir)/mrw/libmrwexclog4cxx.la -llog4cxx if AUTOFNTRACE mrwautofunctiontracelog4cxx_test_SOURCES = \ mrwautofunctiontracelog4cxx_test.cpp version.cpp mrwautofunctiontracelog4cxx_test_CPPFLAGS = \ - -I${top_srcdir} @CPPUNIT_CFLAGS@ -finstrument-functions -g3 -O0 + -I$(top_srcdir) @CPPUNIT_CFLAGS@ -finstrument-functions -g3 -O0 mrwautofunctiontracelog4cxx_test_CXXFLAGS = -g3 -O0 -finstrument-functions mrwautofunctiontracelog4cxx_test_LDFLAGS = \ - @CPPUNIT_LIBS@ -finstrument-functions + @CPPUNIT_LIBS@ -L.libs -finstrument-functions mrwautofunctiontracelog4cxx_test_LDADD = \ - -llog4cxx ${top_builddir}/mrw/libmrwautofunctiontracelog4cxx.la + -llog4cxx $(top_builddir)/mrw/libmrwautofunctiontracelog4cxx.la if HAVE_THREADS if HAVE_BOOST_THREAD mrwautofunctiontracelog4cxx_test_mt_SOURCES = \ mrwautofunctiontracelog4cxx_test.cpp version.cpp mrwautofunctiontracelog4cxx_test_mt_CPPFLAGS = \ - -I${top_srcdir} @CPPUNIT_CFLAGS@ -finstrument-functions -g3 -O0 + -I$(top_srcdir) @CPPUNIT_CFLAGS@ -finstrument-functions -g3 -O0 mrwautofunctiontracelog4cxx_test_mt_CXXFLAGS = -g3 -O0 \ -finstrument-functions @THREADS@ mrwautofunctiontracelog4cxx_test_mt_LDFLAGS = \ - @CPPUNIT_LIBS@ @THREADS@ -finstrument-functions + @CPPUNIT_LIBS@ -L.libs @THREADS@ -finstrument-functions mrwautofunctiontracelog4cxx_test_mt_LDADD = \ - -llog4cxx ${top_builddir}/mrw/libmrwautofunctiontracelog4cxx-mt.la @BOOST_THREAD_LIB@ + -llog4cxx $(top_builddir)/mrw/libmrwautofunctiontracelog4cxx-mt.la @BOOST_THREAD_LIB@ endif endif endif @@ -328,51 +360,59 @@ endif endif dist_check_DATA = test.dat configfile.ini configfile.ini.result -EXTRA_DIST = head.html foot.html style.css -TESTS = ${check_PROGRAMS} ${dist_check_SCRIPTS} +EXTRA_DIST = head.html foot.html style.css hintergrund.png +if HAVE_VALGRIND +VALTESTS=$(VALGRIND_CHECKS:%=valcheck_%) +TESTS = $(VALTESTS) $(NO_VALGRIND_CHECKS) $(dist_check_SCRIPTS) +valcheck_%: % + echo "LD_LIBRARY_PATH=.libs $(top_srcdir)/valcheck.sh .libs/$<" > $@ + chmod ugo+x $@ +else +TESTS = $(check_PROGRAMS) $(dist_check_SCRIPTS) +endif +check_PROGRAMS = $(VALGRIND_CHECKS) $(NO_VALGRIND_CHECKS) .PHONY: doc clean-local distclean-local dist-hool install-data-hook \ uninstall-hook -deps = ${top_srcdir}/COPYING ${top_srcdir}/README ${top_srcdir}/INSTALL ${top_srcdir}/NEWS ${top_srcdir}/ChangeLog +deps = $(top_srcdir)/COPYING $(top_srcdir)/README $(top_srcdir)/INSTALL $(top_srcdir)/NEWS $(top_srcdir)/ChangeLog -doc: ${top_builddir}/doc/html/index.html ${top_builddir}/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf +doc: $(top_builddir)/doc/html/index.html $(top_builddir)/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf -${html_DATA}: doxyfile *.[ch]pp ${deps} style.css head.html foot.html - test -d ${top_builddir}/doc/latex || mkdir -p ${top_builddir}/doc/latex - test -d ${top_builddir}/doc/html || mkdir -p ${top_builddir}/doc/html - @test -f ${top_builddir}/doc/html/hintergrund.png || \ - cp ~/www/marc/linux/hintergrund.png \ - ${top_builddir}/doc/html || \ - ( \ - echo "**** sorry, you are missing the html background image"; \ - echo " (after distclean doc/html/hintergrund.png is deleted)" \ - ) +$(html_DATA): doxyfile *.[ch]pp $(deps) style.css head.html foot.html + test -d $(top_builddir)/doc/latex || mkdir -p $(top_builddir)/doc/latex + test -d $(top_builddir)/doc/html || mkdir -p $(top_builddir)/doc/html + @test -f $(top_builddir)/doc/html/hintergrund.png || \ + cp $(srcdir)/hintergrund.png \ + $(top_builddir)/doc/html doxygen doxyfile if PEDANTIC test \! -s doxygen.errors endif -${top_builddir}/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf: doxyfile *.[ch]pp ${deps} ${html_DATA} - cd ${top_builddir}/doc/latex && make && \ +$(top_builddir)/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf: doxyfile *.[ch]pp $(deps) $(html_DATA) + cd $(top_builddir)/doc/latex && make && \ mv refman.pdf @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf clean-local: - rm doxygen.err libmrw.doxytag distclean-local: - - rm -r ${top_builddir}/doc/html/* ${top_builddir}/doc/latex/* + - rm -r $(top_builddir)/doc/html/* $(top_builddir)/doc/latex/* - rm makefile makefile.in doxygen.err libmrw.doxytag dist-hook: - test -d ${distdir}/doc/html || \ - mkdir -p ${distdir}/doc/html - cp ${top_builddir}/doc/html/* ${distdir}/doc/html/. + test -d $(distdir)/doc/html || \ + mkdir -p $(distdir)/doc/html + cp $(top_builddir)/doc/html/* $(distdir)/doc/html/. install-data-hook: - chmod -R u+w ${pkgdatadir}/doc - cp -rf ${top_builddir}/doc/html ${pkgdatadir}/doc/ + env | grep -i tmp + test -d "$(DESTDIR)$(pkgdatadir)/doc" || \ + mkdir -p "$(DESTDIR)$(pkgdatadir)/doc" + chmod -R u+w "$(DESTDIR)$(pkgdatadir)/doc" + cp -rf $(top_builddir)/doc/html "$(DESTDIR)$(pkgdatadir)/doc/" uninstall-hook: - chmod -R u+w ${pkgdatadir}/doc - rm -rf ${pkgdatadir}/doc/html + chmod -R u+w "$(DESTDIR)$(pkgdatadir)/doc" + rm -rf "$(DESTDIR)$(pkgdatadir)/doc/html" diff --git a/mrw/mrw.hpp.in b/mrw/mrw.hpp.in index ea16e57..40c7e81 100644 --- a/mrw/mrw.hpp.in +++ b/mrw/mrw.hpp.in @@ -1,7 +1,15 @@ /** @mainpage The official homepage is on: - - http://marc.waeckerlin.org/@PACKAGENAME@/index.html + - http://marc.waeckerlin.org/computer/c_/mrw-c_/index + + The minimal runtime package (for use with VideoreKorder): + + Minimalpaket (für den VideoreKorder): + + - @PACKAGENAME@-minimal-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + + More downloads see @ref downloads. All features are listed on the "Modules" page. @@ -39,8 +47,8 @@ See the "Related Pages". + - @ref downloads - @ref readme - - @ref download - @ref usage - @ref threads - @ref libversion @@ -50,63 +58,53 @@ - @ref changes */ -/** @page download Download and Installation +/** @page downloads Download and Installation of the MRW-C++ Library + + Download this documentation in PDF: + - @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf Download this version from here: - - Requirements: - - Boost thread library for multi threading: - http://boost.org - - log4cxx for automated tracing and function traces: - - http://logging.apache.org/log4cxx - - RPM: http://marc.waeckerlin.org/mrw-c++/log4cxx-0.9.7-3.i386.rpm - - @ref mrw::StackTrace requires: - - the GNU Binutils - - either GNU Compiler gcc or GNU C library glibc - - runs better on: either Linux or Solaris - - Binary - - Binary RPM Packages (built on i586/SuSE): - - http://marc.waeckerlin.org/@PACKAGENAME@/@PACKAGENAME@-minimal-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - - Minimal runtime package without debugging support. - Does not depend on boost and log4cxx and ltdl. - To be used - e.g. with http://marc.waeckerlin.org/videorekorder - - Installation:
- rpm -Uvh @PACKAGENAME@-minimal-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - - http://marc.waeckerlin.org/@PACKAGENAME@/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - - Full runtime library, no multithreading. - - Installation:
- rpm -Uvh @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - - http://marc.waeckerlin.org/@PACKAGENAME@/@PACKAGENAME@-mt-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - - Full runtime library, with multithreading support. - - Installation:
- rpm -Uvh @PACKAGENAME@-mt-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - - http://marc.waeckerlin.org/@PACKAGENAME@/@PACKAGENAME@-devel-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - - The package for developers. - - Installation:
- rpm -Uvh @PACKAGENAME@-devel-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm - Source + - Source TAR-Ball: + - @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.tar.gz + - Installation: + -# tar xzf @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.tar.gz + -# cd @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@ + -# ./configure && make all install + - Source RPM Packages: + - @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.src.rpm + - Installation:
sudo rpmbuild --rebuild @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.src.rpm - Requirements to build from source: - boost: http://boost.org - cppunit: http://cppunit.sf.net - log4cxx: http://logging.apache.org/log4cxx - doxygen: http://doxygen.org - graphviz: http://www.research.att.com/sw/tools/graphviz - - GNU binutils (you also need the development package, if it is - separete (e.g. in Debian)) + - GNU binutils (you also need the development package, if it is separete (e.g. in Debian)) - GNU g++, GNU make, GNU autotools: http://gnu.org - - Source TAR-Ball: - - http://marc.waeckerlin.org/@PACKAGENAME@/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.tar.gz - - Installation: - -# tar xzf @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.tar.gz - -# cd @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@ - -# ./configure && make all install - - Source RPM Packages: - - http://marc.waeckerlin.org/@PACKAGENAME@/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.src.rpm - - Installation:
- sudo rpmbuild --rebuild @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.src.rpm - - Download this documentation in PDF: - - http://marc.waeckerlin.org/@PACKAGENAME@/@PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@.pdf + - Binary + - Binary RPM Packages (built on i586/SuSE): + - @PACKAGENAME@-minimal-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - Minimal runtime package without debugging support.
Does not depend on boost and log4cxx and ltdl.
To be used e.g. with [[:Computer:Linux:Programme:Videorekorder]] + - Installation:
rpm -Uvh @PACKAGENAME@-minimal-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - Full runtime library, no multithreading. + - Installation:
rpm -Uvh @PACKAGENAME@-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - @PACKAGENAME@-mt-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - Full runtime library, with multithreading support. + - Installation:
rpm -Uvh @PACKAGENAME@-mt-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - @PACKAGENAME@-devel-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - The package for developers. + - Installation:
rpm -Uvh @PACKAGENAME@-devel-@MAJOR@.@MINOR@.@LEAST@-1.i586.rpm + - Requirements: + - Boost thread library for multi threading:
http://boost.org + - log4cxx for automated tracing and function traces: + - http://logging.apache.org/log4cxx + - RPM: log4cxx-0.9.7-3.i386.rpm + - mrw::StackTrace requires: + - the GNU Binutils + - either GNU Compiler gcc or GNU C library glibc + - runs better on: either Linux or Solaris */ /** @page usage Usage of the Library: Include and Link diff --git a/mrw/mrwautofunctiontracelog4cxx_test.cpp b/mrw/mrwautofunctiontracelog4cxx_test.cpp index 73fb463..6a889a7 100644 --- a/mrw/mrwautofunctiontracelog4cxx_test.cpp +++ b/mrw/mrwautofunctiontracelog4cxx_test.cpp @@ -86,40 +86,85 @@ namespace mrw { #endif catch (...) {} log4cxx::helpers::Properties properties; - properties.setProperty("log4j.rootLogger", - "OFF, A1"); - properties.setProperty("log4j.logger.mrw.fn", - "DEBUG"); - properties.setProperty("log4j.logger.mrw.fn.log4cxx", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.boost", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.Thread", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.mrw", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.std", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.new", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.CppUnit", - "OFF"); - properties.setProperty("log4j.logger.mrw.fn.__gnu_cxx", - "OFF"); - properties.setProperty("log4j.appender.A1", - "org.apache.log4j.FileAppender"); - properties.setProperty("log4j.appender.A1.layout", - "org.apache.log4j.PatternLayout"); + std::string name, cont; + properties.setProperty((name="log4j.rootLogger", + log4cxx::String(name.begin(), name.end())), + (cont="OFF, A1", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn", + log4cxx::String(name.begin(), name.end())), + (cont="DEBUG", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.global", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.allocator", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.std.*", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.log4cxx", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.boost", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.Thread", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.mrw", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.std", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.new", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.CppUnit", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.logger.mrw.fn.__gnu_cxx", + log4cxx::String(name.begin(), name.end())), + (cont="OFF", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1", + log4cxx::String(name.begin(), name.end())), + (cont="org.apache.log4j.FileAppender", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1.layout", + log4cxx::String(name.begin(), name.end())), + (cont="org.apache.log4j.PatternLayout", + log4cxx::String(cont.begin(), cont.end()))); #ifdef _MT - properties.setProperty("log4j.appender.A1.layout.ConversionPattern", - "%t-%-27c%m%n"); - properties.setProperty("log4j.appender.A1.filename", - "mrwautofunctiontracelog4cxx_test-mt.log"); + properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", + log4cxx::String(name.begin(), name.end())), + (cont="%t-%-27c%m%n", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1.filename", + log4cxx::String(name.begin(), name.end())), + (cont="mrwautofunctiontracelog4cxx_test-mt.log", + log4cxx::String(cont.begin(), cont.end()))); #else - properties.setProperty("log4j.appender.A1.layout.ConversionPattern", - "%-27c%m%n"); - properties.setProperty("log4j.appender.A1.filename", - "mrwautofunctiontracelog4cxx_test.log"); + properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", + log4cxx::String(name.begin(), name.end())), + (cont="%-27c%m%n", + log4cxx::String(cont.begin(), cont.end()))); + properties.setProperty((name="log4j.appender.A1.filename", + log4cxx::String(name.begin(), name.end())), + (cont="mrwautofunctiontracelog4cxx_test.log", + log4cxx::String(cont.begin(), cont.end()))); #endif log4cxx::PropertyConfigurator::configure(properties); #ifdef _MT diff --git a/mrw/stacktrace.cpp b/mrw/stacktrace.cpp index 493ed4a..def645d 100644 --- a/mrw/stacktrace.cpp +++ b/mrw/stacktrace.cpp @@ -87,34 +87,74 @@ namespace mrw { //---------------------------------------------------------------------------- mrw::StackTrace::StackTrace() throw(std::bad_exception) { // maximum trace level is limited here to 50, see below why -# if defined(__GLIBC__) +# if defined(__GNUG__) + { +# define PUSH(i) \ + (__builtin_frame_address(i)!=0 ? \ + (_trace.push_back(__builtin_return_address(i)), true) : false) + PUSH(0) && PUSH(1) && PUSH(2) && PUSH(3) && PUSH(4) && PUSH(5) && + PUSH(6) && PUSH(7) && PUSH(8) && PUSH(9) && PUSH(10) && PUSH(11) && + PUSH(12) && PUSH(13) && PUSH(14) && PUSH(15) && PUSH(16) && PUSH(17) + && PUSH(18) && PUSH(19) && PUSH(20) && PUSH(21) && PUSH(22) && + PUSH(23) && PUSH(24) && PUSH(25) && PUSH(26) && PUSH(27) && PUSH(28) + && PUSH(29) && PUSH(30) && PUSH(31) && PUSH(32) && PUSH(33) && + PUSH(34) && PUSH(35) && PUSH(36) && PUSH(37) && PUSH(38) && PUSH(39) + && PUSH(40) && PUSH(41) && PUSH(42) && PUSH(43) && PUSH(44) && + PUSH(45) && PUSH(46) && PUSH(47) && PUSH(48) && PUSH(49); +# undef PUSH + } +# elif defined(__GLIBC__) { const int TRACE_LEVEL(50); void* ba[TRACE_LEVEL]; for (int n(backtrace(ba, TRACE_LEVEL)), i(0); i + Memcheck:Leak + fun:_vgrZU_libcZdsoZa_malloc + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:do_dlopen + fun:_dl_catch_error + fun:dlerror_run + fun:__libc_dlopen_mode + fun:init + fun:backtrace + fun:_ZN3mrw10StackTraceC1Ev +} + + */ +# endif +} //---------------------------------------------------------------------------- mrw::StackTrace::operator std::string() const throw(std::bad_exception) { std::stringstream s; @@ -220,7 +260,7 @@ bool mrw::StackTrace::createSymtable(const std::string& fname, void* offs) "for file: \""+fname+'"'; return false; } - mrw::AutoPtr syms(new asymbol*[memsz]); + mrw::AutoPtrAry syms(new asymbol*[memsz]); if (bfd_canonicalize_symtab(const_cast(static_cast(abfd)), syms)<0) { _error = "cannot map bfd symbols - 'bfd_canonicalize_symtab' failed" @@ -339,7 +379,7 @@ std::map mrw::StackTrace::_dic; std::map mrw::StackTrace::_addrs; std::map mrw::StackTrace::_bfd; -std::map > mrw::StackTrace::_syms; +std::map > mrw::StackTrace::_syms; #ifdef _MT boost::recursive_mutex mrw::StackTrace::_mutex; #endif diff --git a/mrw/stacktrace.hpp b/mrw/stacktrace.hpp index 75d0478..57553db 100644 --- a/mrw/stacktrace.hpp +++ b/mrw/stacktrace.hpp @@ -157,6 +157,8 @@ namespace mrw { //................................................................ methods /// the constructor stores the actual stack trace StackTrace() throw(std::bad_exception); + /// depending on how we got the stack trace, we may have to free memory + ~StackTrace() throw(); /// evaluates the symbol table and returns the formatted stack trace operator std::string() const throw(std::bad_exception); /** @return list of raw stack addresses */ @@ -262,7 +264,7 @@ namespace mrw { static std::map _dic; static std::map _addrs; static std::map _bfd; - static std::map > _syms; + static std::map > _syms; #ifdef _MT static boost::recursive_mutex _mutex; #endif diff --git a/mrw/stacktrace_test.cpp b/mrw/stacktrace_test.cpp index 449a864..9e6f441 100644 --- a/mrw/stacktrace_test.cpp +++ b/mrw/stacktrace_test.cpp @@ -26,7 +26,10 @@ namespace mrw { bool init(mrw::StackTrace::createSymtable()); CPPUNIT_ASSERT_MESSAGE("createSymtable() failed! ERROR=" +mrw::StackTrace::error(), - init); + init + || + mrw::StackTrace::error().find("/valgrind/") + !=std::string::npos); mrw::StackTrace s; int l(__LINE__); std::string f(__FILE__); std::stringstream ss; ss< class LIST> - std::string join(const LIST& l, + template class LIST, + typename CONTENTS> + std::string join(const LIST& l, const std::string& delimiter=" ") throw(std::bad_exception) { std::string result; - for (typename LIST::const_iterator it(l.begin()); + for (typename LIST::const_iterator it(l.begin()); it!=l.end(); ++it) result+=(result.size()?delimiter:"")+mrw::string(*it); return result;