[Spice-devel] [PATCH] Remove files moved to spice-protocol

Frediano Ziglio fziglio at redhat.com
Fri Aug 7 07:43:46 PDT 2015


Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
 Makefile.am                    |    2 +-
 autogen.sh                     |    2 -
 configure.ac                   |    1 -
 python_modules/Makefile.am     |   16 -
 python_modules/__init__.py     |    0
 python_modules/codegen.py      |  380 ------------
 python_modules/demarshal.py    | 1270 ----------------------------------------
 python_modules/marshal.py      |  420 -------------
 python_modules/ptypes.py       | 1129 -----------------------------------
 python_modules/spice_parser.py |  162 -----
 10 files changed, 1 insertion(+), 3381 deletions(-)
 delete mode 100644 python_modules/Makefile.am
 delete mode 100644 python_modules/__init__.py
 delete mode 100644 python_modules/codegen.py
 delete mode 100644 python_modules/demarshal.py
 delete mode 100644 python_modules/marshal.py
 delete mode 100644 python_modules/ptypes.py
 delete mode 100644 python_modules/spice_parser.py

diff --git a/Makefile.am b/Makefile.am
index e39273d..ecf7bd9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
 NULL =
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = python_modules common
+SUBDIRS = common
 
 EXTRA_DIST =				\
 	spice_codegen.py		\
diff --git a/autogen.sh b/autogen.sh
index 0a69542..95717c7 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -8,8 +8,6 @@ test -z "$srcdir" && srcdir=.
 olddir=`pwd`
 cd "$srcdir"
 
-git submodule update --init
-
 mkdir -p m4
 autoreconf --verbose --force --install
 
diff --git a/configure.ac b/configure.ac
index bc7ace2..98311bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,7 +47,6 @@ AC_SUBST(SPICE_COMMON_LIBS)
 AC_CONFIG_FILES([
   Makefile
   common/Makefile
-  python_modules/Makefile
 ])
 
 AH_BOTTOM([
diff --git a/python_modules/Makefile.am b/python_modules/Makefile.am
deleted file mode 100644
index 50e1a71..0000000
--- a/python_modules/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-NULL =
-
-PYTHON_MODULES =				\
-	__init__.py				\
-	codegen.py				\
-	demarshal.py				\
-	marshal.py				\
-	ptypes.py				\
-	spice_parser.py				\
-	$(NULL)
-
-EXTRA_DIST = $(PYTHON_MODULES)
-
-DISTCLEANFILES = *.pyc
-
--include $(top_srcdir)/git.mk
diff --git a/python_modules/__init__.py b/python_modules/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/python_modules/codegen.py b/python_modules/codegen.py
deleted file mode 100644
index f7a2048..0000000
--- a/python_modules/codegen.py
+++ /dev/null
@@ -1,380 +0,0 @@
-
-import six
-from io import StringIO
-
-def camel_to_underscores(s, upper = False):
-    res = ""
-    for i in range(len(s)):
-        c = s[i]
-        if i > 0 and c.isupper():
-            res = res + "_"
-        if upper:
-            res = res + c.upper()
-        else:
-            res = res + c.lower()
-    return res
-
-def underscores_to_camel(s):
-    res = ""
-    do_upper = True
-    for i in range(len(s)):
-        c = s[i]
-        if c == "_":
-            do_upper = True
-        else:
-            if do_upper:
-                res = res + c.upper()
-            else:
-                res = res + c
-            do_upper = False
-    return res
-
-proto_prefix = "Temp"
-
-def set_prefix(prefix):
-    global proto_prefix
-    global proto_prefix_upper
-    global proto_prefix_lower
-    proto_prefix = prefix
-    proto_prefix_upper = prefix.upper()
-    proto_prefix_lower = prefix.lower()
-
-def prefix_underscore_upper(*args):
-    s = proto_prefix_upper
-    for arg in args:
-        s = s + "_" + arg
-    return s
-
-def prefix_underscore_lower(*args):
-    s = proto_prefix_lower
-    for arg in args:
-        s = s + "_" + arg
-    return s
-
-def prefix_camel(*args):
-    s = proto_prefix
-    for arg in args:
-        s = s + underscores_to_camel(arg)
-    return s
-
-def increment_identifier(idf):
-    v = idf[-1:]
-    if v.isdigit():
-        return idf[:-1] + str(int(v) + 1)
-    return idf + "2"
-
-def sum_array(array):
-    if len(array) == 0:
-        return 0
-    return " + ".join(array)
-
-class CodeWriter:
-    def __init__(self):
-        self.out = StringIO()
-        self.contents = [self.out]
-        self.indentation = 0
-        self.at_line_start = True
-        self.indexes = ["i", "j", "k", "ii", "jj", "kk"]
-        self.current_index = 0
-        self.generated = {}
-        self.vars = []
-        self.has_error_check = False
-        self.options = {}
-        self.function_helper_writer = None
-        self.index_type = 'uint32_t'
-
-    def set_option(self, opt, value = True):
-        self.options[opt] = value
-
-    def has_option(self, opt):
-        return opt in self.options
-
-    def set_is_generated(self, kind, name):
-        if kind not in self.generated:
-            v = {}
-            self.generated[kind] = v
-        else:
-            v = self.generated[kind]
-        v[name] = 1
-
-    def is_generated(self, kind, name):
-        if kind not in self.generated:
-            return False
-        v = self.generated[kind]
-        return name in v
-
-    def getvalue(self):
-        strs = [writer.getvalue() for writer in self.contents]
-        return "".join(strs)
-
-    def get_subwriter(self):
-        writer = CodeWriter()
-        self.contents.append(writer)
-        self.out = StringIO()
-        self.contents.append(self.out)
-        writer.indentation = self.indentation
-        writer.at_line_start = self.at_line_start
-        writer.index_type = self.index_type
-        writer.generated = self.generated
-        writer.options = self.options
-        writer.public_prefix = self.public_prefix
-
-        return writer
-
-    def write(self, s):
-        # Ensure its a unicode string
-        if six.PY3:
-            s = str(s)
-        else:
-            s = unicode(s)
-
-        if len(s) == 0:
-            return
-
-        if self.at_line_start:
-            self.out.write(u" " * self.indentation)
-            self.at_line_start = False
-        self.out.write(s)
-        return self
-
-    def newline(self):
-        self.out.write(u"\n")
-        self.at_line_start = True
-        return self
-
-    def writeln(self, s):
-        self.write(s)
-        self.newline()
-        return self
-
-    def label(self, s):
-        self.indentation = self.indentation - 1
-        self.write(s + ":")
-        self.indentation = self.indentation + 1
-        self.newline()
-
-    def statement(self, s):
-        self.write(s)
-        self.write(";")
-        self.newline()
-        return self
-
-    def assign(self, var, val):
-        self.write("%s = %s" % (var, val))
-        self.write(";")
-        self.newline()
-        return self
-
-    def increment(self, var, val):
-        self.write("%s += %s" % (var, val))
-        self.write(";")
-        self.newline()
-        return self
-
-    def comment(self, str):
-        self.write("/* " + str + " */")
-        return self
-
-    def todo(self, str):
-        self.comment("TODO: *** %s ***" % str).newline()
-        return self
-
-    def error_check(self, check, label = "error"):
-        self.has_error_check = True
-        with self.block("if (SPICE_UNLIKELY(%s))" % check):
-            if self.has_option("print_error"):
-                self.statement('printf("%%s: Caught error - %s", __PRETTY_FUNCTION__)' % check)
-            if self.has_option("assert_on_error"):
-                self.statement("assert(0)")
-            self.statement("goto %s" % label)
-
-    def indent(self):
-        self.indentation += 4
-
-    def unindent(self):
-        self.indentation -= 4
-        if self.indentation < 0:
-            self.indentation = 0
-
-    def begin_block(self, prefix= "", comment = ""):
-        if len(prefix) > 0:
-            self.write(prefix)
-        if self.at_line_start:
-            self.write("{")
-        else:
-            self.write(" {")
-        if len(comment) > 0:
-            self.write(" ")
-            self.comment(comment)
-        self.newline()
-        self.indent()
-
-    def end_block(self, semicolon=False, newline=True):
-        self.unindent()
-        if self.at_line_start:
-            self.write("}")
-        else:
-            self.write(" }")
-        if semicolon:
-            self.write(";")
-        if newline:
-            self.newline()
-
-    class Block:
-        def __init__(self, writer, semicolon, newline):
-            self.writer = writer
-            self.semicolon = semicolon
-            self.newline = newline
-
-        def __enter__(self):
-            return self.writer.get_subwriter()
-
-        def __exit__(self, exc_type, exc_value, traceback):
-            self.writer.end_block(self.semicolon, self.newline)
-
-    class PartialBlock:
-        def __init__(self, writer, scope, semicolon, newline):
-            self.writer = writer
-            self.scope = scope
-            self.semicolon = semicolon
-            self.newline = newline
-
-        def __enter__(self):
-            return self.scope
-
-        def __exit__(self, exc_type, exc_value, traceback):
-            self.writer.end_block(self.semicolon, self.newline)
-
-    class NoBlock:
-        def __init__(self, scope):
-            self.scope = scope
-
-        def __enter__(self):
-            return self.scope
-
-        def __exit__(self, exc_type, exc_value, traceback):
-            pass
-
-    def block(self, prefix= "", comment = "", semicolon=False, newline=True):
-        self.begin_block(prefix, comment)
-        return self.Block(self, semicolon, newline)
-
-    def partial_block(self, scope, semicolon=False, newline=True):
-        return self.PartialBlock(self, scope, semicolon, newline)
-
-    def no_block(self, scope):
-        return self.NoBlock(scope)
-
-    def optional_block(self, scope):
-        if scope != None:
-            return self.NoBlock(scope)
-        return self.block()
-
-    def for_loop(self, index, limit):
-        return self.block("for (%s = 0; %s < %s; %s++)" % (index, index, limit, index))
-
-    def while_loop(self, expr):
-        return self.block("while (%s)" % (expr))
-
-    def if_block(self, check, elseif=False, newline=True):
-        s = "if (%s)" % (check)
-        if elseif:
-            s = " else " + s
-        self.begin_block(s, "")
-        return self.Block(self, False, newline)
-
-    def variable_defined(self, name):
-        for n in self.vars:
-            if n == name:
-                return True
-        return False
-
-    def variable_def(self, ctype, *names):
-        for n in names:
-            # Strip away initialization
-            i = n.find("=")
-            if i != -1:
-                n = n[0:i]
-            self.vars.append(n.strip())
-        # only add space for non-pointer types
-        if ctype[-1] == "*":
-            ctype = ctype[:-1].rstrip()
-            self.writeln("%s *%s;"%(ctype, ", *".join(names)))
-        else:
-            self.writeln("%s %s;"%(ctype, ", ".join(names)))
-        return self
-
-    def function_helper(self):
-        if self.function_helper_writer != None:
-            writer = self.function_helper_writer.get_subwriter()
-            self.function_helper_writer.newline()
-        else:
-            writer = self.get_subwriter()
-        return writer
-
-    def function(self, name, return_type, args, static = False):
-        self.has_error_check = False
-        self.function_helper_writer = self.get_subwriter()
-        if static:
-            self.write("static ")
-        self.write(return_type)
-        self.write(" %s(%s)"% (name, args)).newline()
-        self.begin_block()
-        self.function_variables_writer = self.get_subwriter()
-        self.function_variables = {}
-        return self.function_variables_writer
-
-    def macro(self, name, args, define):
-        self.write("#define %s(%s) %s" % (name, args, define)).newline()
-
-    def ifdef(self, name):
-        indentation = self.indentation
-        self.indentation = 0;
-        self.write("#ifdef %s" % (name)).newline()
-        self.indentation = indentation
-
-    def ifdef_else(self, name):
-        indentation = self.indentation
-        self.indentation = 0;
-        self.write("#else /* %s */" % (name)).newline()
-        self.indentation = indentation
-
-    def endif(self, name):
-        indentation = self.indentation
-        self.indentation = 0;
-        self.write("#endif /* %s */" % (name)).newline()
-        self.indentation = indentation
-
-    def add_function_variable(self, ctype, name):
-        if name in self.function_variables:
-            assert(self.function_variables[name] == ctype)
-        else:
-            self.function_variables[name] = ctype
-            self.function_variables_writer.variable_def(ctype, name)
-
-    def pop_index(self):
-        index = self.indexes[self.current_index]
-        self.current_index = self.current_index + 1
-        self.add_function_variable(self.index_type, index)
-        return index
-
-    def push_index(self):
-        assert self.current_index > 0
-        self.current_index = self.current_index - 1
-
-    class Index:
-        def __init__(self, writer, val):
-            self.writer = writer
-            self.val = val
-
-        def __enter__(self):
-            return self.val
-
-        def __exit__(self, exc_type, exc_value, traceback):
-            self.writer.push_index()
-
-    def index(self, no_block = False):
-        if no_block:
-            return self.no_block(None)
-        val = self.pop_index()
-        return self.Index(self, val)
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
deleted file mode 100644
index 209eafc..0000000
--- a/python_modules/demarshal.py
+++ /dev/null
@@ -1,1270 +0,0 @@
-
-from . import ptypes
-from . import codegen
-
-# The handling of sizes is somewhat complex, as there are several types of size:
-# * nw_size
-#   This is the network size, i.e. the number of bytes on the network
-#
-# * mem_size
-#   The total amount of memory used for the representation of something inside
-#   spice. This is generally sizeof(C struct), but can be larger if for instance
-#   the type has a variable size array at the end or has a pointer in it that
-#   points to another data chunk (which will be allocated after the main
-#   data chunk). This is essentially how much memory you need to allocate to
-#   contain the data type.
-#
-# * extra_size
-#   This is the size of anything that is not part of the containing structure.
-#   For instance, a primitive (say uint32_t) member has no extra size, because
-#   when allocating its part of the sizeof(MessageStructType) struct. However
-#   a variable array can be places at the end of a structure (@end) and its
-#   size is then extra_size. Note that this extra_size is included in the
-#   mem_size of the enclosing struct, and even if you request the mem_size
-#   of the array itself. However, extra_size is typically not requested
-#   when the full mem_size is also requested.
-#
-#   extra sizes come in two flavours. contains_extra_size means that the item
-#   has a normal presence in the parent container, but has some additional
-#   extra_size it references. For instance via a pointer somewhere in it.
-#   There is also is_extra_size(). This indicates that the whole elements
-#   "normal" mem size should be considered extra size for the container, so
-#   when computing the parent mem_size you should add the mem_size of this
-#   part as extra_size
-
-def write_parser_helpers(writer):
-    if writer.is_generated("helper", "demarshaller"):
-        return
-
-    writer.set_is_generated("helper", "demarshaller")
-
-    writer = writer.function_helper()
-
-    writer.writeln("#ifdef WORDS_BIGENDIAN")
-    for size in [8, 16, 32, 64]:
-        for sign in ["", "u"]:
-            utype = "uint%d" % (size)
-            type = "%sint%d" % (sign, size)
-            swap = "SPICE_BYTESWAP%d" % size
-            if size == 8:
-                writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
-                writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = val" % (type))
-            else:
-                writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr))))" % (type, swap, utype))
-                writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = %s((%s_t)val)" % (utype, swap, utype))
-    writer.writeln("#else")
-    for size in [8, 16, 32, 64]:
-        for sign in ["", "u"]:
-            type = "%sint%d" % (sign, size)
-            writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
-            writer.macro("write_%s" % type, "ptr, val", "(*((%s_t *)(ptr))) = val" % type)
-    writer.writeln("#endif")
-
-    for size in [8, 16, 32, 64]:
-        for sign in ["", "u"]:
-            writer.newline()
-            type = "%sint%d" % (sign, size)
-            ctype = "%s_t" % type
-            scope = writer.function("SPICE_GNUC_UNUSED consume_%s" % type, ctype, "uint8_t **ptr", True)
-            scope.variable_def(ctype, "val")
-            writer.assign("val", "read_%s(*ptr)" % type)
-            writer.increment("*ptr", size // 8)
-            writer.statement("return val")
-            writer.end_block()
-
-    writer.newline()
-    writer.statement("typedef struct PointerInfo PointerInfo")
-    writer.statement("typedef void (*message_destructor_t)(uint8_t *message)")
-    writer.statement("typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor)")
-    writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message)")
-    writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message)")
-
-    writer.newline()
-    writer.begin_block("struct PointerInfo")
-    writer.variable_def("uint64_t", "offset")
-    writer.variable_def("parse_func_t", "parse")
-    writer.variable_def("void **", "dest")
-    writer.variable_def("uint32_t", "nelements")
-    writer.end_block(semicolon=True)
-
-def write_read_primitive(writer, start, container, name, scope):
-    m = container.lookup_member(name)
-    assert(m.is_primitive())
-    writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
-    writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size())
-
-    var = "%s__value" % (name.replace(".", "_"))
-    if not scope.variable_defined(var):
-        scope.variable_def(m.member_type.c_type(), var)
-    writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type()))
-    return var
-
-def write_write_primitive(writer, start, container, name, val):
-    m = container.lookup_member(name)
-    assert(m.is_primitive())
-    writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
-
-    var = "%s__value" % (name)
-    writer.statement("write_%s(pos, %s)" % (m.member_type.primitive_type(), val))
-    return var
-
-def write_read_primitive_item(writer, item, scope):
-    assert(item.type.is_primitive())
-    writer.assign("pos", item.get_position())
-    writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size())
-    var = "%s__value" % (item.subprefix.replace(".", "_"))
-    scope.variable_def(item.type.c_type(), var)
-    writer.assign(var, "read_%s(pos)" % (item.type.primitive_type()))
-    return var
-
-class ItemInfo:
-    def __init__(self, type, prefix, position):
-        self.type = type
-        self.prefix = prefix
-        self.subprefix = prefix
-        self.position = position
-        self.member = None
-
-    def nw_size(self):
-        return self.prefix + "__nw_size"
-
-    def mem_size(self):
-        return self.prefix + "__mem_size"
-
-    def extra_size(self):
-        return self.prefix + "__extra_size"
-
-    def get_position(self):
-        return self.position
-
-class MemberItemInfo(ItemInfo):
-    def __init__(self, member, mprefix, container, start):
-        if not member.is_switch():
-            self.type = member.member_type
-        self.prefix = member.name
-        if mprefix:
-            mprefix = mprefix + "_"
-            self.prefix = mprefix + self.prefix
-        self.subprefix = member.name
-        self.position = "(%s + %s)" % (start, container.get_nw_offset(member, mprefix or "", "__nw_size"))
-        self.member = member
-
-def write_validate_switch_member(writer, mprefix, container, switch_member, scope, parent_scope, start,
-                                 want_nw_size, want_mem_size, want_extra_size):
-    var = container.lookup_member(switch_member.variable)
-    var_type = var.member_type
-
-    v = write_read_primitive(writer, start, container, switch_member.variable, parent_scope)
-
-    item = MemberItemInfo(switch_member, mprefix, container, start)
-
-    first = True
-    for c in switch_member.cases:
-        check = c.get_check(v, var_type)
-        m = c.member
-        with writer.if_block(check, not first, False) as if_scope:
-            item.type = c.member.member_type
-            item.subprefix = item.prefix + "_" + m.name
-            item.member = c.member
-
-            all_as_extra_size = m.is_extra_size() and want_extra_size
-            if not want_mem_size and all_as_extra_size and not scope.variable_defined(item.mem_size()):
-                scope.variable_def("uint32_t", item.mem_size())
-
-            sub_want_mem_size = want_mem_size or all_as_extra_size
-            sub_want_extra_size = want_extra_size and not all_as_extra_size
-
-            write_validate_item(writer, container, item, if_scope, scope, start,
-                                want_nw_size, sub_want_mem_size, sub_want_extra_size)
-
-            if all_as_extra_size:
-                writer.assign(item.extra_size(), item.mem_size())
-
-        first = False
-
-    with writer.block(" else"):
-        if want_nw_size:
-            writer.assign(item.nw_size(), 0)
-        if want_mem_size:
-            writer.assign(item.mem_size(), 0)
-        if want_extra_size:
-            writer.assign(item.extra_size(), 0)
-
-    writer.newline()
-
-def write_validate_struct_function(writer, struct):
-    validate_function = "validate_%s" % struct.c_type()
-    if writer.is_generated("validator", validate_function):
-        return validate_function
-
-    writer.set_is_generated("validator", validate_function)
-    writer = writer.function_helper()
-    scope = writer.function(validate_function, "static intptr_t", "uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor")
-    scope.variable_def("uint8_t *", "start = message_start + offset")
-    scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos")
-    scope.variable_def("size_t", "mem_size", "nw_size")
-    num_pointers = struct.get_num_pointers()
-    if  num_pointers != 0:
-        scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
-
-    writer.newline()
-    with writer.if_block("offset == 0"):
-        writer.statement("return 0")
-
-    writer.newline()
-    writer.error_check("start >= message_end")
-
-    writer.newline()
-    write_validate_container(writer, None, struct, "start", scope, True, True, False)
-
-    writer.newline()
-    writer.comment("Check if struct fits in reported side").newline()
-    writer.error_check("start + nw_size > message_end")
-
-    writer.statement("return mem_size")
-
-    writer.newline()
-    writer.label("error")
-    writer.statement("return -1")
-
-    writer.end_block()
-
-    return validate_function
-
-def write_validate_pointer_item(writer, container, item, scope, parent_scope, start,
-                                want_nw_size, want_mem_size, want_extra_size):
-    if want_nw_size:
-        writer.assign(item.nw_size(), item.type.get_fixed_nw_size())
-
-    if want_mem_size or want_extra_size:
-        target_type = item.type.target_type
-
-        v = write_read_primitive_item(writer, item, scope)
-        if item.type.has_attr("nonnull"):
-            writer.error_check("%s == 0" % v)
-
-        # pointer target is struct, or array of primitives
-        # if array, need no function check
-
-        if target_type.is_array():
-            writer.error_check("message_start + %s >= message_end" % v)
-
-
-            assert target_type.element_type.is_primitive()
-
-            array_item = ItemInfo(target_type, "%s__array" % item.prefix, start)
-            scope.variable_def("uint32_t", array_item.nw_size())
-            # don't create a variable that isn't used, fixes -Werror=unused-but-set-variable
-            need_mem_size = want_mem_size or (
-                want_extra_size and not item.member.has_attr("chunk")
-                and not target_type.is_cstring_length())
-            if need_mem_size:
-                scope.variable_def("uint32_t", array_item.mem_size())
-            if target_type.is_cstring_length():
-                writer.assign(array_item.nw_size(), "spice_strnlen((char *)message_start + %s, message_end - (message_start + %s))" % (v, v))
-                writer.error_check("*(message_start + %s + %s) != 0" % (v, array_item.nw_size()))
-            else:
-                write_validate_array_item(writer, container, array_item, scope, parent_scope, start,
-                                          True, want_mem_size=need_mem_size, want_extra_size=False)
-                writer.error_check("message_start + %s + %s > message_end" % (v, array_item.nw_size()))
-
-            if want_extra_size:
-                if item.member and item.member.has_attr("chunk"):
-                    writer.assign(item.extra_size(), "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
-                elif item.member and item.member.has_attr("nocopy"):
-                    writer.comment("@nocopy, so no extra size").newline()
-                    writer.assign(item.extra_size(), 0)
-                elif target_type.element_type.get_fixed_nw_size == 1:
-                    writer.assign(item.extra_size(), array_item.mem_size())
-                # If not bytes or zero, add padding needed for alignment
-                else:
-                    writer.assign(item.extra_size(), "%s + /* for alignment */ 3" % array_item.mem_size())
-            if want_mem_size:
-                writer.assign(item.mem_size(), "sizeof(void *) + %s" % array_item.mem_size())
-
-        elif target_type.is_struct():
-            validate_function = write_validate_struct_function(writer, target_type)
-            writer.assign("ptr_size", "%s(message_start, message_end, %s, minor)" % (validate_function, v))
-            writer.error_check("ptr_size < 0")
-
-            if want_extra_size:
-                writer.assign(item.extra_size(), "ptr_size + /* for alignment */ 3")
-            if want_mem_size:
-                writer.assign(item.mem_size(), "sizeof(void *) + ptr_size")
-        else:
-            raise NotImplementedError("pointer to unsupported type %s" % target_type)
-
-
-def write_validate_array_item(writer, container, item, scope, parent_scope, start,
-                              want_nw_size, want_mem_size, want_extra_size):
-    array = item.type
-    is_byte_size = False
-    element_type = array.element_type
-    if array.is_bytes_length():
-        nelements = "%s__nbytes" %(item.prefix)
-        real_nelements = "%s__nelements" %(item.prefix)
-        if not parent_scope.variable_defined(real_nelements):
-            parent_scope.variable_def("uint32_t", real_nelements)
-    else:
-        nelements = "%s__nelements" %(item.prefix)
-    if not parent_scope.variable_defined(nelements):
-        parent_scope.variable_def("uint32_t", nelements)
-
-    if array.is_constant_length():
-        writer.assign(nelements, array.size)
-    elif array.is_remaining_length():
-        if element_type.is_fixed_nw_size():
-            if element_type.get_fixed_nw_size() == 1:
-                writer.assign(nelements, "message_end - %s" % item.get_position())
-            else:
-                writer.assign(nelements, "(message_end - %s) / (%s)" %(item.get_position(), element_type.get_fixed_nw_size()))
-        else:
-            raise NotImplementedError("TODO array[] of dynamic element size not done yet")
-    elif array.is_identifier_length():
-        v = write_read_primitive(writer, start, container, array.size, scope)
-        writer.assign(nelements, v)
-    elif array.is_image_size_length():
-        bpp = array.size[1]
-        width = array.size[2]
-        rows = array.size[3]
-        width_v = write_read_primitive(writer, start, container, width, scope)
-        rows_v = write_read_primitive(writer, start, container, rows, scope)
-        # TODO: Handle multiplication overflow
-        if bpp == 8:
-            writer.assign(nelements, "%s * %s" % (width_v, rows_v))
-        elif bpp == 1:
-            writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v))
-        else:
-            writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
-    elif array.is_bytes_length():
-        is_byte_size = True
-        v = write_read_primitive(writer, start, container, array.size[1], scope)
-        writer.assign(nelements, v)
-        writer.assign(real_nelements, 0)
-    elif array.is_cstring_length():
-        writer.todo("cstring array size type not handled yet")
-    else:
-        writer.todo("array size type not handled yet")
-
-    writer.newline()
-
-    nw_size = item.nw_size()
-    mem_size = item.mem_size()
-    extra_size = item.extra_size()
-
-    if is_byte_size and want_nw_size:
-        writer.assign(nw_size, nelements)
-        want_nw_size = False
-
-    if element_type.is_fixed_nw_size() and want_nw_size:
-        element_size = element_type.get_fixed_nw_size()
-        # TODO: Overflow check the multiplication
-        if element_size == 1:
-            writer.assign(nw_size, nelements)
-        else:
-            writer.assign(nw_size, "(%s) * %s" % (element_size, nelements))
-        want_nw_size = False
-
-    if array.has_attr("as_ptr") and want_mem_size:
-        writer.assign(mem_size, "sizeof(void *)")
-        want_mem_size = False
-
-    if array.has_attr("chunk"):
-        if want_mem_size:
-            writer.assign(extra_size, "sizeof(SpiceChunks *)")
-            want_mem_size = False
-        if want_extra_size:
-            writer.assign(extra_size, "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
-            want_extra_size = False
-
-    if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size:
-        # TODO: Overflow check the multiplication
-        if array.has_attr("ptr_array"):
-            writer.assign(mem_size, "sizeof(void *) + SPICE_ALIGN(%s * %s, 4)" % (element_type.sizeof(), nelements))
-        else:
-            writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements))
-        want_mem_size = False
-
-    if not element_type.contains_extra_size() and want_extra_size:
-        writer.assign(extra_size, 0)
-        want_extra_size = False
-
-    if not (want_mem_size or want_nw_size or want_extra_size):
-        return
-
-    start2 = codegen.increment_identifier(start)
-    scope.variable_def("uint8_t *", "%s = %s" % (start2, item.get_position()))
-    if is_byte_size:
-        start2_end = "%s_array_end" % start2
-        scope.variable_def("uint8_t *", start2_end)
-
-    element_item = ItemInfo(element_type, "%s__element" % item.prefix, start2)
-
-    element_nw_size = element_item.nw_size()
-    element_mem_size = element_item.mem_size()
-    element_extra_size = element_item.extra_size()
-    scope.variable_def("uint32_t", element_nw_size)
-    scope.variable_def("uint32_t", element_mem_size)
-    if want_extra_size:
-        scope.variable_def("uint32_t", element_extra_size)
-
-    if want_nw_size:
-        writer.assign(nw_size, 0)
-    if want_mem_size:
-        writer.assign(mem_size, 0)
-    if want_extra_size:
-        writer.assign(extra_size, 0)
-
-    want_element_nw_size = want_nw_size
-    if element_type.is_fixed_nw_size():
-        start_increment = element_type.get_fixed_nw_size()
-    else:
-        want_element_nw_size = True
-        start_increment = element_nw_size
-
-    if is_byte_size:
-        writer.assign(start2_end, "%s + %s" % (start2, nelements))
-
-    with writer.index(no_block = is_byte_size) as index:
-        with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope:
-            if is_byte_size:
-                writer.increment(real_nelements, 1)
-            write_validate_item(writer, container, element_item, scope, parent_scope, start2,
-                                want_element_nw_size, want_mem_size, want_extra_size)
-
-            if want_nw_size:
-                writer.increment(nw_size, element_nw_size)
-            if want_mem_size:
-                if array.has_attr("ptr_array"):
-                    writer.increment(mem_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size)
-                else:
-                    writer.increment(mem_size, element_mem_size)
-            if want_extra_size:
-                writer.increment(extra_size, element_extra_size)
-
-            writer.increment(start2, start_increment)
-    if is_byte_size:
-        writer.error_check("%s != %s" % (start2, start2_end))
-        write_write_primitive(writer, start, container, array.size[1], real_nelements)
-
-def write_validate_struct_item(writer, container, item, scope, parent_scope, start,
-                               want_nw_size, want_mem_size, want_extra_size):
-    struct = item.type
-    start2 = codegen.increment_identifier(start)
-    scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", start2 + " = %s" % (item.get_position()))
-
-    write_validate_container(writer, item.prefix, struct, start2, scope, want_nw_size, want_mem_size, want_extra_size)
-
-def write_validate_primitive_item(writer, container, item, scope, parent_scope, start,
-                                  want_nw_size, want_mem_size, want_extra_size):
-    if want_nw_size:
-        nw_size = item.nw_size()
-        writer.assign(nw_size, item.type.get_fixed_nw_size())
-    if want_mem_size:
-        mem_size = item.mem_size()
-        writer.assign(mem_size, item.type.sizeof())
-    if want_extra_size:
-        writer.assign(item.extra_size(), 0)
-
-def write_validate_item(writer, container, item, scope, parent_scope, start,
-                        want_nw_size, want_mem_size, want_extra_size):
-    if item.member and item.member.has_attr("to_ptr"):
-        want_nw_size = True
-    if item.type.is_pointer():
-        write_validate_pointer_item(writer, container, item, scope, parent_scope, start,
-                                    want_nw_size, want_mem_size, want_extra_size)
-    elif item.type.is_array():
-        write_validate_array_item(writer, container, item, scope, parent_scope, start,
-                                  want_nw_size, want_mem_size, want_extra_size)
-    elif item.type.is_struct():
-        write_validate_struct_item(writer, container, item, scope, parent_scope, start,
-                                   want_nw_size, want_mem_size, want_extra_size)
-    elif item.type.is_primitive():
-        write_validate_primitive_item(writer, container, item, scope, parent_scope, start,
-                                      want_nw_size, want_mem_size, want_extra_size)
-    else:
-        writer.todo("Implement validation of %s" % item.type)
-
-    if item.member and item.member.has_attr("to_ptr"):
-        saved_size = "%s__saved_size" % item.member.name
-        writer.add_function_variable("uint32_t", saved_size + " = 0")
-        writer.assign(saved_size, item.nw_size())
-
-def write_validate_member(writer, mprefix, container, member, parent_scope, start,
-                          want_nw_size, want_mem_size, want_extra_size):
-    if member.has_attr("virtual"):
-        return
-
-    if member.has_minor_attr():
-        prefix = "if (minor >= %s)" % (member.get_minor_attr())
-        newline = False
-    else:
-        prefix = ""
-        newline = True
-    item = MemberItemInfo(member, mprefix, container, start)
-    with writer.block(prefix, newline=newline, comment=member.name) as scope:
-        if member.is_switch():
-            write_validate_switch_member(writer, mprefix, container, member, scope, parent_scope, start,
-                                         want_nw_size, want_mem_size, want_extra_size)
-        else:
-            write_validate_item(writer, container, item, scope, parent_scope, start,
-                                want_nw_size, want_mem_size, want_extra_size)
-
-    if member.has_minor_attr():
-        with writer.block(" else", comment = "minor < %s" % (member.get_minor_attr())):
-            if member.is_array():
-                nelements = "%s__nelements" %(item.prefix)
-                writer.assign(nelements, 0)
-            if want_nw_size:
-                writer.assign(item.nw_size(), 0)
-
-            if want_mem_size:
-                if member.is_fixed_sizeof():
-                    writer.assign(item.mem_size(), member.sizeof())
-                elif member.is_array():
-                    writer.assign(item.mem_size(), 0)
-                else:
-                    raise NotImplementedError("TODO minor check for non-constant items")
-
-            assert not want_extra_size
-
-def write_validate_container(writer, prefix, container, start, parent_scope, want_nw_size, want_mem_size, want_extra_size):
-    def prefix_m(prefix, m):
-        name = m.name
-        if prefix:
-            name = prefix + "_" + name
-        return name
-
-    for m in container.members:
-        sub_want_nw_size = want_nw_size and not m.is_fixed_nw_size()
-        sub_want_mem_size = m.is_extra_size() and want_mem_size
-        sub_want_extra_size = not m.is_extra_size() and m.contains_extra_size()
-        defs = ["size_t"]
-        name = prefix_m(prefix, m)
-        if sub_want_nw_size:
-
-            defs.append (name + "__nw_size")
-        if sub_want_mem_size:
-            defs.append (name + "__mem_size")
-        if sub_want_extra_size:
-            defs.append (name + "__extra_size")
-
-        if sub_want_nw_size or sub_want_mem_size or sub_want_extra_size:
-            parent_scope.variable_def(*defs)
-            write_validate_member(writer, prefix, container, m, parent_scope, start,
-                                  sub_want_nw_size, sub_want_mem_size, sub_want_extra_size)
-            writer.newline()
-
-    if want_nw_size:
-        if prefix:
-            nw_size = prefix + "__nw_size"
-        else:
-            nw_size = "nw_size"
-
-        size = 0
-        for m in container.members:
-            if m.is_fixed_nw_size():
-                size = size + m.get_fixed_nw_size()
-
-        nm_sum = str(size)
-        for m in container.members:
-            name = prefix_m(prefix, m)
-            if not m.is_fixed_nw_size():
-                nm_sum = nm_sum + " + " + name + "__nw_size"
-
-        writer.assign(nw_size, nm_sum)
-
-    if want_mem_size:
-        if prefix:
-            mem_size = prefix + "__mem_size"
-        else:
-            mem_size = "mem_size"
-
-        mem_sum = container.sizeof()
-        for m in container.members:
-            name = prefix_m(prefix, m)
-            if m.is_extra_size():
-                mem_sum = mem_sum + " + " + name + "__mem_size"
-            elif m.contains_extra_size():
-                mem_sum = mem_sum + " + " + name + "__extra_size"
-
-        writer.assign(mem_size, mem_sum)
-
-    if want_extra_size:
-        if prefix:
-            extra_size = prefix + "__extra_size"
-        else:
-            extra_size = "extra_size"
-
-        extra_sum = []
-        for m in container.members:
-            name = prefix_m(prefix, m)
-            if m.is_extra_size():
-                extra_sum.append(name + "__mem_size")
-            elif m.contains_extra_size():
-                extra_sum.append(name + "__extra_size")
-        writer.assign(extra_size, codegen.sum_array(extra_sum))
-
-class DemarshallingDestination:
-    def __init__(self):
-        pass
-
-    def child_at_end(self, writer, t):
-        return RootDemarshallingDestination(self, t.c_type(), t.sizeof())
-
-    def child_sub(self, member):
-        return SubDemarshallingDestination(self, member)
-
-    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
-
-class RootDemarshallingDestination(DemarshallingDestination):
-    def __init__(self, parent_dest, c_type, sizeof, pointer = None):
-        self.is_helper = False
-        self.reuse_scope = None
-        self.parent_dest = parent_dest
-        if parent_dest:
-            self.base_var = codegen.increment_identifier(parent_dest.base_var)
-        else:
-            self.base_var = "out"
-        self.c_type = c_type
-        self.sizeof = sizeof
-        self.pointer = pointer # None == at "end"
-
-    def get_ref(self, member):
-        return self.base_var + "->" + member
-
-    def declare(self, writer):
-        if self.reuse_scope:
-            scope = self.reuse_scope
-        else:
-            writer.begin_block()
-            scope = writer.get_subwriter()
-
-        scope.variable_def(self.c_type + " *", self.base_var)
-        if not self.reuse_scope:
-            scope.newline()
-
-        if self.pointer:
-            writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer))
-        else:
-            writer.assign(self.base_var, "(%s *)end" % (self.c_type))
-            writer.increment("end", self.sizeof)
-        writer.newline()
-
-        if self.reuse_scope:
-            return writer.no_block(self.reuse_scope)
-        else:
-            return writer.partial_block(scope)
-
-class SubDemarshallingDestination(DemarshallingDestination):
-    def __init__(self, parent_dest, member):
-        self.reuse_scope = None
-        self.parent_dest = parent_dest
-        self.base_var = parent_dest.base_var
-        self.member = member
-        self.is_helper = False
-
-    def get_ref(self, member):
-        return self.parent_dest.get_ref(self.member) + "." + member
-
-# Note: during parsing, byte_size types have been converted to count during validation
-def read_array_len(writer, prefix, array, dest, scope, is_ptr):
-    if is_ptr:
-        nelements = "%s__array__nelements" % prefix
-    else:
-        nelements = "%s__nelements" % prefix
-    if dest.is_toplevel() and scope.variable_defined(nelements):
-        return nelements # Already there for toplevel, need not recalculate
-    element_type = array.element_type
-    scope.variable_def("uint32_t", nelements)
-    if array.is_constant_length():
-        writer.assign(nelements, array.size)
-    elif array.is_identifier_length():
-        writer.assign(nelements, dest.get_ref(array.size))
-    elif array.is_remaining_length():
-        if element_type.is_fixed_nw_size():
-            writer.assign(nelements, "(message_end - in) / (%s)" %(element_type.get_fixed_nw_size()))
-        else:
-            raise NotImplementedError("TODO array[] of dynamic element size not done yet")
-    elif array.is_image_size_length():
-        bpp = array.size[1]
-        width = array.size[2]
-        rows = array.size[3]
-        width_v = dest.get_ref(width)
-        rows_v = dest.get_ref(rows)
-        # TODO: Handle multiplication overflow
-        if bpp == 8:
-            writer.assign(nelements, "%s * %s" % (width_v, rows_v))
-        elif bpp == 1:
-            writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v))
-        else:
-            writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
-    elif array.is_bytes_length():
-        writer.assign(nelements, dest.get_ref(array.size[2]))
-    else:
-        raise NotImplementedError("TODO array size type not handled yet")
-    return nelements
-
-def write_switch_parser(writer, container, switch, dest, scope):
-    var = container.lookup_member(switch.variable)
-    var_type = var.member_type
-
-    if switch.has_attr("fixedsize"):
-        scope.variable_def("uint8_t *", "in_save")
-        writer.assign("in_save", "in")
-
-    first = True
-    for c in switch.cases:
-        check = c.get_check(dest.get_ref(switch.variable), var_type)
-        m = c.member
-        with writer.if_block(check, not first, False) as block:
-            t = m.member_type
-            if switch.has_end_attr():
-                dest2 = dest.child_at_end(writer, m.member_type)
-            elif switch.has_attr("anon"):
-                if t.is_struct() and not m.has_attr("to_ptr"):
-                    dest2 = dest.child_sub(m.name)
-                else:
-                    dest2 = dest
-            else:
-                if t.is_struct():
-                    dest2 = dest.child_sub(switch.name + "." + m.name)
-                else:
-                    dest2 = dest.child_sub(switch.name)
-            dest2.reuse_scope = block
-
-            if m.has_attr("to_ptr"):
-                write_parse_to_pointer(writer, t, False, dest2, m.name, block)
-            elif t.is_pointer():
-                write_parse_pointer(writer, t, False, dest2, m.name, block)
-            elif t.is_struct():
-                write_container_parser(writer, t, dest2)
-            elif t.is_primitive():
-                if m.has_attr("zero"):
-                    writer.statement("consume_%s(&in)" % (t.primitive_type()))
-                else:
-                    writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type()))
-                #TODO validate e.g. flags and enums
-            elif t.is_array():
-                nelements = read_array_len(writer, m.name, t, dest, block, False)
-                write_array_parser(writer, m, nelements, t, dest2, block)
-            else:
-                writer.todo("Can't handle type %s" % m.member_type)
-
-        first = False
-
-    writer.newline()
-
-    if switch.has_attr("fixedsize"):
-        writer.assign("in", "in_save + %s" % switch.get_fixed_nw_size())
-
-def write_parse_ptr_function(writer, target_type):
-    if target_type.is_array():
-        parse_function = "parse_array_%s" % target_type.element_type.primitive_type()
-    else:
-        parse_function = "parse_struct_%s" % target_type.c_type()
-    if writer.is_generated("parser", parse_function):
-        return parse_function
-
-    writer.set_is_generated("parser", parse_function)
-
-    writer = writer.function_helper()
-    scope = writer.function(parse_function, "static uint8_t *", "uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor")
-    scope.variable_def("uint8_t *", "in = message_start + this_ptr_info->offset")
-    scope.variable_def("uint8_t *", "end")
-
-    num_pointers = target_type.get_num_pointers()
-    if  num_pointers != 0:
-        scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
-        scope.variable_def("uint32_t", "n_ptr=0")
-        scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
-
-    writer.newline()
-    if target_type.is_array():
-        writer.assign("end", "struct_data")
-    else:
-        writer.assign("end", "struct_data + %s" % (target_type.sizeof()))
-
-    dest = RootDemarshallingDestination(None, target_type.c_type(), target_type.sizeof(), "struct_data")
-    dest.is_helper = True
-    dest.reuse_scope = scope
-    if target_type.is_array():
-        write_array_parser(writer, None, "this_ptr_info->nelements", target_type, dest, scope)
-    else:
-        write_container_parser(writer, target_type, dest)
-
-    if num_pointers != 0:
-        write_ptr_info_check(writer)
-
-    writer.statement("return end")
-
-    if writer.has_error_check:
-        writer.newline()
-        writer.label("error")
-        writer.statement("return NULL")
-
-    writer.end_block()
-
-    return parse_function
-
-def write_array_parser(writer, member, nelements, array, dest, scope):
-    is_byte_size = array.is_bytes_length()
-
-    element_type = array.element_type
-    if member:
-        array_start = dest.get_ref(member.name)
-        at_end = member.has_attr("end")
-    else:
-        array_start = "end"
-        at_end = True
-
-    if element_type == ptypes.uint8 or element_type == ptypes.int8:
-        writer.statement("memcpy(%s, in, %s)" % (array_start, nelements))
-        writer.increment("in", nelements)
-        if at_end:
-            writer.increment("end", nelements)
-    else:
-        with writer.index() as index:
-            if member:
-                array_pos = "%s[%s]" % (array_start, index)
-            else:
-                array_pos = "*(%s *)end" % (element_type.c_type())
-
-            if array.has_attr("ptr_array"):
-                scope.variable_def("void **", "ptr_array")
-                scope.variable_def("int", "ptr_array_index")
-                writer.assign("ptr_array_index", 0)
-                writer.assign("ptr_array", "(void **)%s" % array_start)
-                writer.increment("end", "sizeof(void *) * %s" % nelements)
-                array_start = "end"
-                array_pos = "*(%s *)end" % (element_type.c_type())
-                at_end = True
-
-            with writer.for_loop(index, nelements) as array_scope:
-                if array.has_attr("ptr_array"):
-                    writer.statement("ptr_array[ptr_array_index++] = end")
-                if element_type.is_primitive():
-                    writer.statement("%s = consume_%s(&in)" % (array_pos, element_type.primitive_type()))
-                    if at_end:
-                        writer.increment("end", element_type.sizeof())
-                else:
-                    if at_end:
-                        dest2 = dest.child_at_end(writer, element_type)
-                    else:
-                        dest2 = RootDemarshallingDestination(dest, element_type.c_type(), element_type.c_type(), array_pos)
-                    dest2.reuse_scope = array_scope
-                    write_container_parser(writer, element_type, dest2)
-                if array.has_attr("ptr_array"):
-                    writer.comment("Align ptr_array element to 4 bytes").newline()
-                    writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
-
-def write_parse_pointer_core(writer, target_type, offset, at_end, dest, member_name, scope):
-    writer.assign("ptr_info[n_ptr].offset", offset)
-    writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type))
-    if at_end:
-        writer.assign("ptr_info[n_ptr].dest", "(void **)end")
-        writer.increment("end", "sizeof(void *)")
-    else:
-        writer.assign("ptr_info[n_ptr].dest", "(void **)&%s" % dest.get_ref(member_name))
-    if target_type.is_array():
-        nelements = read_array_len(writer, member_name, target_type, dest, scope, True)
-        writer.assign("ptr_info[n_ptr].nelements", nelements)
-
-    writer.statement("n_ptr++")
-
-def write_parse_pointer(writer, t, at_end, dest, member_name, scope):
-    write_parse_pointer_core(writer, t.target_type, "consume_%s(&in)" % t.primitive_type(),
-                             at_end, dest, member_name, scope)
-
-def write_parse_to_pointer(writer, t, at_end, dest, member_name, scope):
-    write_parse_pointer_core(writer, t, "in - start",
-                             at_end, dest, member_name, scope)
-    writer.increment("in", "%s__saved_size" % member_name)
-
-def write_member_parser(writer, container, member, dest, scope):
-    if member.has_attr("virtual"):
-        writer.assign(dest.get_ref(member.name), member.attributes["virtual"][0])
-        return
-
-    if member.is_switch():
-        write_switch_parser(writer, container, member, dest, scope)
-        return
-
-    t = member.member_type
-
-    if member.has_attr("to_ptr"):
-        write_parse_to_pointer(writer, t, member.has_end_attr(), dest, member.name, scope)
-    elif t.is_pointer():
-        if member.has_attr("chunk"):
-            assert(t.target_type.is_array())
-            nelements = read_array_len(writer, member.name, t.target_type, dest, scope, True)
-            writer.comment("Reuse data from network message as chunk").newline()
-            scope.variable_def("SpiceChunks *", "chunks")
-            writer.assign("chunks", "(SpiceChunks *)end")
-            writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
-            writer.assign(dest.get_ref(member.name), "chunks")
-            writer.assign("chunks->data_size", nelements)
-            writer.assign("chunks->flags", 0)
-            writer.assign("chunks->num_chunks", 1)
-            writer.assign("chunks->chunk[0].len", nelements)
-            writer.assign("chunks->chunk[0].data", "message_start + consume_%s(&in)" % t.primitive_type())
-        elif member.has_attr("nocopy"):
-            writer.comment("Reuse data from network message").newline()
-            writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_%s(&in))" % t.primitive_type())
-        else:
-            write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, scope)
-    elif t.is_primitive():
-        if member.has_attr("zero"):
-            writer.statement("consume_%s(&in)" % t.primitive_type())
-        elif member.has_end_attr():
-            writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type()))
-            writer.increment("end", t.sizeof())
-        else:
-            if member.has_attr("bytes_count"):
-                dest_var = dest.get_ref(member.attributes["bytes_count"][0])
-            else:
-                dest_var = dest.get_ref(member.name)
-            writer.assign(dest_var, "consume_%s(&in)" % (t.primitive_type()))
-        #TODO validate e.g. flags and enums
-    elif t.is_array():
-        nelements = read_array_len(writer, member.name, t, dest, scope, False)
-        if member.has_attr("chunk") and t.element_type.is_fixed_nw_size() and t.element_type.get_fixed_nw_size() == 1:
-            writer.comment("use array as chunk").newline()
-
-            scope.variable_def("SpiceChunks *", "chunks")
-            writer.assign("chunks", "(SpiceChunks *)end")
-            writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
-            writer.assign(dest.get_ref(member.name), "chunks")
-            writer.assign("chunks->data_size", nelements)
-            writer.assign("chunks->flags", 0)
-            writer.assign("chunks->num_chunks", 1)
-            writer.assign("chunks->chunk[0].len", nelements)
-            writer.assign("chunks->chunk[0].data", "in")
-            writer.increment("in", "%s" % (nelements))
-        elif member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size():
-            writer.comment("use array as pointer").newline()
-            writer.assign(dest.get_ref(member.name), "(%s *)in" % t.element_type.c_type())
-            len_var = member.attributes["as_ptr"]
-            if len(len_var) > 0:
-                writer.assign(dest.get_ref(len_var[0]), nelements)
-            el_size = t.element_type.get_fixed_nw_size()
-            if el_size != 1:
-                writer.increment("in", "%s * %s" % (nelements, el_size))
-            else:
-                writer.increment("in", "%s" % (nelements))
-        else:
-            write_array_parser(writer, member, nelements, t, dest, scope)
-    elif t.is_struct():
-        if member.has_end_attr():
-            dest2 = dest.child_at_end(writer, t)
-        else:
-            dest2 = dest.child_sub(member.name)
-        writer.comment(member.name)
-        write_container_parser(writer, t, dest2)
-    else:
-        raise NotImplementedError("TODO can't handle parsing of %s" % t)
-
-def write_container_parser(writer, container, dest):
-    with dest.declare(writer) as scope:
-        for m in container.members:
-            if m.has_minor_attr():
-                writer.begin_block("if (minor >= %s)" % m.get_minor_attr())
-            write_member_parser(writer, container, m, dest, scope)
-            if m.has_minor_attr():
-                # We need to zero out the fixed part of all optional fields
-                if not m.member_type.is_array():
-                    writer.end_block(newline=False)
-                    writer.begin_block(" else")
-                    # TODO: This is not right for fields that don't exist in the struct
-                    if m.has_attr("zero"):
-                        pass
-                    elif m.member_type.is_primitive():
-                        writer.assign(dest.get_ref(m.name), "0")
-                    elif m.is_fixed_sizeof():
-                        writer.statement("memset ((char *)&%s, 0, %s)" % (dest.get_ref(m.name), m.sizeof()))
-                    else:
-                        raise NotImplementedError("TODO Clear optional dynamic fields")
-                writer.end_block()
-
-def write_ptr_info_check(writer):
-    writer.newline()
-    with writer.index() as index:
-        with writer.for_loop(index, "n_ptr") as scope:
-            offset = "ptr_info[%s].offset" % index
-            function = "ptr_info[%s].parse" % index
-            dest = "ptr_info[%s].dest" % index
-            with writer.if_block("%s == 0" % offset, newline=False):
-                writer.assign("*%s" % dest, "NULL")
-            with writer.block(" else"):
-                writer.comment("Align to 32 bit").newline()
-                writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
-                writer.assign("*%s" % dest, "(void *)end")
-                writer.assign("end", "%s(message_start, message_end, end, &ptr_info[%s], minor)" % (function, index))
-                writer.error_check("end == NULL")
-    writer.newline()
-
-def write_nofree(writer):
-    if writer.is_generated("helper", "nofree"):
-        return
-    writer = writer.function_helper()
-    scope = writer.function("nofree", "static void", "SPICE_GNUC_UNUSED uint8_t *data")
-    writer.end_block()
-
-def write_msg_parser(writer, message):
-    msg_name = message.c_name()
-    function_name = "parse_%s" % msg_name
-    if writer.is_generated("demarshaller", function_name):
-        return function_name
-    writer.set_is_generated("demarshaller", function_name)
-
-    msg_type = message.c_type()
-    msg_sizeof = message.sizeof()
-
-    want_mem_size = (len(message.members) != 1 or message.members[0].is_fixed_nw_size()
-                         or not message.members[0].is_array())
-
-    writer.newline()
-    if message.has_attr("ifdef"):
-        writer.ifdef(message.attributes["ifdef"][0])
-    parent_scope = writer.function(function_name,
-                                   "uint8_t *",
-                                   "uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message", True)
-    parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos")
-    parent_scope.variable_def("uint8_t *", "start = message_start")
-    parent_scope.variable_def("uint8_t *", "data = NULL")
-    parent_scope.variable_def("size_t", "nw_size")
-    if want_mem_size:
-        parent_scope.variable_def("size_t", "mem_size")
-    if not message.has_attr("nocopy"):
-        parent_scope.variable_def("uint8_t *", "in", "end")
-    num_pointers = message.get_num_pointers()
-    if  num_pointers != 0:
-        parent_scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
-        parent_scope.variable_def("uint32_t", "n_ptr=0")
-        parent_scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
-    writer.newline()
-
-    write_parser_helpers(writer)
-
-    write_validate_container(writer, None, message, "start", parent_scope, True,
-                             want_mem_size=want_mem_size, want_extra_size=False)
-
-    writer.newline()
-
-    writer.comment("Check if message fits in reported side").newline()
-    with writer.block("if (start + nw_size > message_end)"):
-        writer.statement("return NULL")
-
-    writer.newline().comment("Validated extents and calculated size").newline()
-
-    if message.has_attr("nocopy"):
-        write_nofree(writer)
-        writer.assign("data", "message_start")
-        writer.assign("*size", "message_end - message_start")
-        writer.assign("*free_message", "nofree")
-    else:
-        writer.assign("data", "(uint8_t *)malloc(mem_size)")
-        writer.error_check("data == NULL")
-        writer.assign("end", "data + %s" % (msg_sizeof))
-        writer.assign("in", "start").newline()
-
-        # avoid defined and assigned but not used warnings of gcc 4.6.0+
-        if message.is_extra_size() or not message.is_fixed_nw_size() or message.get_fixed_nw_size() > 0:
-            dest = RootDemarshallingDestination(None, msg_type, msg_sizeof, "data")
-            dest.reuse_scope = parent_scope
-            write_container_parser(writer, message, dest)
-
-        writer.newline()
-        writer.statement("assert(in <= message_end)")
-
-        if num_pointers != 0:
-            write_ptr_info_check(writer)
-
-        writer.statement("assert(end <= data + mem_size)")
-
-        writer.newline()
-        writer.assign("*size", "end - data")
-        writer.assign("*free_message", "(message_destructor_t) free")
-
-    writer.statement("return data")
-    writer.newline()
-    if writer.has_error_check:
-        writer.label("error")
-        with writer.block("if (data != NULL)"):
-            writer.statement("free(data)")
-        writer.statement("return NULL")
-    writer.end_block()
-
-    if message.has_attr("ifdef"):
-        writer.endif(message.attributes["ifdef"][0])
-
-    return function_name
-
-def write_channel_parser(writer, channel, server):
-    writer.newline()
-    ids = {}
-    min_id = 1000000
-    if server:
-        messages = channel.server_messages
-    else:
-        messages = channel.client_messages
-    for m in messages:
-        ids[m.value] = m
-
-    ranges = []
-    ids2 = ids.copy()
-    while len(ids2) > 0:
-        end = start = min(ids2.keys())
-        while end in ids2:
-            del ids2[end]
-            end = end + 1
-
-        ranges.append( (start, end) )
-
-    if server:
-        function_name = "parse_%s_msg" % channel.name
-    else:
-        function_name = "parse_%s_msgc" % channel.name
-    writer.newline()
-    if channel.has_attr("ifdef"):
-        writer.ifdef(channel.attributes["ifdef"][0])
-    scope = writer.function(function_name,
-                            "static uint8_t *",
-                            "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message")
-
-    helpers = writer.function_helper()
-
-    d = 0
-    for r in ranges:
-        d = d + 1
-        writer.write("static parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0]))
-        writer.begin_block()
-        for i in range(r[0], r[1]):
-            func = write_msg_parser(helpers, ids[i].message_type)
-            writer.write(func)
-            if i != r[1] -1:
-                writer.write(",")
-            writer.newline()
-
-        writer.end_block(semicolon = True)
-
-    d = 0
-    for r in ranges:
-        d = d + 1
-        with writer.if_block("message_type >= %d && message_type < %d" % (r[0], r[1]), d > 1, False):
-            writer.statement("return funcs%d[message_type-%d](message_start, message_end, minor, size_out, free_message)" % (d, r[0]))
-    writer.newline()
-
-    writer.statement("return NULL")
-    writer.end_block()
-    if channel.has_attr("ifdef"):
-        writer.endif(channel.attributes["ifdef"][0])
-
-    return function_name
-
-def write_get_channel_parser(writer, channel_parsers, max_channel, is_server):
-    writer.newline()
-    if is_server:
-        function_name = "spice_get_server_channel_parser" + writer.public_prefix
-    else:
-        function_name = "spice_get_client_channel_parser" + writer.public_prefix
-
-    scope = writer.function(function_name,
-                            "spice_parse_channel_func_t",
-                            "uint32_t channel, unsigned int *max_message_type")
-
-    writer.write("static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[%d] = " % (max_channel+1))
-    writer.begin_block()
-    channel = None
-    for i in range(0, max_channel + 1):
-        if i in channel_parsers:
-            channel = channel_parsers[i][0]
-            if channel.has_attr("ifdef"):
-                writer.ifdef(channel.attributes["ifdef"][0])
-            writer.write("{ ")
-            writer.write(channel_parsers[i][1])
-            writer.write(", ")
-
-            max_msg = 0
-            if is_server:
-                messages = channel.server_messages
-            else:
-                messages = channel.client_messages
-            for m in messages:
-                max_msg = max(max_msg, m.value)
-            writer.write(max_msg)
-            writer.write("}")
-        else:
-            writer.write("{ NULL, 0 }")
-
-        if i != max_channel:
-            writer.write(",")
-        writer.newline()
-        if channel and channel.has_attr("ifdef"):
-            writer.ifdef_else(channel.attributes["ifdef"][0])
-            writer.write("{ NULL, 0 }")
-            if i != max_channel:
-                writer.write(",")
-            writer.newline()
-            writer.endif(channel.attributes["ifdef"][0])
-    writer.end_block(semicolon = True)
-
-    with writer.if_block("channel < %d" % (max_channel + 1)):
-        with writer.if_block("max_message_type != NULL"):
-            writer.assign("*max_message_type", "channels[channel].max_messages")
-        writer.statement("return channels[channel].func")
-
-    writer.statement("return NULL")
-    writer.end_block()
-
-
-def write_full_protocol_parser(writer, is_server):
-    writer.newline()
-    if is_server:
-        function_name = "spice_parse_msg"
-    else:
-        function_name = "spice_parse_reply"
-    scope = writer.function(function_name + writer.public_prefix,
-                            "uint8_t *",
-                            "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message")
-    scope.variable_def("spice_parse_channel_func_t", "func" )
-
-    if is_server:
-        writer.assign("func", "spice_get_server_channel_parser%s(channel, NULL)" % writer.public_prefix)
-    else:
-        writer.assign("func", "spice_get_client_channel_parser%s(channel, NULL)" % writer.public_prefix)
-
-    with writer.if_block("func != NULL"):
-        writer.statement("return func(message_start, message_end, message_type, minor, size_out, free_message)")
-
-    writer.statement("return NULL")
-    writer.end_block()
-
-def write_protocol_parser(writer, proto, is_server):
-    max_channel = 0
-    parsers = {}
-
-    for channel in proto.channels:
-        max_channel = max(max_channel, channel.value)
-
-        parsers[channel.value] = (channel.channel_type, write_channel_parser(writer, channel.channel_type, is_server))
-
-    write_get_channel_parser(writer, parsers, max_channel, is_server)
-    write_full_protocol_parser(writer, is_server)
-
-def write_includes(writer):
-    writer.writeln("#include <string.h>")
-    writer.writeln("#include <assert.h>")
-    writer.writeln("#include <stdlib.h>")
-    writer.writeln("#include <stdio.h>")
-    writer.writeln("#include <spice/protocol.h>")
-    writer.writeln("#include <spice/macros.h>")
-    writer.writeln('#include <common/mem.h>')
-    writer.newline()
-    writer.writeln("#ifdef _MSC_VER")
-    writer.writeln("#pragma warning(disable:4101)")
-    writer.writeln("#endif")
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
deleted file mode 100644
index 1d38d3d..0000000
--- a/python_modules/marshal.py
+++ /dev/null
@@ -1,420 +0,0 @@
-
-from . import ptypes
-from . import codegen
-
-def write_includes(writer):
-    writer.header.writeln("#include <spice/protocol.h>")
-    writer.header.writeln('#include "common/marshaller.h"')
-    writer.header.newline()
-    writer.header.writeln("#ifndef _GENERATED_HEADERS_H")
-    writer.header.writeln("#define _GENERATED_HEADERS_H")
-
-    writer.writeln("#include <string.h>")
-    writer.writeln("#include <assert.h>")
-    writer.writeln("#include <stdlib.h>")
-    writer.writeln("#include <stdio.h>")
-    writer.writeln("#include <spice/protocol.h>")
-    writer.writeln("#include <spice/macros.h>")
-    writer.writeln('#include "common/marshaller.h"')
-    writer.newline()
-    writer.writeln("#ifdef _MSC_VER")
-    writer.writeln("#pragma warning(disable:4101)")
-    writer.writeln("#pragma warning(disable:4018)")
-    writer.writeln("#endif")
-    writer.newline()
-
-class MarshallingSource:
-    def __init__(self):
-        pass
-
-    def child_at_end(self, t):
-        return RootMarshallingSource(self, t.c_type(), t.sizeof())
-
-    def child_sub(self, containee):
-        return SubMarshallingSource(self, containee)
-
-    def declare(self, writer):
-        return writer.optional_block(self.reuse_scope)
-
-    def is_toplevel(self):
-        return self.parent_src == None and not self.is_helper
-
-class RootMarshallingSource(MarshallingSource):
-    def __init__(self, parent_src, c_type, sizeof, pointer = None):
-        self.is_helper = False
-        self.reuse_scope = None
-        self.parent_src = parent_src
-        if parent_src:
-            self.base_var = codegen.increment_identifier(parent_src.base_var)
-        else:
-            self.base_var = "src"
-        self.c_type = c_type
-        self.sizeof = sizeof
-        self.pointer = pointer
-        assert pointer != None
-
-    def get_self_ref(self):
-        return self.base_var
-
-    def get_ref(self, member):
-        return self.base_var + "->" + member
-
-    def declare(self, writer):
-        if self.reuse_scope:
-            scope = self.reuse_scope
-        else:
-            writer.begin_block()
-            scope = writer.get_subwriter()
-
-        scope.variable_def(self.c_type + " *", self.base_var)
-        if not self.reuse_scope:
-            scope.newline()
-
-        writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer))
-        writer.newline()
-
-        if self.reuse_scope:
-            return writer.no_block(self.reuse_scope)
-        else:
-            return writer.partial_block(scope)
-
-class SubMarshallingSource(MarshallingSource):
-    def __init__(self, parent_src, containee):
-        self.reuse_scope = None
-        self.parent_src = parent_src
-        self.base_var = parent_src.base_var
-        self.containee = containee
-        self.name = containee.name
-        self.is_helper = False
-
-    def get_self_ref(self):
-        if self.containee.has_attr("to_ptr"):
-            return "%s" % self.parent_src.get_ref(self.name)
-        else:
-            return "&%s" % self.parent_src.get_ref(self.name)
-
-    def get_ref(self, member):
-        if self.containee.has_attr("to_ptr"):
-            return self.parent_src.get_ref(self.name) + "->" + member
-        else:
-            return self.parent_src.get_ref(self.name) + "." + member
-
-def write_marshal_ptr_function(writer, target_type, is_helper=True):
-    if target_type.is_array():
-        marshal_function = "spice_marshall_array_%s" % target_type.element_type.primitive_type()
-    else:
-        marshal_function = "spice_marshall_%s" % target_type.name
-    if writer.is_generated("marshaller", marshal_function):
-        return marshal_function
-
-    writer.set_is_generated("marshaller", marshal_function)
-
-    names = target_type.get_pointer_names(False)
-    names_args = ""
-    if len(names) > 0:
-        n = [", SpiceMarshaller **%s_out" % name for name in names]
-        names_args = "".join(n)
-
-    header = writer.header
-    if is_helper:
-        writer = writer.function_helper()
-    writer.header = header
-    writer.out_prefix = ""
-    if target_type.is_array():
-        scope = writer.function(marshal_function, "SPICE_GNUC_UNUSED static void", "SpiceMarshaller *m, %s_t *ptr, unsigned count" % target_type.element_type.primitive_type() + names_args)
-    else:
-        scope = writer.function(marshal_function, "void", "SpiceMarshaller *m, %s *ptr" % target_type.c_type() + names_args)
-        header.writeln("void " + marshal_function + "(SpiceMarshaller *m, %s *msg" % target_type.c_type() + names_args + ");")
-    scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2")
-
-    for n in names:
-        writer.assign("*%s_out" % n, "NULL")
-
-    writer.newline()
-
-    if target_type.is_struct():
-        src = RootMarshallingSource(None, target_type.c_type(), target_type.sizeof(), "ptr")
-        src.reuse_scope = scope
-        write_container_marshaller(writer, target_type, src)
-    elif target_type.is_array() and target_type.element_type.is_primitive():
-        with writer.index() as index:
-            with writer.for_loop(index, "count") as array_scope:
-                writer.statement("spice_marshaller_add_%s(m, *ptr++)" % (target_type.element_type.primitive_type()))
-    else:
-        writer.todo("Unsuppored pointer marshaller type")
-
-    writer.end_block()
-
-    return marshal_function
-
-def get_array_size(array, container_src):
-    if array.is_constant_length():
-        return array.size
-    elif array.is_identifier_length():
-        return container_src.get_ref(array.size)
-    elif array.is_remaining_length():
-        raise NotImplementedError("remaining size array sizes marshalling not supported")
-    elif array.is_image_size_length():
-        bpp = array.size[1]
-        width = array.size[2]
-        rows = array.size[3]
-        width_v = container_src.get_ref(width)
-        rows_v = container_src.get_ref(rows)
-        # TODO: Handle multiplication overflow
-        if bpp == 8:
-            return "(unsigned) (%s * %s)" % (width_v, rows_v)
-        elif bpp == 1:
-            return "(unsigned) (((%s + 7) / 8 ) * %s)" % (width_v, rows_v)
-        else:
-            return "(unsigned) (((%s * %s + 7) / 8 ) * %s)" % (bpp, width_v, rows_v)
-    elif array.is_bytes_length():
-        return container_src.get_ref(array.size[2])
-    else:
-        raise NotImplementedError("TODO array size type not handled yet: %s"  % array)
-
-def write_array_marshaller(writer, member, array, container_src, scope):
-    element_type = array.element_type
-
-    if array.is_remaining_length():
-        writer.comment("Remaining data must be appended manually").newline()
-        return
-
-    nelements = get_array_size(array, container_src)
-    is_byte_size = array.is_bytes_length()
-
-    element = "%s__element" % member.name
-
-    if not scope.variable_defined(element):
-        if array.has_attr("ptr_array"):
-            stars = " **"
-        else:
-            stars = " *"
-        scope.variable_def(element_type.c_type() + stars, element)
-    element_array = element
-    if array.has_attr("ptr_array"):
-        element = "*" + element
-
-    writer.assign(element_array, container_src.get_ref(member.name))
-
-    if is_byte_size:
-        size_start_var = "%s__size_start" % member.name
-        scope.variable_def("size_t", size_start_var)
-        writer.assign(size_start_var, "spice_marshaller_get_size(m)")
-
-    with writer.index() as index:
-        with writer.for_loop(index, nelements) as array_scope:
-            if element_type.is_primitive():
-                writer.statement("spice_marshaller_add_%s(m, *%s)" % (element_type.primitive_type(), element))
-            elif element_type.is_struct():
-                src2 = RootMarshallingSource(container_src, element_type.c_type(), element_type.sizeof(), element)
-                src2.reuse_scope = array_scope
-                write_container_marshaller(writer, element_type, src2)
-            else:
-                writer.todo("array element unhandled type").newline()
-
-            writer.statement("%s++" % element_array)
-
-    if is_byte_size:
-        size_var = member.container.lookup_member(array.size[1])
-        size_var_type = size_var.member_type
-        var = "%s__ref" % array.size[1]
-        writer.statement("spice_marshaller_set_%s(m, %s, spice_marshaller_get_size(m) - %s)" % (size_var_type.primitive_type(), var, size_start_var))
-
-def write_pointer_marshaller(writer, member, src):
-    t = member.member_type
-    ptr_func = write_marshal_ptr_function(writer, t.target_type)
-    submarshaller = "spice_marshaller_get_ptr_submarshaller(m, %d)" % (1 if member.get_fixed_nw_size() == 8 else 0)
-    if member.has_attr("marshall"):
-        rest_args = ""
-        if t.target_type.is_array():
-            rest_args = ", %s" % get_array_size(t.target_type, src)
-        writer.assign("m2", submarshaller)
-        if t.has_attr("nonnull"):
-            writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args))
-        else:
-            with writer.if_block("%s != NULL" % src.get_ref(member.name)) as block:
-                writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args))
-    else:
-        writer.assign("*%s_out" % (writer.out_prefix + member.name), submarshaller)
-
-def write_switch_marshaller(writer, container, switch, src, scope):
-    var = container.lookup_member(switch.variable)
-    var_type = var.member_type
-
-    saved_out_prefix = writer.out_prefix
-    first = True
-    for c in switch.cases:
-        check = c.get_check(src.get_ref(switch.variable), var_type)
-        m = c.member
-        writer.out_prefix = saved_out_prefix
-        if m.has_attr("outvar"):
-            writer.out_prefix = "%s_%s" % (m.attributes["outvar"][0], writer.out_prefix)
-        with writer.if_block(check, not first, False) as block:
-            t = m.member_type
-            if switch.has_attr("anon"):
-                if t.is_struct():
-                    src2 = src.child_sub(m)
-                else:
-                    src2 = src
-            else:
-                if t.is_struct():
-                    src2 = src.child_sub(switch).child_sub(m)
-                else:
-                    src2 = src.child_sub(switch)
-            src2.reuse_scope = block
-
-            if t.is_struct():
-                write_container_marshaller(writer, t, src2)
-            elif t.is_pointer():
-                write_pointer_marshaller(writer, m, src2)
-            elif t.is_primitive():
-                if m.has_attr("zero"):
-                    writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type()))
-                else:
-                    writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src2.get_ref(m.name)))
-                #TODO validate e.g. flags and enums
-            elif t.is_array():
-                write_array_marshaller(writer, m, t, src2, scope)
-            else:
-                writer.todo("Can't handle type %s" % m.member_type)
-
-            if switch.has_attr("fixedsize"):
-                remaining = switch.get_fixed_nw_size() - t.get_fixed_nw_size()
-                if remaining != 0:
-                    writer.statement("spice_marshaller_reserve_space(m, %s)" % remaining)
-
-        first = False
-    if switch.has_attr("fixedsize"):
-        with writer.block(" else"):
-            writer.statement("spice_marshaller_reserve_space(m, %s)" % switch.get_fixed_nw_size())
-
-    writer.newline()
-
-def write_member_marshaller(writer, container, member, src, scope):
-    if member.has_attr("outvar"):
-        writer.out_prefix = "%s_%s" % (member.attributes["outvar"][0], writer.out_prefix)
-    if member.has_attr("virtual"):
-        writer.comment("Don't marshall @virtual %s" % member.name).newline()
-        return
-    if member.has_attr("nomarshal"):
-        writer.comment("Don't marshall @nomarshal %s" % member.name).newline()
-        return
-    if member.is_switch():
-        write_switch_marshaller(writer, container, member, src, scope)
-        return
-
-    t = member.member_type
-
-    if t.is_pointer():
-        write_pointer_marshaller(writer, member, src)
-    elif t.is_primitive():
-        if member.has_attr("zero"):
-            writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type()))
-        if member.has_attr("bytes_count"):
-            var = "%s__ref" % member.name
-            scope.variable_def("void *", var)
-            writer.statement("%s = spice_marshaller_add_%s(m, %s)" % (var, t.primitive_type(), 0))
-
-        else:
-            writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src.get_ref(member.name)))
-    elif t.is_array():
-        write_array_marshaller(writer, member, t, src, scope)
-    elif t.is_struct():
-        src2 = src.child_sub(member)
-        writer.comment(member.name)
-        write_container_marshaller(writer, t, src2)
-    else:
-        raise NotImplementedError("TODO can't handle parsing of %s" % t)
-
-def write_container_marshaller(writer, container, src):
-    saved_out_prefix = writer.out_prefix
-    with src.declare(writer) as scope:
-        for m in container.members:
-            writer.out_prefix = saved_out_prefix
-            write_member_marshaller(writer, container, m, src, scope)
-
-def write_message_marshaller(writer, message, is_server, private):
-    if message.has_attr("ifdef"):
-        writer.ifdef(message.attributes["ifdef"][0])
-    writer.out_prefix = ""
-    function_name = "spice_marshall_" + message.c_name()
-    if writer.is_generated("marshaller", function_name):
-        return function_name
-    writer.set_is_generated("marshaller", function_name)
-
-    names = message.get_pointer_names(False)
-    names_args = ""
-    if len(names) > 0:
-        n = [", SpiceMarshaller **%s_out" % name for name in names]
-        names_args = "".join(n)
-
-    if not private:
-        writer.header.writeln("void " + function_name + "(SpiceMarshaller *m, %s *msg" % message.c_type() + names_args + ");")
-
-    scope = writer.function(function_name,
-                            "static void" if private else "void",
-                            "SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED %s *msg" % message.c_type() + names_args)
-    scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2")
-
-    for n in names:
-        writer.assign("*%s_out" % n, "NULL")
-
-    # fix warnings about unused variables by not creating body if no members to parse
-    if any(x.is_fixed_nw_size() for x in message.members):
-        src = RootMarshallingSource(None, message.c_type(), message.sizeof(), "msg")
-        src.reuse_scope = scope
-
-        write_container_marshaller(writer, message, src)
-
-    writer.end_block()
-    if message.has_attr("ifdef"):
-        writer.endif(message.attributes["ifdef"][0])
-    writer.newline()
-    return function_name
-
-def write_protocol_marshaller(writer, proto, is_server, private_marshallers):
-    functions = {}
-    for c in proto.channels:
-        channel = c.channel_type
-        if channel.has_attr("ifdef"):
-            writer.ifdef(channel.attributes["ifdef"][0])
-            writer.header.ifdef(channel.attributes["ifdef"][0])
-        if is_server:
-            messages = channel.client_messages
-        else:
-            messages = channel.server_messages
-        for m in messages:
-            message = m.message_type
-            f = write_message_marshaller(writer, message, is_server, private_marshallers)
-            if channel.has_attr("ifdef") and f not in functions:
-                functions[f] = channel.attributes["ifdef"][0]
-            elif message.has_attr("ifdef") and f not in functions:
-                functions[f] = message.attributes["ifdef"][0]
-            else:
-                functions[f] = True
-        if channel.has_attr("ifdef"):
-            writer.endif(channel.attributes["ifdef"][0])
-            writer.header.endif(channel.attributes["ifdef"][0])
-
-    if private_marshallers:
-        scope = writer.function("spice_message_marshallers_get" +  writer.public_prefix,
-                                "SpiceMessageMarshallers *",
-                                "void")
-        writer.writeln("static SpiceMessageMarshallers marshallers = {NULL};").newline()
-        for f in sorted(functions.keys()):
-            member = f[len("spice_marshall_"):]
-            if not member.startswith("msg"):
-                member = "msg_" + member
-            if functions[f] != True:
-                writer.ifdef(functions[f])
-            writer.assign("marshallers.%s" % member, f)
-            if functions[f] != True:
-                writer.endif(functions[f])
-
-        writer.newline()
-        writer.statement("return &marshallers")
-        writer.end_block()
-        writer.newline()
-
-def write_trailer(writer):
-    writer.header.writeln("#endif")
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
deleted file mode 100644
index 7ab2771..0000000
--- a/python_modules/ptypes.py
+++ /dev/null
@@ -1,1129 +0,0 @@
-from . import codegen
-import types
-
-_types_by_name = {}
-_types = []
-
-default_pointer_size = 4
-
-def type_exists(name):
-    return name in _types_by_name
-
-def lookup_type(name):
-    return _types_by_name[name]
-
-def get_named_types():
-    return _types
-
-class FixedSize:
-    def __init__(self, val = 0, minor = 0):
-        if isinstance(val, FixedSize):
-            self.vals = val.vals
-        else:
-            self.vals = [0] * (minor + 1)
-            self.vals[minor] = val
-
-    def __add__(self, other):
-        if isinstance(other, int):
-            other = FixedSize(other)
-
-        new = FixedSize()
-        l = max(len(self.vals), len(other.vals))
-        shared = min(len(self.vals), len(other.vals))
-
-        new.vals = [0] * l
-
-        for i in range(shared):
-            new.vals[i] = self.vals[i] + other.vals[i]
-
-        for i in range(shared,len(self.vals)):
-            new.vals[i] = self.vals[i]
-
-        for i in range(shared,len(other.vals)):
-            new.vals[i] = new.vals[i] + other.vals[i]
-
-        return new
-
-    def __radd__(self, other):
-        return self.__add__(other)
-
-    def __str__(self):
-        s = "%d" % (self.vals[0])
-
-        for i in range(1,len(self.vals)):
-            if self.vals[i] > 0:
-                s = s + " + ((minor >= %d)?%d:0)" % (i, self.vals[i])
-        return s
-
-# Some attribute are propagated from member to the type as they really
-# are part of the type definition, rather than the member. This applies
-# only to attributes that affect pointer or array attributes, as these
-# are member local types, unlike e.g. a Struct that may be used by
-# other members
-propagated_attributes=["ptr_array", "nonnull", "chunk"]
-
-valid_attributes=set([
-    # embedded/appended at the end of the structure
-    'end',
-    # the C structure contains a pointer to data
-    # for instance we want to write an array to an allocated array
-    'to_ptr',
-    # write output to this C structure
-    'ctype',
-    # prefix for flags/values enumerations
-    'prefix',
-    # used in demarshaller to use directly data from message without a copy
-    'nocopy',
-    # store member array in a pointer
-    # similar to to_ptr but has an additional argument which is the name of a C
-    # field which will store the array length
-    'as_ptr',
-    # do not generate marshall code
-    # used for last members to be able to marshall them manually
-    'nomarshal',
-    # ??? not used by python code
-    'zero_terminated',
-    'marshall',
-    # this pointer member cannot be null
-    'nonnull',
-    # this flag member contains only a single flag
-    'unique_flag',
-    'ptr_array',
-    'outvar',
-    # C structure has an anonymous member (used in switch)
-    'anon',
-    'chunk',
-    # this channel is contained in an #ifdef section
-    # the argument specifies the preprocessor define to check
-    'ifdef',
-    # write this member as zero on network
-    'zero',
-    # specify minor version required for these members
-    'minor',
-    # this member contains the byte count for an array.
-    # the argument is the member name for item count (not bytes)
-    'bytes_count',
-    # this attribute does not exist on the network, fill just structure with the value
-    'virtual',
-    # for a switch this indicates that on network
-    # it will occupy always the same size (maximum size required for all members)
-    'fixedsize',
-])
-
-attributes_with_arguments=set([
-    'ctype',
-    'prefix',
-    'as_ptr',
-    'outvar',
-    'ifdef',
-    'minor',
-    'bytes_count',
-    'virtual',
-])
-
-def fix_attributes(attribute_list):
-    attrs = {}
-    for attr in attribute_list:
-        name = attr[0][1:]
-        lst = attr[1:]
-        if not name in valid_attributes:
-            raise Exception("Attribute %s not recognized" % name)
-        if not name in attributes_with_arguments:
-            if len(lst) > 0:
-                raise Exception("Attribute %s specified with options" % name)
-        elif len(lst) > 1:
-            raise Exception("Attribute %s has more than 1 argument" % name)
-        attrs[name] = lst
-    return attrs
-
-class Type:
-    def __init__(self):
-        self.attributes = {}
-        self.registred = False
-        self.name = None
-
-    def has_name(self):
-        return self.name != None
-
-    def get_type(self, recursive=False):
-        return self
-
-    def is_primitive(self):
-        return False
-
-    def is_fixed_sizeof(self):
-        return True
-
-    def is_extra_size(self):
-        return False
-
-    def contains_extra_size(self):
-        return False
-
-    def is_fixed_nw_size(self):
-        return True
-
-    def is_array(self):
-        return isinstance(self, ArrayType)
-
-    def contains_member(self, member):
-        return False
-
-    def is_struct(self):
-        return isinstance(self, StructType)
-
-    def is_pointer(self):
-        return isinstance(self, PointerType)
-
-    def get_num_pointers(self):
-        return 0
-
-    def get_pointer_names(self, marshalled):
-        return []
-
-    def sizeof(self):
-        return "sizeof(%s)" % (self.c_type())
-
-    def __repr__(self):
-        return self.__str__()
-
-    def __str__(self):
-        if self.name != None:
-            return self.name
-        return "anonymous type"
-
-    def resolve(self):
-        return self
-
-    def register(self):
-        if self.registred or self.name == None:
-            return
-        self.registred = True
-        if self.name in _types_by_name:
-            raise Exception("Type %s already defined" % self.name)
-        _types.append(self)
-        _types_by_name[self.name] = self
-
-    def has_attr(self, name):
-        if not name in valid_attributes:
-            raise Exception('attribute %s not expected' % name)
-        return name in self.attributes
-
-class TypeRef(Type):
-    def __init__(self, name):
-        Type.__init__(self)
-        self.name = name
-
-    def __str__(self):
-        return "ref to %s" % (self.name)
-
-    def resolve(self):
-        if self.name not in _types_by_name:
-            raise Exception("Unknown type %s" % self.name)
-        return _types_by_name[self.name]
-
-    def register(self):
-        assert True, "Can't register TypeRef!"
-
-
-class IntegerType(Type):
-    def __init__(self, bits, signed):
-        Type.__init__(self)
-        self.bits = bits
-        self.signed = signed
-
-        if signed:
-            self.name = "int%d" % bits
-        else:
-            self.name = "uint%d" % bits
-
-    def primitive_type(self):
-        return self.name
-
-    def c_type(self):
-        return self.name + "_t"
-
-    def get_fixed_nw_size(self):
-        return self.bits // 8
-
-    def is_primitive(self):
-        return True
-
-class TypeAlias(Type):
-    def __init__(self, name, the_type, attribute_list):
-        Type.__init__(self)
-        self.name = name
-        self.the_type = the_type
-        self.attributes = fix_attributes(attribute_list)
-
-    def get_type(self, recursive=False):
-        if recursive:
-            return self.the_type.get_type(True)
-        else:
-            return self.the_type
-
-    def primitive_type(self):
-        return self.the_type.primitive_type()
-
-    def resolve(self):
-        self.the_type = self.the_type.resolve()
-        return self
-
-    def __str__(self):
-        return "alias %s" % self.name
-
-    def is_primitive(self):
-        return self.the_type.is_primitive()
-
-    def is_fixed_sizeof(self):
-        return self.the_type.is_fixed_sizeof()
-
-    def is_fixed_nw_size(self):
-        return self.the_type.is_fixed_nw_size()
-
-    def get_fixed_nw_size(self):
-        return self.the_type.get_fixed_nw_size()
-
-    def get_num_pointers(self):
-        return self.the_type.get_num_pointers()
-
-    def get_pointer_names(self, marshalled):
-        return self.the_type.get_pointer_names(marshalled)
-
-    def c_type(self):
-        if self.has_attr("ctype"):
-            return self.attributes["ctype"][0]
-        return self.name
-
-class EnumBaseType(Type):
-    def is_enum(self):
-        return isinstance(self, EnumType)
-
-    def primitive_type(self):
-        return "uint%d" % (self.bits)
-
-    def c_type(self):
-        return "uint%d_t" % (self.bits)
-
-    def c_name(self):
-        return codegen.prefix_camel(self.name)
-
-    def c_enumname(self, value):
-        return self.c_enumname_by_name(self.names[value])
-
-    def c_enumname_by_name(self, name):
-        if self.has_attr("prefix"):
-            return self.attributes["prefix"][0] + name
-        return codegen.prefix_underscore_upper(self.name.upper(), name)
-
-    def is_primitive(self):
-        return True
-
-    def get_fixed_nw_size(self):
-        return self.bits // 8
-
-    # generates a value-name table suitable for use with the wireshark protocol
-    # dissector
-    def c_describe(self, writer):
-        writer.write("static const value_string %s_vs[] = " % codegen.prefix_underscore_lower(self.name))
-        writer.begin_block()
-        values = list(self.names.keys())
-        values.sort()
-        for i in values:
-            writer.write("{ ")
-            writer.write(self.c_enumname(i))
-            writer.write(", \"%s\" }," % self.names[i])
-            writer.newline()
-        writer.write("{ 0, NULL }")
-        writer.end_block(semicolon=True)
-        writer.newline()
-
-
-class EnumType(EnumBaseType):
-    def __init__(self, bits, name, enums, attribute_list):
-        Type.__init__(self)
-        self.bits = bits
-        self.name = name
-
-        last = -1
-        names = {}
-        values = {}
-        for v in enums:
-            name = v[0]
-            if len(v) > 1:
-                value = v[1]
-            else:
-                value = last + 1
-            last = value
-
-            assert value not in names
-            names[value] = name
-            values[name] = value
-
-        self.names = names
-        self.values = values
-
-        self.attributes = fix_attributes(attribute_list)
-
-    def __str__(self):
-        return "enum %s" % self.name
-
-    def c_define(self, writer):
-        writer.write("typedef enum ")
-        writer.write(self.c_name())
-        writer.begin_block()
-        values = list(self.names.keys())
-        values.sort()
-        current_default = 0
-        for i in values:
-            writer.write(self.c_enumname(i))
-            if i != current_default:
-                writer.write(" = %d" % (i))
-            writer.write(",")
-            writer.newline()
-            current_default = i + 1
-        writer.newline()
-        writer.write(codegen.prefix_underscore_upper(self.name.upper(), "ENUM_END"))
-        writer.newline()
-        writer.end_block(newline=False)
-        writer.write(" ")
-        writer.write(self.c_name())
-        writer.write(";")
-        writer.newline()
-        writer.newline()
-
-class FlagsType(EnumBaseType):
-    def __init__(self, bits, name, flags, attribute_list):
-        Type.__init__(self)
-        self.bits = bits
-        self.name = name
-
-        last = -1
-        names = {}
-        values = {}
-        for v in flags:
-            name = v[0]
-            if len(v) > 1:
-                value = v[1]
-            else:
-                value = last + 1
-            last = value
-
-            assert value not in names
-            names[value] = name
-            values[name] = value
-
-        self.names = names
-        self.values = values
-
-        self.attributes = fix_attributes(attribute_list)
-
-    def __str__(self):
-        return "flags %s" % self.name
-
-    def c_define(self, writer):
-        writer.write("typedef enum ")
-        writer.write(self.c_name())
-        writer.begin_block()
-        values = list(self.names.keys())
-        values.sort()
-        mask = 0
-        for i in values:
-            writer.write(self.c_enumname(i))
-            mask = mask |  (1<<i)
-            writer.write(" = (1 << %d)" % (i))
-            writer.write(",")
-            writer.newline()
-            current_default = i + 1
-        writer.newline()
-        writer.write(codegen.prefix_underscore_upper(self.name.upper(), "MASK"))
-        writer.write(" = 0x%x" % (mask))
-        writer.newline()
-        writer.end_block(newline=False)
-        writer.write(" ")
-        writer.write(self.c_name())
-        writer.write(";")
-        writer.newline()
-        writer.newline()
-
-class ArrayType(Type):
-    def __init__(self, element_type, size):
-        Type.__init__(self)
-        self.name = None
-
-        self.element_type = element_type
-        self.size = size
-
-    def __str__(self):
-        if self.size == None:
-            return "%s[]" % (str(self.element_type))
-        else:
-            return "%s[%s]" % (str(self.element_type), str(self.size))
-
-    def resolve(self):
-        self.element_type = self.element_type.resolve()
-        return self
-
-    def is_constant_length(self):
-        return isinstance(self.size, int)
-
-    def is_remaining_length(self):
-        return isinstance(self.size, str) and len(self.size) == 0
-
-    def is_identifier_length(self):
-        return isinstance(self.size, str) and len(self.size) > 0
-
-    def is_image_size_length(self):
-        if isinstance(self.size, int) or isinstance(self.size, str):
-            return False
-        return self.size[0] == "image_size"
-
-    def is_bytes_length(self):
-        if isinstance(self.size, int) or isinstance(self.size, str):
-            return False
-        return self.size[0] == "bytes"
-
-    def is_cstring_length(self):
-        if isinstance(self.size, int) or isinstance(self.size, str):
-            return False
-        return self.size[0] == "cstring"
-
-    def is_fixed_sizeof(self):
-        return self.is_constant_length() and self.element_type.is_fixed_sizeof()
-
-    def is_fixed_nw_size(self):
-        return self.is_constant_length() and self.element_type.is_fixed_nw_size()
-
-    def get_fixed_nw_size(self):
-        if not self.is_fixed_nw_size():
-            raise Exception("Not a fixed size type")
-
-        return self.element_type.get_fixed_nw_size() * self.size
-
-    def get_num_pointers(self):
-        element_count = self.element_type.get_num_pointers()
-        if element_count  == 0:
-            return 0
-        if self.is_constant_length(self):
-            return element_count * self.size
-        raise Exception("Pointers in dynamic arrays not supported")
-
-    def get_pointer_names(self, marshalled):
-        element_count = self.element_type.get_num_pointers()
-        if element_count  == 0:
-            return []
-        raise Exception("Pointer names in arrays not supported")
-
-    def is_extra_size(self):
-        return self.has_attr("ptr_array")
-
-    def contains_extra_size(self):
-        return self.element_type.contains_extra_size() or self.has_attr("chunk")
-
-    def sizeof(self):
-        return "%s * %s" % (self.element_type.sizeof(), self.size)
-
-    def c_type(self):
-        return self.element_type.c_type()
-
-class PointerType(Type):
-    def __init__(self, target_type):
-        Type.__init__(self)
-        self.name = None
-        self.target_type = target_type
-        self.pointer_size = default_pointer_size
-
-    def __str__(self):
-        return "%s*" % (str(self.target_type))
-
-    def resolve(self):
-        self.target_type = self.target_type.resolve()
-        return self
-
-    def set_ptr_size(self, new_size):
-        self.pointer_size = new_size
-
-    def is_fixed_nw_size(self):
-        return True
-
-    def is_primitive(self):
-        return True
-
-    def primitive_type(self):
-        if self.pointer_size == 4:
-            return "uint32"
-        else:
-            return "uint64"
-
-    def get_fixed_nw_size(self):
-        return self.pointer_size
-
-    def c_type(self):
-        if self.pointer_size == 4:
-            return "uint32_t"
-        else:
-            return "uint64_t"
-
-    def contains_extra_size(self):
-        return True
-
-    def get_num_pointers(self):
-        return 1
-
-class Containee:
-    def __init__(self):
-        self.attributes = {}
-
-    def is_switch(self):
-        return False
-
-    def is_pointer(self):
-        return not self.is_switch() and self.member_type.is_pointer()
-
-    def is_array(self):
-        return not self.is_switch() and self.member_type.is_array()
-
-    def is_struct(self):
-        return not self.is_switch() and self.member_type.is_struct()
-
-    def is_primitive(self):
-        return not self.is_switch() and self.member_type.is_primitive()
-
-    def has_attr(self, name):
-        if not name in valid_attributes:
-            raise Exception('attribute %s not expected' % name)
-        return name in self.attributes
-
-    def has_minor_attr(self):
-        return self.has_attr("minor")
-
-    def has_end_attr(self):
-        return self.has_attr("end")
-
-    def get_minor_attr(self):
-        return self.attributes["minor"][0]
-
-class Member(Containee):
-    def __init__(self, name, member_type, attribute_list):
-        Containee.__init__(self)
-        self.name = name
-        self.member_type = member_type
-        self.attributes = fix_attributes(attribute_list)
-
-    def resolve(self, container):
-        self.container = container
-        self.member_type = self.member_type.resolve()
-        self.member_type.register()
-        for i in propagated_attributes:
-            if self.has_attr(i):
-                self.member_type.attributes[i] = self.attributes[i]
-        return self
-
-    def contains_member(self, member):
-        return self.member_type.contains_member(member)
-
-    def is_primitive(self):
-        return self.member_type.is_primitive()
-
-    def is_fixed_sizeof(self):
-        if self.has_end_attr():
-            return False
-        return self.member_type.is_fixed_sizeof()
-
-    def is_extra_size(self):
-        return self.has_end_attr() or self.has_attr("to_ptr") or self.member_type.is_extra_size()
-
-    def is_fixed_nw_size(self):
-        if self.has_attr("virtual"):
-            return True
-        return self.member_type.is_fixed_nw_size()
-
-    def get_fixed_nw_size(self):
-        if self.has_attr("virtual"):
-            return 0
-        size = self.member_type.get_fixed_nw_size()
-        if self.has_minor_attr():
-            minor = self.get_minor_attr()
-            size = FixedSize(size, minor)
-        return size
-
-    def contains_extra_size(self):
-        return self.member_type.contains_extra_size()
-
-    def sizeof(self):
-        return self.member_type.sizeof()
-
-    def __repr__(self):
-        return "%s (%s)" % (str(self.name), str(self.member_type))
-
-    def get_num_pointers(self):
-        if self.has_attr("to_ptr"):
-            return 1
-        return self.member_type.get_num_pointers()
-
-    def get_pointer_names(self, marshalled):
-        if self.member_type.is_pointer():
-            if self.has_attr("marshall") == marshalled:
-                names = [self.name]
-            else:
-                names = []
-        else:
-            names = self.member_type.get_pointer_names(marshalled)
-        if self.has_attr("outvar"):
-            prefix = self.attributes["outvar"][0]
-            names = [prefix + "_" + name for name in names]
-        return names
-
-class SwitchCase:
-    def __init__(self, values, member):
-        self.values = values
-        self.member = member
-        self.members = [member]
-
-    def get_check(self, var_cname, var_type):
-        checks = []
-        for v in self.values:
-            if v == None:
-                return "1"
-            elif var_type.is_enum():
-                checks.append("%s == %s" % (var_cname, var_type.c_enumname_by_name(v[1])))
-            else:
-                checks.append("%s(%s & %s)" % (v[0], var_cname, var_type.c_enumname_by_name(v[1])))
-        return " || ".join(checks)
-
-    def resolve(self, container):
-        self.switch = container
-        self.member = self.member.resolve(self)
-        return self
-
-    def get_num_pointers(self):
-        return self.member.get_num_pointers()
-
-    def get_pointer_names(self, marshalled):
-        return self.member.get_pointer_names(marshalled)
-
-class Switch(Containee):
-    def __init__(self, variable, cases, name, attribute_list):
-        Containee.__init__(self)
-        self.variable = variable
-        self.name = name
-        self.cases = cases
-        self.attributes = fix_attributes(attribute_list)
-
-    def is_switch(self):
-        return True
-
-    def lookup_case_member(self, name):
-        for c in self.cases:
-            if c.member.name == name:
-                return c.member
-        return None
-
-    def has_switch_member(self, member):
-        for c in self.cases:
-            if c.member == member:
-                return True
-        return False
-
-    def resolve(self, container):
-        self.container = container
-        self.cases = [c.resolve(self) for c in self.cases]
-        return self
-
-    def __repr__(self):
-        return "switch on %s %s" % (str(self.variable),str(self.name))
-
-    def is_fixed_sizeof(self):
-        # Kinda weird, but we're unlikely to have a real struct if there is an @end
-        if self.has_end_attr():
-            return False
-        return True
-
-    def is_fixed_nw_size(self):
-        if self.has_attr("fixedsize"):
-            return True
-
-        size = None
-        has_default = False
-        for c in self.cases:
-            for v in c.values:
-                if v == None:
-                    has_default = True
-            if not c.member.is_fixed_nw_size():
-                return False
-            if size == None:
-                size = c.member.get_fixed_nw_size()
-            elif size != c.member.get_fixed_nw_size():
-                return False
-        # Fixed size if all elements listed, or has default
-        if has_default:
-            return True
-        key = self.container.lookup_member(self.variable)
-        return len(self.cases) == len(key.member_type.values)
-
-    def is_extra_size(self):
-        return self.has_end_attr()
-
-    def contains_extra_size(self):
-        for c in self.cases:
-            if c.member.is_extra_size():
-                return True
-            if c.member.contains_extra_size():
-                return True
-        return False
-
-    def get_fixed_nw_size(self):
-        if not self.is_fixed_nw_size():
-            raise Exception("Not a fixed size type")
-        size = 0
-        for c in self.cases:
-            size = max(size, c.member.get_fixed_nw_size())
-        return size
-
-    def sizeof(self):
-        return "sizeof(((%s *)NULL)->%s)" % (self.container.c_type(),
-                                             self.name)
-
-    def contains_member(self, member):
-        return False # TODO: Don't support switch deep member lookup yet
-
-    def get_num_pointers(self):
-        count = 0
-        for c in self.cases:
-            count = max(count, c.get_num_pointers())
-        return count
-
-    def get_pointer_names(self, marshalled):
-        names = []
-        for c in self.cases:
-            names = names + c.get_pointer_names(marshalled)
-        return names
-
-class ContainerType(Type):
-    def is_fixed_sizeof(self):
-        for m in self.members:
-            if not m.is_fixed_sizeof():
-                return False
-        return True
-
-    def contains_extra_size(self):
-        for m in self.members:
-            if m.is_extra_size():
-                return True
-            if m.contains_extra_size():
-                return True
-        return False
-
-    def is_fixed_nw_size(self):
-        for i in self.members:
-            if not i.is_fixed_nw_size():
-                return False
-        return True
-
-    def get_fixed_nw_size(self):
-        size = 0
-        for i in self.members:
-            size = size + i.get_fixed_nw_size()
-        return size
-
-    def contains_member(self, member):
-        for m in self.members:
-            if m == member or m.contains_member(member):
-                return True
-        return False
-
-    def get_fixed_nw_offset(self, member):
-        size = 0
-        for i in self.members:
-            if i == member:
-                break
-            if i.contains_member(member):
-                size = size  + i.member_type.get_fixed_nw_offset(member)
-                break
-            if i.is_fixed_nw_size():
-                size = size + i.get_fixed_nw_size()
-        return size
-
-    def resolve(self):
-        self.members = [m.resolve(self) for m in self.members]
-        return self
-
-    def get_num_pointers(self):
-        count = 0
-        for m in self.members:
-            count = count + m.get_num_pointers()
-        return count
-
-    def get_pointer_names(self, marshalled):
-        names = []
-        for m in self.members:
-            names = names + m.get_pointer_names(marshalled)
-        return names
-
-    def get_nw_offset(self, member, prefix = "", postfix = ""):
-        fixed = self.get_fixed_nw_offset(member)
-        v = []
-        container = self
-        while container != None:
-            members = container.members
-            container = None
-            for m in members:
-                if m == member:
-                    break
-                if m.contains_member(member):
-                    container = m.member_type
-                    break
-                if m.is_switch() and m.has_switch_member(member):
-                    break
-                if not m.is_fixed_nw_size():
-                    v.append(prefix + m.name + postfix)
-        if len(v) > 0:
-            return str(fixed) + " + " + (" + ".join(v))
-        else:
-            return str(fixed)
-
-    def lookup_member(self, name):
-        dot = name.find('.')
-        rest = None
-        if dot >= 0:
-            rest = name[dot+1:]
-            name = name[:dot]
-
-        member = None
-        if name in self.members_by_name:
-            member = self.members_by_name[name]
-        else:
-            for m in self.members:
-                if m.is_switch():
-                    member = m.lookup_case_member(name)
-                    if member != None:
-                        break
-                if member != None:
-                    break
-
-        if member == None:
-            raise Exception("No member called %s found" % name)
-
-        if rest != None:
-            return member.member_type.lookup_member(rest)
-
-        return member
-
-class StructType(ContainerType):
-    def __init__(self, name, members, attribute_list):
-        Type.__init__(self)
-        self.name = name
-        self.members = members
-        self.members_by_name = {}
-        for m in members:
-            self.members_by_name[m.name] = m
-        self.attributes = fix_attributes(attribute_list)
-
-    def __str__(self):
-        if self.name == None:
-            return "anonymous struct"
-        else:
-            return "struct %s" % self.name
-
-    def c_type(self):
-        if self.has_attr("ctype"):
-            return self.attributes["ctype"][0]
-        return codegen.prefix_camel(self.name)
-
-class MessageType(ContainerType):
-    def __init__(self, name, members, attribute_list):
-        Type.__init__(self)
-        self.name = name
-        self.members = members
-        self.members_by_name = {}
-        for m in members:
-            self.members_by_name[m.name] = m
-        self.reverse_members = {} # ChannelMembers referencing this message
-        self.attributes = fix_attributes(attribute_list)
-
-    def __str__(self):
-        if self.name == None:
-            return "anonymous message"
-        else:
-            return "message %s" % self.name
-
-    def c_name(self):
-        if self.name == None:
-            cms = list(self.reverse_members.keys())
-            if len(cms) != 1:
-                raise "Unknown typename for message"
-            cm = cms[0]
-            channelname = cm.channel.member_name
-            if channelname == None:
-                channelname = ""
-            else:
-                channelname = channelname + "_"
-            if cm.is_server:
-                return "msg_" + channelname +  cm.name
-            else:
-                return "msgc_" + channelname +  cm.name
-        else:
-            return codegen.prefix_camel("Msg", self.name)
-
-    def c_type(self):
-        if self.has_attr("ctype"):
-            return self.attributes["ctype"][0]
-        if self.name == None:
-            cms = list(self.reverse_members.keys())
-            if len(cms) != 1:
-                raise "Unknown typename for message"
-            cm = cms[0]
-            channelname = cm.channel.member_name
-            if channelname == None:
-                channelname = ""
-            if cm.is_server:
-                return codegen.prefix_camel("Msg", channelname, cm.name)
-            else:
-                return codegen.prefix_camel("Msgc", channelname, cm.name)
-        else:
-            return codegen.prefix_camel("Msg", self.name)
-
-class ChannelMember(Containee):
-    def __init__(self, name, message_type, value):
-        Containee.__init__(self)
-        self.name = name
-        self.message_type = message_type
-        self.value = value
-
-    def resolve(self, channel):
-        self.channel = channel
-        self.message_type = self.message_type.resolve()
-        self.message_type.reverse_members[self] = 1
-
-        return self
-
-    def __repr__(self):
-        return "%s (%s)" % (str(self.name), str(self.message_type))
-
-class ChannelType(Type):
-    def __init__(self, name, base, members, attribute_list):
-        Type.__init__(self)
-        self.name = name
-        self.base = base
-        self.member_name = None
-        self.members = members
-        self.attributes = fix_attributes(attribute_list)
-
-    def __str__(self):
-        if self.name == None:
-            return "anonymous channel"
-        else:
-            return "channel %s" % self.name
-
-    def is_fixed_nw_size(self):
-        return False
-
-    def get_client_message(self, name):
-        return self.client_messages_byname[name]
-
-    def get_server_message(self, name):
-        return self.server_messages_byname[name]
-
-    def resolve(self):
-        if self.base != None:
-            self.base = self.base.resolve()
-
-            server_messages = self.base.server_messages[:]
-            server_messages_byname = self.base.server_messages_byname.copy()
-            client_messages = self.base.client_messages[:]
-            client_messages_byname = self.base.client_messages_byname.copy()
-
-            # Set default member_name, FooChannel -> foo
-            self.member_name = self.name[:-7].lower()
-        else:
-            server_messages = []
-            server_messages_byname = {}
-            client_messages = []
-            client_messages_byname = {}
-
-        server_count = 1
-        client_count = 1
-
-        server = True
-        for m in self.members:
-            if m == "server":
-                server = True
-            elif m == "client":
-                server = False
-            elif server:
-                m.is_server = True
-                m = m.resolve(self)
-                if m.value:
-                    server_count = m.value + 1
-                else:
-                    m.value = server_count
-                    server_count = server_count + 1
-                server_messages.append(m)
-                server_messages_byname[m.name] = m
-            else:
-                m.is_server = False
-                m = m.resolve(self)
-                if m.value:
-                    client_count = m.value + 1
-                else:
-                    m.value = client_count
-                    client_count = client_count + 1
-                client_messages.append(m)
-                client_messages_byname[m.name] = m
-
-        self.server_messages = server_messages
-        self.server_messages_byname = server_messages_byname
-        self.client_messages = client_messages
-        self.client_messages_byname = client_messages_byname
-
-        return self
-
-class ProtocolMember:
-    def __init__(self, name, channel_type, value):
-        self.name = name
-        self.channel_type = channel_type
-        self.value = value
-
-    def resolve(self, protocol):
-        self.channel_type = self.channel_type.resolve()
-        self.channel_type.member_name = self.name
-        return self
-
-    def __repr__(self):
-        return "%s (%s)" % (str(self.name), str(self.channel_type))
-
-class ProtocolType(Type):
-    def __init__(self, name, channels):
-        Type.__init__(self)
-        self.name = name
-        self.channels = channels
-
-    def __str__(self):
-        if self.name == None:
-            return "anonymous protocol"
-        else:
-            return "protocol %s" % self.name
-
-    def is_fixed_nw_size(self):
-        return False
-
-    def resolve(self):
-        count = 1
-        for m in self.channels:
-            m = m.resolve(self)
-            if m.value:
-                count = m.value + 1
-            else:
-                m.value = count
-                count = count + 1
-
-        return self
-
-int8 = IntegerType(8, True)
-uint8 = IntegerType(8, False)
-int16 = IntegerType(16, True)
-uint16 = IntegerType(16, False)
-int32 = IntegerType(32, True)
-uint32 = IntegerType(32, False)
-int64 = IntegerType(64, True)
-uint64 = IntegerType(64, False)
diff --git a/python_modules/spice_parser.py b/python_modules/spice_parser.py
deleted file mode 100644
index 97af8b2..0000000
--- a/python_modules/spice_parser.py
+++ /dev/null
@@ -1,162 +0,0 @@
-import six
-
-try:
-    from pyparsing import Literal, CaselessLiteral, Word, OneOrMore, ZeroOrMore, \
-            Forward, delimitedList, Group, Optional, Combine, alphas, nums, restOfLine, cStyleComment, \
-            alphanums, ParseException, ParseResults, Keyword, StringEnd, replaceWith
-except ImportError:
-    six.print_("Module pyparsing not found.")
-    exit(1)
-
-
-from . import ptypes
-import sys
-
-cvtInt = lambda toks: int(toks[0])
-
-def parseVariableDef(toks):
-    t = toks[0][0]
-    pointer = toks[0][1]
-    name = toks[0][2]
-    array_size = toks[0][3]
-    attributes = toks[0][4]
-
-    if array_size != None:
-        t = ptypes.ArrayType(t, array_size)
-
-    if pointer != None:
-        t = ptypes.PointerType(t)
-
-    return ptypes.Member(name, t, attributes)
-
-bnf = None
-def SPICE_BNF():
-    global bnf
-
-    if not bnf:
-
-        # punctuation
-        colon  = Literal(":").suppress()
-        lbrace = Literal("{").suppress()
-        rbrace = Literal("}").suppress()
-        lbrack = Literal("[").suppress()
-        rbrack = Literal("]").suppress()
-        lparen = Literal("(").suppress()
-        rparen = Literal(")").suppress()
-        equals = Literal("=").suppress()
-        comma  = Literal(",").suppress()
-        semi   = Literal(";").suppress()
-
-        # primitive types
-        int8_      = Keyword("int8").setParseAction(replaceWith(ptypes.int8))
-        uint8_     = Keyword("uint8").setParseAction(replaceWith(ptypes.uint8))
-        int16_     = Keyword("int16").setParseAction(replaceWith(ptypes.int16))
-        uint16_    = Keyword("uint16").setParseAction(replaceWith(ptypes.uint16))
-        int32_     = Keyword("int32").setParseAction(replaceWith(ptypes.int32))
-        uint32_    = Keyword("uint32").setParseAction(replaceWith(ptypes.uint32))
-        int64_     = Keyword("int64").setParseAction(replaceWith(ptypes.int64))
-        uint64_    = Keyword("uint64").setParseAction(replaceWith(ptypes.uint64))
-
-        # keywords
-        enum32_    = Keyword("enum32").setParseAction(replaceWith(32))
-        enum16_    = Keyword("enum16").setParseAction(replaceWith(16))
-        enum8_     = Keyword("enum8").setParseAction(replaceWith(8))
-        flags32_   = Keyword("flags32").setParseAction(replaceWith(32))
-        flags16_   = Keyword("flags16").setParseAction(replaceWith(16))
-        flags8_    = Keyword("flags8").setParseAction(replaceWith(8))
-        channel_   = Keyword("channel")
-        server_    = Keyword("server")
-        client_    = Keyword("client")
-        protocol_  = Keyword("protocol")
-        typedef_   = Keyword("typedef")
-        struct_    = Keyword("struct")
-        message_   = Keyword("message")
-        image_size_ = Keyword("image_size")
-        bytes_     = Keyword("bytes")
-        cstring_   = Keyword("cstring")
-        switch_    = Keyword("switch")
-        default_   = Keyword("default")
-        case_      = Keyword("case")
-
-        identifier = Word( alphas, alphanums + "_" )
-        enumname = Word( alphanums + "_" )
-
-        integer = ( Combine( CaselessLiteral("0x") + Word( nums+"abcdefABCDEF" ) ) |
-                    Word( nums+"+-", nums ) ).setName("int").setParseAction(cvtInt)
-
-        typename = identifier.copy().setParseAction(lambda toks : ptypes.TypeRef(str(toks[0])))
-
-        # This is just normal "types", i.e. not channels or messages
-        typeSpec = Forward()
-
-        attributeValue = integer ^ identifier
-        attribute = Group(Combine ("@" + identifier) + Optional(lparen + delimitedList(attributeValue) + rparen))
-        attributes = Group(ZeroOrMore(attribute))
-        arraySizeSpecImage = Group(image_size_ + lparen + integer + comma + identifier + comma + identifier + rparen)
-        arraySizeSpecBytes = Group(bytes_ + lparen + identifier + comma + identifier + rparen)
-        arraySizeSpecCString = Group(cstring_ + lparen + rparen)
-        arraySizeSpec = lbrack + Optional(identifier ^ integer ^ arraySizeSpecImage ^ arraySizeSpecBytes ^arraySizeSpecCString, default="") + rbrack
-        variableDef = Group(typeSpec + Optional("*", default=None) + identifier + Optional(arraySizeSpec, default=None) + attributes - semi) \
-            .setParseAction(parseVariableDef)
-
-        switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | Group(case_.suppress() + Optional("!", default="") + identifier) + colon)) + variableDef) \
-            .setParseAction(lambda toks: ptypes.SwitchCase(toks[0][0], toks[0][1]))
-        switchBody = Group(switch_ + lparen + delimitedList(identifier,delim='.', combine=True) + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \
-            .setParseAction(lambda toks: ptypes.Switch(toks[0][1], toks[0][2], toks[0][3], toks[0][4]))
-        messageBody = structBody = Group(lbrace + ZeroOrMore(variableDef | switchBody)  + rbrace)
-        structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))
-
-        # have to use longest match for type, in case a user-defined type name starts with a keyword type, like "channel_type"
-        typeSpec << ( structSpec ^ int8_ ^ uint8_ ^ int16_ ^ uint16_ ^
-                     int32_ ^ uint32_ ^ int64_ ^ uint64_ ^
-                     typename).setName("type")
-
-        flagsBody = enumBody = Group(lbrace + delimitedList(Group (enumname + Optional(equals + integer))) + Optional(comma) + rbrace)
-
-        messageSpec = Group(message_ + messageBody + attributes).setParseAction(lambda toks: ptypes.MessageType(None, toks[0][1], toks[0][2])) | typename
-
-        channelParent = Optional(colon + typename, default=None)
-        channelMessage = Group(messageSpec + identifier + Optional(equals + integer, default=None) + semi) \
-            .setParseAction(lambda toks: ptypes.ChannelMember(toks[0][1], toks[0][0], toks[0][2]))
-        channelBody = channelParent + Group(lbrace + ZeroOrMore( server_ + colon | client_ + colon | channelMessage)  + rbrace)
-
-        enum_ = (enum32_ | enum16_ | enum8_)
-        flags_ = (flags32_ | flags16_ | flags8_)
-        enumDef = Group(enum_ + identifier + enumBody + attributes - semi).setParseAction(lambda toks: ptypes.EnumType(toks[0][0], toks[0][1], toks[0][2], toks[0][3]))
-        flagsDef = Group(flags_ + identifier + flagsBody + attributes  - semi).setParseAction(lambda toks: ptypes.FlagsType(toks[0][0], toks[0][1], toks[0][2], toks[0][3]))
-        messageDef = Group(message_ + identifier + messageBody + attributes - semi).setParseAction(lambda toks: ptypes.MessageType(toks[0][1], toks[0][2], toks[0][3]))
-        channelDef = Group(channel_ + identifier + channelBody + attributes - semi).setParseAction(lambda toks: ptypes.ChannelType(toks[0][1], toks[0][2], toks[0][3], toks[0][4]))
-        structDef = Group(struct_ + identifier + structBody + attributes - semi).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))
-        typedefDef = Group(typedef_ + identifier  + typeSpec + attributes - semi).setParseAction(lambda toks: ptypes.TypeAlias(toks[0][1], toks[0][2], toks[0][3]))
-
-        definitions = typedefDef | structDef | enumDef | flagsDef | messageDef | channelDef
-
-        protocolChannel = Group(typename + identifier +  Optional(equals + integer, default=None) + semi) \
-            .setParseAction(lambda toks: ptypes.ProtocolMember(toks[0][1], toks[0][0], toks[0][2]))
-        protocolDef = Group(protocol_ + identifier + Group(lbrace + ZeroOrMore(protocolChannel) + rbrace) + semi) \
-            .setParseAction(lambda toks: ptypes.ProtocolType(toks[0][1], toks[0][2]))
-
-        bnf = ZeroOrMore (definitions) +  protocolDef + StringEnd()
-
-        singleLineComment = "//" + restOfLine
-        bnf.ignore( singleLineComment )
-        bnf.ignore( cStyleComment )
-
-    return bnf
-
-
-def parse(filename):
-    try:
-        bnf = SPICE_BNF()
-        types = bnf.parseFile(filename)
-    except ParseException as err:
-        six.print_(err.line, file=sys.stderr)
-        six.print_(" "*(err.column-1) + "^", file=sys.stderr)
-        six.print_(err, file=sys.stderr)
-        return None
-
-    for t in types:
-        t.resolve()
-        t.register()
-    protocol = types[-1]
-    return protocol
-- 
2.1.0



More information about the Spice-devel mailing list