**************************************************************************/
+#include "formatter.hpp"
#include "trace_model.hpp"
namespace Trace {
-void Null::visit(Visitor &visitor) {
- visitor.visit(this);
-}
+Call::~Call() {
+ for (unsigned i = 0; i < args.size(); ++i) {
+ delete args[i];
+ }
-void Bool::visit(Visitor &visitor) {
- visitor.visit(this);
+ if (ret) {
+ delete ret;
+ }
}
-void SInt::visit(Visitor &visitor) {
- visitor.visit(this);
-}
-void UInt::visit(Visitor &visitor) {
- visitor.visit(this);
+Struct::~Struct() {
+ for (std::vector<Value *>::iterator it = members.begin(); it != members.end(); ++it) {
+ delete *it;
+ }
}
-void Float::visit(Visitor &visitor) {
- visitor.visit(this);
-}
-void String::visit(Visitor &visitor) {
- visitor.visit(this);
+Array::~Array() {
+ for (std::vector<Value *>::iterator it = values.begin(); it != values.end(); ++it) {
+ delete *it;
+ }
}
-void Const::visit(Visitor &visitor) {
- visitor.visit(this);
+Blob::~Blob() {
+ // TODO: Don't leak blobs. Blobs are often bound and accessed during many
+ // calls, so we can't delete them here.
+ //delete [] buf;
}
-void Array::visit(Visitor &visitor) {
- visitor.visit(this);
-}
-void Blob::visit(Visitor &visitor) {
- visitor.visit(this);
-}
+// bool cast
+Null ::operator bool(void) const { return false; }
+Bool ::operator bool(void) const { return value; }
+SInt ::operator bool(void) const { return value != 0; }
+UInt ::operator bool(void) const { return value != 0; }
+Float ::operator bool(void) const { return value != 0; }
+String ::operator bool(void) const { return true; }
+Enum ::operator bool(void) const { return static_cast<bool>(*sig->second); }
+Struct ::operator bool(void) const { return true; }
+Array ::operator bool(void) const { return true; }
+Blob ::operator bool(void) const { return true; }
+Pointer::operator bool(void) const { return value != 0; }
+
+
+// signed integer cast
+Value ::operator signed long long (void) const { assert(0); return 0; }
+Null ::operator signed long long (void) const { return 0; }
+Bool ::operator signed long long (void) const { return static_cast<signed long long>(value); }
+SInt ::operator signed long long (void) const { return value; }
+UInt ::operator signed long long (void) const { assert(static_cast<signed long long>(value) >= 0); return static_cast<signed long long>(value); }
+Float ::operator signed long long (void) const { return static_cast<signed long long>(value); }
+Enum ::operator signed long long (void) const { return static_cast<signed long long>(*sig->second); }
+
+
+// unsigned integer cast
+Value ::operator unsigned long long (void) const { assert(0); return 0; }
+Null ::operator unsigned long long (void) const { return 0; }
+Bool ::operator unsigned long long (void) const { return static_cast<unsigned long long>(value); }
+SInt ::operator unsigned long long (void) const { assert(value >= 0); return static_cast<signed long long>(value); }
+UInt ::operator unsigned long long (void) const { return value; }
+Float ::operator unsigned long long (void) const { return static_cast<unsigned long long>(value); }
+Enum ::operator unsigned long long (void) const { return static_cast<unsigned long long>(*sig->second); }
+
+
+// floating point cast
+Value ::operator double (void) const { assert(0); return 0; }
+Null ::operator double (void) const { return 0; }
+Bool ::operator double (void) const { return static_cast<double>(value); }
+SInt ::operator double (void) const { return static_cast<double>(value); }
+UInt ::operator double (void) const { return static_cast<double>(value); }
+Float ::operator double (void) const { return value; }
+Enum ::operator double (void) const { return static_cast<unsigned long long>(*sig->second); }
+
+
+// blob cast
+void * Value ::blob(void) const { assert(0); return NULL; }
+void * Null ::blob(void) const { return NULL; }
+void * Blob ::blob(void) const { return buf; }
+void * Pointer::blob(void) const { assert(value < 0x100000ULL); return (void *)value; }
+
+
+// virtual Value::visit()
+void Null ::visit(Visitor &visitor) { visitor.visit(this); }
+void Bool ::visit(Visitor &visitor) { visitor.visit(this); }
+void SInt ::visit(Visitor &visitor) { visitor.visit(this); }
+void UInt ::visit(Visitor &visitor) { visitor.visit(this); }
+void Float ::visit(Visitor &visitor) { visitor.visit(this); }
+void String ::visit(Visitor &visitor) { visitor.visit(this); }
+void Enum ::visit(Visitor &visitor) { visitor.visit(this); }
+void Bitmask::visit(Visitor &visitor) { visitor.visit(this); }
+void Struct ::visit(Visitor &visitor) { visitor.visit(this); }
+void Array ::visit(Visitor &visitor) { visitor.visit(this); }
+void Blob ::visit(Visitor &visitor) { visitor.visit(this); }
+void Pointer::visit(Visitor &visitor) { visitor.visit(this); }
+
+
+void Visitor::visit(Null *) { assert(0); }
+void Visitor::visit(Bool *) { assert(0); }
+void Visitor::visit(SInt *) { assert(0); }
+void Visitor::visit(UInt *) { assert(0); }
+void Visitor::visit(Float *) { assert(0); }
+void Visitor::visit(String *) { assert(0); }
+void Visitor::visit(Enum *node) { _visit(node->sig->second); }
+void Visitor::visit(Bitmask *node) { visit(static_cast<UInt *>(node)); }
+void Visitor::visit(Struct *) { assert(0); }
+void Visitor::visit(Array *) { assert(0); }
+void Visitor::visit(Blob *) { assert(0); }
+void Visitor::visit(Pointer *) { assert(0); }
class Dumper : public Visitor
{
+protected:
+ std::ostream &os;
+ Formatter::Formatter *formatter;
+ Formatter::Attribute *normal;
+ Formatter::Attribute *bold;
+ Formatter::Attribute *italic;
+ Formatter::Attribute *red;
+ Formatter::Attribute *pointer;
+ Formatter::Attribute *literal;
+
public:
- std::ostream &os;
-
- Dumper() : os(std::cout) {}
-
- Dumper(std::ostream &_os) : os(_os) {}
-
- void visit(Null *node) {
- os << "NULL";
- }
-
- void visit(Bool *node) {
- os << (node->value ? "true" : "false");
- }
-
- void visit(SInt *node) {
- os << node->value;
- }
-
- void visit(UInt *node) {
- os << node->value;
- }
-
- void visit(Float *node) {
- os << node->value;
- }
-
- void visit(String *node) {
- os << '"' << node->value << '"';
- }
-
- void visit(Const *node) {
- os << node->name;
- }
-
- void visit(Array *array) {
- if (array->values.size() == 1) {
- os << "&";
- array->values[0]->visit(*this);
- }
- else {
- const char *sep = "";
- os << "{";
- for (std::vector<Value *>::iterator it = array->values.begin(); it != array->values.end(); ++it) {
- os << sep;
- (*it)->visit(*this);
- sep = ", ";
- }
- os << "}";
- }
- }
-
- void visit(Blob *blob) {
- os << "... " << blob->size;
- }
-};
+ Dumper(std::ostream &_os) : os(_os) {
+ formatter = Formatter::defaultFormatter();
+ normal = formatter->normal();
+ bold = formatter->bold();
+ italic = formatter->italic();
+ red = formatter->color(Formatter::RED);
+ pointer = formatter->color(Formatter::GREEN);
+ literal = formatter->color(Formatter::BLUE);
+ }
+ ~Dumper() {
+ delete normal;
+ delete bold;
+ delete italic;
+ delete red;
+ delete pointer;
+ delete literal;
+ delete formatter;
+ }
-std::ostream & operator <<(std::ostream &os, Value *value) {
- Dumper d(os);
- if (value) {
- value->visit(d);
- }
- return os;
-}
+ void visit(Null *) {
+ os << "NULL";
+ }
+ void visit(Bool *node) {
+ os << literal << (node->value ? "true" : "false") << normal;
+ }
-static inline const Value *unwrap(const Value *node) {
- const Const *c = dynamic_cast<const Const *>(node);
- if (c)
- return c->value;
- return node;
-}
+ void visit(SInt *node) {
+ os << literal << node->value << normal;
+ }
+ void visit(UInt *node) {
+ os << literal << node->value << normal;
+ }
-Value::operator signed long long(void) const {
- const SInt *sint = dynamic_cast<const SInt *>(unwrap(this));
- if (sint)
- return sint->value;
- const UInt *uint = dynamic_cast<const UInt *>(unwrap(this));
- if (uint)
- return uint->value;
- assert(0);
- return 0;
-}
+ void visit(Float *node) {
+ os << literal << node->value << normal;
+ }
+
+ void visit(String *node) {
+ os << literal << "\"";
+ for (std::string::const_iterator it = node->value.begin(); it != node->value.end(); ++it) {
+ unsigned char c = (unsigned char) *it;
+ if (c == '\"')
+ os << "\\\"";
+ else if (c == '\\')
+ os << "\\\\";
+ else if (c >= 0x20 && c <= 0x7e)
+ os << c;
+ else if (c == '\t') {
+ os << "\t";
+ } else if (c == '\r') {
+ // Ignore carriage-return
+ } else if (c == '\n') {
+ // Reset formatting so that it looks correct with 'less -R'
+ os << normal << '\n' << literal;
+ } else {
+ unsigned octal0 = c & 0x7;
+ unsigned octal1 = (c >> 3) & 0x7;
+ unsigned octal2 = (c >> 3) & 0x7;
+ os << "\\";
+ if (octal2)
+ os << octal2;
+ if (octal1)
+ os << octal1;
+ os << octal0;
+ }
+ }
+ os << "\"" << normal;
+ }
+
+ void visit(Enum *node) {
+ os << literal << node->sig->first << normal;
+ }
+
+ void visit(Bitmask *bitmask) {
+ unsigned long long value = bitmask->value;
+ const Bitmask::Signature *sig = bitmask->sig;
+ bool first = true;
+ for (Bitmask::Signature::const_iterator it = sig->begin(); value != 0 && it != sig->end(); ++it) {
+ if ((it->second && (value & it->second) == it->second) ||
+ (!it->second && value == 0)) {
+ if (!first) {
+ os << " | ";
+ }
+ os << literal << it->first << normal;
+ value &= ~it->second;
+ first = false;
+ }
+ }
+ if (value || first) {
+ if (!first) {
+ os << " | ";
+ }
+ os << literal << "0x" << std::hex << value << std::dec << normal;
+ }
+ }
+
+ void visit(Struct *s) {
+ const char *sep = "";
+ os << "{";
+ for (unsigned i = 0; i < s->members.size(); ++i) {
+ os << sep << italic << s->sig->member_names[i] << normal << " = ";
+ _visit(s->members[i]);
+ sep = ", ";
+ }
+ os << "}";
+ }
+
+ void visit(Array *array) {
+ if (array->values.size() == 1) {
+ os << "&";
+ _visit(array->values[0]);
+ }
+ else {
+ const char *sep = "";
+ os << "{";
+ for (std::vector<Value *>::iterator it = array->values.begin(); it != array->values.end(); ++it) {
+ os << sep;
+ _visit(*it);
+ sep = ", ";
+ }
+ os << "}";
+ }
+ }
+
+ void visit(Blob *blob) {
+ os << pointer << "blob(" << blob->size << ")" << normal;
+ }
+
+ void visit(Pointer *p) {
+ os << pointer << "0x" << std::hex << p->value << std::dec << normal;
+ }
-Value::operator unsigned long long(void) const {
- const UInt *uint = dynamic_cast<const UInt *>(unwrap(this));
- if (uint)
- return uint->value;
- assert(0);
- return 0;
+ void visit(Call *call) {
+ const char *sep = "";
+ os << bold << call->sig->name << normal << "(";
+ for (unsigned i = 0; i < call->args.size(); ++i) {
+ os << sep << italic << call->sig->arg_names[i] << normal << " = ";
+ _visit(call->args[i]);
+ sep = ", ";
+ }
+ os << ")";
+ if (call->ret) {
+ os << " = ";
+ _visit(call->ret);
+ }
+ os << "\n";
+ }
+};
+
+
+std::ostream & operator <<(std::ostream &os, Value *value) {
+ Dumper d(os);
+ if (value) {
+ value->visit(d);
+ }
+ return os;
}
-Value::operator double(void) const {
- const Float *fl = dynamic_cast<const Float *>(unwrap(this));
- assert(fl);
- return fl->value;
+static inline const Value *unwrap(const Value *node) {
+ const Enum *c = dynamic_cast<const Enum *>(node);
+ if (c)
+ return c->sig->second;
+ return node;
}
+
static Null null;
const Value & Value::operator[](size_t index) const {
return null;
}
-void * Value::blob(void) const {
- const Blob *blob = dynamic_cast<const Blob *>(unwrap(this));
- if (blob)
- return blob->buf;
- const Null *null = dynamic_cast<const Null *>(unwrap(this));
- if (null);
- return NULL;
- assert(0);
- return NULL;
-}
-
const char * Value::string(void) const {
- const String *string = dynamic_cast<const String *>(unwrap(this));
- if (string)
- return string->value.c_str();
- const Null *null = dynamic_cast<const Null *>(unwrap(this));
- if (null);
- return NULL;
- assert(0);
- return NULL;
-}
-
-Value & Call::arg(const char *name) {
- for (std::list<Arg>::iterator it = args.begin(); it != args.end(); ++it) {
- if (it->first == name) {
- return *it->second;
- }
- }
- return null;
+ const String *string = dynamic_cast<const String *>(unwrap(this));
+ if (string)
+ return string->value.c_str();
+ const Null *null = dynamic_cast<const Null *>(unwrap(this));
+ if (null)
+ return NULL;
+ assert(0);
+ return NULL;
}
std::ostream & operator <<(std::ostream &os, Call &call) {
- const char *sep = "";
- os << call.name << "(";
- for (std::list<Arg>::iterator it = call.args.begin(); it != call.args.end(); ++it) {
- os << sep << it->first << " = " << it->second;
- sep = ", ";
- }
- os << ")";
- if (call.ret) {
- os << " = " << call.ret;
- }
- os << "\n";
- return os;
+ Dumper d(os);
+ os << call.no << " ";
+ d.visit(&call);
+ return os;
}