text: // Copyright Antony Polukhin, 2016-2017.
  //
  // Distributed under the Boost Software License, Version 1.0. (See
  // accompanying file LICENSE_1_0.txt or copy at
  // http://www.boost.org/LICENSE_1_0.txt)
  
  #ifndef BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP
  #define BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP
  
  #include <boost/config.hpp>
  #ifdef BOOST_HAS_PRAGMA_ONCE
  #   pragma once
  #endif
  
  #include <boost/stacktrace/frame.hpp>
  
  #include <boost/stacktrace/detail/to_hex_array.hpp>
  #include <boost/stacktrace/detail/location_from_symbol.hpp>
  #include <boost/core/demangle.hpp>
  #include <boost/lexical_cast.hpp>
  
  #include <cstdio>
  
  #ifdef BOOST_STACKTRACE_USE_BACKTRACE
  #   include <boost/stacktrace/detail/libbacktrace_impls.hpp>
  #elif defined(BOOST_STACKTRACE_USE_ADDR2LINE)
  #   include <boost/stacktrace/detail/addr2line_impls.hpp>
  #else
  #   include <boost/stacktrace/detail/unwind_base_impls.hpp>
  #endif
  
  namespace boost { namespace stacktrace { namespace detail {
  
  template <class Base>
  class to_string_impl_base: private Base {
  public:
      std::string operator()(boost::stacktrace::detail::native_frame_ptr_t addr) {
          Base::res.clear();
          Base::prepare_function_name(addr);
          if (!Base::res.empty()) {
              Base::res = boost::core::demangle(Base::res.c_str());
          } else {
              Base::res = to_hex_array(addr).data();
          }
  
          if (Base::prepare_source_location(addr)) {
              return Base::res;
          }
  
          boost::stacktrace::detail::location_from_symbol loc(addr);
          if (!loc.empty()) {
              Base::res += " in ";
              Base::res += loc.name();
          }
  
          return Base::res;
      }
  };
  
  std::string to_string(const frame* frames, std::size_t size) {
      std::string res;
      res.reserve(64 * size);
  
      to_string_impl impl;
  
      for (std::size_t i = 0; i < size; ++i) {
          if (i < 10) {
              res += ' ';
          }
          res += boost::lexical_cast<boost::array<char, 40> >(i).data();
          res += '#';
          res += ' ';
          res += impl(frames[i].address());
          res += '\n';
      }
  
      return res;
  }
  
  
  } // namespace detail
  
  
  std::string frame::name() const {
  #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
      ::Dl_info dli;
      const bool dl_ok = !!::dladdr(addr_, &dli);
      if (dl_ok && dli.dli_sname) {
          return boost::core::demangle(dli.dli_sname);
      }
  #endif
      return boost::stacktrace::detail::name_impl(addr_);
  }
  
  std::string to_string(const frame& f) {
      boost::stacktrace::detail::to_string_impl impl;
      return impl(f.address());
  }
  
  
  }} // namespace boost::stacktrace
  
  #endif // BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP
  