diff --git a/ChangeLog b/ChangeLog index 6cdd462..6ce154f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +* Wed Aug 25 2004 Marc Wäckerlin - mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - pissibility to compile without stack trace +* Wed May 28 2004 Marc Wäckerlin - mrw-c++-0.92 (mrw) + - no more mrw:: exceptions in header files, all moved to .cpp + - make distclean now clean everything that was generated + - smartpointer_test.cpp was missing in CVS + - new makefile targets tag and release +* Wed May 19 2004 Marc Wäckerlin - mrw-c++-0.92 (mrw) + - no more auto.cpp +* Tue May 18 2004 Marc Wäckerlin - mrw-c++-0.92 (mrw) + - correct bfd detection on solaris + - templated auto classes + - forgotten to install in 0.91: header arg.hpp and smartpointer.hpp * Tue Apr 27 2004 Marc Wäckerlin - mrw-c++-0.91 (mrw) - mrw/arg.hpp: Command line argument evaluation - mrw/smartpointer.hpp: Smart pointer implementation diff --git a/NEWS b/NEWS index 4418edc..cf3a682 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,4 @@ -New: Command line argument evaluation and SmartPointer - -This is a preliminary release. Especially tests, configure -environment, packages and documentation are not yet finished. It -should already work, even though it may be not yet perfect. - -It is know not to link on Solaris. \ No newline at end of file +Configure can disable stack trace, if you have problems compiling it on your machine. It is also possible to compile without log4cxx. + +New Feature: Templates are now used for automated resource management +New Feature: Command line argument evaluation and SmartPointer \ No newline at end of file diff --git a/README b/README index a252eca..3b528d6 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ -C++ Library for automated C-Library resource management, UNIX -Pipes, simple and secure UNIX system command execution, runtime -stack trace and automated unexpected exception handling. +C++ Library for automated C-Library resource management, UNIX Pipes, +simple and secure UNIX system command execution, runtime stack trace +and automated unexpected exception handling. HTML and PDF documentation is include in the installation (built with Doxygen). diff --git a/bootstrap.sh b/bootstrap.sh index 805ee7d..c3c21b4 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,4 +1,4 @@ #! /bin/sh -make distclean -aclocal && libtoolize --force && automake && autoconf +test -f makefile && make distclean +aclocal && libtoolize --force && automake -a && autoconf diff --git a/configure.in b/configure.in index 7bb7b95..1561876 100644 --- a/configure.in +++ b/configure.in @@ -1,9 +1,34 @@ +## @file +## +## $Id$ +## +## $Date$ +## $Author$ +## +## @copy © Marc Wäckerlin +## @license LGPL, see file COPYING +## +## $Log$ +## Revision 1.6 2004/08/28 16:21:07 marc +## mrw-c++-0.92 (mrw) +## - new file: version.cpp +## - new file header for all sources +## - work around warning in mrw::auto +## - possibility to compile without log4cxx +## - work around bugs in demangle.h and libiberty.h +## - corrections in documentation +## - added simple tracing mechanism +## - more warnings +## - small corrections in Auto<>::Free and a new test for it +## - possibility to compile without stack trace +## + # init AC_INIT([mrw/mrw.hpp.in]) PACKAGENAME=mrw-c++ MAJOR=0 -MINOR=91 -SUPPORT=beta +MINOR=92 +SUPPORT= AM_INIT_AUTOMAKE(@PACKAGENAME@, @MAJOR@.@MINOR@, [marc@waeckerlin.org]) # macros @@ -29,10 +54,12 @@ AC_CHECK_PROG(have_dot, dot, yes, no) AC_CHECK_HEADER(sys/old_procfs.h, [AM_CPPFLAGS=-D__solaris__]) # libraries +AC_CHECK_HEADER(log4cxx/logger.h, [have_log4cxx=yes]) AC_SEARCH_LIBS(cplus_demangle, iberty, [AC_MSG_RESULT([OK])], [AC_MSG_ERROR([Library iberty is required!])]) AC_SEARCH_LIBS(bfd_arch_list, bfd, [AC_MSG_RESULT([OK])], - AC_SEARCH_LIBS(bfd_arch_list, bfd, [AC_MSG_RESULT([OK])], + [ac_cv_search_bfd_arch_list=; + ]AC_SEARCH_LIBS(bfd_arch_list, bfd, [AC_MSG_RESULT([OK])], [AC_MSG_ERROR([BFD library libbfd is required])], [-lintl])) # Arguments @@ -40,12 +67,24 @@ AM_MAINTAINER_MODE AC_ARG_ENABLE(pedantic, [ --enable-pedantic enable all warnings and checks, abort on warnings], [test "$enableval" = "yes" && \ - AM_CXXFLAGS="${AM_CXXFLAGS:-} -pedantic-errors -Wall -W -Wfloat-equal -Wundef -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Wconversion -Wsign-compare -Wmissing-format-attribute -Wno-multichar -Wpacked -Wredundant-decls -Werror"]) -dnl lib: -Wshadow -Wcast-qual + AM_CXXFLAGS="${AM_CXXFLAGS:-} -pedantic-errors -Wall -W -Wfloat-equal -Wundef -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Wconversion -Wsign-compare -Wmissing-format-attribute -Wno-multichar -Wpacked -Wredundant-decls -Werror -Wshadow -Wcast-qual -Wno-ctor-dtor-privacy"]) +dnl problem in libs: -Wshadow -Wcast-qual +dnl auto.hpp: -Wno-ctor-dtor-privacy (removed) AC_ARG_ENABLE(dot, - [ --disable-dot disable dot graphic tools for documentation], + [ --disable-dot disable dot graphic tools for documentation], [have_dot="$enableval"]) test "$enableval" = "yes" && HAVE_DOT="YES" || HAVE_DOT="NO"; +AC_ARG_ENABLE(log4cxx, + [ --disable-log4cxx disable use of log4cxx library in automated + stack trace], + [have_log4cxx="$enableval"]) +AM_CONDITIONAL(HAVE_LOG4CXX, test "$have_log4cxx" = "yes") +AC_ARG_ENABLE(stacktrace, + [ --disable-stacktrace disable stack trace, use this if you cannot + compile the library on your system otherwise and + you still want to use the other parts], + [have_stacktrace="$enableval"], [have_stacktrace="yes"]) +AM_CONDITIONAL(HAVE_STACKTRACE, test "$have_stacktrace" = "yes") # export macros AC_SUBST(HAVE_DOT) @@ -58,7 +97,7 @@ AC_SUBST(AM_CPPFLAGS) # create output AC_CONFIG_FILES([makefile mrw-c++.spec mrw-c++-devel.spec - mrw/makefile mrw/doxyfile mrw/mrw.hpp]) + mrw/makefile mrw/doxyfile mrw/mrw.hpp mrw/version.cpp]) AC_OUTPUT # infos and warnings @@ -70,6 +109,9 @@ if test "$have_dot" = "no"; then AC_MSG_WARN([Missing program dot! - when you rebild documentation with make doc, there are no generated images - there are precompiled derieved files in the distribution]); fi - - -AC_MSG_WARN([************** THE FLAGS = ${AM_CXXFLAGS}]); \ No newline at end of file +if test "$have_log4cxx" != "yes"; then +AC_MSG_WARN([Library log4cxx will not be used! + - if you want it, download it from: + http://logging.apache.org/log4cxx]); fi +if test "$have_stacktrace" != "yes"; then +AC_MSG_WARN([mrw::StackTrace is disabled!]); fi diff --git a/makefile.am b/makefile.am index 314f0b3..1cf3d3e 100644 --- a/makefile.am +++ b/makefile.am @@ -1,10 +1,35 @@ +## @file +## +## $Id$ +## +## $Date$ +## $Author$ +## +## @copy © Marc Wäckerlin +## @license LGPL, see file COPYING +## +## $Log$ +## Revision 1.6 2004/08/28 16:21:07 marc +## mrw-c++-0.92 (mrw) +## - new file: version.cpp +## - new file header for all sources +## - work around warning in mrw::auto +## - possibility to compile without log4cxx +## - work around bugs in demangle.h and libiberty.h +## - corrections in documentation +## - added simple tracing mechanism +## - more warnings +## - small corrections in Auto<>::Free and a new test for it +## - possibility to compile without stack trace +## + SUBDIRS = mrw EXTRA_DIST = bootstrap.sh nobase_include_HEADERS = mrw/auto.hpp mrw/unistd.hpp \ mrw/stacktrace.hpp mrw/exception.hpp \ - mrw/exec.hpp + mrw/exec.hpp mrw/arg.hpp mrw/smartpointer.hpp infosdir = ${pkgdatadir} infos_DATA = AUTHORS NEWS README COPYING INSTALL ChangeLog \ @PACKAGENAME@.spec @PACKAGENAME@-devel.spec @@ -12,15 +37,29 @@ infos_DATA = AUTHORS NEWS README COPYING INSTALL ChangeLog \ RPMS = /usr/src/packages/RPMS/i586/@PACKAGENAME@-@MAJOR@.@MINOR@-1.i586.rpm \ /usr/src/packages/RPMS/i586/@PACKAGENAME@-devel-@MAJOR@.@MINOR@-1.i586.rpm +release: rpm tag webserver + +tag: + cvs ci -R . + cvs tag -FR REL_@PACKAGENAME@-@MAJOR@-@MINOR@ . + rpm: dist cp @PACKAGENAME@-@MAJOR@.@MINOR@.tar.gz /usr/src/packages/SOURCES/ rpmbuild -bb --clean @PACKAGENAME@.spec rpmbuild -bb --clean @PACKAGENAME@-devel.spec webserver: all check dist ${RPMS} - ssh root@waeckerlin.org mkdir -p /home/marc/mrw-c++ + ssh root@waeckerlin.org bash -c \ + '"rm -r /home/marc/mrw-c++; mkdir -p /home/marc/mrw-c++"' scp mrw/doc/html/* \ mrw/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.pdf \ @PACKAGENAME@-@MAJOR@.@MINOR@.tar.gz \ ${RPMS} \ root@waeckerlin.org:/home/marc/mrw-c++/ + +distclean-local: + - find . -name '*~' | xargs rm + - rm -r autom4te.cache + - rm aclocal.m4 config.guess config.sub configure \ + depcomp install-sh ltmain.sh makefile makefile.in \ + missing mkinstalldirs diff --git a/mrw-c++-devel.spec.in b/mrw-c++-devel.spec.in index 9f73928..d672606 100644 --- a/mrw-c++-devel.spec.in +++ b/mrw-c++-devel.spec.in @@ -1,3 +1,28 @@ +## @file +## +## $Id$ +## +## $Date$ +## $Author$ +## +## @copy © Marc Wäckerlin +## @license LGPL, see file COPYING +## +## $Log$ +## Revision 1.2 2004/08/28 16:21:07 marc +## mrw-c++-0.92 (mrw) +## - new file: version.cpp +## - new file header for all sources +## - work around warning in mrw::auto +## - possibility to compile without log4cxx +## - work around bugs in demangle.h and libiberty.h +## - corrections in documentation +## - added simple tracing mechanism +## - more warnings +## - small corrections in Auto<>::Free and a new test for it +## - possibility to compile without stack trace +## + # rpmbuild -bb --clean @PACKAGENAME@.spec Summary: MRW's C++ Class Library, facilities for ease and quality Name: @PACKAGENAME@-devel diff --git a/mrw-c++.spec.in b/mrw-c++.spec.in index 69d9927..89ce497 100644 --- a/mrw-c++.spec.in +++ b/mrw-c++.spec.in @@ -1,3 +1,28 @@ +## @file +## +## $Id$ +## +## $Date$ +## $Author$ +## +## @copy © Marc Wäckerlin +## @license LGPL, see file COPYING +## +## $Log$ +## Revision 1.2 2004/08/28 16:21:07 marc +## mrw-c++-0.92 (mrw) +## - new file: version.cpp +## - new file header for all sources +## - work around warning in mrw::auto +## - possibility to compile without log4cxx +## - work around bugs in demangle.h and libiberty.h +## - corrections in documentation +## - added simple tracing mechanism +## - more warnings +## - small corrections in Auto<>::Free and a new test for it +## - possibility to compile without stack trace +## + # rpmbuild -bb --clean @PACKAGENAME@.spec Summary: MRW's C++ Class Library, facilities for ease and quality Name: @PACKAGENAME@ diff --git a/mrw/arg.hpp b/mrw/arg.hpp index 8571ee9..2d3bb90 100644 --- a/mrw/arg.hpp +++ b/mrw/arg.hpp @@ -1,7 +1,30 @@ -#include +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.2 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include -#include #include // exit #include #include @@ -125,7 +148,7 @@ namespace mrw { bool theBoolean = args[3]->toBool(); @endcode - @section argParts Setup Command Line from Different Program Parts +

Setup Command Line from Different Program Parts

If your software is large and splitted into different parts (or sub projects or modules, ...), all with their own parameter, you @@ -180,19 +203,15 @@ namespace mrw { @throw mrw::bad_cast if the instance is not a string @return the string, if the instance is a string */ - virtual const std::string& toString() const throw(mrw::exception) { - throw mrw::bad_cast(); - } + virtual const std::string& toString() const throw(std::exception); /** @brief If the instance is an @c int, return that integer, otherwise throw an exception. @throw mrw::bad_cast if the instance is not a integer @return the integer, if the instance is a integer */ - virtual int toInt() const throw(mrw::exception) { - throw mrw::bad_cast(); - } - + virtual int toInt() const throw(std::exception); + /** @brief If the instance is an @c bool, return that boolean, otherwise throw an exception. @note the following typings are converted to @c true: @@ -203,19 +222,19 @@ namespace mrw { @throw mrw::bad_cast if the instance is not a boolean @return the boolean, if the instance is a boolean */ - virtual bool toBool() const throw(mrw::exception) { - throw mrw::bad_cast(); - } + virtual bool toBool() const throw(std::exception); /// @brief returns a printable representation of the value - virtual std::string printable() const throw(mrw::bad_exception) = 0; + virtual std::string printable() const throw(std::bad_exception) = 0; /// @brief returns a printable typename of the value - virtual const std::string& typestr() const throw(mrw::bad_exception)=0; + virtual const std::string& typestr() const throw(std::bad_exception)=0; protected: - friend class Args; // allow assign for Param - virtual void operator=(const std::string&) throw(mrw::exception) = 0; + /// Allow assign for Args, make it a friend. + friend class Args; + /// Only the class itself and friends (Args) are allowed to assign. + virtual void operator=(const std::string&) throw(std::exception) = 0; }; private: @@ -223,20 +242,20 @@ namespace mrw { class StringValue: public Value { public: virtual ~StringValue() {} - StringValue(const std::string& s) throw(mrw::bad_exception): _s(s) { + StringValue(const std::string& s) throw(std::bad_exception): _s(s) { } - virtual const std::string& toString() const throw(mrw::exception) { + virtual const std::string& toString() const throw(std::exception) { return _s; } - virtual const std::string& typestr() const throw(mrw::bad_exception) { + virtual const std::string& typestr() const throw(std::bad_exception) { static std::string name("string"); return name; } - virtual std::string printable() const throw(mrw::bad_exception) { + virtual std::string printable() const throw(std::bad_exception) { return _s; } protected: - virtual void operator=(const std::string& s) throw(mrw::exception) { + virtual void operator=(const std::string& s) throw(std::exception) { _s = s; } private: @@ -246,22 +265,20 @@ namespace mrw { class IntValue: public Value { public: virtual ~IntValue() {} - IntValue(int i) throw(mrw::bad_exception): _i(i) { + IntValue(int i) throw(std::bad_exception): _i(i) { } - virtual int toInt() const throw(mrw::exception) { + virtual int toInt() const throw(std::exception) { return _i; } - virtual const std::string& typestr() const throw(mrw::bad_exception) { + virtual const std::string& typestr() const throw(std::bad_exception) { static std::string name("integer"); return name; } - virtual std::string printable() const throw(mrw::bad_exception) { + virtual std::string printable() const throw(std::bad_exception) { return ((std::stringstream&)(std::stringstream()<<_i)).str(); } protected: - virtual void operator=(const std::string& s) throw(mrw::exception) { - if (!(std::stringstream(s)>>_i)) throw mrw::bad_cast(); - } + virtual void operator=(const std::string& s) throw(std::exception); private: int _i; }; @@ -269,20 +286,20 @@ namespace mrw { class BoolValue: public Value { public: virtual ~BoolValue() {} - BoolValue(bool b) throw(mrw::bad_exception): _b(b) { + BoolValue(bool b) throw(std::bad_exception): _b(b) { } - virtual bool toBool() const throw(mrw::exception) { + virtual bool toBool() const throw(std::exception) { return _b; } - virtual const std::string& typestr() const throw(mrw::bad_exception) { + virtual const std::string& typestr() const throw(std::bad_exception) { static std::string name("boolean (\"yes\" or \"no\")"); return name; } - virtual std::string printable() const throw(mrw::bad_exception) { + virtual std::string printable() const throw(std::bad_exception) { return _b?"yes":"no"; } protected: - virtual void operator=(const std::string& s) throw(mrw::exception) { + virtual void operator=(const std::string& s) throw(std::exception) { _b = s=="true" || s=="yes" || s=="on"; } private: @@ -300,25 +317,25 @@ namespace mrw { } /// @brief add one more mandatory string parameter - Param& operator<<(const char* const s) throw(mrw::bad_exception) { + Param& operator<<(const char* const s) throw(std::bad_exception) { _params.push_back(new StringValue(s)); return *this; } /// @brief add one more mandatory string parameter - Param& operator<<(const std::string& s) throw(mrw::bad_exception) { + Param& operator<<(const std::string& s) throw(std::bad_exception) { _params.push_back(new StringValue(s)); return *this; } /// @brief add one more mandatory integer parameter - Param& operator<<(int i) throw(mrw::bad_exception) { + Param& operator<<(int i) throw(std::bad_exception) { _params.push_back(new IntValue(i)); return *this; } // @brief add one more mandatory boolean parameter - Param& operator<<(bool b) throw(mrw::bad_exception) { + Param& operator<<(bool b) throw(std::bad_exception) { _params.push_back(new BoolValue(b)); return *this; } @@ -326,26 +343,15 @@ namespace mrw { /** @brief get parameter number @i @throw mrw::out_of_range if @c i is too big */ const mrw::SmartPointer& operator[](unsigned int i) const - throw(mrw::exception) { - if (i<_params.size()) return _params[i]; - throw mrw::out_of_range - (((std::stringstream&) - (std::stringstream()<<"check failed: " - <& setable(unsigned int i) - throw(mrw::exception) { - if (i<_params.size()) return _params[i]; - throw mrw::out_of_range - (((std::stringstream&) - (std::stringstream()<<"check failed: " - <& setable(unsigned int i) throw(std::exception); }; /** @brief this class represents one command line option @@ -369,13 +375,13 @@ namespace mrw { @param shortname short name of the option @param longname long name of the option, must start with "--" @param param the additional parameter - @param help the help string for this option + @param helptext the help string for this option */ - Opt::Opt(const char shortname, const std::string& longname, - const Param& param, const std::string& help) - throw(mrw::bad_exception): + Opt(const char shortname, const std::string& longname, + const Param& param, const std::string& helptext) + throw(std::bad_exception): _set(false), _shortname(shortname), _longname(longname), - _param(param), _help(help) { + _param(param), _help(helptext) { } /** @brief create a simple @c mrw::Opt @@ -385,17 +391,16 @@ namespace mrw { @param shortname short name of the option @param longname long name of the option, must start with "--" - @param help the help string for this option + @param helptext the help string for this option */ - Opt::Opt(const char shortname, const std::string& longname, - const std::string& help) - throw(mrw::bad_exception): + Opt(const char shortname, const std::string& longname, + const std::string& helptext) throw(std::bad_exception): _set(false), _shortname(shortname), _longname(longname), - _help(help) { + _help(helptext) { } /** @brief get the help text for this option */ - const std::string& help() const throw(mrw::bad_exception) { + const std::string& help() const throw(std::bad_exception) { return _help; } @@ -423,17 +428,19 @@ namespace mrw { @return a smart pointer to the value (default or given by the user) */ const mrw::SmartPointer& operator[](unsigned int i) const - throw(mrw::exception) { + throw(std::exception) { return _param[i]; } private: - - friend class Args; // is allowed to set values - void set() const throw(mrw::bad_exception) { + + /// Allow set values, make Args a friend. + friend class Args; + /// Set @c _set to true, available only for friends (Args). + void set() const throw(std::bad_exception) { _set = true; } - Param& args() const throw(mrw::bad_exception) { + Param& args() const throw(std::bad_exception) { return _param; } mutable bool _set; @@ -469,7 +476,7 @@ namespace mrw { typedef std::list OtherArgs; /// @brief get the one and only instance - static Args& instance() throw(mrw::bad_exception) { // singleton + static Args& instance() throw(std::bad_exception) { // singleton static Args _instance; return _instance; } @@ -485,15 +492,7 @@ namespace mrw { <second; - } + const Opt& find(char c) const throw(std::exception); /** @brief get an option, given the long option name @throw mrw::out_of_range if the option does not exist */ - const Opt& find(const std::string& s) const throw(mrw::exception) { - LongOpts::const_iterator it(_longopts.find(s)); - if (it==_longopts.end()) throw mrw::out_of_range(s); - return *it->second; - } - + const Opt& find(const std::string& s) const throw(std::exception); + /** @brief get all non interpreted options All user options that don't fit the defined and interpreted @@ -603,7 +590,7 @@ namespace mrw { } /** @brief get the file name of the executable, that's @c argv[0] */ - const std::string& filename() throw(mrw::bad_exception) { + const std::string& filename() throw(std::bad_exception) { return _filename; } @@ -630,48 +617,12 @@ namespace mrw { } private: - Args& parse(int argc, const char*const*const argv) throw(mrw::exception) { - if (argc>0) _filename = argv[0]; - for (int i(1); isecond->args().size()>=argc) - throw mrw::invalid_argument(arg); - it->second->set(); - for (int j(0), l(it->second->args().size()); jsecond->args().setable(j)) = argv[++i]; - } - } else if (arg.find("-")==0) { // short arguments - // first check all, then set all - for (int j(1), l(arg.size()); jsecond->args().size()>0 && - (j+1!=l || i+it->second->args().size()>=argc)) - throw mrw::invalid_argument(arg); - } - for (int j(1), l(arg.size()); jsecond->set(); - if (j+1==l && it->second->args().size()>0) { - for (int k(0); k < it->second->args().size(); ++k) { - *(it->second->args().setable(k)) = argv[++i]; - } - } - } - } else { - if (arg!="--") _otherargs.push_back(arg); - while (++i Options; typedef std::map ShortOpts; typedef std::map LongOpts; - Args(): _argc(-1), _help(0) {} // singleton - Args& operator=(const Args&); // singleton, not implemented std::string _filename; Options _options; ShortOpts _shortopts; diff --git a/mrw/auto.hpp b/mrw/auto.hpp index eba4375..b903b8e 100644 --- a/mrw/auto.hpp +++ b/mrw/auto.hpp @@ -1,9 +1,38 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.3 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #ifndef __MRW_AUTO_HPP__ #define __MRW_AUTO_HPP__ #include // size_t -#include // PROT_READ, MAP_SHARED -#include // bfd* +#include // munmap, PROT_READ, MAP_SHARED +#include + +// forward +class bfd; +extern "C" int bfd_close(bfd*); namespace mrw { @@ -18,126 +47,183 @@ namespace mrw { */ //@{ - /** @brief Automatically closes a file when destructed. + /** @brief Automatically frees a resource when destructed. @pre #include - AutoFile works exactly like std::auto_ptr, but not for files - instead of pointers. Whenever the context of AutoFile is left, - the opened file is close. This way, resources are freed even in - case of exceptions. + AutoResource works exactly like std::auto_ptr, but for any + resource instead of new allocated pointers. Whenever the context + of AutoResource is left, the resource is freed by a call to the + given function. This way, resources are freed even in case of + exceptions. + + Declare an automated file descriptor handler, a BFD handler and + a @c malloc-/ @c free handler (all these typedefs are already + part of the library): + + @code + typedef mrw::AutoResource AutoFile; + typedef mrw::AutoResource AutoBfd; + template class Auto { + public: + typedef mrw::AutoResource Free; + }; + @endcode + + @param RESOURCE_TYPE type of the resorce to manage + @param FUNCTION_PTR type of the function that frees the resource + @param FREE_FUNCTION the function that frees the resource + @param INITIAL_VALUE_TYPE type of the initial value + (pointers may have to be initialized by an integer) + @param INITIAL_VALUE value when the resource is unassigned + @param FREE_TYPE type to free, if cast is needed */ - class AutoFile { + template + class AutoResource { public: - /// @brief Construct from an opened file. - /// @note Don't close @c fd - explicit AutoFile(int fd = -1) throw(): _fd(fd) {} - /// @brief Takeover ownership from another AutoFile. - AutoFile(AutoFile& o) throw(): _fd(o.release()) {} - /// @brief Closes file if open. - ~AutoFile() throw() {reset();} - /// @brief Assign new file descriptor. - /// The old file of @c this is closed if open. - AutoFile& operator=(int fd) throw() {return reset(fd);} - /// @brief Takeover ownership from another AutoFile. - /// The old file of @c this is closed if open. - AutoFile& operator=(AutoFile& other) throw() { + /// @brief Construct from an allocated resource. + /// The resource is freed if necessary. + /// AutoResource takes over ownership of the resource. + explicit AutoResource(FREE_TYPE res = INITIAL_VALUE) + throw(std::bad_exception): _res((RESOURCE_TYPE)res) { + } + /// @brief Takeover ownership from another AutoResource. + AutoResource(AutoResource& o) throw(std::bad_exception): + _res(o.release()) { + } + /// @brief Free resource. Calls @c reset(). + ~AutoResource() throw(std::bad_exception) {reset();} + /// @brief Assign new resource. Calls @c reset(). + /// The resource is freed if necessary. + AutoResource& operator=(RESOURCE_TYPE res) throw(std::bad_exception) { + return reset(res); + } + /// @brief Takeover ownership from another AutoResorce. + /// Calls @c reset() from @c this and @c release() from @c other. + AutoResource& operator=(AutoResource& other) throw(std::bad_exception) { return reset(other.release()); } - /// @brief get the file descriptor @return file descriptor - operator const int() const throw() { - return _fd; + /// @brief Get the resource. + operator const RESOURCE_TYPE&() const throw(std::bad_exception) { + 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). + RESOURCE_TYPE& getClean() throw(std::bad_exception) { + reset(); + 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!=INITIAL_VALUE; + } + /// @brief Give away ownership of the resource. + /// @return old resource + RESOURCE_TYPE release() throw(std::bad_exception) { + RESOURCE_TYPE res(_res); _res=INITIAL_VALUE; + return res; } - /// @brief Give away ownership of the file. @return old file descriptor - int release() throw() { - int ret(_fd); _fd=-1; - return ret; + /// @brief Assign a new resorce. + /// The old resource of @c this is freed if necessary. + AutoResource& reset(RESOURCE_TYPE res = INITIAL_VALUE) + throw(std::bad_exception) { + if (_res!=INITIAL_VALUE) (*FREE_FUNCTION)((FREE_TYPE)_res); + _res = res; + return *this; } - /// @brief assign a new file descriptor - /** The old file of @c this is closed if open. */ - AutoFile& reset(int = -1) throw(); private: - int _fd; ///< the file descriptor + RESOURCE_TYPE _res; ///< the resource to be managed }; - /** @brief Automatically call @c munmap for mmaped files on destruction. + /** @brief Automatically closes a file when destructed. + @pre #include + + AutoFile works exactly like std::auto_ptr, but for files + instead of pointers. Whenever the context of AutoFile is left, + the opened file is close. This way, resources are freed even in + case of exceptions. + */ + typedef mrw::AutoResource AutoFile; + + /** @brief Resorce handle for @c mmap. + + It integrates pointer and size of a memory mapped file similar + to a @c std::pair. + */ + class MMapHandle { + public: + void* first; + size_t second; + /// @brief Constructor that initializes the values through a call to mmap. + MMapHandle(int, size_t=0, void* = 0, + int = PROT_READ, int = MAP_SHARED, off_t = 0) + throw(std::bad_exception); + /// @brief Reset to zero, value of int is ignored. + MMapHandle& operator=(int) throw(std::bad_exception) { + first = 0; second = 0; + return *this; + } + /// @brief Compare to zero, returns true, if i and handle are both zero. + bool operator==(int i) const throw(std::bad_exception) { + return i==0 && first==0 && second==0; + } + }; + inline void munmap(MMapHandle& res) throw(std::bad_exception) { + if (res.first!=0 && res.second>0) + ::munmap(res.first, res.second); + } + /** @brief Automatically calls @c munmap on destruction for mmaped files. @pre #include It's the same as std::auto_ptr, but for @c mmap instead of @c new. When the context of @c AutoMapper is left, @c munmap is called. */ - class AutoMapper { - public: - AutoMapper(void* cont = 0, size_t sz = 0) throw(): - _cont(cont), _sz(sz) {} - AutoMapper(int, size_t=0, void* = 0, - int = PROT_READ, int = MAP_SHARED, off_t = 0) throw(); - ~AutoMapper() throw(); - operator const void*() const throw() {return _cont;} - AutoMapper& set(void* cont, size_t sz) throw() { - _cont=cont; _sz=sz; - return *this; - } - void* release() throw() { - void* ret(_cont); _cont=0; _sz=0; - return ret; - } - const void* last() const throw() { - return _cont && _sz ? (void*)((size_t)_cont+_sz-1) : 0; - } - private: - void* _cont; - size_t _sz; - }; + typedef mrw::AutoResource + AutoMapper; - /** @brief Automatically call @c bfd_close for @c bfd*. + /** @brief Automatically calls @c bfd_close for @c bfd*. @pre #include It acts like a @c std::auto_ptr, but for @c bfd*, that means it calls @c bfd_close whenever the context is left. */ - class AutoBfd { - public: - AutoBfd(bfd* p=0) throw(): _bfd(p) {} - ~AutoBfd() throw() {if (_bfd) bfd_close(_bfd);} - AutoBfd& operator=(bfd* p) throw() { - release(); _bfd=p; return *this; - } - AutoBfd& operator=(AutoBfd& o) throw() { - release(); _bfd=o.release(); return *this; - } - operator bfd*() throw() {return _bfd;} - bfd* operator->() throw() {return _bfd;} - bfd* release() throw() {bfd* res(_bfd); _bfd = 0; return res;} - private: - bfd* _bfd; - }; + typedef mrw::AutoResource AutoBfd; /** @brief Automatically calls @c free for @c malloc allocated memory. + Instanciate it as @c mrw::Auto::Free. @pre #include It works like a @c std::auto_ptr, but for memory that was allocated with @c malloc, not @c new. Memory is freed, whenever the context od @c AutoFree is left. + + @code + { // enter context + Auto::Free cp = (char*)malloc(5); + cp.getClean() = (char*)malloc(10); // old storage of 5 bytes is freed + } // memory is freed on destruction of cp + @endcode */ - template class AutoFree { - public: - AutoFree(T* p=0) throw(): _p(p) {} - AutoFree(AutoFree& o) throw(): _p(o.release()) {} - ~AutoFree() throw() {if (_p) free(_p);} - AutoFree& operator=(T* p) throw() { - release(); _p=p; return *this; - } - AutoFree& operator=(AutoFree& o) throw() { - release(); _p=o.release(); return *this; - } - operator T*() {return _p;} - operator T**() {return &_p;} - operator bool() {return _p;} - T* release() throw() {T* r(_p); _p=0; return r;} - private: - T* _p; + template class Auto { + public: + typedef mrw::AutoResource Free; + private: + /** @internal + work around compiler warning: + "only defines private constructors and has no friends" */ + friend class ThisIsADummyToEliminateWarnings; + /// Forbidden to instanciate. + Auto(); Auto(const Auto&); }; + //@} } #endif diff --git a/mrw/auto_test.cpp b/mrw/auto_test.cpp index a7e9a8c..8c5f4ba 100644 --- a/mrw/auto_test.cpp +++ b/mrw/auto_test.cpp @@ -1,9 +1,35 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.3 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include #include #include #include // open +#include // strncpy class AutoTest: public CppUnit::TestFixture { public: @@ -18,10 +44,10 @@ public: mrw::AutoFile b(a); CPPUNIT_ASSERT(a==-1 && i==b); // b has taken ownership CPPUNIT_ASSERT(read(b, &c, 1)==1 && c=='H'); // file is good - mrw::AutoFile c(i); - CPPUNIT_ASSERT(i==b && b==c); // ooops, two owner! - c.release(); - CPPUNIT_ASSERT(i==b && c==-1); // it's ok now + mrw::AutoFile cc(i); + CPPUNIT_ASSERT(i==b && b==cc); // ooops, two owner! + cc.release(); + CPPUNIT_ASSERT(i==b && cc==-1); // it's ok now b = open("test.dat", O_RDONLY); //close(i); CPPUNIT_ASSERT(read(i, &c, 1)==-1); // old file is closed @@ -31,8 +57,18 @@ public: } CPPUNIT_ASSERT(read(i, &c, 1)==-1); // file is closed now } + void AutoFree() { + const char C[] = "Hello World"; + mrw::Auto::Free c(malloc(sizeof(C))); + CPPUNIT_ASSERT(c); + strncpy(c, C, sizeof(C)); + CPPUNIT_ASSERT(std::string(c)==C); + c.release(); + CPPUNIT_ASSERT(c==0); + } CPPUNIT_TEST_SUITE(AutoTest); CPPUNIT_TEST(AutoFile); + CPPUNIT_TEST(AutoFree); CPPUNIT_TEST_SUITE_END(); }; CPPUNIT_TEST_SUITE_REGISTRATION(AutoTest); diff --git a/mrw/autostacktracelog4cxx.cpp b/mrw/autostacktracelog4cxx.cpp index 4adb105..b9d05e8 100644 --- a/mrw/autostacktracelog4cxx.cpp +++ b/mrw/autostacktracelog4cxx.cpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.2 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include @@ -27,9 +52,6 @@ namespace mrw { */ //@{ - /// The log4cxx logger where the trace is written to. - static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw")); - /** @brief unexpected handler, that traces using log4cxx The unexpected handler is installed automatically when you link @@ -38,19 +60,21 @@ namespace mrw { @code void unexpected_log4cxx() { + log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw")); logger->fatal("Unexpected Exception", __FILE__, __LINE__); + StackTrace::createSymtable(); + std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { - StackTrace::createSymtable(); logger->fatal(std::string("Reason:\n")+x.what() - +"\nStack:+\n"+x.stacktrace()); + +"\nStack:+\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() - +"\nStack: **** not available ****"); + +"\nStack:\n"+st); } catch (...) { - logger->fatal(std::string("Reason: **** not available ****\n") - +"\nStack: **** not available ****"); + logger->fatal(std::string("Reason: **** not available ****") + +"\nStack:\n"+st); } throw std::bad_exception(); } @@ -58,19 +82,21 @@ namespace mrw { */ void unexpected_log4cxx() { + log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw")); logger->fatal("Unexpected Exception", __FILE__, __LINE__); + StackTrace::createSymtable(); + std::string st((std::string)StackTrace()); try { throw; } catch (const mrw::exception& x) { - StackTrace::createSymtable(); logger->fatal(std::string("Reason:\n")+x.what() - +"\nStack:+\n"+x.stacktrace()); + +"\nStack:+\n"+x.stacktrace()); } catch (const std::exception& x) { logger->fatal(std::string("Reason:\n")+x.what() - +"\nStack: **** not available ****"); + +"\nStack:\n"+st); } catch (...) { - logger->fatal(std::string("Reason: **** not available ****\n") - +"\nStack: **** not available ****"); + logger->fatal(std::string("Reason: **** not available ****") + +"\nStack:\n"+st); } throw std::bad_exception(); } diff --git a/mrw/autostacktracestderr.cpp b/mrw/autostacktracestderr.cpp index f956361..082a98d 100644 --- a/mrw/autostacktracestderr.cpp +++ b/mrw/autostacktracestderr.cpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.3 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include diff --git a/mrw/doxyfile.in b/mrw/doxyfile.in index cc430d8..c119dea 100644 --- a/mrw/doxyfile.in +++ b/mrw/doxyfile.in @@ -9,6 +9,19 @@ ## @license LGPL, see file COPYING ## ## $Log$ +## Revision 1.7 2004/08/28 16:21:25 marc +## mrw-c++-0.92 (mrw) +## - new file: version.cpp +## - new file header for all sources +## - work around warning in mrw::auto +## - possibility to compile without log4cxx +## - work around bugs in demangle.h and libiberty.h +## - corrections in documentation +## - added simple tracing mechanism +## - more warnings +## - small corrections in Auto<>::Free and a new test for it +## - possibility to compile without stack trace +## ## Revision 1.6 2004/08/25 15:26:18 marc ## new file header ## @@ -879,7 +892,7 @@ INCLUDE_FILE_PATTERNS = # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. -PREDEFINED = +PREDEFINED = HAVE_STACKTRACE # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/mrw/exception.cpp b/mrw/exception.cpp index ded4a55..0a00f08 100644 --- a/mrw/exception.cpp +++ b/mrw/exception.cpp @@ -1,5 +1,40 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.2 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include -#include + +#ifdef HAVE_STACKTRACE +# include +#else + namespace mrw { + class StackTrace { + public: + operator std::string() throw() {return "";} + }; + } +#endif namespace mrw { exception::exception() throw(std::bad_exception): diff --git a/mrw/exception.hpp b/mrw/exception.hpp index e6bdaeb..e1e073a 100644 --- a/mrw/exception.hpp +++ b/mrw/exception.hpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.4 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #ifndef __MRW_EXCEPTION_HPP__ #define __MRW_EXCEPTION_HPP__ @@ -51,10 +76,20 @@ namespace mrw { @subsection excsug Suggested Exception Handling Rules -# derieve all your exceptions from mrw::exception - -# write exception specifications as follows: - - if any exception is thrown, specify @c throw(mrw::exception) + -# write exception specifications as follows: @n + (this specification is "binary", it only declares whether an exception + is thrown or not, but it does not specify which exact exception can + be thrown) - if no exception is thrown, specify @c throw(std::bad_exception) - -# document the exact exception thrown with Doxygen's \@throw tag + instead of @c throw() as you would normally specify + - if any exception is thrown specify @c throw(std::exception) @n + (@b Note: If you need a more specific declaration, you must also + declare @c std::bad_exception in addition to your exceptions!) + - only declare @c throw() if you are 100% sure, that it is absolutely + impossible that this method ever throws an exception, that means + this method calls no other function or method (not even from a + system library) that does not declare @c throw() + -# document the exact exception thrown with Doxygen's @c \@throw tag -# write an unexpected handler as follows (or link to a @ref AutoTrace "library"): @@ -164,7 +199,7 @@ call of fn0 successful ... } @endcode - */ + */ class exception: public std::exception { public: exception() throw(std::bad_exception); diff --git a/mrw/exec.cpp b/mrw/exec.cpp index b547543..f3fe3c5 100644 --- a/mrw/exec.cpp +++ b/mrw/exec.cpp @@ -1,5 +1,31 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.4 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include +#include #include // waitpid #include // fork, exec #include // memcpy @@ -47,7 +73,7 @@ mrw::Cmd::operator mrw::Exec() const throw(std::bad_exception) { return mrw::Exec(*this); } -mrw::Exec mrw::Cmd::execute(bool throwExc) const throw(mrw::exception) { +mrw::Exec mrw::Cmd::execute(bool throwExc) const throw(std::exception) { return mrw::Exec(*this).execute(throwExc); } @@ -83,13 +109,13 @@ mrw::Exec& mrw::Exec::operator=(const mrw::Exec& e) throw(std::bad_exception) { return *this; } -mrw::Exec& mrw::Exec::execute(bool throwExc) throw(mrw::exception) { +mrw::Exec& mrw::Exec::execute(bool throwExc) throw(std::exception) { /** This method calls @c fork, sets up a pipe connection to pass @c stdout and @c stderr from the child process to the parent process - using mrw::pipe and calls @c execvp to execute the program. */ + using mrw::Pipe and calls @c execvp to execute the program. */ _success = false; _res = _err = ""; - mrw::pipe stdOut, stdErr; + mrw::Pipe stdOut, stdErr; if (!stdOut || !stdErr) throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd); pid_t pid(fork()); @@ -131,13 +157,13 @@ mrw::Exec& mrw::Exec::execute(bool throwExc) throw(mrw::exception) { return *this; } -mrw::Exec& mrw::Exec::operator>>(std::string& res) throw(mrw::exception) { +mrw::Exec& mrw::Exec::operator>>(std::string& res) throw(std::exception) { execute(); res += _res; return *this; } -mrw::Exec::operator std::string&() throw(mrw::exception) { +mrw::Exec::operator std::string&() throw(std::exception) { if (!_success) execute(); return _res; } @@ -146,12 +172,12 @@ mrw::Exec::operator bool() throw(std::bad_exception) { return _success; } -std::string& mrw::Exec::result() throw(mrw::exception) { +std::string& mrw::Exec::result() throw(std::exception) { if (!_success) execute(); return _res; } -std::string& mrw::Exec::error() throw(mrw::exception) { +std::string& mrw::Exec::error() throw(std::exception) { if (!_success) execute(); return _err; } diff --git a/mrw/exec.hpp b/mrw/exec.hpp index 80a5c2a..9ef811c 100644 --- a/mrw/exec.hpp +++ b/mrw/exec.hpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.3 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #ifndef __MRW_EXEC_HPP__ #define __MRW_EXEC_HPP__ @@ -116,7 +141,7 @@ namespace mrw { - if given parameter is @c true (the default) also if the executed program terminates with an error */ - Exec& execute(bool=true) throw(mrw::exception); + Exec& execute(bool=true) throw(std::exception); /** @brief Executes the command if not done, streams @c stdout into a string @@ -127,7 +152,7 @@ namespace mrw { @throw ExecutionFailedExc in case of any failure or if the executed program does not return a zero exit status. */ - Exec& operator>>(std::string&) throw(mrw::exception); + Exec& operator>>(std::string&) throw(std::exception); /** @brief Executes the command if not done, returns @c stdout as string @@ -140,7 +165,7 @@ namespace mrw { @throw ExecutionFailedExc in case of any failure or if the executed program does not return a zero exit status. */ - operator std::string&() throw(mrw::exception); + operator std::string&() throw(std::exception); /** @return - @c true if the last execution was successful @@ -160,7 +185,7 @@ namespace mrw { @throw ExecutionFailedExc in case of any failure or if the executed program does not return a zero exit status. */ - std::string& result() throw(mrw::exception); + std::string& result() throw(std::exception); /** @brief Executes the command if not done, returns @c stderr as string @@ -173,7 +198,7 @@ namespace mrw { @throw ExecutionFailedExc in case of any failure or if the executed program does not return a zero exit status. */ - std::string& error() throw(mrw::exception); + std::string& error() throw(std::exception); /** @return - @c true if the last execution was successful @@ -231,7 +256,7 @@ namespace mrw { operator std::string() const throw(std::bad_exception); /** @return a mrw::Exec that's constructed with this class */ - operator Exec() const throw(std::bad_exception); + operator mrw::Exec() const throw(std::bad_exception); /** @brief Create a mrw::Exec and execute the command @@ -254,11 +279,13 @@ namespace mrw { - if given parameter is @c true (the default) also if the executed program terminates with an error */ - Exec execute(bool=true) const throw(mrw::exception); + Exec execute(bool=true) const throw(std::exception); private: - friend class Exec; // is allowed to call path() and args() - Cmd(); // no default constructor + /// Exec is allowed to call @c path() and @c args(). + friend class Exec; + /// No default constructor. + Cmd(); const char* path() const throw(std::bad_exception); char** args() const throw(std::bad_exception); typedef std::list ArgList; diff --git a/mrw/exec_test.cpp b/mrw/exec_test.cpp index a082e20..9d4d7db 100644 --- a/mrw/exec_test.cpp +++ b/mrw/exec_test.cpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.4 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include diff --git a/mrw/libmrw.doxytag b/mrw/libmrw.doxytag index a4ba8b4..e581b89 100644 --- a/mrw/libmrw.doxytag +++ b/mrw/libmrw.doxytag @@ -1,9 +1,161 @@ - index - index + + index + moreinfo + download + intro + threads + usage + + + arg.cpp + /privat/home/marc/pro/mrw-c++/mrw/ + arg_8cpp + + + arg.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + arg_8hpp + + + auto.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + auto_8hpp + + int + bfd_close + a0 + (bfd *) + + + + autostacktracelog4cxx.cpp + /privat/home/marc/pro/mrw-c++/mrw/ + autostacktracelog4cxx_8cpp + + + autostacktracestderr.cpp + /privat/home/marc/pro/mrw-c++/mrw/ + autostacktracestderr_8cpp + + + exception.cpp + /privat/home/marc/pro/mrw-c++/mrw/ + exception_8cpp + + + exception.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + exception_8hpp + + + exec.cpp + /privat/home/marc/pro/mrw-c++/mrw/ + exec_8cpp + + + exec.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + exec_8hpp + + + simpletrace.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + simpletrace_8hpp + + #define + METHOD + ga0 + (name) + + + #define + FUNCTION + ga1 + (name) + + + #define + CALL + ga2 + (name) + + + #define + TRACE + ga3 + (text) + + + #define + TRACE_OFF + ga4 + + + + #define + TRACE_ON + ga5 + + + + #define + NO_TRACE + ga6 + + + + + smartpointer.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + smartpointer_8hpp + + + stacktrace.cpp + /privat/home/marc/pro/mrw-c++/mrw/ + stacktrace_8cpp + + #define + HAVE_DECL_BASENAME + a0 + + + + #define + HAVE_DECL_ASPRINTF + a1 + + + + #define + HAVE_DECL_VASPRINTF + a2 + + + + #define + typename + a3 + + + + + stacktrace.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + stacktrace_8hpp + + + unistd.hpp + /privat/home/marc/pro/mrw-c++/mrw/ + unistd_8hpp + + + version.cpp + /privat/home/marc/pro/mrw-c++/mrw/ + version_8cpp license @@ -34,20 +186,43 @@ arguments C++ Evaluation of Command Line Arguments group__arguments.html - mrw::Args - mrw::Opt mrw::Param + mrw::Opt + mrw::Args AutoTools Classes for Automated Resource Handling group__AutoTools.html - mrw::AutoBfd - mrw::AutoFile - mrw::AutoFree - mrw::AutoMapper - mrw::pipe + mrw::AutoResource + mrw::MMapHandle + mrw::Auto mrw::SmartPointer + mrw::Pipe + + mrw::AutoResource< int, int(*)(int),&close, int,-1 > + AutoFile + ga0 + + + + mrw::AutoResource< MMapHandle, void(*)(MMapHandle &),&mrw::munmap, int > + AutoMapper + ga1 + + + + mrw::AutoResource< bfd *, int(*)(bfd *),&bfd_close, int > + AutoBfd + ga2 + + + + void + munmap + ga3 + (MMapHandle &res) + AutoTrace @@ -56,50 +231,257 @@ void unexpected_log4cxx - a1 + ga0 () void unexpected_stderr - a2 + ga1 () + trcstderr + trclog4cxx CmdExec Execute UNIX Commands group__CmdExec.html - mrw::Cmd - mrw::Exec mrw::ExecutionFailedExc + mrw::Exec + mrw::Cmd + + + SimpleTrace + Simple Tracing (for temporary debugging) + group__SimpleTrace.html + mrw + + #define + METHOD + ga0 + (name) + + + #define + FUNCTION + ga1 + (name) + + + #define + CALL + ga2 + (name) + + + #define + TRACE + ga3 + (text) + + + #define + TRACE_OFF + ga4 + + + + #define + TRACE_ON + ga5 + + + + #define + NO_TRACE + ga6 + + StackTrace Collect and Format a Stack Trace group__StackTrace.html AutoTrace + mrw::exception mrw::bad_alloc mrw::bad_cast mrw::bad_exception mrw::bad_typeid + mrw::logic_error mrw::domain_error - mrw::exception mrw::invalid_argument mrw::length_error - mrw::logic_error mrw::out_of_range + mrw::runtime_error mrw::overflow_error mrw::range_error - mrw::runtime_error - mrw::StackTrace mrw::underflow_error + mrw::StackTrace std::ostream & operator<< - a0 + ga0 (std::ostream &os, const StackTrace &st) + excsug + excprob + exc + + + mrw::Param + classmrw_1_1Param.html + + int + size + a0 + () const + + + Param & + operator<< + a1 + (const char *const s) + + + Param & + operator<< + a2 + (const std::string &s) + + + Param & + operator<< + a3 + (int i) + + + Param & + operator<< + a4 + (bool b) + + + const mrw::SmartPointer< Value > & + operator[] + a5 + (unsigned int i) const + + + + mrw::Param::Value + classmrw_1_1Param_1_1Value.html + + virtual const std::string & + toString + a1 + () const + + + virtual int + toInt + a2 + () const + + + virtual bool + toBool + a3 + () const + + + virtual std::string + printable + a4 + () const=0 + + + virtual const std::string & + typestr + a5 + () const=0 + + + virtual void + operator= + b0 + (const std::string &)=0 + + + + mrw::Param::Value + classmrw_1_1Param_1_1Value.html + + virtual const std::string & + toString + a1 + () const + + + virtual int + toInt + a2 + () const + + + virtual bool + toBool + a3 + () const + + + virtual std::string + printable + a4 + () const=0 + + + virtual const std::string & + typestr + a5 + () const=0 + + + virtual void + operator= + b0 + (const std::string &)=0 + + + + mrw::Opt + classmrw_1_1Opt.html + + + Opt + a0 + (const char shortname, const std::string &longname, const Param &param, const std::string &helptext) + + + + Opt + a1 + (const char shortname, const std::string &longname, const std::string &helptext) + + + const std::string & + help + a2 + () const + + + + operator bool + a3 + () const + + + const mrw::SmartPointer< Param::Value > & + operator[] + a4 + (unsigned int i) const + mrw::Args @@ -138,19 +520,19 @@ Args & operator<< a4 - (char help) + (char helpopt) const Opt & find a5 - (char c) const + (char c) const const Opt & find a6 - (const std::string &s) const + (const std::string &s) const const OtherArgs & @@ -178,188 +560,134 @@ - mrw::AutoBfd - classmrw_1_1AutoBfd.html + mrw::AutoResource + classmrw_1_1AutoResource.html + RESOURCE_TYPE + FUNCTION_PTR + FREE_FUNCTION + INITIAL_VALUE_TYPE + INITIAL_VALUE + FREE_TYPE - AutoBfd + AutoResource a0 - (bfd *p=0) + (FREE_TYPE res=INITIAL_VALUE) - AutoBfd & - operator= + + AutoResource + a1 + (AutoResource &o) + + + + ~AutoResource a2 - (bfd *p) + () - AutoBfd & + AutoResource & operator= a3 - (AutoBfd &o) + (RESOURCE_TYPE res) - - operator bfd * + AutoResource & + operator= a4 - () + (AutoResource &other) - bfd * - operator-> + + operator const RESOURCE_TYPE & a5 + () const + + + RESOURCE_TYPE & + getClean + a6 () - bfd * + + operator bool + a7 + () const + + + RESOURCE_TYPE release - a6 + a8 () + + AutoResource & + reset + a9 + (RESOURCE_TYPE res=INITIAL_VALUE) + - mrw::AutoFile - classmrw_1_1AutoFile.html + mrw::MMapHandle + classmrw_1_1MMapHandle.html - AutoFile + MMapHandle a0 - (int fd=-1) + (int, size_t=0, void *=0, int=PROT_READ, int=MAP_SHARED, off_t=0) - - AutoFile + MMapHandle & + operator= a1 - (AutoFile &o) + (int) - - ~AutoFile + bool + operator== a2 - () + (int i) const - - AutoFile & - operator= - a3 - (int fd) - - - AutoFile & - operator= - a4 - (AutoFile &other) - - - - operator const int - a5 - () const - - - int - release - a6 - () + + void * + first + o0 + - - AutoFile & - reset - a7 - (int=-1) + + size_t + second + o1 + - mrw::AutoFree - classmrw_1_1AutoFree.html + mrw::Auto + classmrw_1_1Auto.html T - - - AutoFree - a0 - (T *p=0) - - - - AutoFree - a1 - (AutoFree &o) - - - AutoFree & - operator= - a3 - (T *p) - - - AutoFree & - operator= - a4 - (AutoFree &o) - - - - operator T * - a5 - () - - - - operator T ** - a6 - () - - - - operator bool - a7 - () - - - T * - release - a8 - () + + mrw::AutoResource< T, void(*)(void *),&free, int, 0, void * > + Free + w0 + - mrw::AutoMapper - classmrw_1_1AutoMapper.html - - - AutoMapper - a0 - (void *cont=0, size_t sz=0) - - - - AutoMapper - a1 - (int, size_t=0, void *=0, int=PROT_READ, int=MAP_SHARED, off_t=0) + mrw::exception + classmrw_1_1exception.html + + virtual const char * + what + a2 + () const - - operator const void * + const std::string & + stacktrace a3 - () const - - - AutoMapper & - set - a4 - (void *cont, size_t sz) - - - void * - release - a5 - () - - - const void * - last - a6 - () const + () const @@ -370,7 +698,7 @@ virtual const char * what a0 - () const + () const @@ -381,7 +709,7 @@ virtual const char * what a0 - () const + () const @@ -392,7 +720,7 @@ virtual const char * what a0 - () const + () const @@ -403,47 +731,24 @@ virtual const char * what a0 - () const + () const - mrw::Cmd - classmrw_1_1Cmd.html + mrw::logic_error + classmrw_1_1logic__error.html + mrw::exception - Cmd + logic_error a0 - (const std::string &) + (const std::string &arg) - - Cmd & - operator, + + virtual const char * + what a1 - (const std::string &) - - - Cmd & - operator<< - a2 - (const std::string &) - - - - operator std::string - a3 - () const - - - - operator Exec - a4 - () const - - - Exec - execute - a5 - (bool=true) const + () const @@ -460,104 +765,7 @@ virtual const char * what a1 - () const - - - - mrw::exception - classmrw_1_1exception.html - - virtual const char * - what - a2 - () const - - - const std::string & - stacktrace - a3 - () const - - - - mrw::Exec - classmrw_1_1Exec.html - - - Exec - a0 - (const mrw::Cmd &) - - - - Exec - a1 - (const mrw::Exec &) - - - Exec & - operator= - a3 - (const mrw::Exec &) - - - Exec & - execute - a4 - (bool=true) - - - Exec & - operator>> - a5 - (std::string &) - - - - operator std::string & - a6 - () - - - - operator bool - a7 - () - - - std::string & - result - a8 - () - - - std::string & - error - a9 - () - - - bool - success - a10 - () - - - - mrw::ExecutionFailedExc - classmrw_1_1ExecutionFailedExc.html - mrw::exception - - - ExecutionFailedExc - a0 - (const std::string &, const std::string &) - - - virtual const char * - what - a2 - () const + () const @@ -574,7 +782,7 @@ virtual const char * what a1 - () const + () const @@ -591,16 +799,16 @@ virtual const char * what a1 - () const + () const - mrw::logic_error - classmrw_1_1logic__error.html + mrw::out_of_range + classmrw_1_1out__of__range.html mrw::exception - logic_error + out_of_range a0 (const std::string &arg) @@ -608,50 +816,16 @@ virtual const char * what a1 - () const - - - - mrw::Opt - classmrw_1_1Opt.html - - - Opt::Opt - a0 - (const char shortname, const std::string &longname, const Param &param, const std::string &help) - - - - Opt::Opt - a1 - (const char shortname, const std::string &longname, const std::string &help) - - - const std::string & - help - a2 - () const - - - - operator bool - a3 - () const - - - const mrw::SmartPointer< Param::Value > & - operator[] - a4 - (unsigned int i) const + () const - mrw::out_of_range - classmrw_1_1out__of__range.html + mrw::runtime_error + classmrw_1_1runtime__error.html mrw::exception - out_of_range + runtime_error a0 (const std::string &arg) @@ -659,7 +833,7 @@ virtual const char * what a1 - () const + () const @@ -674,233 +848,164 @@ virtual const char * - what - a1 - () const - - - - mrw::Param - classmrw_1_1Param.html - - int - size - a0 - () const - - - Param & - operator<< - a1 - (const char *const s) - - - Param & - operator<< - a2 - (const std::string &s) - - - Param & - operator<< - a3 - (int i) - - - Param & - operator<< - a4 - (bool b) - - - const mrw::SmartPointer< Value > & - operator[] - a5 - (unsigned int i) const + what + a1 + () const - mrw::Param::Value - classmrw_1_1Param_1_1Value.html + mrw::range_error + classmrw_1_1range__error.html + mrw::exception + + + range_error + a0 + (const std::string &arg) + - virtual const std::string & - toString + virtual const char * + what a1 - () const + () const - - virtual int - toInt - a2 - () const + + + mrw::underflow_error + classmrw_1_1underflow__error.html + mrw::exception + + + underflow_error + a0 + (const std::string &arg) - virtual bool - toBool - a3 - () const - - - virtual std::string - printable - a4 - () const=0 - - - virtual const std::string & - typestr - a5 - () const=0 - - - virtual void - operator= - b0 - (const std::string &)=0 + virtual const char * + what + a1 + () const - mrw::Param::Value - classmrw_1_1Param_1_1Value.html - - virtual const std::string & - toString - a1 - () const + mrw::ExecutionFailedExc + classmrw_1_1ExecutionFailedExc.html + mrw::exception + + + ExecutionFailedExc + a0 + (const std::string &, const std::string &) - virtual int - toInt + virtual const char * + what a2 - () const - - - virtual bool - toBool - a3 - () const - - - virtual std::string - printable - a4 - () const=0 - - - virtual const std::string & - typestr - a5 - () const=0 - - - virtual void - operator= - b0 - (const std::string &)=0 + () const - mrw::pipe - classmrw_1_1pipe.html + mrw::Exec + classmrw_1_1Exec.html - pipe + Exec a0 - () + (const mrw::Cmd &) - ~pipe + Exec a1 - () - - - void - close - a2 - () + (const mrw::Exec &) - void - close_in + Exec & + operator= a3 - () + (const mrw::Exec &) - void - close_out + Exec & + execute a4 - () + (bool=true) - - operator bool + Exec & + operator>> a5 - () + (std::string &) - int - error + + operator std::string & a6 () - void - connect_cout + + operator bool a7 () - void - connect_cerr + std::string & + result a8 () - int - istream + std::string & + error a9 () - int - ostream + bool + success a10 () - mrw::range_error - classmrw_1_1range__error.html - mrw::exception + mrw::Cmd + classmrw_1_1Cmd.html - range_error + Cmd a0 - (const std::string &arg) + (const std::string &) - - virtual const char * - what + + Cmd & + operator, a1 - () const + (const std::string &) + + + Cmd & + operator<< + a2 + (const std::string &) - - - mrw::runtime_error - classmrw_1_1runtime__error.html - mrw::exception - runtime_error - a0 - (const std::string &arg) + operator std::string + a3 + () const - - virtual const char * - what - a1 - () const + + + operator mrw::Exec + a4 + () const + + + Exec + execute + a5 + (bool=true) const @@ -953,19 +1058,19 @@ const TYPE & operator * a9 - () const + () const - TYPE *const + TYPE *const operator-> a10 () - const TYPE *const + const TYPE *const operator-> a11 - () const + () const @@ -993,19 +1098,19 @@ operator std::string a1 - () const + () const operator const AddressTrace & a2 - () const + () const const StackTrace & print a3 - (std::ostream &os) const + (std::ostream &os) const CodePos @@ -1089,20 +1194,73 @@ - mrw::underflow_error - classmrw_1_1underflow__error.html - mrw::exception + mrw::Pipe + classmrw_1_1Pipe.html - underflow_error + Pipe a0 - (const std::string &arg) + () - - virtual const char * - what + + + ~Pipe a1 - () const + () + + + void + close + a2 + () + + + void + close_in + a3 + () + + + void + close_out + a4 + () + + + + operator bool + a5 + () + + + int + error + a6 + () + + + void + connect_cout + a7 + () + + + void + connect_cerr + a8 + () + + + int + istream + a9 + () + + + int + ostream + a10 + () diff --git a/mrw/makefile.am b/mrw/makefile.am index 9dcdcbe..a59e704 100644 --- a/mrw/makefile.am +++ b/mrw/makefile.am @@ -1,51 +1,102 @@ -AM_CPPFLAGS := ${AM_CPPFLAGS} -I.. +## @file +## +## $Id$ +## +## $Date$ +## $Author$ +## +## @copy © Marc Wäckerlin +## @license LGPL, see file COPYING +## +## $Log$ +## Revision 1.6 2004/08/28 16:21:25 marc +## mrw-c++-0.92 (mrw) +## - new file: version.cpp +## - new file header for all sources +## - work around warning in mrw::auto +## - possibility to compile without log4cxx +## - work around bugs in demangle.h and libiberty.h +## - corrections in documentation +## - added simple tracing mechanism +## - more warnings +## - small corrections in Auto<>::Free and a new test for it +## - possibility to compile without stack trace +## + +AM_CPPFLAGS += -I.. + +if HAVE_STACKTRACE + AM_CPPFLAGS += -DHAVE_STACKTRACE +endif CLEANFILES = doxygen.error examplesdir = ${pkgdatadir}/examples examples_DATA = examples/* htmldir = ${pkgdatadir}/doc/html -html_DATA = doc/html/* +html_DATA = doc/html/index.html doc/html/* pdfdir = ${pkgdatadir}/doc/pdf pdf_DATA = doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.pdf EXTRA_DIST = test.dat ${examples_DATA} ${html_DATA} ${pdf_DATA} -lib_LTLIBRARIES = libmrw.la libmrwexcstderr.la libmrwexclog4cxx.la +lib_LTLIBRARIES = libmrw.la +if HAVE_STACKTRACE + lib_LTLIBRARIES += libmrwexcstderr.la +if HAVE_LOG4CXX + lib_LTLIBRARIES += libmrwexclog4cxx.la +endif +endif libmrw_la_SOURCES = mrw.hpp \ - auto.hpp auto.cpp unistd.hpp smartpointer.hpp \ - stacktrace.hpp stacktrace.cpp exception.hpp exception.cpp \ + auto.hpp unistd.hpp smartpointer.hpp \ + exception.hpp exception.cpp \ exec.hpp exec.cpp \ - arg.hpp + arg.hpp arg.cpp version.cpp +if HAVE_STACKTRACE + libmrw_la_SOURCES += stacktrace.hpp stacktrace.cpp +endif libmrw_la_LDFLAGS = -version-info @MAJOR@:@MINOR@ -libmrwexcstderr_la_SOURCES = autostacktracestderr.cpp -libmrwexcstderr_la_LDFLAGS = -version-info @MAJOR@:@MINOR@ -libmrwexcstderr_la_LIBADD = -lmrw +if HAVE_STACKTRACE + libmrwexcstderr_la_SOURCES = autostacktracestderr.cpp version.cpp + libmrwexcstderr_la_LDFLAGS = -version-info @MAJOR@:@MINOR@ + libmrwexcstderr_la_LIBADD = -lmrw -libmrwexclog4cxx_la_SOURCES = autostacktracelog4cxx.cpp -libmrwexclog4cxx_la_LDFLAGS = -version-info @MAJOR@:@MINOR@ -libmrwexclog4cxx_la_LIBADD = -lmrw +if HAVE_LOG4CXX + libmrwexclog4cxx_la_SOURCES = autostacktracelog4cxx.cpp version.cpp + libmrwexclog4cxx_la_LDFLAGS = -version-info @MAJOR@:@MINOR@ + libmrwexclog4cxx_la_LIBADD = -lmrw +endif +endif -check_PROGRAMS = auto_test smartpointer_test exec_test \ - stacktrace_test mrwexcstderr_test mrwexclog4cxx_test -auto_test_SOURCES = auto_test.cpp +check_PROGRAMS = auto_test smartpointer_test exec_test +if HAVE_STACKTRACE + check_PROGRAMS += stacktrace_test mrwexcstderr_test +if HAVE_LOG4CXX + check_PROGRAMS += mrwexclog4cxx_test +endif +endif +auto_test_SOURCES = auto_test.cpp version.cpp auto_test_CPPFLAGS = -I.. -g3 auto_test_LDADD = -lmrw -lcppunit -smartpointer_test_SOURCES = smartpointer_test.cpp +smartpointer_test_SOURCES = smartpointer_test.cpp version.cpp smartpointer_test_CPPFLAGS = -I.. -g3 smartpointer_test_LDADD = -lmrw -lcppunit -exec_test_SOURCES = exec_test.cpp +exec_test_SOURCES = exec_test.cpp version.cpp exec_test_CPPFLAGS = -I.. -g3 exec_test_LDADD = -lmrw -lcppunit -stacktrace_test_SOURCES = stacktrace_test.cpp -stacktrace_test_CPPFLAGS = -I.. -g3 -stacktrace_test_LDADD = -lmrw -lcppunit -mrwexcstderr_test_SOURCES = mrwexcstderr_test.cpp -mrwexcstderr_test_CPPFLAGS = -I.. -g3 -mrwexcstderr_test_LDADD = -lmrwexcstderr -lcppunit -mrwexclog4cxx_test_SOURCES = mrwexclog4cxx_test.cpp -mrwexclog4cxx_test_CPPFLAGS = -I.. -g3 -mrwexclog4cxx_test_LDADD = -lmrwexclog4cxx -lcppunit -llog4cxx +if HAVE_STACKTRACE + stacktrace_test_SOURCES = stacktrace_test.cpp version.cpp + stacktrace_test_CPPFLAGS = -I.. -g3 + stacktrace_test_LDADD = -lmrw -lcppunit + mrwexcstderr_test_SOURCES = mrwexcstderr_test.cpp version.cpp + mrwexcstderr_test_CPPFLAGS = -I.. -g3 + mrwexcstderr_test_LDADD = -lmrwexcstderr -lcppunit +if HAVE_LOG4CXX + mrwexclog4cxx_test_SOURCES = mrwexclog4cxx_test.cpp version.cpp + mrwexclog4cxx_test_CPPFLAGS = -I.. -g3 + mrwexclog4cxx_test_LDADD = -lmrwexclog4cxx -lcppunit -llog4cxx +endif +endif TESTS = ${check_PROGRAMS} deps = ../COPYING ../README ../INSTALL ../NEWS ../ChangeLog @@ -55,3 +106,8 @@ doc/html/index.html: doxyfile *.[ch]pp ${deps} doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.pdf: doxyfile *.[ch]pp ${deps} cd doc/latex && make && \ mv refman.pdf @PACKAGENAME@-@MAJOR@.@MINOR@.pdf +clean-local: + - rm doxygen.err libmrw.doxytag +distclean-local: + - rm -r doc/html/* doc/latex/* + - rm makefile makefile.in doxygen.err libmrw.doxytag diff --git a/mrw/mrw.hpp.in b/mrw/mrw.hpp.in index 34f02e0..f463893 100644 --- a/mrw/mrw.hpp.in +++ b/mrw/mrw.hpp.in @@ -41,6 +41,14 @@ @section moreinfo Additional Information + @section threads Thread Safety + + All classes are not thread safe, that means they should either + always be accessed from the same thread, or you are responsible + for locking. If you need thread safety as a feature, please send + me an email and ask me for it (you find the adress in the package + or on my personal homepage: http://marc.waeckerlin.org). + See the "Related Pages". - @ref license "License Information (LGPL)" diff --git a/mrw/mrwexclog4cxx_test.cpp b/mrw/mrwexclog4cxx_test.cpp index b02d27a..a122f7a 100644 --- a/mrw/mrwexclog4cxx_test.cpp +++ b/mrw/mrwexclog4cxx_test.cpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.2 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include diff --git a/mrw/mrwexcstderr_test.cpp b/mrw/mrwexcstderr_test.cpp index c0bc5d1..d10df8b 100644 --- a/mrw/mrwexcstderr_test.cpp +++ b/mrw/mrwexcstderr_test.cpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.2 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include diff --git a/mrw/simpletrace.hpp b/mrw/simpletrace.hpp index f5a4eed..245f914 100644 --- a/mrw/simpletrace.hpp +++ b/mrw/simpletrace.hpp @@ -1,63 +1,182 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.2 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #ifndef __MRW_SIMPLETRACE_HPP__ #define __MRW_SIMPLETRACE_HPP__ #include #include #include -// GENERIC TRACER FOR TESTS --------------------------------------------------- -// (without file/line) +/** @defgroup SimpleTrace Simple Tracing (for temporary debugging) + @pre #include + + Here is a simple tracing to @c std::cout mechanism for temporary + debugging and simple testing purposes. Might be useful when + experimenting and exploring new C++ language constructs. Please + note that you can only trace in methods and functions that start + with @c METHOD respectively @c FUNCTION. + + Please note that you should not use this simple mechanism for real + projects, only for your experiments! For your work, use + log4cxx! + + The trace of the following code: + + @code + #include + void fn(int i=0) { + FUNCTION; // trace entry and exit + if (!i) TRACE("Hello World, this is a nice text!"); + if (i<4) fn(++i); + } + class A { + public: + A() { + NO_TRACE; // don't trace in constructor + method(); // not traced + } + void method() { + METHOD; // trace entry and exit + CALL(fn()); // trace before call + fn(); + } + }; + int main(int, char**) { + FUNCTION; + CALL(A().method()); + A().method(); + TRACE("No more trace:"); + TRACE_OFF; + A().method(); + TRACE_ON; + TRACE("Back again"); + return 0; + } + @endcode + + Produces this output: + + @verbatim + tmp.cpp:20 0: \ main + tmp.cpp:21 0: -> A().method() + tmp.cpp:14 0xbffff10f: \ method + tmp.cpp:15 0xbffff10f: -> fn() + tmp.cpp:3 0: \ fn + tmp.cpp:4 0: **** Hello World, this is a nice text! **** + tmp.cpp:3 0: \ fn + tmp.cpp:3 0: \ fn + tmp.cpp:3 0: \ fn + tmp.cpp:3 0: \ fn + tmp.cpp:3 0: / fn + tmp.cpp:3 0: / fn + tmp.cpp:3 0: / fn + tmp.cpp:3 0: / fn + tmp.cpp:3 0: / fn + tmp.cpp:14 0xbffff10f: / method + tmp.cpp:23 0: **** No more trace: **** + tmp.cpp:27 0: **** Back again **** + tmp.cpp:20 0: / main + @endverbatim +*/ +//@{ #ifndef __GNUG__ -#define METHOD(name) mrw::FnTrace fnTrace(this, name) -#define FUNCTION(name) mrw::FnTrace fnTrace(0, name) +/// Declare method entrance, place as first line in method. +#define METHOD(name) mrw::FnTrace fnTrace(this, #name, __FILE__, __LINE__) +/// Declare function entrance, place as first line in function. +#define FUNCTION(name) mrw::FnTrace fnTrace(0, #name, __FILE__, __LINE__) #else -#define METHOD mrw::FnTrace fnTrace(this, __FUNCTION__) -#define FUNCTION mrw::FnTrace fnTrace(0, __FUNCTION__) +/// Declare method entrance, place as first line in method. +/// GNU g++ knows the method name. +#define METHOD mrw::FnTrace fnTrace(this, __FUNCTION__, __FILE__, __LINE__) +/// Declare function entrance, place as first line in function. +/// GNU g++ knows the method name. +#define FUNCTION mrw::FnTrace fnTrace(0, __FUNCTION__, __FILE__, __LINE__) #endif -#define CALL(name) fnTrace.call(name) -#define TRACE(name) fnTrace.trace(name) +/// Document the call of another method (before you call it). +#define CALL(name) fnTrace.call(#name, __FILE__, __LINE__) +/// Trace an arbitrary text. +#define TRACE(text) fnTrace.trace(text, __FILE__, __LINE__) +/// Turn all tracing off (from here on). #define TRACE_OFF mrw::FnTrace::off() +/// Turn all tracing off (from here on). #define TRACE_ON mrw::FnTrace::on() +/// Don't trace in this scope (from here on). #define NO_TRACE mrw::NoTrace noTrace; namespace mrw { class FnTrace { public: - FnTrace(const void* addr, const std::string& name): - _addr(addr), _name(name) { + FnTrace(const void* addr, const std::string& name, + const std::string& file, unsigned long line) throw(): + _addr(addr), _name(name), _file(file), _line(line) { if (_off==0) - std::cout< "<0) --_off; } private: const void* _addr; const std::string _name; + const std::string _file; + unsigned long _line; static unsigned int _level; static unsigned int _off; }; @@ -65,8 +184,9 @@ namespace mrw { unsigned int FnTrace::_off(0); class NoTrace { public: - NoTrace() {TRACE_OFF;} - ~NoTrace() {TRACE_ON;} + NoTrace() throw() {TRACE_OFF;} + ~NoTrace() throw() {TRACE_ON;} }; } +//@} #endif diff --git a/mrw/smartpointer.hpp b/mrw/smartpointer.hpp index b693702..585eda5 100644 --- a/mrw/smartpointer.hpp +++ b/mrw/smartpointer.hpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.2 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #ifndef __MRW__SMARTPOINTER_HPP__ #define __MRW__SMARTPOINTER_HPP__ @@ -7,17 +32,17 @@ namespace mrw { private: unsigned int _cnt; public: - PointerCounter(): + PointerCounter() throw(): _cnt(1) { } - PointerCounter* incr() { + PointerCounter* incr() throw() { ++_cnt; return this; } - int decr() { + int decr() throw() { return --_cnt; } - int get() { + int get() throw() { return _cnt; } }; @@ -25,11 +50,11 @@ namespace mrw { class SmartPointerParent { protected: template - PointerCounter* getCounter(TYPE& sp) { + PointerCounter* getCounter(TYPE& sp) throw() { return sp._cnt; } template - typename TYPE::Pointer getPointer(TYPE& sp) { + typename TYPE::Pointer getPointer(TYPE& sp) throw() { return sp._ptr; } }; @@ -68,7 +93,7 @@ namespace mrw { PointerCounter* _cnt; TYPE* _ptr; private: - void drop() { + void drop() throw() { if (_cnt && !_cnt->decr()) { delete _cnt; _cnt=0; delete _ptr; _ptr=0; @@ -78,30 +103,30 @@ namespace mrw { friend class SmartPointerParent; friend class SmartPointerTest; public: - SmartPointer(): + SmartPointer() throw(): _cnt(0), _ptr(0) { } - SmartPointer(const SmartPointer& o): + SmartPointer(const SmartPointer& o) throw(): _cnt(o._cnt?o._cnt->incr():0), _ptr(o._ptr) { } - SmartPointer(TYPE* ptr): + SmartPointer(TYPE* ptr) throw(): _cnt(ptr ? new PointerCounter : 0), _ptr(ptr) { } - template SmartPointer(const SmartPointer& o): + template SmartPointer(const SmartPointer& o) throw(): _cnt(0), _ptr(dynamic_cast(getPointer(o))) { if (_ptr) _cnt = getCounter(o)->incr(); } - ~SmartPointer() { + ~SmartPointer() throw() { drop(); } - SmartPointer& operator=(const SmartPointer& o) { + SmartPointer& operator=(const SmartPointer& o) throw() { if (o._ptr==_ptr) return *this; drop(); _cnt = o._cnt ? o._cnt->incr() : 0; _ptr = o._ptr; return *this; } - SmartPointer& operator=(TYPE* ptr) { + SmartPointer& operator=(TYPE* ptr) throw() { if (ptr==_ptr) return *this; drop(); _cnt = ptr ? new PointerCounter : 0; @@ -109,26 +134,26 @@ namespace mrw { return *this; } template - SmartPointer& operator=(const SmartPointer& o) { + SmartPointer& operator=(const SmartPointer& o) throw() { if (getPointer(o)==_ptr) return *this; drop(); _ptr = dynamic_cast(getPointer(o)); _cnt = _ptr ? getCounter(o)->incr() : 0; return *this; } - TYPE& operator*() { + TYPE& operator*() throw() { return *_ptr; } - const TYPE& operator*() const { + const TYPE& operator*() const throw() { return *_ptr; } - TYPE* const operator->() { + TYPE* const operator->() throw() { return _ptr; } - const TYPE* const operator->() const { + const TYPE* const operator->() const throw() { return _ptr; } - operator bool() { + operator bool() throw() { return _ptr!=0; } }; diff --git a/mrw/stacktrace.cpp b/mrw/stacktrace.cpp index 9e13659..e2fcff8 100644 --- a/mrw/stacktrace.cpp +++ b/mrw/stacktrace.cpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.3 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include @@ -17,7 +42,33 @@ #endif #include extern "C" { -#include + + /// @bug redefined in libiberty.h +# define HAVE_DECL_BASENAME 1 + /// @bug redefined in libiberty.h +# define HAVE_DECL_ASPRINTF 1 + /// @bug redefined in libiberty.h +# define HAVE_DECL_VASPRINTF 1 +/** @bug + + - in file file: /usr/include/demangle.h + - of package: binutils-2.15.90.0.1.1-31 + + An idiot unfortunately abused the C++ keyword @c typename as + variable name to @c cplus_demangle_fill_builtin_type, so I have + to work around it. + */ +# define typename anotherNameThatsNotAKeyword +# include +# undef typename +// // copied from demangle.h because of compiler warnings in libliberty.h +// // (... throws different exception) +// #define DMGL_PARAMS (1 << 0) /* Include function args */ +// #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ +// /// @bug demangle.h includes libiberty.h which throws different +// /// exceptions for the same functions than other standard libraries, +// /// so I can't include demangle.h! +// extern char * cplus_demangle(const char *, int); } #include @@ -31,15 +82,15 @@ namespace mrw { or the MS PE format. These formats have a number of leading '.'s on at least some symbols, so we remove all dots to avoid confusing the demangler. */ - const char* p (name); + const char* p(name); while (p && *p == '.') ++p; - mrw::AutoFree res(cplus_demangle(p, DMGL_ANSI | DMGL_PARAMS)); + Auto::Free res(cplus_demangle(p, DMGL_ANSI | DMGL_PARAMS)); if (res) { /* Now put back any stripped dots. */ - if (p==name) return (char*)res; + if (p==name) return static_cast(res); std::string add_dots('.', p-name); - return add_dots+=(char*)res; + return add_dots+=static_cast(res); } return name; } @@ -118,7 +169,8 @@ namespace mrw { static const char* file(0); static const char* function(0); unsigned int line; - if (!bfd_find_nearest_line(_bfd, (*_dic)[*it].second, _syms.get(), + if (!bfd_find_nearest_line(const_cast(static_cast(_bfd)), + (*_dic)[*it].second, _syms.get(), vma_addr-*it, &file, &function, &line)) return CodePos(addr, "????", "????", 0); return CodePos(addr, mrw::demangle(_bfd, function), file?file:"????", line); @@ -129,13 +181,18 @@ namespace mrw { if (_dic.get()) return true; AutoBfd abfd(bfd_openr((fname!="" ? fname : filename()).c_str(), 0)); long memsz(-1); - AutoFree m(0); + Auto::Free m(0); if (!abfd || bfd_check_format(abfd, bfd_archive) || - !bfd_check_format_matches(abfd, bfd_object, m) || - !(bfd_get_file_flags(abfd)&HAS_SYMS) || - (memsz=bfd_get_symtab_upper_bound(abfd))<0) return false; + !bfd_check_format_matches(abfd, bfd_object, &(m.getClean())) || + !(bfd_get_file_flags(const_cast(static_cast(abfd))) + &HAS_SYMS) || + (memsz=bfd_get_symtab_upper_bound + (const_cast(static_cast(abfd))))<0) + return false; std::auto_ptr syms(new asymbol*[memsz]); - if (bfd_canonicalize_symtab(abfd, syms.get())<0) return false; + if (bfd_canonicalize_symtab(const_cast(static_cast(abfd)), + syms.get())<0) + return false; _bfd = abfd; _syms = syms; _dic = std::auto_ptr(new Translator()); diff --git a/mrw/stacktrace.hpp b/mrw/stacktrace.hpp index 7eb7a4e..a671211 100644 --- a/mrw/stacktrace.hpp +++ b/mrw/stacktrace.hpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.4 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ // g++ -Wall -D__SOLARIS__ -g -I /home/public/freeware/include -L /home/public/freeware/lib -I . stacktrace.cxx -lbfd -liberty #ifndef __MRW_STACKTRACE_HPP__ #define __MRW_STACKTRACE_HPP__ @@ -82,7 +107,7 @@ namespace mrw { @note Symbol evaluation requires the ELF library and an ELF system. - @section sttech Technology +

Technology

On GNU glibc based systems (Linux), the stack trace is collected with GNU glibc's function @c backtrace(). On other systems @@ -103,7 +128,7 @@ namespace mrw { executable file name as an argument to @c mrw::StackTrace::createSymtable(). - @section stdrawbacks Draw Backs +

Draw Backs

Unfortunately it is not possible to extract the source file name and line number information if the executable was not compiled @@ -139,7 +164,7 @@ namespace mrw { StackTrace() throw(std::bad_exception); /// evaluates the symbol table and returns the formatted stack trace operator std::string() const throw(std::bad_exception); - /// @return list of raw stack addresses + /** @return list of raw stack addresses */ operator const AddressTrace&() const throw(std::bad_exception) { return _trace; } diff --git a/mrw/stacktrace_test.cpp b/mrw/stacktrace_test.cpp index 8d841ca..ae1626e 100644 --- a/mrw/stacktrace_test.cpp +++ b/mrw/stacktrace_test.cpp @@ -1,3 +1,28 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.4 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + +*/ #include #include #include diff --git a/mrw/unistd.hpp b/mrw/unistd.hpp index 2a04852..ca08b57 100644 --- a/mrw/unistd.hpp +++ b/mrw/unistd.hpp @@ -1,18 +1,33 @@ /** @file + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + $Log$ + Revision 1.5 2004/08/28 16:21:25 marc + mrw-c++-0.92 (mrw) + - new file: version.cpp + - new file header for all sources + - work around warning in mrw::auto + - possibility to compile without log4cxx + - work around bugs in demangle.h and libiberty.h + - corrections in documentation + - added simple tracing mechanism + - more warnings + - small corrections in Auto<>::Free and a new test for it + - possibility to compile without stack trace + Revision 1.4 2004/08/25 08:35:09 marc change in file header Revision 1.3 2004/08/25 08:22:19 marc added file header - - @copy © Copyright Marc Wäckerlin $Date$ - @author Last Change: $Author$ - @date Last Change: $Date$ - @version $Id$ - @licence see file COPYING or license.html */ #ifndef __MRW_UNISTD_HPP__ #define __MRW_UNISTD_HPP__ @@ -36,7 +51,7 @@ namespace mrw { int _lastError; public: /// creates a unix pipe - Pipe(): _lastError(-1) { + Pipe() throw(std::bad_exception): _lastError(-1) { _fd[0] = -1; _fd[1] = -1; if (::pipe(_fd)==-1) @@ -45,16 +60,16 @@ namespace mrw { } } /// destructor closes pipe if still open - ~Pipe() { + ~Pipe() throw(std::bad_exception) { close(); } /// closes pipe if open - void close() { + void close() throw(std::bad_exception) { close_in(); close_out(); } /// closes input pipe if open - void close_in() { + void close_in() throw(std::bad_exception) { if (_fd[0]!=-1) while (::close(_fd[0])==-1) if (errno!=EINTR) { _lastError = errno; break; @@ -62,30 +77,30 @@ namespace mrw { _fd[0] = -1; } /// closes output pipe if open - void close_out() { + void close_out() throw(std::bad_exception) { if (_fd[1]!=-1) while (::close(_fd[1])==-1) if (errno!=EINTR) { _lastError = errno; break; } _fd[1] = -1; } - /// @return true if no error occured - operator bool() { + /** @return true if no error occured */ + operator bool() throw() { return _lastError == -1; } - /// @return last error code, -1 if no error - int error() { + /** @return last error code, -1 if no error */ + int error() throw() { return _lastError; } /// connect output stream to @c stdout - void connect_cout() { + void connect_cout() throw(std::bad_exception) { while (::dup2(_fd[1], 1)==-1) if (errno!=EINTR) { _lastError = errno; return; } } /// connect output stream to @c stderr - void connect_cerr() { + void connect_cerr() throw(std::bad_exception) { while (::dup2(_fd[1], 2)==-1) if (errno!=EINTR) { _lastError = errno; return; @@ -94,13 +109,13 @@ namespace mrw { /// get an input stream /** @return stream to read from @note invalid after destruction or @c close or @c close_in */ - int istream() { + int istream() throw(std::bad_exception) { return _fd[0]; } /// get an output stream /** @return stream to write to @note invalid after destruction or @c close or @c close_out */ - int ostream() { + int ostream() throw(std::bad_exception) { return _fd[1]; } };