diff --git a/mrw/autofunctiontracelog4cxx.cpp b/mrw/autofunctiontracelog4cxx.cpp
new file mode 100644
index 0000000..b004c18
--- /dev/null
+++ b/mrw/autofunctiontracelog4cxx.cpp
@@ -0,0 +1,239 @@
+/** @file
+
+ $Id$
+
+ $Date$
+ $Author$
+
+ @copy © Marc Wäckerlin
+ @license LGPL, see file COPYING
+
+ $Log$
+ Revision 1.1 2005/03/11 21:07:54 marc
+ initial version
+
+
+ 1 2 3 4 5 6 7 8
+ 5678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
+
+#ifndef __GNUG__
+#error GNU C++ Compiler is required for automatical function trace
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+
+// these are special built in functions of GNU Compiler Collection
+extern "C" void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));
+extern "C" void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function));
+
+namespace mrw {
+
+ struct ThreadInfo {
+ int level;
+ bool recurse;
+ };
+
+#ifdef _REENTRANT
+ static __thread ThreadInfo info = {0, false};
+#else
+ static ThreadInfo info = {0, false};
+#endif
+
+ static bool mainPassed(false);
+
+ class Lock {
+ public:
+ Lock() __attribute__((no_instrument_function));
+ ~Lock() __attribute__((no_instrument_function));
+ };
+ Lock::Lock() {
+ info.recurse = true;
+ }
+ Lock::~Lock() {
+ info.recurse = false;
+ }
+
+}
+
+extern "C" int main(int, char**);
+
+/** @addtogroup FunctionTrace
+
+ @note There is also a fully automagic function trace, similar to
+ @ref AutoTrace. It is described in @ref AutoFunctionTrace
+ and requires the GNU Compiler Collection gcc, because it
+ makes use of a proprietary compiler feature. */
+//@{
+
+/** @defgroup AutoFunctionTrace Automatic Function Trace for GNU g++
+
+ If you compile your program with GNU g++ / gcc, and you want
+ to add function tracing without changing a single line of your
+ code, here's the solution:
+
+ If you link to the library @c libmrwautofunctiontracelog4cxx using
+ a linker option such as: @c -lmrwautofunctiontracelog4cxx and you
+ must enable the GNU Compiler Collection specific function trace
+ feature with compile and link option @c -finstrument-functions
+ then you get an automatical function trace, that traces to level
+ @c DEBUG using the log4cxx library. You don't need to change a single
+ line in your code!
+
+ This feature depends on:
+ - the GNU C++ compiler gcc
+ - @ref mrw::StackTrace
+ - log4cxx http://logging.apache.org/log4cxx
+ - optional: boost for thread support http://boost.org
+
+ The logger hiararchy name is: @c
+ "mrw.gccfunctiontrace." where @c
+ is the full name of the method, including
+ namespace and class name, seperated not by double colon @c :: but
+ by single dots @c . as it is common use in log4cxx. This way, you
+ can enable or disable the function trace per namespace, per class
+ or even per method.
+
+ The function trace does not start, before the program @c main is
+ reached! Only the calls within the @c main are traced, but not during
+ the initialisation and destruction of static members. This is
+ necessary, because otherwise access the incompletely initialized
+ MRW-C++ library itself may cause a crash.
+
+ I use the following log4cxx @c log4cxx::PropertyConfigurator
+ configuration in the test program to enable all function traces,
+ except from some third party and standard libraries:
+
+ @verbatim
+log4j.rootLogger = OFF, A1
+log4j.logger.mrw.gccfunctiontrace = DEBUG
+log4j.logger.mrw.gccfunctiontrace.log4cxx = OFF
+log4j.logger.mrw.gccfunctiontrace.boost = OFF
+log4j.logger.mrw.gccfunctiontrace.Thread = OFF
+log4j.logger.mrw.gccfunctiontrace.mrw = OFF
+log4j.logger.mrw.gccfunctiontrace.std = OFF
+log4j.logger.mrw.gccfunctiontrace.new = OFF
+log4j.logger.mrw.gccfunctiontrace.CppUnit = OFF
+log4j.logger.mrw.gccfunctiontrace.__gnu_cxx = OFF
+log4j.appender.A1 = org.apache.log4j.FileAppender
+log4j.appender.A1.layout = org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern = %t-%-41c%m%n
+log4j.appender.A1.filename = filename.log
+ @endverbatim
+
+ Depending on your log4cxx configuration, a function trace may look
+ e.g. like this (very simple configuration with very few additional
+ information):
+
+ @verbatim
+mrw.gccfunctiontrace.anotherFunction \ anotherFunction()
+mrw.gccfunctiontrace.HalloWelt.fn1 \ HalloWelt::fn1()
+mrw.gccfunctiontrace.HalloWelt.fn \ HalloWelt::fn()
+mrw.gccfunctiontrace.HalloWelt.A.method \ HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.A.method / HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.A.method \ HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.A.method / HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.fn / HalloWelt::fn()
+mrw.gccfunctiontrace.HalloWelt.fn \ HalloWelt::fn()
+mrw.gccfunctiontrace.HalloWelt.A.method \ HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.A.method / HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.A.method \ HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.A.method / HalloWelt::A::method()
+mrw.gccfunctiontrace.HalloWelt.fn / HalloWelt::fn()
+mrw.gccfunctiontrace.HalloWelt.fn1 / HalloWelt::fn1()
+mrw.gccfunctiontrace.anotherFunction / anotherFunction()
+ @endverbatim
+
+ @note The configurator is not installed automatically. If you
+ want to trace e.g. on the console, you have to call @c
+ log4cxx::BasicConfigurator::configure(); as first statement
+ in your @c main().
+
+ @section AutoFunctionTraceThread Multithreading
+
+ Multithreading is also supported, then you need to link to the
+ thread safe compilat of the library @c
+ libmrwautofunctiontracelog4cxx-mt with option @c
+ -libmrwautofunctiontracelog4cxx-mt and you need the option @c
+ -pthread in addition to @c -finstrument-functions which is still
+ required.
+
+ Thread support requires the boost thread library. See
+ http://boost.org for details.
+ */
+//@{
+
+extern "C" void __cyg_profile_func_enter(void *this_fn, void*) {
+ if (!mrw::mainPassed)
+ if (this_fn == (void*)&::main) // not ANSI C++ conform...
+ mrw::mainPassed=true;
+ else
+ return;
+ try {
+ if (mrw::info.recurse) return;
+ mrw::Lock lock;
+ {
+ static bool init(mrw::StackTrace::createSymtable());
+ if (!init) return;
+ mrw::StackTrace::CodePos pos(mrw::StackTrace::translate(this_fn));
+ std::string hierarchy(pos.function);
+ for (std::string::size_type p(0);
+ (p=hierarchy.find("::", p))!=std::string::npos;
+ hierarchy.replace(p, 2, "."));
+ hierarchy.erase(hierarchy.rfind('('));
+ std::string::size_type p(hierarchy.rfind(' ', hierarchy.find('<')));
+ if (p!=std::string::npos) hierarchy.erase(0, p+1);
+ log4cxx::Logger* logger
+ (log4cxx::Logger::getLogger(_T("mrw.gccfunctiontrace.")+hierarchy));
+ if (logger->isDebugEnabled()) {
+ std::stringstream ss;
+ ss<forcedLog(::log4cxx::Level::DEBUG, ss.str(),
+ pos.file.c_str(), pos.line);
+ }
+ }
+ } catch (...) {}
+}
+
+extern "C" void __cyg_profile_func_exit(void *this_fn, void*) {
+ if (!mrw::mainPassed)
+ return;
+ else
+ if (this_fn == (void*)&::main) { // not ANSI C++ conform...
+ mrw::mainPassed=false;
+ return;
+ }
+ try {
+ if (mrw::info.recurse || mrw::info.level==0) return;
+ mrw::Lock lock;
+ {
+ mrw::StackTrace::CodePos pos(mrw::StackTrace::translate(this_fn));
+ std::string hierarchy(pos.function);
+ for (std::string::size_type p(0);
+ (p=hierarchy.find("::", p))!=std::string::npos;
+ hierarchy.replace(p, 2, "."));
+ hierarchy.erase(hierarchy.find('('));
+ std::string::size_type p(hierarchy.rfind(' ', hierarchy.find('<')));
+ if (p!=std::string::npos) hierarchy.erase(0, p+1);
+ log4cxx::Logger* logger
+ (log4cxx::Logger::getLogger(_T("mrw.gccfunctiontrace.")+hierarchy));
+ if (logger->isDebugEnabled()) {
+ std::stringstream ss;
+ ss<forcedLog(::log4cxx::Level::DEBUG, ss.str(),
+ pos.file.c_str(), pos.line);
+ }
+ }
+ } catch (...) {}
+}
+
+//@}
+
+//@}
diff --git a/mrw/functiontrace.cpp b/mrw/functiontrace.cpp
new file mode 100644
index 0000000..92dff82
--- /dev/null
+++ b/mrw/functiontrace.cpp
@@ -0,0 +1,22 @@
+/** @file
+
+ $Id$
+
+ $Date$
+ $Author$
+
+ @copy © Marc Wäckerlin
+ @license LGPL, see file COPYING
+
+ $Log$
+ Revision 1.1 2005/03/11 21:07:54 marc
+ initial version
+
+
+ 1 2 3 4 5 6 7 8
+ 5678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
+
+#include
+
+unsigned int mrw::FnTrace::_level(0);
diff --git a/mrw/functiontrace.hpp b/mrw/functiontrace.hpp
new file mode 100644
index 0000000..f782635
--- /dev/null
+++ b/mrw/functiontrace.hpp
@@ -0,0 +1,274 @@
+/** @file
+
+ $Id$
+
+ $Date$
+ $Author$
+
+ @copy © Marc Wäckerlin
+ @license LGPL, see file COPYING
+
+ $Log$
+ Revision 1.1 2005/03/11 21:07:54 marc
+ initial version
+
+
+ 1 2 3 4 5 6 7 8
+ 5678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
+
+#ifndef __MRW_FUNCTIONTRACE_HPP__
+#define __MRW_FUNCTIONTRACE_HPP__
+
+#include
+#include
+#include
+#include
+
+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
+ traced.
+
+ There are alternative macros @ref METHOD2 and @ref 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.
+
+ @attention Be careful when you copy paste the declarations from
+ one method to the other! Don't forget to correctly change the
+ method's name! I recommend to use a tool like OpenC++
+ (http://opencxx.sf.net) to automatically place function trace
+ statements into classes, so that the coder does not have to care
+ about. I have already partly written such a module and I will
+ provide it for free (GPL) when it is good enough.
+
+ The trace of the following code:
+
+ @code
+ #include
+ #include
+ void fn(int i=0) {
+ FUNCTION("fn(int)"); // trace entry and exit
+ if (i<4) fn(++i);
+ }
+ class A {
+ public:
+ A() { // not traced
+ method();
+ }
+ void method() {
+ METHOD("A::method()"); // trace entry and exit
+ fn();
+ }
+ };
+ int main(int, char**) {
+ log4cxx::BasicConfigurator::configure();
+ FUNCTION("main(int, char**)");
+ A().method();
+ return 0;
+ }
+ @endcode
+
+ Produces this output:
+
+ @verbatim
+1 [1078671488] DEBUG mrw.fntrace - \ main(int, char**)
+1 [1078671488] DEBUG mrw.fntrace - 0xbfffef3f: \ A::method()
+1 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+2 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+2 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+2 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+2 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+2 [1078671488] DEBUG mrw.fntrace - / fn(int)
+2 [1078671488] DEBUG mrw.fntrace - / fn(int)
+2 [1078671488] DEBUG mrw.fntrace - / fn(int)
+3 [1078671488] DEBUG mrw.fntrace - / fn(int)
+3 [1078671488] DEBUG mrw.fntrace - / fn(int)
+3 [1078671488] DEBUG mrw.fntrace - 0xbfffef3f: / A::method()
+3 [1078671488] DEBUG mrw.fntrace - 0xbfffef3f: \ A::method()
+3 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+3 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+3 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+4 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+4 [1078671488] DEBUG mrw.fntrace - \ fn(int)
+4 [1078671488] DEBUG mrw.fntrace - / fn(int)
+4 [1078671488] DEBUG mrw.fntrace - / fn(int)
+4 [1078671488] DEBUG mrw.fntrace - / fn(int)
+4 [1078671488] DEBUG mrw.fntrace - / fn(int)
+4 [1078671488] DEBUG mrw.fntrace - / fn(int)
+4 [1078671488] DEBUG mrw.fntrace - 0xbfffef3f: / A::method()
+5 [1078671488] DEBUG mrw.fntrace - / main(int, char**)
+ @endverbatim
+
+ The indentation is according to the call stack depth level, the
+ name is preceded by a @c \\ on entry and by a @c / on exit. The
+ methods are preceded by the address of @c this, so that
+ different instances can be distinguished. All before and
+ including the dash @c - is configurable through the normal
+ log4cxx trace patterns.
+ */
+ //@{
+
+ /** @brief Declare method entrance, place as first line in method.
+
+ Place this macro as first statement in each method that should
+ write a function trace.
+
+ Example:
+
+ @code
+ namespace xxx {
+ namespace yyy {
+ class Zzz {
+ public: void doIt(int, char) {
+ METHOD("xxx::yyy::Zzz::doIt(int, char)");
+ [...]
+ }
+ };
+ }
+ }
+ @endcode
+
+ @param name the full name of the method, including namespaces
+ and class name
+ */
+#define METHOD(name) mrw::FnTrace fnTrace(this, name, __FILE__, __LINE__)
+
+ /** @brief Declare function entrance, place as first line in functions.
+
+ Place this macro as first statement in each function that should
+ write a function trace.
+
+ Example:
+
+ @code
+ namespace xxx {
+ namespace yyy {
+ void doIt(int, char) {
+ FUNCTION("xxx::yyy::doIt(int, char)");
+ [...]
+ }
+ }
+ }
+ @endcode
+
+ @param name the full name of the function, including namespaces
+ */
+#define FUNCTION(name) mrw::FnTrace fnTrace(name, __FILE__, __LINE__)
+
+ /** @brief Declare method entrance, place as first line in method.
+
+ Place this macro as first statement in each method that should
+ write a function trace.
+
+ This macro allows you to define a logging hierarchy string.
+
+ Example:
+
+ @code
+ namespace xxx {
+ namespace yyy {
+ class Zzz {
+ public: void doIt(int, char) {
+ METHOD2("xxx::yyy::Zzz::doIt(int, char)", "fn.xxx.yyy.Zzz");
+ [...]
+ }
+ };
+ }
+ }
+ @endcode
+
+ @param name the full name of the method, including namespaces
+ and class name
+ @param tracer the tracer hierarchy
+ */
+#define METHOD2(name, tracer) \
+ mrw::FnTrace fnTrace(this, name, __FILE__, __LINE__, tracer)
+
+ /** @brief Declare function entrance, place as first line in functions.
+
+ Place this macro as first statement in each function that should
+ write a function trace.
+
+ This macro allows you to define a logging hierarchy string.
+
+ Example:
+
+ @code
+ namespace xxx {
+ namespace yyy {
+ void doIt(int, char) {
+ FUNCTION2("xxx::yyy::doIt(int, char)", "fn.xxx.yyy");
+ [...]
+ }
+ }
+ }
+ @endcode
+
+ @param name the full name of the function, including namespaces
+ @param tracer the tracer hierarchy
+ */
+#define FUNCTION2(name, tracer) \
+ mrw::FnTrace fnTrace(name, __FILE__, __LINE__, tracer)
+
+ class FnTrace {
+ public:
+ 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) {
+ log4cxx::Logger* logger(log4cxx::Logger::getLogger(_tracer));
+ if (logger->isDebugEnabled()) {
+ std::stringstream oss;
+ oss<forcedLog(log4cxx::Level::DEBUG, oss.str(),
+ _file.c_str(), _line);
+ ++_level;
+ }
+ }
+ 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) {
+ log4cxx::Logger* logger(log4cxx::Logger::getLogger(_tracer));
+ if (logger->isDebugEnabled()) {
+ std::stringstream oss;
+ oss<forcedLog(log4cxx::Level::DEBUG, oss.str(),
+ _file.c_str(), _line);
+ ++_level;
+ }
+ }
+ ~FnTrace() throw() {
+ log4cxx::Logger* logger(log4cxx::Logger::getLogger(_tracer));
+ if (logger->isDebugEnabled()) {
+ --_level;
+ std::stringstream oss;
+ if (_addr)
+ oss<forcedLog(log4cxx::Level::DEBUG, oss.str(),
+ _file.c_str(), _line);
+ }
+ }
+ private:
+ const void* _addr;
+ const std::string _name;
+ const std::string _file;
+ unsigned long _line;
+ const std::string _tracer;
+ /** @todo for multithreading, use thread specific storage */
+ static unsigned int _level;
+ };
+ //@}
+}
+#endif
diff --git a/mrw/functiontrace_test.cpp b/mrw/functiontrace_test.cpp
new file mode 100644
index 0000000..14e6d57
--- /dev/null
+++ b/mrw/functiontrace_test.cpp
@@ -0,0 +1,116 @@
+/** @file
+
+ $Id$
+
+ $Date$
+ $Author$
+
+ @copy © Marc Wäckerlin
+ @license LGPL, see file COPYING
+
+ $Log$
+ Revision 1.1 2005/03/11 21:07:55 marc
+ initial version
+
+
+ 1 2 3 4 5 6 7 8
+ 5678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+class A {
+ public:
+ A() {
+ METHOD("A::A()");
+ }
+ ~A() {
+ METHOD("A::~A()");
+ }
+ void fn1() {
+ METHOD("A::fn1()");
+ fn2();
+ }
+ void fn2() {
+ METHOD("A::fn2()");
+ fn3();
+ fn4();
+ }
+ void fn3() {
+ METHOD("A::fn3()");
+ fn4();
+ }
+ void fn4(bool flag=true) {
+ METHOD("A::fn4()");
+ if (flag) fn4(false);
+ }
+};
+
+void fn(A a) {
+ FUNCTION("fn(A)");
+ a.fn1();
+}
+
+class FunctionTraceTest: public CppUnit::TestFixture {
+ public:
+ 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");
+ log4cxx::PropertyConfigurator::configure(properties);
+ }
+ void Calls() {
+ fn(A());
+ mrw::RegExp match
+ ("functiontrace_test.cpp:30 - *0x[0-9a-fA-F]+: \\\\ A::A\\(\\)\n"
+ "functiontrace_test.cpp:30 - *0x[0-9a-fA-F]+: / A::A\\(\\)\n"
+ "functiontrace_test.cpp:55 - \\\\ fn\\(A\\)\n"
+ "functiontrace_test.cpp:36 - *0x[0-9a-fA-F]+: \\\\ A::fn1\\(\\)\n"
+ "functiontrace_test.cpp:40 - *0x[0-9a-fA-F]+: \\\\ A::fn2\\(\\)\n"
+ "functiontrace_test.cpp:45 - *0x[0-9a-fA-F]+: \\\\ A::fn3\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: \\\\ A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: \\\\ A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: / A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: / A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:45 - *0x[0-9a-fA-F]+: / A::fn3\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: \\\\ A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: \\\\ A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: / A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:49 - *0x[0-9a-fA-F]+: / A::fn4\\(\\)\n"
+ "functiontrace_test.cpp:40 - *0x[0-9a-fA-F]+: / A::fn2\\(\\)\n"
+ "functiontrace_test.cpp:36 - *0x[0-9a-fA-F]+: / A::fn1\\(\\)\n"
+ "functiontrace_test.cpp:55 - / fn\\(A\\)\n"
+ "functiontrace_test.cpp:33 - *0x[0-9a-fA-F]+: \\\\ A::~A\\(\\)\n"
+ "functiontrace_test.cpp:33 - *0x[0-9a-fA-F]+: / A::~A\\(\\)\n");
+ CPPUNIT_ASSERT(match(mrw::File::read("functiontrace_test.log")));
+ mrw::File::remove("functiontrace_test.log");
+ }
+ CPPUNIT_TEST_SUITE(FunctionTraceTest);
+ CPPUNIT_TEST(Init);
+ CPPUNIT_TEST(Calls);
+ CPPUNIT_TEST_SUITE_END();
+};
+CPPUNIT_TEST_SUITE_REGISTRATION(FunctionTraceTest);
+
+int main() {
+ CppUnit::TextUi::TestRunner runner;
+ runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
+ return runner.run() ? 0 : 1;
+}
diff --git a/mrw/mrwautofunctiontracelog4cxx_test.cpp b/mrw/mrwautofunctiontracelog4cxx_test.cpp
new file mode 100644
index 0000000..b247d1d
--- /dev/null
+++ b/mrw/mrwautofunctiontracelog4cxx_test.cpp
@@ -0,0 +1,179 @@
+/** @file
+
+ $Id$
+
+ $Date$
+ $Author$
+
+ @copy © Marc Wäckerlin
+ @license LGPL, see file COPYING
+
+ $Log$
+ Revision 1.1 2005/03/11 21:07:55 marc
+ initial version
+
+
+ 1 2 3 4 5 6 7 8
+ 5678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include