[Spice-devel] [PATCH v4 11/41] dissector: Add code to handle destination variable
Frediano Ziglio
fziglio at redhat.com
Thu Jul 23 08:54:28 PDT 2015
Add some classes to be able to store retrieved data from structure
and messages.
The idea is to generate code dynamically when variable are read.
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
python_modules/dissector.py | 104 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 103 insertions(+), 1 deletion(-)
diff --git a/python_modules/dissector.py b/python_modules/dissector.py
index ea13033..10da2e7 100644
--- a/python_modules/dissector.py
+++ b/python_modules/dissector.py
@@ -67,6 +67,106 @@ def write_parser_helpers(writer):
writer.writeln('#endif')
writer.newline()
+# generate code to declare a variable only when needed
+# code is generated only when we read the reference
+class Reference:
+ def __init__(self, writer, name):
+ self.defined = False
+ self.written = False
+ self.name = name
+ # create a subwriter to write code to read variable only once
+ self.writer = writer.get_subwriter()
+
+ def write(self, size, value, scope):
+ if not size in (8, 16, 32, 64):
+ raise Exception('Unknown size %d for %s' % (size, self.name))
+ assert(not self.defined or (value, size) == (self.value, self.size))
+ if not self.defined:
+ self.value = value
+ self.size = size
+ self.scope = scope
+ self.defined = True
+
+ def read(self):
+ # variable not yet defined
+ assert(self.defined)
+ if not self.written:
+ assert(not self.scope.variable_defined(self.name))
+ t = { 8: 'guint32', 16: 'guint32', 32: 'guint32', 64: 'guint64' }[self.size]
+ self.scope.variable_def(t, self.name)
+ self.writer.assign(self.name, self.value)
+ self.written = True
+ return self.name
+
+class Level:
+ def __init__(self, n=0):
+ self.level = n
+ def __enter__(self):
+ self.level += 1
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.level -= 1
+ def __getattr__(self, name):
+ if not name in {'tree', 'ti'}:
+ raise Exception('Not possible to get name %s' % name)
+ return name if self.level == 0 else name + str(self.level)
+
+# represent part of a destination to write to
+# for instance if we are parsing a structure dest represent that structure output
+class Destination:
+ def __init__(self, scope):
+ self.refs = {}
+ self.is_helper = False
+ self.reuse_scope = scope
+ self.parent_dest = None
+ self.level = Level()
+
+ def child_sub(self, member, scope):
+ return SubDestination(self, member, scope)
+
+ def declare(self, writer):
+ return writer.optional_block(self.reuse_scope)
+
+ def is_toplevel(self):
+ return self.parent_dest == None and not self.is_helper
+
+ def read_ref(self, member):
+ return self.get_ref(member).read()
+
+ def write_ref(self, writer, size, member, value):
+ ref = self.get_ref(member, writer)
+ ref.write(size, value, self.reuse_scope)
+
+ def ref_size(self, member):
+ return self.get_ref(member).size
+
+class RootDestination(Destination):
+ def __init__(self, scope):
+ Destination.__init__(self, scope)
+ self.base_var = "fld"
+
+ def get_ref(self, member, writer=None):
+ name = (self.base_var + "." + member).replace('.', '__')
+ if name in self.refs:
+ return self.refs[name]
+ if not writer:
+ raise Exception('trying to read a reference to %s' % member)
+ self.refs[name] = ref = Reference(writer, name)
+ return ref
+
+ def declare(self, writer):
+ return writer.no_block(self.reuse_scope)
+
+class SubDestination(Destination):
+ def __init__(self, parent_dest, member, scope):
+ Destination.__init__(self, scope)
+ self.parent_dest = parent_dest
+ self.member = member
+ self.level = parent_dest.level
+
+ def get_ref(self, member, writer=None):
+ return self.parent_dest.get_ref(self.member + "." + member, writer)
+
+
def write_msg_parser(writer, message, server):
msg_name = message.c_name()
function_name = "dissect_spice_%s_%s" % ('server' if server else 'client', msg_name)
@@ -81,7 +181,9 @@ def write_msg_parser(writer, message, server):
writer.ifdef(message)
parent_scope = writer.function(function_name,
"guint32",
- "GlobalInfo *glb _U_, proto_tree *tree0 _U_, guint32 offset", True)
+ "GlobalInfo *glb _U_, proto_tree *tree _U_, guint32 offset", True)
+
+ dest = RootDestination(parent_scope)
writer.statement("return offset")
writer.end_block()
--
2.1.0
More information about the Spice-devel
mailing list