**************************************************************************/
+#include <limits>
+
#include "formatter.hpp"
#include "trace_dump.hpp"
{
protected:
std::ostream &os;
- DumpFlags flags;
+ DumpFlags dumpFlags;
formatter::Formatter *formatter;
formatter::Attribute *normal;
formatter::Attribute *bold;
public:
Dumper(std::ostream &_os, DumpFlags _flags) :
os(_os),
- flags(_flags)
+ dumpFlags(_flags)
{
- bool color = !(flags & DUMP_FLAG_NO_COLOR);
+ bool color = !(dumpFlags & DUMP_FLAG_NO_COLOR);
formatter = formatter::defaultFormatter(color);
normal = formatter->normal();
bold = formatter->bold();
}
void visit(Null *) {
- os << "NULL";
+ os << literal << "NULL" << normal;
}
void visit(Bool *node) {
}
void visit(Float *node) {
+ std::streamsize oldPrecision = os.precision(std::numeric_limits<float>::digits10 + 1);
os << literal << node->value << normal;
+ os.precision(oldPrecision);
}
void visit(Double *node) {
+ std::streamsize oldPrecision = os.precision(std::numeric_limits<double>::digits10 + 1);
os << literal << node->value << normal;
+ os.precision(oldPrecision);
}
void visit(String *node) {
}
void visit(Enum *node) {
- const EnumSig *sig = node->sig;
- for (const EnumValue *it = sig->values; it != sig->values + sig->num_values; ++it) {
- if (it->value == node->value) {
- os << literal << it->name << normal;
- return;
- }
+ const EnumValue *it = node->lookup();
+ if (it) {
+ os << literal << it->name << normal;
+ return;
}
os << literal << node->value << normal;
}
unsigned long long value = bitmask->value;
const BitmaskSig *sig = bitmask->sig;
bool first = true;
- for (const BitmaskFlag *it = sig->flags; value != 0 && it != sig->flags + sig->num_flags; ++it) {
+ for (const BitmaskFlag *it = sig->flags; it != sig->flags + sig->num_flags; ++it) {
+ assert(it->value || first);
if ((it->value && (value & it->value) == it->value) ||
(!it->value && value == 0)) {
if (!first) {
value &= ~it->value;
first = false;
}
+ if (value == 0) {
+ break;
+ }
}
if (value || first) {
if (!first) {
}
}
- void visit(Struct *s) {
- const char *sep = "";
- os << "{";
+ const char *
+ visitMembers(Struct *s, const char *sep = "") {
for (unsigned i = 0; i < s->members.size(); ++i) {
- os << sep << italic << s->sig->member_names[i] << normal << " = ";
- _visit(s->members[i]);
+ const char *memberName = s->sig->member_names[i];
+ Value *memberValue = s->members[i];
+
+ if (!memberName || !*memberName) {
+ // Anonymous structure
+ Struct *memberStruct = dynamic_cast<Struct *>(memberValue);
+ assert(memberStruct);
+ if (memberStruct) {
+ sep = visitMembers(memberStruct, sep);
+ continue;
+ }
+ }
+
+ os << sep << italic << memberName << normal << " = ",
+ _visit(memberValue);
sep = ", ";
}
+ return sep;
+ }
+
+ void visit(Struct *s) {
+ os << "{";
+ visitMembers(s);
os << "}";
}
os << pointer << "0x" << std::hex << p->value << std::dec << normal;
}
+ void visit(Repr *r) {
+ _visit(r->humanValue);
+ }
+
+ void visit(StackFrame *frame) {
+ if (frame->module != NULL) {
+ os << frame->module << " ";
+ }
+ if (frame->function != NULL) {
+ os << "at " << frame->function << "() ";
+ }
+ if (frame->filename != NULL) {
+ os << "at " << frame->filename;
+ if (frame->linenumber >= 0) {
+ os << ":" << frame->linenumber << " ";
+ }
+ }
+ else {
+ if (frame->offset >= 0) {
+ os << "[" << "0x" << std::hex << frame->offset << std::dec << "]";
+ }
+ }
+ }
+
+ void visit(Backtrace & backtrace) {
+ for (int i = 0; i < backtrace.size(); i ++) {
+ visit(backtrace[i]);
+ os << "\n";
+ }
+ }
+
void visit(Call *call) {
- CallFlags flags = call->flags;
+ CallFlags callFlags = call->flags;
+
+ if (!(dumpFlags & DUMP_FLAG_NO_CALL_NO)) {
+ os << call->no << " ";
+ }
- if (flags & CALL_FLAG_NON_REPRODUCIBLE) {
+ if (callFlags & CALL_FLAG_NON_REPRODUCIBLE) {
os << strike;
- } else if (flags & (CALL_FLAG_FAKE | CALL_FLAG_NO_SIDE_EFFECTS)) {
+ } else if (callFlags & (CALL_FLAG_FAKE | CALL_FLAG_NO_SIDE_EFFECTS)) {
os << normal;
} else {
os << bold;
const char *sep = "";
for (unsigned i = 0; i < call->args.size(); ++i) {
os << sep;
- if (!(flags = DUMP_FLAG_NO_ARG_NAMES)) {
+ if (!(dumpFlags & DUMP_FLAG_NO_ARG_NAMES)) {
os << italic << call->sig->arg_names[i] << normal << " = ";
}
- if (call->args[i]) {
- _visit(call->args[i]);
+ if (call->args[i].value) {
+ _visit(call->args[i].value);
} else {
os << "?";
}
_visit(call->ret);
}
- if (flags & CALL_FLAG_INCOMPLETE) {
+ if (callFlags & CALL_FLAG_INCOMPLETE) {
os << " // " << red << "incomplete" << normal;
}
os << "\n";
- if (flags & CALL_FLAG_END_FRAME) {
+ if (call->backtrace != NULL) {
+ os << bold << red << "Backtrace:\n" << normal;
+ visit(*call->backtrace);
+ }
+ if (callFlags & CALL_FLAG_END_FRAME) {
os << "\n";
}
}
void dump(Call &call, std::ostream &os, DumpFlags flags) {
Dumper d(os, flags);
- os << call.no << " ";
d.visit(&call);
}