55#include < Rinternals.h>
66#include < sstream>
77
8+ // for backtraces
9+ #if defined(__GCC__) || defined(__clang__)
10+ #include < execinfo.h>
11+ #endif
12+
813#define GET_STACKTRACE () stack_trace( __FILE__, __LINE__ )
914
1015namespace Rcpp {
1116
1217class exception : public std ::exception {
1318public:
14- explicit exception (const char * message_) : message(message_){}
19+ explicit exception (const char * message_) : message(message_) {
20+
21+ #if defined(__GCC__) || defined(__clang__)
22+
23+ const size_t max_depth = 100 ;
24+ size_t stack_depth;
25+ void *stack_addrs[max_depth];
26+ char **stack_strings;
27+
28+ stack_depth = backtrace (stack_addrs, max_depth);
29+ stack_strings = backtrace_symbols (stack_addrs, stack_depth);
30+ std::vector<std::string> demangled;
31+ demangled.reserve (stack_depth);
32+
33+ // demangle the lines and add back in
34+ for (int i=0 ; i < stack_depth-2 ; ++i) {
35+
36+ std::string buffer ( stack_strings[i] );
37+ std::string buffer2 (stack_strings[i] );
38+
39+ std::string to_add;
40+
41+ size_t demangle_end = buffer.find_last_of (' +' ) - 1 ;
42+ buffer.resize ( buffer.find_last_of (' +' ) - 1 ) ;
43+ size_t demangle_begin = buffer.find_last_of (' ' );
44+ to_add += std::string ( buffer.begin (), buffer.begin () + demangle_begin + 1 );
45+ buffer.erase (
46+ buffer.begin (),
47+ buffer.begin () + buffer.find_last_of (' ' ) + 1
48+ ) ;
49+ to_add += Rcpp::demangle (buffer);
50+ to_add += std::string ( buffer2.begin () + demangle_end, buffer2.end () );
51+ demangled.emplace_back (to_add);
52+ }
53+
54+ message += " \n\n Traceback (most recent call first):\n " ;
55+
56+ for (int i=0 ; i < stack_depth-2 ; ++i) {
57+ message += demangled[i];
58+ message += " \n " ;
59+ }
60+
61+ free (stack_strings); // malloc()ed by backtrace_symbols
62+
63+ #endif
64+
65+ }
1566 exception (const char * message_, const char * file, int line ): message(message_){
1667 rcpp_set_stack_trace ( stack_trace (file,line) ) ;
1768 }
@@ -21,17 +72,10 @@ class exception : public std::exception {
2172 std::string message ;
2273} ;
2374
24- // simple helper
25- static std::string toString (const int i) {
26- std::ostringstream ostr;
27- ostr << i;
28- return ostr.str ();
29- }
30-
3175class no_such_env : public std ::exception{
3276public:
3377 no_such_env ( const std::string& name ) throw () : message( std::string(" no such environment: '" ) + name + " '" ){}
34- no_such_env ( int pos ) throw () : message( " no environment in given position '" + toString (pos) + " '" ) {}
78+ no_such_env ( int pos ) throw () : message( " no environment in given position '" + std::to_string (pos) + " '" ) {}
3579 virtual ~no_such_env () throw (){}
3680 virtual const char * what () const throw(){ return message.c_str () ; }
3781private:
@@ -41,7 +85,7 @@ class no_such_env : public std::exception{
4185class file_io_error : public std ::exception {
4286public:
4387 file_io_error (const std::string& file_) throw () : message( std::string(" file io error: '" ) + file_ + " '" ), file(file_) {}
44- file_io_error (int code, const std::string& file_) throw () : message( " file io error " + toString (code) + " : '" + file_ + " '" ), file(file_) {}
88+ file_io_error (int code, const std::string& file_) throw () : message( " file io error " + std::to_string (code) + " : '" + file_ + " '" ), file(file_) {}
4589 file_io_error (const std::string& msg, const std::string& file_) throw () : message( msg + " : '" + file_ + " '" ), file(file_) {}
4690 virtual ~file_io_error () throw (){}
4791 virtual const char * what () const throw(){ return message.c_str () ; }
0 commit comments