[Spice-devel,v3,21/51] Add code to handle destination variable

Submitted by Frediano Ziglio on July 21, 2015, 4:45 p.m.

Details

Message ID 1437497181-26929-22-git-send-email-fziglio@redhat.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Frediano Ziglio July 21, 2015, 4:45 p.m.
Add some classes to be able to store retrieved data from structure
and messages.
The idea is to generate code dynamically when variable are readed.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
---
 python_modules/dissector.py | 104 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 103 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/python_modules/dissector.py b/python_modules/dissector.py
index 40e348a..588becd 100644
--- a/python_modules/dissector.py
+++ b/python_modules/dissector.py
@@ -66,6 +66,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)
@@ -80,7 +180,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()

Comments

On Tue, Jul 21, 2015 at 05:45:51PM +0100, Frediano Ziglio wrote:
> Add some classes to be able to store retrieved data from structure
> and messages.
> The idea is to generate code dynamically when variable are readed.

'are read'

> 
> Signed-off-by: Frediano Ziglio <fziglio@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 40e348a..588becd 100644
> --- a/python_modules/dissector.py
> +++ b/python_modules/dissector.py
> @@ -66,6 +66,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)
> @@ -80,7 +180,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
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel