TuttleOFX
1
|
00001 // 00002 // Copyright (c) 2010 Artyom Beilis (Tonkikh) 00003 // 00004 // Distributed under the Boost Software License, Version 1.0. (See 00005 // accompanying file LICENSE_1_0.txt or copy at 00006 // http://www.boost.org/LICENSE_1_0.txt) 00007 // 00008 #ifndef BOOST_BACKTRACE_HPP 00009 #define BOOST_BACKTRACE_HPP 00010 00011 #include <boost/config.hpp> 00012 #include <stdexcept> 00013 #include <typeinfo> 00014 #include <vector> 00015 #include <iosfwd> 00016 #include <string> 00017 00018 namespace boost { 00019 00020 namespace stack_trace { 00021 int trace(void **addresses,int size); 00022 void write_symbols(void *const *addresses,int size,std::ostream &); 00023 std::string get_symbol(void *address); 00024 std::string get_symbols(void * const *address,int size); 00025 } // stack_trace 00026 00027 00028 class backtrace 00029 { 00030 public: 00031 static size_t const default_stack_size = 32; 00032 00033 backtrace(size_t frames_no = default_stack_size) 00034 { 00035 if(frames_no == 0) 00036 return; 00037 frames_.resize(frames_no,0); 00038 int size = stack_trace::trace(&frames_.front(),frames_no); 00039 frames_.resize(size); 00040 } 00041 00042 virtual ~backtrace() throw() 00043 { 00044 } 00045 00046 size_t stack_size() const 00047 { 00048 return frames_.size(); 00049 } 00050 00051 void *return_address(unsigned frame_no) const 00052 { 00053 if(frame_no < stack_size()) 00054 return frames_[frame_no]; 00055 return 0; 00056 } 00057 00058 void trace_line(unsigned frame_no,std::ostream &out) const 00059 { 00060 if(frame_no < frames_.size()) 00061 stack_trace::write_symbols(&frames_[frame_no],1,out); 00062 } 00063 00064 std::string trace_line(unsigned frame_no) const 00065 { 00066 if(frame_no < frames_.size()) 00067 return stack_trace::get_symbol(frames_[frame_no]); 00068 return std::string(); 00069 } 00070 00071 std::string trace() const 00072 { 00073 if(frames_.empty()) 00074 return std::string(); 00075 return stack_trace::get_symbols(&frames_.front(),frames_.size()); 00076 } 00077 00078 void trace(std::ostream &out) const 00079 { 00080 if(frames_.empty()) 00081 return; 00082 stack_trace::write_symbols(&frames_.front(),frames_.size(),out); 00083 } 00084 00085 private: 00086 std::vector<void *> frames_; 00087 }; 00088 00089 00090 namespace details { 00091 class trace_manip { 00092 public: 00093 trace_manip(backtrace const *tr) : 00094 tr_(tr) 00095 { 00096 } 00097 std::ostream &write(std::ostream &out) const 00098 { 00099 if(tr_) 00100 tr_->trace(out); 00101 return out; 00102 } 00103 private: 00104 backtrace const *tr_; 00105 }; 00106 00107 inline std::ostream &operator<<(std::ostream &out,details::trace_manip const &t) 00108 { 00109 return t.write(out); 00110 } 00111 } 00112 00113 template<typename E> 00114 details::trace_manip trace(E const &e) 00115 { 00116 backtrace const *tr = dynamic_cast<backtrace const *>(&e); 00117 return details::trace_manip(tr); 00118 } 00119 00120 00121 } // boost 00122 00123 #endif 00124 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 00125