X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=trace_model.cpp;h=79bb7575801b4842c2bb23be04deacc9986a5c9d;hb=712429a22a8cc9d51b620d433ade6d327fbabbf0;hp=e6ec467ad10bd3cbae8eaeaae030f41ba2b3f982;hpb=d35973cb47a75034dbbb64e9b0a91fcb4cc971d6;p=apitrace diff --git a/trace_model.cpp b/trace_model.cpp index e6ec467..79bb757 100644 --- a/trace_model.cpp +++ b/trace_model.cpp @@ -31,225 +31,319 @@ namespace Trace { -void Null::visit(Visitor &visitor) { - visitor.visit(this); -} - -void Bool::visit(Visitor &visitor) { - visitor.visit(this); -} +Call::~Call() { + for (unsigned i = 0; i < args.size(); ++i) { + delete args[i]; + } -void SInt::visit(Visitor &visitor) { - visitor.visit(this); + if (ret) { + delete ret; + } } -void UInt::visit(Visitor &visitor) { - visitor.visit(this); -} -void Float::visit(Visitor &visitor) { - visitor.visit(this); +Struct::~Struct() { + for (std::vector::iterator it = members.begin(); it != members.end(); ++it) { + delete *it; + } } -void String::visit(Visitor &visitor) { - visitor.visit(this); -} -void Const::visit(Visitor &visitor) { - visitor.visit(this); +Array::~Array() { + for (std::vector::iterator it = values.begin(); it != values.end(); ++it) { + delete *it; + } } -void Bitmask::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 +bool Null ::toBool(void) const { return false; } +bool Bool ::toBool(void) const { return value; } +bool SInt ::toBool(void) const { return value != 0; } +bool UInt ::toBool(void) const { return value != 0; } +bool Float ::toBool(void) const { return value != 0; } +bool String ::toBool(void) const { return true; } +bool Enum ::toBool(void) const { return sig->value != 0; } +bool Struct ::toBool(void) const { return true; } +bool Array ::toBool(void) const { return true; } +bool Blob ::toBool(void) const { return true; } +bool Pointer::toBool(void) const { return value != 0; } + + +// signed integer cast +signed long long Value ::toSInt(void) const { assert(0); return 0; } +signed long long Null ::toSInt(void) const { return 0; } +signed long long Bool ::toSInt(void) const { return static_cast(value); } +signed long long SInt ::toSInt(void) const { return value; } +signed long long UInt ::toSInt(void) const { assert(static_cast(value) >= 0); return static_cast(value); } +signed long long Float ::toSInt(void) const { return static_cast(value); } +signed long long Enum ::toSInt(void) const { return sig->value; } + + +// unsigned integer cast +unsigned long long Value ::toUInt(void) const { assert(0); return 0; } +unsigned long long Null ::toUInt(void) const { return 0; } +unsigned long long Bool ::toUInt(void) const { return static_cast(value); } +unsigned long long SInt ::toUInt(void) const { assert(value >= 0); return static_cast(value); } +unsigned long long UInt ::toUInt(void) const { return value; } +unsigned long long Float ::toUInt(void) const { return static_cast(value); } +unsigned long long Enum ::toUInt(void) const { assert(sig->value >= 0); return sig->value; } + + +// floating point cast +float Value ::toFloat(void) const { assert(0); return 0; } +float Null ::toFloat(void) const { return 0; } +float Bool ::toFloat(void) const { return static_cast(value); } +float SInt ::toFloat(void) const { return static_cast(value); } +float UInt ::toFloat(void) const { return static_cast(value); } +float Float ::toFloat(void) const { return value; } +float Enum ::toFloat(void) const { return static_cast(sig->value); } + + +// floating point cast +double Value ::toDouble(void) const { assert(0); return 0; } +double Null ::toDouble(void) const { return 0; } +double Bool ::toDouble(void) const { return static_cast(value); } +double SInt ::toDouble(void) const { return static_cast(value); } +double UInt ::toDouble(void) const { return static_cast(value); } +double Float ::toDouble(void) const { return value; } +double Enum ::toDouble(void) const { return static_cast(sig->value); } + + +// pointer cast +void * Value ::toPointer(void) const { assert(0); return NULL; } +void * Null ::toPointer(void) const { return NULL; } +void * Blob ::toPointer(void) const { return buf; } +void * Pointer::toPointer(void) const { return (void *)value; } + + +// pointer cast +unsigned long long Value ::toUIntPtr(void) const { assert(0); return 0; } +unsigned long long Null ::toUIntPtr(void) const { return 0; } +unsigned long long Pointer::toUIntPtr(void) const { return value; } + + +// string cast +const char * Value ::toString(void) const { assert(0); return NULL; } +const char * Null ::toString(void) const { return NULL; } +const char * String::toString(void) const { return 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) { assert(0); } +void Visitor::visit(Bitmask *node) { visit(static_cast(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; + 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: - 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; - } - - void visit(Null *) { - os << "NULL"; - } - - void visit(Bool *node) { - os << literal << (node->value ? "true" : "false") << normal; - } - - void visit(SInt *node) { - os << literal << node->value << normal; - } - - void visit(UInt *node) { - os << literal << node->value << normal; - } - - void visit(Float *node) { - os << literal << node->value << normal; - } - - void visit(String *node) { - os << literal << '"' << node->value << '"' << normal; - } - - void visit(Const *node) { - os << literal << node->name << 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) { - assert(it->second); - if ((value & it->second) == it->second) { - if (!first) { - os << " | "; - } - os << literal << it->first << normal; - value &= ~it->second; - first = false; - } - } - if (value || first) { - if (!first) { - os << " | "; - } - os << literal << std::hex << value << std::dec << normal; - } - } - - void visit(Array *array) { - if (array->values.size() == 1) { - os << "&"; - _visit(array->values[0]); - } - else { - const char *sep = ""; - os << "{"; - for (std::vector::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(Call *call) { - const char *sep = ""; - os << bold << call->name << normal << "("; - for (std::vector::iterator it = call->args.begin(); it != call->args.end(); ++it) { - os << sep << italic << it->first << normal << " = "; - _visit(it->second); - sep = ", "; - } - os << ")"; - if (call->ret) { - os << " = "; - _visit(call->ret); - } - os << "\n"; - } -}; + Dumper(std::ostream &_os, bool color) : os(_os) { + formatter = Formatter::defaultFormatter(color); + 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(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 bool(void) const { - const Bool *b = dynamic_cast(unwrap(this)); - if (b) - return b->value; - assert(0); - return false; -} + void visit(Float *node) { + os << literal << node->value << normal; + } -Value::operator signed long long(void) const { - const SInt *sint = dynamic_cast(unwrap(this)); - if (sint) - return sint->value; - const UInt *uint = dynamic_cast(unwrap(this)); - if (uint) - return uint->value; - assert(0); - return 0; -} + void visit(String *node) { + os << literal << "\""; + for (const char *it = node->value; *it; ++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; + } -Value::operator unsigned long long(void) const { - const UInt *uint = dynamic_cast(unwrap(this)); - if (uint) - return uint->value; - assert(0); - return 0; -} + void visit(Enum *node) { + os << literal << node->sig->name << normal; + } + void visit(Bitmask *bitmask) { + 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) { + if ((it->value && (value & it->value) == it->value) || + (!it->value && value == 0)) { + if (!first) { + os << " | "; + } + os << literal << it->name << normal; + value &= ~it->value; + 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 << "}"; + } -Value::operator double(void) const { - const Float *fl = dynamic_cast(unwrap(this)); - assert(fl); - return fl->value; + void visit(Array *array) { + if (array->values.size() == 1) { + os << "&"; + _visit(array->values[0]); + } + else { + const char *sep = ""; + os << "{"; + for (std::vector::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; + } + + 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 << " = "; + if (call->args[i]) { + _visit(call->args[i]); + } else { + os << "?"; + } + sep = ", "; + } + os << ")"; + if (call->ret) { + os << " = "; + _visit(call->ret); + } + os << "\n"; + } +}; + + +void Value::dump(std::ostream &os, bool color) { + Dumper d(os, color); + visit(d); } + static Null null; const Value & Value::operator[](size_t index) const { - const Array *array = dynamic_cast(unwrap(this)); + const Array *array = dynamic_cast(this); if (array) { if (index < array->values.size()) { return *array->values[index]; @@ -258,32 +352,10 @@ const Value & Value::operator[](size_t index) const { return null; } -void * Value::blob(void) const { - const Blob *blob = dynamic_cast(unwrap(this)); - if (blob) - return blob->buf; - const Null *null = dynamic_cast(unwrap(this)); - if (null) - return NULL; - assert(0); - return NULL; -} - -const char * Value::string(void) const { - const String *string = dynamic_cast(unwrap(this)); - if (string) - return string->value.c_str(); - const Null *null = dynamic_cast(unwrap(this)); - if (null) - return NULL; - assert(0); - return NULL; -} - -std::ostream & operator <<(std::ostream &os, Call &call) { - Dumper d(os); - d.visit(&call); - return os; +void Call::dump(std::ostream &os, bool color) { + Dumper d(os, color); + os << no << " "; + d.visit(this); }