From 501f286cc204a80469885da32c1ca87640ad91fc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Fri, 19 Nov 2010 20:41:18 +0000 Subject: [PATCH] Start migrating to the visitor pattern. --- base.py | 86 ++++++++++++++++++++++++++++++++++++++++++++---- glretrace.py | 66 ++++++++++++++++++++++++------------- trace_model.cpp | 33 +++++++++++-------- trace_model.hpp | 15 +++------ trace_parser.hpp | 8 ++--- 5 files changed, 151 insertions(+), 57 deletions(-) diff --git a/base.py b/base.py index 3c93c42..ab2382f 100644 --- a/base.py +++ b/base.py @@ -31,6 +31,45 @@ import debug all_types = {} + +class Visitor: + + def visit(self, type, *args, **kwargs): + return type.visit(self, *args, **kwargs) + + __call__ = visit + + def visit_void(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_literal(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_const(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_struct(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_array(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_enum(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_bitmask(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_pointer(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_alias(self, type, *args, **kwargs): + raise NotImplementedError + + def visit_opaque(self, type, *args, **kwargs): + raise NotImplementedError + + class Type: __seq = 0 @@ -55,6 +94,9 @@ class Type: def __str__(self): return self.expr + def visit(self, visitor, *args, **kwargs): + raise NotImplementedError + def isoutput(self): return False @@ -79,6 +121,9 @@ class _Void(Type): def __init__(self): Type.__init__(self, "void") + def visit(self, visitor, *args, **kwargs): + return visitor.visit_void(self, *args, **kwargs) + Void = _Void() @@ -106,6 +151,9 @@ class Literal(Concrete): Concrete.__init__(self, expr) self.format = format + def visit(self, visitor, *args, **kwargs): + return visitor.visit_literal(self, *args, **kwargs) + def _dump(self, instance): print ' Log::Literal%s(%s);' % (self.format, instance) @@ -123,6 +171,9 @@ class Const(Type): self.type = type + def visit(self, visitor, *args, **kwargs): + return visitor.visit_const(self, *args, **kwargs) + def dump(self, instance): self.type.dump(instance) @@ -133,6 +184,9 @@ class Pointer(Type): Type.__init__(self, type.expr + " *", 'P' + type.id) self.type = type + def visit(self, visitor, *args, **kwargs): + return visitor.visit_pointer(self, *args, **kwargs) + def dump(self, instance): print ' if(%s) {' % instance print ' Log::BeginPointer("%s", (const void *)%s);' % (self.type, instance) @@ -168,6 +222,9 @@ class Enum(Concrete): Concrete.__init__(self, name) self.values = values + def visit(self, visitor, *args, **kwargs): + return visitor.visit_enum(self, *args, **kwargs) + def _dump(self, instance): print ' switch(%s) {' % instance for value in self.values: @@ -180,20 +237,20 @@ class Enum(Concrete): print ' }' -class FakeEnum(Enum): - - def __init__(self, type, values): - Enum.__init__(self, type.expr, values) - self.type = type +def FakeEnum(type, values): + return Enum(type.expr, values) -class Flags(Concrete): +class Bitmask(Concrete): def __init__(self, type, values): Concrete.__init__(self, type.expr) self.type = type self.values = values + def visit(self, visitor, *args, **kwargs): + return visitor.visit_bitmask(self, *args, **kwargs) + def _dump(self, instance): print ' %s l_Value = %s;' % (self.type, instance) print ' Log::BeginBitmask("%s");' % (self.type,) @@ -207,6 +264,8 @@ class Flags(Concrete): print ' }' print ' Log::EndBitmask();' +Flags = Bitmask + class Array(Type): @@ -215,6 +274,9 @@ class Array(Type): self.type = type self.length = length + def visit(self, visitor, *args, **kwargs): + return visitor.visit_array(self, *args, **kwargs) + def dump(self, instance): index = '__i' + self.type.id print ' Log::BeginArray("%s", %s);' % (self.type, self.length) @@ -245,6 +307,9 @@ class Struct(Concrete): self.name = name self.members = members + def visit(self, visitor, *args, **kwargs): + return visitor.visit_struct(self, *args, **kwargs) + def _dump(self, instance): print ' Log::BeginStruct("%s");' % (self.name,) for type, name in self.members: @@ -260,6 +325,9 @@ class Alias(Type): Type.__init__(self, name) self.type = type + def visit(self, visitor, *args, **kwargs): + return visitor.visit_alias(self, *args, **kwargs) + def dump(self, instance): self.type.dump(instance) @@ -505,6 +573,9 @@ class _String(Type): def __init__(self): Type.__init__(self, "char *") + def visit(self, visitor, *args, **kwargs): + return visitor.visit_literal(self, *args, **kwargs) + def dump(self, instance): print ' Log::LiteralString((const char *)%s);' % instance @@ -516,6 +587,9 @@ class _Opaque(Type): def __init__(self): Type.__init__(self, "void") + def visit(self, visitor, *args, **kwargs): + return visitor.visit_opaque(self, *args, **kwargs) + def dump(self, instance): print ' Log::LiteralOpaque();' diff --git a/glretrace.py b/glretrace.py index 82cd713..49a467a 100644 --- a/glretrace.py +++ b/glretrace.py @@ -43,15 +43,45 @@ def is_function_supported(function): return True -def extract_value(arg_type, arg_value): - if isinstance(arg_type, base.Literal): - return 'Trace::as%s(%s)' % (arg_type.format, value) - if isinstance(arg_type, base.Enum): - return 'Trace::asSInt(%s)' % (value) - if isinstance(arg_type, (base.Alias, base.Flags)): - return extract_value(arg_type.type, value) - assert false - return '0' +class ValueExtractor(base.Visitor): + + def visit_literal(self, type, lvalue, rvalue): + #print ' %s = static_cast<%s>(Trace::as%s(%s));' % (lvalue, type, type.format, rvalue) + print ' %s = Trace::as%s(%s);' % (lvalue, type.format, rvalue) + + def visit_alias(self, type, lvalue, rvalue): + self.visit(type.type, lvalue, rvalue) + + def visit_enum(self, type, lvalue, rvalue): + #print ' %s = static_cast<%s>(Trace::as%s(%s));' % (lvalue, type, 'SInt', rvalue) + print ' %s = Trace::as%s(%s);' % (lvalue, 'SInt', rvalue) + + def visit_bitmask(self, type, lvalue, rvalue): + self.visit(type.type, lvalue, rvalue) + + + +def retrace_function(function): + print 'static void retrace_%s(Trace::Call &call) {' % function.name + if not function.name.startswith('glX'): + success = True + for arg_type, arg_name in function.args: + print ' %s %s;' % (arg_type, arg_name) + for arg_type, arg_name in function.args: + rvalue = 'call.arg("%s")' % (arg_name,) + lvalue = arg_name + try: + ValueExtractor().visit(arg_type, lvalue, rvalue) + except NotImplementedError: + success = False + print ' %s = 0; // FIXME' % arg_name + if not success: + print ' std::cerr << "warning: unsupported call %s\\n";' % function.name + print ' return;' + arg_names = ", ".join([arg_name for arg_type, arg_name in function.args]) + print ' %s(%s);' % (function.name, arg_names) + print '}' + print if __name__ == '__main__': @@ -66,26 +96,16 @@ if __name__ == '__main__': functions = filter(is_function_supported, libgl.functions) - for function in functions: - print 'static void retrace_%s(Trace::Call &call) {' % function.name - for arg_type, arg_name in function.args: - print ' %s %s;' % (arg_type, arg_name) - for arg_type, arg_name in function.args: - value = 'call.get_arg("%s")' % (arg_name,) - value = extract_value(arg_type, value) - print ' %s = static_cast<%s>(%s);' % (arg_name, arg_type, value) - arg_names = ", ".join([arg_name for arg_type, arg_name in function.args]) - print ' %s(%s);' % (function.name, arg_names) - print '}' - print + for function in libgl.functions: + retrace_function(function) print 'static bool retrace_call(Trace::Call &call) {' - for function in functions: + for function in libgl.functions: print ' if (call.name == "%s") {' % function.name print ' retrace_%s(call);' % function.name print ' return true;' print ' }' - print ' std::cerr << "Unsupported call " << call.name << "\\n";' + print ' std::cerr << "warning: unsupported call " << call.name << "\\n";' print ' return false;' print '}' print ''' diff --git a/trace_model.cpp b/trace_model.cpp index 1d33ba6..8f10224 100644 --- a/trace_model.cpp +++ b/trace_model.cpp @@ -121,28 +121,26 @@ std::ostream & operator <<(std::ostream &os, Value *value) { } -static const Value *unwrap(const Value *node) { - const Const *c = dynamic_cast(node); +static const Value *unwrap(const Value &node) { + const Const *c = dynamic_cast(&node); if (c) return c->value; - return node; + return &node; } -signed long long asSInt(const Value *node) { - node = unwrap(node); - const SInt *sint = dynamic_cast(node); +signed long long asSInt(const Value &node) { + const SInt *sint = dynamic_cast(unwrap(node)); if (sint) return sint->value; - const UInt *uint = dynamic_cast(node); + const UInt *uint = dynamic_cast(unwrap(node)); if (uint) return uint->value; assert(0); return 0; } -unsigned long long asUInt(const Value *node) { - node = unwrap(node); - const UInt *uint = dynamic_cast(node); +unsigned long long asUInt(const Value &node) { + const UInt *uint = dynamic_cast(unwrap(node)); if (uint) return uint->value; assert(0); @@ -150,13 +148,22 @@ unsigned long long asUInt(const Value *node) { } -double asFloat(const Value *node) { - node = unwrap(node); - const Float *fl = dynamic_cast(node); +double asFloat(const Value &node) { + const Float *fl = dynamic_cast(unwrap(node)); assert(fl); return fl->value; } +static Void void_; + +Value & Call::arg(const char *name) { + for (std::list::iterator it = args.begin(); it != args.end(); ++it) { + if (it->first == name) { + return *it->second; + } + } + return void_; +} std::ostream & operator <<(std::ostream &os, Call &call) { const char *sep = ""; diff --git a/trace_model.hpp b/trace_model.hpp index 9bb3e1d..8702374 100644 --- a/trace_model.hpp +++ b/trace_model.hpp @@ -153,9 +153,9 @@ public: std::ostream & operator <<(std::ostream &os, Value *value); -signed long long asSInt(const Value *node); -unsigned long long asUInt(const Value *node); -double asFloat(const Value *node); +signed long long asSInt(const Value &node); +unsigned long long asUInt(const Value &node); +double asFloat(const Value &node); typedef std::pair Arg; @@ -169,14 +169,7 @@ public: Call() : ret(0) { } - Value * get_arg(const char *name) { - for (std::list::iterator it = args.begin(); it != args.end(); ++it) { - if (it->first == name) { - return it->second; - } - } - return NULL; - } + Value & arg(const char *name); }; diff --git a/trace_parser.hpp b/trace_parser.hpp index 50f315c..221957b 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -59,7 +59,7 @@ public: version = read_uint(); if (version != TRACE_VERSION) { - std::cerr << "Unsupported format version" << version << "\n"; + std::cerr << "error: unsupported format version" << version << "\n"; return false; } @@ -90,7 +90,7 @@ public: break; default: assert(0); - std::cerr << "Unknown call detail " << c << "\n"; + std::cerr << "error: unknown call detail " << c << "\n"; break; } } while(true); @@ -134,7 +134,7 @@ public: case Trace::TYPE_VOID: return NULL; default: - std::cerr << "Unknown type " << c << "\n"; + std::cerr << "error: unknown type " << c << "\n"; assert(0); return NULL; } @@ -194,7 +194,7 @@ public: case Trace::TYPE_VOID: goto done; default: - std::cerr << "Unexpected type " << c << "\n"; + std::cerr << "error: uexpected type " << c << "\n"; assert(0); return NULL; } -- 2.45.2