class Colorize {
public:
Colorize(std::FILE*) {}
void init() {}
void set_color(Color::type) {}
};
#endif // BACKWARD_SYSTEM_LINUX
class Printer {
public:
bool snippet;
bool color;
bool address;
bool object;
Printer():
snippet(true),
color(true),
address(false),
object(false)
{}
template <typename ST>
FILE* print(ST& st, FILE* os = stderr) {
Colorize colorize(os);
if (color) {
colorize.init();
}
print_header(os, st.thread_id());
_resolver.load_stacktrace(st);
for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) {
print_trace(os, _resolver.resolve(st[trace_idx-1]), colorize);
}
return os;
}
template <typename IT>
FILE* print(IT begin, IT end, FILE* os = stderr, size_t thread_id = 0) {
Colorize colorize(os);
if (color) {
colorize.init();
}
print_header(os, thread_id);
for (; begin != end; ++begin) {
print_trace(os, *begin, colorize);
}
return os;
}
private:
TraceResolver _resolver;
SnippetFactory _snippets;
void print_header(FILE* os, unsigned thread_id) {
fprintf(os, "Stack trace (most recent call last)");
if (thread_id) {
fprintf(os, " in thread %u:\n", thread_id);
} else {
fprintf(os, ":\n");
}
}
void print_trace(FILE* os, const ResolvedTrace& trace,
Colorize& colorize) {
fprintf(os, "#%-2u", trace.idx);
bool already_indented = true;
if (!trace.source.filename.size() || object) {
fprintf(os, " Object \"%s\", at %p, in %s\n",
trace.object_filename.c_str(), trace.addr,
trace.object_function.c_str());
already_indented = false;
}
for (size_t inliner_idx = trace.inliners.size();
inliner_idx > 0; --inliner_idx) {
if (!already_indented) {
fprintf(os, " ");
}
const ResolvedTrace::SourceLoc& inliner_loc
= trace.inliners[inliner_idx-1];
print_source_loc(os, " | ", inliner_loc);
if (snippet) {
print_snippet(os, " | ", inliner_loc,
colorize, Color::purple, 5);
}
already_indented = false;
}
if (trace.source.filename.size()) {
if (!already_indented) {
fprintf(os, " ");
}
print_source_loc(os, " ", trace.source, trace.addr);
if (snippet) {
print_snippet(os, " ", trace.source,
colorize, Color::yellow, 7);
}
}
}
void print_snippet(FILE* os, const char* indent,
const ResolvedTrace::SourceLoc& source_loc,
Colorize& colorize, Color::type color_code,
int context_size)
{
using namespace std;
typedef SnippetFactory::lines_t lines_t;
lines_t lines = _snippets.get_snippet(source_loc.filename,
source_loc.line, context_size);
for (lines_t::const_iterator it = lines.begin();
it != lines.end(); ++it) {
if (it-> first == source_loc.line) {
colorize.set_color(color_code);
fprintf(os, "%s>", indent);
} else {
fprintf(os, "%s ", indent);
}
fprintf(os, "%4u: %s\n", it->first, it->second.c_str());
if (it-> first == source_loc.line) {
colorize.set_color(Color::reset);
}
}
}
void print_source_loc(FILE* os, const char* indent,
const ResolvedTrace::SourceLoc& source_loc,
void* addr=0) {
fprintf(os, "%sSource \"%s\", line %i, in %s",
indent, source_loc.filename.c_str(), (int)source_loc.line,
source_loc.function.c_str());
if (address && addr != 0) {
fprintf(os, " [%p]\n", addr);
} else {
fprintf(os, "\n");
}
}
};
详细注释上述代码
最新发布