Skip to content

Commit

Permalink
Merge pull request #154 from dpacbach/master
Browse files Browse the repository at this point in the history
Allow specifying list of source file search paths in environment var
  • Loading branch information
bombela authored Mar 3, 2020
2 parents c51737a + c122f1f commit 1ab8c87
Showing 1 changed file with 63 additions and 2 deletions.
65 changes: 63 additions & 2 deletions backward.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,16 @@ template <typename T> T &move(T &v) { return v; }
} // namespace backward
#endif // BACKWARD_ATLEAST_CXX11

namespace backward {
namespace details {
#if defined(BACKWARD_SYSTEM_WINDOWS)
const char kBackwardPathDelimiter[] = ";";
#else
const char kBackwardPathDelimiter[] = ":";
#endif
} // namespace details
} // namespace backward

namespace backward {

namespace system_tag {
Expand Down Expand Up @@ -587,6 +597,29 @@ template <> struct demangler_impl<system_tag::current_tag> {

struct demangler : public demangler_impl<system_tag::current_tag> {};

// Split a string on the platform's PATH delimiter. Example: if delimiter
// is ":" then:
// "" --> []
// ":" --> ["",""]
// "::" --> ["","",""]
// "/a/b/c" --> ["/a/b/c"]
// "/a/b/c:/d/e/f" --> ["/a/b/c","/d/e/f"]
// etc.
inline std::vector<std::string> split_source_prefixes(const std::string &s) {
std::vector<std::string> out;
size_t last = 0;
size_t next = 0;
size_t delimiter_size = sizeof(kBackwardPathDelimiter)-1;
while ((next = s.find(kBackwardPathDelimiter, last)) != std::string::npos) {
out.push_back(s.substr(last, next-last));
last = next + delimiter_size;
}
if (last <= s.length()) {
out.push_back(s.substr(last));
}
return out;
}

} // namespace details

/*************** A TRACE ***************/
Expand Down Expand Up @@ -3360,8 +3393,22 @@ class SourceFile {
typedef std::vector<std::pair<unsigned, std::string>> lines_t;

SourceFile() {}
SourceFile(const std::string &path)
: _file(new std::ifstream(path.c_str())) {}
SourceFile(const std::string &path) {
// 1. If BACKWARD_CXX_SOURCE_PREFIXES is set then assume it contains
// a colon-separated list of path prefixes. Try prepending each
// to the given path until a valid file is found.
const std::vector<std::string>& prefixes = get_paths_from_env_variable();
for (size_t i = 0; i < prefixes.size(); ++i) {
// Double slashes (//) should not be a problem.
std::string new_path = prefixes[i] + '/' + path;
_file.reset(new std::ifstream(new_path.c_str()));
if (is_open()) break;
}
// 2. If no valid file found then fallback to opening the path as-is.
if (!_file || !is_open()) {
_file.reset(new std::ifstream(path.c_str()));
}
}
bool is_open() const { return _file->is_open(); }

lines_t &get_lines(unsigned line_start, unsigned line_count, lines_t &lines) {
Expand Down Expand Up @@ -3457,6 +3504,20 @@ class SourceFile {
details::handle<std::ifstream *, details::default_delete<std::ifstream *>>
_file;

std::vector<std::string> get_paths_from_env_variable_impl() {
std::vector<std::string> paths;
const char* prefixes_str = std::getenv("BACKWARD_CXX_SOURCE_PREFIXES");
if (prefixes_str && prefixes_str[0]) {
paths = details::split_source_prefixes(prefixes_str);
}
return paths;
}

const std::vector<std::string>& get_paths_from_env_variable() {
static std::vector<std::string> paths = get_paths_from_env_variable_impl();
return paths;
}

#ifdef BACKWARD_ATLEAST_CXX11
SourceFile(const SourceFile &) = delete;
SourceFile &operator=(const SourceFile &) = delete;
Expand Down

0 comments on commit 1ab8c87

Please sign in to comment.