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 00017 namespace boost { 00018 00019 namespace stack_trace { 00020 int trace(void **addresses,int size); 00021 void write_symbols(void *const *addresses,int size,std::ostream &); 00022 std::string get_symbol(void *address); 00023 std::string get_symbols(void * const *address,int size); 00024 } // stack_trace 00025 00026 00027 class backtrace 00028 { 00029 public: 00030 static size_t const default_stack_size = 32; 00031 00032 backtrace(size_t frames_no = default_stack_size) 00033 { 00034 if(frames_no == 0) 00035 return; 00036 frames_.resize(frames_no,0); 00037 int size = stack_trace::trace(&frames_.front(),frames_no); 00038 frames_.resize(size); 00039 } 00040 00041 virtual ~backtrace() throw() 00042 { 00043 } 00044 00045 size_t stack_size() const 00046 { 00047 return frames_.size(); 00048 } 00049 00050 void *return_address(unsigned frame_no) const 00051 { 00052 if(frame_no < stack_size()) 00053 return frames_[frame_no]; 00054 return 0; 00055 } 00056 00057 void trace_line(unsigned frame_no,std::ostream &out) const 00058 { 00059 if(frame_no < frames_.size()) 00060 stack_trace::write_symbols(&frames_[frame_no],1,out); 00061 } 00062 00063 std::string trace_line(unsigned frame_no) const 00064 { 00065 if(frame_no < frames_.size()) 00066 return stack_trace::get_symbol(frames_[frame_no]); 00067 return std::string(); 00068 } 00069 00070 std::string trace() const 00071 { 00072 if(frames_.empty()) 00073 return std::string(); 00074 return stack_trace::get_symbols(&frames_.front(),frames_.size()); 00075 } 00076 00077 void trace(std::ostream &out) const 00078 { 00079 if(frames_.empty()) 00080 return; 00081 stack_trace::write_symbols(&frames_.front(),frames_.size(),out); 00082 } 00083 00084 private: 00085 std::vector<void *> frames_; 00086 }; 00087 00088 00089 namespace details { 00090 class trace_manip { 00091 public: 00092 trace_manip(backtrace const *tr) : 00093 tr_(tr) 00094 { 00095 } 00096 std::ostream &write(std::ostream &out) const 00097 { 00098 if(tr_) 00099 tr_->trace(out); 00100 return out; 00101 } 00102 private: 00103 backtrace const *tr_; 00104 }; 00105 00106 inline std::ostream &operator<<(std::ostream &out,details::trace_manip const &t) 00107 { 00108 return t.write(out); 00109 } 00110 } 00111 00112 template<typename E> 00113 details::trace_manip trace(E const &e) 00114 { 00115 backtrace const *tr = dynamic_cast<backtrace const *>(&e); 00116 return details::trace_manip(tr); 00117 } 00118 00119 00120 } // boost 00121 00122 #endif 00123 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 00124