parent
7338ddc5cf
commit
5ac0645c20
7 changed files with 199 additions and 12 deletions
Binary file not shown.
@ -0,0 +1,132 @@ |
||||
/** @file
|
||||
|
||||
$Id: autofunctiontracelog4cxx.cpp,v 1.3 2005/04/14 19:12:18 marc Exp $ |
||||
|
||||
$Date: 2005/04/14 19:12:18 $ |
||||
$Author: marc $ |
||||
|
||||
@copy © Marc Wäckerlin |
||||
@license LGPL, see file <a href="license.html">COPYING</a> |
||||
|
||||
1 2 3 4 5 6 7 8 |
||||
5678901234567890123456789012345678901234567890123456789012345678901234567890 |
||||
*/ |
||||
|
||||
#ifndef __GNUG__ |
||||
#error GNU C++ Compiler is required for automatical function trace |
||||
#endif |
||||
|
||||
#include <mrw/string.hpp> |
||||
#include <mrw/stacktrace.hpp> |
||||
#include <iostream> |
||||
#include <iomanip> |
||||
|
||||
#if (__GNUC__==3 && __GNUC_MINOR__<4 || __GNUC__<3) && _REENTRANT && !_MT |
||||
#define _MT |
||||
#endif |
||||
|
||||
// these are special built in functions of GNU Compiler Collection
|
||||
extern "C" void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function)); |
||||
extern "C" void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function)); |
||||
|
||||
namespace mrw { |
||||
|
||||
// workaround doxygen problem:
|
||||
// - the C++ compiler compiles the following code
|
||||
// - doxygen ignores it
|
||||
#ifndef LET_DOXYGEN_IGNORE_THIS // no matching class member found for
|
||||
// int mrw::ThreadInfo::level()
|
||||
struct ThreadInfo { |
||||
int level; |
||||
bool recurse; |
||||
}; |
||||
#endif |
||||
|
||||
#ifdef _MT |
||||
static __thread ThreadInfo info = {0, false}; |
||||
#else |
||||
static ThreadInfo info = {0, false}; |
||||
#endif |
||||
|
||||
static bool mainPassed(false); |
||||
|
||||
class Lock { |
||||
public: |
||||
Lock() __attribute__((no_instrument_function)); |
||||
~Lock() __attribute__((no_instrument_function)); |
||||
}; |
||||
// workaround doxygen problem:
|
||||
// - the C++ compiler compiles the following code
|
||||
// - doxygen ignores it
|
||||
#ifndef LET_DOXYGEN_IGNORE_THIS // doxygen can't match with __attribute__ above
|
||||
Lock::Lock() { |
||||
info.recurse = true; |
||||
} |
||||
Lock::~Lock() { |
||||
info.recurse = false; |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
extern "C" int main(int, char**); |
||||
|
||||
/** @addtogroup FunctionTrace */ |
||||
//@{
|
||||
|
||||
/** @defgroup AutoFunctionTraceStdlog Automatic Function Trace to standard out for GNU g++
|
||||
|
||||
Same as @ref AutoFunctionTrace, but traces to @c stdlog. |
||||
|
||||
If you link to the library @c libmrwautofunctiontracestdlog using |
||||
a linker option such as: @c -lmrwautofunctiontracestdlog and you |
||||
must enable the GNU Compiler Collection specific function trace |
||||
feature with compile and link option @c -finstrument-functions |
||||
then you get an automatical function trace, that traces to @c |
||||
stdlog. You don't need to change a single line in your code! |
||||
|
||||
*/ |
||||
//@{
|
||||
|
||||
//@}
|
||||
|
||||
//@}
|
||||
|
||||
extern "C" void __cyg_profile_func_enter(void *this_fn, void*) { |
||||
if (!mrw::mainPassed) |
||||
if (this_fn == (void*)&::main) // not ANSI C++ conform...
|
||||
mrw::mainPassed=true; |
||||
else |
||||
return; |
||||
try { |
||||
if (mrw::info.recurse) return; |
||||
mrw::Lock lock; |
||||
{ |
||||
static bool init(mrw::StackTrace::createSymtable()); |
||||
if (!init) return; |
||||
mrw::StackTrace::CodePos pos(mrw::StackTrace::translate(this_fn)); |
||||
std::clog<<std::setw(2+mrw::info.level++)<<std::setfill(' ') |
||||
<<"\\ "<<pos.function<<" ("<<pos.file<<':'<<pos.line<<')' |
||||
<<std::endl; |
||||
} |
||||
} 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::clog<<std::setw(2+--mrw::info.level)<<std::setfill(' ') |
||||
<<"/ "<<pos.function<<" ("<<pos.file<<':'<<pos.line<<')' |
||||
<<std::endl; |
||||
} |
||||
} catch (...) {} |
||||
} |
@ -0,0 +1,49 @@ |
||||
/** @file
|
||||
|
||||
$Id$ |
||||
|
||||
$Date$ |
||||
$Author$ |
||||
|
||||
@copy © Marc Wäckerlin |
||||
@license LGPL, see file <a href="license.html">COPYING</a> |
||||
|
||||
$Log$ |
||||
|
||||
1 2 3 4 5 6 7 8 |
||||
5678901234567890123456789012345678901234567890123456789012345678901234567890 |
||||
*/ |
||||
#include <mrw/string.hpp> |
||||
#include <mrw/list.hpp> |
||||
#include <algorithm> |
||||
|
||||
#include <cppunit/TestFixture.h> |
||||
#include <cppunit/ui/text/TestRunner.h> |
||||
#include <cppunit/extensions/HelperMacros.h> |
||||
#include <cppunit/extensions/TestFactoryRegistry.h> |
||||
|
||||
class StringTest: public CppUnit::TestFixture {
|
||||
public: |
||||
void Join() { |
||||
std::list<std::string> l; |
||||
l<<"Hello"<<"World"<<"here"<<"I"<<"am"; |
||||
CPPUNIT_ASSERT(mrw::join(l)=="Hello World here I am"); |
||||
} |
||||
void Split() { |
||||
std::string text("Hello World here I am"); |
||||
std::list<std::string> a(mrw::split(text)), b; |
||||
b<<"Hello"<<"World"<<"here"<<"I"<<"am"; |
||||
CPPUNIT_ASSERT(equal(a.begin(), a.end(), b.begin())); |
||||
} |
||||
CPPUNIT_TEST_SUITE(StringTest); |
||||
CPPUNIT_TEST(Join); |
||||
CPPUNIT_TEST(Split); |
||||
CPPUNIT_TEST_SUITE_END(); |
||||
}; |
||||
CPPUNIT_TEST_SUITE_REGISTRATION(StringTest); |
||||
|
||||
int main() { |
||||
CppUnit::TextUi::TestRunner runner; |
||||
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); |
||||
return runner.run() ? 0 : 1; |
||||
} |
Loading…
Reference in new issue