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

Christophe Fergeau cfergeau at redhat.com
Thu Jul 23 06:13:18 PDT 2015


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 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 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20150723/777fca0f/attachment.sig>


More information about the Spice-devel mailing list