00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #if ( defined( __linux__ ) && defined( __GNUC__ ) )
00026
00027 #include <execinfo.h>
00028 #include <cxxabi.h>
00029 #endif
00030
00031 #include <iostream>
00032 #include <list>
00033 #include <sstream>
00034 #include <stdexcept>
00035 #include <string>
00036
00037 #include <boost/algorithm/string.hpp>
00038
00039 #include "WException.h"
00040
00041
00042
00043
00044 bool WException::noBacktrace = false;
00045
00046 WException::WException( const std::string& msg ):
00047 exception(),
00048 m_labelColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGRed ) ),
00049 m_functionColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGBlue ) ),
00050 m_symbolColor( WTerminalColor() ),
00051 m_headlineColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGYellow ) )
00052 {
00053
00054 m_msg = msg;
00055
00056
00057
00058 if( !noBacktrace )
00059 {
00060 std::cerr << m_headlineColor( std::string( "Exception thrown! Callstack's backtrace:" ) ) << std::endl << getBacktrace() << std::endl;
00061 }
00062 }
00063
00064 WException::WException( const std::exception& e ):
00065 exception( e ),
00066 m_labelColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGRed ) ),
00067 m_functionColor( WTerminalColor( WTerminalColor::Off, WTerminalColor::FGBlue ) ),
00068 m_symbolColor( WTerminalColor() ),
00069 m_headlineColor( WTerminalColor( WTerminalColor::Bold, WTerminalColor::FGYellow ) )
00070 {
00071 m_msg = e.what();
00072
00073
00074
00075 if( !noBacktrace )
00076 {
00077 std::cerr << m_headlineColor( std::string( "Exception thrown! Callstack's backtrace:" ) ) << std::endl << getBacktrace() << std::endl;
00078 }
00079 }
00080
00081 WException::~WException() throw()
00082 {
00083
00084 }
00085
00086 const char* WException::what() const throw()
00087 {
00088
00089 return m_msg.c_str();
00090 }
00091
00092 std::string WException::getTrace() const
00093 {
00094 std::string result( what() );
00095 result += "\n\n";
00096 std::list< std::string >::const_iterator citer;
00097 for( citer = m_trace.begin(); citer != m_trace.end(); ++citer )
00098 result += "trace: " + *citer + "\n";
00099 boost::trim( result );
00100 return result;
00101 }
00102
00103 std::string WException::getBacktrace() const
00104 {
00105
00106 std::ostringstream o;
00107
00108 #if ( defined( __linux__ ) && defined( __GNUC__ ) )
00109
00110
00111
00112 const size_t maxDepth = 100;
00113 size_t stackDepth;
00114 void* stackAddrs[maxDepth];
00115 char** stackSymbols;
00116
00117
00118 stackDepth = backtrace( stackAddrs, maxDepth );
00119 stackSymbols = backtrace_symbols( stackAddrs, stackDepth );
00120
00121
00122 for( size_t i = 1; i < stackDepth; ++i )
00123 {
00124
00125
00126 size_t functionLength = 512;
00127 char* function = new char[functionLength];
00128
00129
00130 char* begin = 0;
00131 char* end = 0;
00132
00133
00134 for( char* j = stackSymbols[i]; *j; ++j )
00135 {
00136 if( *j == '(' )
00137 {
00138 begin = j;
00139 }
00140 else if( *j == '+' )
00141 {
00142 end = j;
00143 }
00144 }
00145
00146
00147 if( begin && end )
00148 {
00149 *begin++ = '(';
00150 *end = '\0';
00151
00152
00153 int status;
00154 char* ret = abi::__cxa_demangle( begin, function, &functionLength, &status );
00155
00156 if( ret )
00157 {
00158
00159 function = ret;
00160 }
00161 else
00162 {
00163
00164 std::strncpy( function, begin, functionLength );
00165 std::strncat( function, "()", functionLength );
00166 function[functionLength-1] = '\0';
00167 }
00168 *end = '+';
00169 o << m_labelColor( std::string( "trace: " ) )
00170 << m_functionColor( function )
00171 << "\t->\t"
00172 << m_symbolColor( stackSymbols[i] ) << std::endl;
00173 }
00174 else
00175 {
00176
00177 o << m_labelColor( std::string( "trace: " ) )
00178 << m_functionColor( std::string( "??? " ) )
00179 << "\t->\t"
00180 << m_symbolColor( stackSymbols[i] ) << std::endl;
00181 }
00182
00183 delete[] function;
00184 }
00185
00186
00187 free( stackSymbols );
00188 #else
00189 o << "Backtrace not supported on your platform. Currently just works on Linux with GCC. Sorry!";
00190 #endif
00191
00192 return o.str();
00193 }
00194
00195 void WException::disableBacktrace()
00196 {
00197 noBacktrace = true;
00198 }
00199