[Spice-devel] [PATCH spice-gtk] build-sys: move codegen & proto to spice-common

Alon Levy alevy at redhat.com
Thu Mar 22 10:30:02 PDT 2012


On Thu, Mar 22, 2012 at 06:05:18PM +0100, Marc-André Lureau wrote:
> With this iteration, all the spice_codegen.py/proto/marshaller
> generation has been moved to spice-common.
> 
> The spice-common directory will ship spice-protocol, since it's needed
> there too to build libspice-common.
> 

Is it possible to split this to:
 remove spice-protocol dependency
 rename common to spice-common

?

Maybe in reverse order?

> Again, make distcheck passes. Build with mingw & fedora linux.
> ---
>  .gitmodules                    |    7 +-
>  Makefile.am                    |   47 +-
>  autogen.sh                     |    3 +-
>  common                         |    1 -
>  configure.ac                   |   11 +-
>  doc/reference/Makefile.am      |    2 +-
>  gtk/Makefile.am                |   91 +---
>  gtk/channel-display-priv.h     |   13 +-
>  gtk/controller/Makefile.am     |    2 +-
>  gtk/decode-glz.c               |    3 +-
>  gtk/decode.h                   |    2 +-
>  gtk/spice-channel-cache.h      |    5 +-
>  gtk/spice-channel-priv.h       |    7 +-
>  gtk/spice-common.h             |    7 +-
>  gtk/spice-session.c            |    8 +-
>  python_modules/Makefile.am     |   10 -
>  python_modules/codegen.py      |  374 ------------
>  python_modules/demarshal.py    | 1257 ----------------------------------------
>  python_modules/marshal.py      |  424 --------------
>  python_modules/ptypes.py       | 1034 ---------------------------------
>  python_modules/spice_parser.py |  161 -----
>  spice-common                   |    1 +
>  spice-protocol                 |    1 -
>  spice.proto                    | 1205 --------------------------------------
>  spice1.proto                   |  934 -----------------------------
>  spice_codegen.py               |  211 -------
>  26 files changed, 72 insertions(+), 5749 deletions(-)
>  delete mode 160000 common
>  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
>  create mode 160000 spice-common
>  delete mode 160000 spice-protocol
>  delete mode 100644 spice.proto
>  delete mode 100644 spice1.proto
>  delete mode 100755 spice_codegen.py
> 
> diff --git a/.gitmodules b/.gitmodules
> index 6981ae4..0c618ee 100644
> --- a/.gitmodules
> +++ b/.gitmodules
> @@ -1,6 +1,3 @@
> -[submodule "spice-protocol"]
> -	path = spice-protocol
> -	url = ../spice-protocol
> -[submodule "common"]
> -	path = common
> +[submodule "spice-common"]
> +	path = spice-common
>  	url = ../spice-common
> diff --git a/Makefile.am b/Makefile.am
> index 5f1353c..0d168a8 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -1,7 +1,8 @@
>  ACLOCAL_AMFLAGS = -I m4
>  NULL =
>  
> -SUBDIRS = spice-protocol common gtk po python_modules doc data
> +SUBDIRS = spice-common gtk po doc data
> +
>  if HAVE_INTROSPECTION
>  if WITH_VALA
>  SUBDIRS += vapi
> @@ -12,30 +13,31 @@ pkgconfigdir = $(libdir)/pkgconfig
>  pkgconfig_DATA =					\
>  	spice-client-glib-2.0.pc			\
>  	spice-client-gtk-$(SPICE_GTK_API_VERSION).pc	\
> -	spice-controller.pc
> +	spice-controller.pc				\
> +	$(NULL)
>  
> -INTLTOOL_FILES = intltool-extract.in		\
> -		 intltool-merge.in		\
> -		 intltool-update.in		\
> -		 $(NULL)
> +INTLTOOL_FILES =				\
> +	intltool-extract.in			\
> +	intltool-merge.in			\
> +	intltool-update.in			\
> +	$(NULL)
>  
> -DISTCLEANFILES = $(pkgconfig_DATA)		\
> -		 intltool-extract		\
> -		 intltool-merge			\
> -		 intltool-update		\
> -		 gnome-doc-utils.make		\
> -		 po/.intltool-merge-cache	\
> -		 $(NULL)
> +DISTCLEANFILES =				\
> +	$(pkgconfig_DATA)			\
> +	intltool-extract			\
> +	intltool-merge				\
> +	intltool-update				\
> +	gnome-doc-utils.make			\
> +	po/.intltool-merge-cache		\
> +	$(NULL)
>  
> -EXTRA_DIST = spice.proto			\
> -	     spice1.proto			\
> -	     spice_codegen.py			\
> -	     build-aux/git-version-gen		\
> -	     gtk-doc.make			\
> -	     .version				\
> -	     THANKS				\
> -	     $(INTLTOOL_FILES)			\
> -	     $(NULL)
> +EXTRA_DIST =					\
> +	build-aux/git-version-gen		\
> +	gtk-doc.make				\
> +	.version				\
> +	THANKS					\
> +	$(INTLTOOL_FILES)			\
> +	$(NULL)
>  
>  MAINTAINERCLEANFILES =				\
>  	ABOUT-NLS				\
> @@ -104,4 +106,3 @@ spicy-for-windows.exe:
>  	 /usr/i686-pc-mingw32/sys-root/mingw/lib/gstreamer-0.10/libgstcoreelements.dll
>  
>  -include $(top_srcdir)/git.mk
> -
> diff --git a/autogen.sh b/autogen.sh
> index f36bb6f..11aedb0 100755
> --- a/autogen.sh
> +++ b/autogen.sh
> @@ -5,8 +5,7 @@ set -e # exit on errors
>  srcdir=`dirname $0`
>  test -z "$srcdir" && srcdir=.
>  
> -git submodule init
> -git submodule update
> +git submodule update --init --recursive
>  
>  gtkdocize
>  autoreconf -v --force --install
> diff --git a/common b/common
> deleted file mode 160000
> index c71904e..0000000
> --- a/common
> +++ /dev/null
> @@ -1 +0,0 @@
> -Subproject commit c71904e26748d7932df581939f64383a18acaf0e
> diff --git a/configure.ac b/configure.ac
> index 1ac291f..45d99dc 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -23,8 +23,6 @@ AC_SUBST(SPICE_GTK_LOCALEDIR)
>  
>  GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
>  
> -# Define default SPICE_COMMON_SRCDIR
> -SPICE_COMMON_SRCDIR='$(top_srcdir)'/common
>  # no opengl support yet
>  AM_CONDITIONAL(SUPPORT_GL, false)
>  
> @@ -71,9 +69,9 @@ AC_CHECK_HEADERS([sys/socket.h netinet/in.h arpa/inet.h])
>  AC_CHECK_LIBM
>  AC_SUBST(LIBM)
>  
> -AC_CONFIG_SUBDIRS([spice-protocol])
> -PROTOCOL_CFLAGS='-I ${top_srcdir}/spice-protocol'
> -AC_SUBST(PROTOCOL_CFLAGS)
> +AC_CONFIG_SUBDIRS([spice-common])
> +COMMON_CFLAGS='-I ${top_srcdir}/spice-common/ -I ${top_srcdir}/spice-common/spice-protocol/'
> +AC_SUBST(COMMON_CFLAGS)
>  
>  dnl =========================================================================
>  dnl Chek optional features
> @@ -593,7 +591,6 @@ SPICE_GTK_CFLAGS="$SPICE_GLIB_CFLAGS $GTK_CFLAGS "
>  AC_SUBST(SPICE_GLIB_CFLAGS)
>  AC_SUBST(SPICE_GTK_CFLAGS)
>  
> -AC_SUBST(SPICE_COMMON_SRCDIR)
>  AC_SUBST(SPICE_GLIB_REQUIRES)
>  AC_SUBST(SPICE_GTK_REQUIRES)
>  
> @@ -605,12 +602,10 @@ spice-client-glib-2.0.pc
>  spice-client-gtk-2.0.pc
>  spice-client-gtk-3.0.pc
>  spice-controller.pc
> -common/Makefile
>  data/Makefile
>  data/spicy.desktop.in
>  data/spicy.nsis
>  po/Makefile.in
> -python_modules/Makefile
>  gtk/Makefile
>  gtk/controller/Makefile
>  doc/Makefile
> diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am
> index 372850a..a0a856c 100644
> --- a/doc/reference/Makefile.am
> +++ b/doc/reference/Makefile.am
> @@ -53,7 +53,7 @@ IGNORE_HFILES=					\
>  	$(NULL)
>  
>  # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
> -GTKDOC_CFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/gtk -I$(top_builddir)/gtk $(SPICE_GLIB_CFLAGS) $(SPICE_GTK_CFLAGS)
> +GTKDOC_CFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/gtk -I$(top_builddir)/gtk $(SPICE_GLIB_CFLAGS) $(SPICE_GTK_CFLAGS) $(COMMON_CFLAGS)
>  GTKDOC_LIBS = $(top_builddir)/gtk/libspice-client-glib-2.0.la $(top_builddir)/gtk/libspice-client-gtk-$(SPICE_GTK_API_VERSION).la
>  
>  include $(top_srcdir)/gtk-doc.make
> diff --git a/gtk/Makefile.am b/gtk/Makefile.am
> index cd6da20..4e72f73 100644
> --- a/gtk/Makefile.am
> +++ b/gtk/Makefile.am
> @@ -2,16 +2,6 @@ NULL =
>  
>  SUBDIRS = controller
>  
> -COMMON_DIR = $(SPICE_COMMON_SRCDIR)
> -
> -# Avoid need for python(pyparsing) by end users
> -MARSHALLERS =					\
> -	generated_demarshallers.c		\
> -	generated_demarshallers1.c		\
> -	generated_marshallers.c			\
> -	generated_marshallers1.c		\
> -	$(NULL)
> -
>  # Avoid need for perl(Text::CSV) by end users
>  KEYMAPS =					\
>  	vncdisplaykeymap_xorgevdev2xtkbd.c	\
> @@ -33,10 +23,9 @@ GLIBGENS =					\
>  	$(NULL)
>  
>  CLEANFILES = $(GLIBGENS)
> -BUILT_SOURCES = $(GLIBGENS) $(KEYMAPS) $(MARSHALLERS)
> +BUILT_SOURCES = $(GLIBGENS) $(KEYMAPS)
>  
>  EXTRA_DIST =					\
> -	$(MARSHALLERS)				\
>  	$(KEYMAPS)				\
>  	decode-glz-tmpl.c			\
>  	keymap-gen.pl				\
> @@ -78,10 +67,8 @@ SPICE_COMMON_CPPFLAGS = \
>  	-DPNP_IDS=\""$(PNP_IDS)"\"      \
>  	-DUSB_IDS=\""$(USB_IDS)"\"      \
>  	-DSPICE_DISABLE_ABORT		\
> -	\
> -	-I$(COMMON_DIR)			\
> -	\
> -	$(PROTOCOL_CFLAGS)		\
> +	-I$(top_srcdir)			\
> +	$(COMMON_CFLAGS)		\
>  	$(PIXMAN_CFLAGS)		\
>  	$(CELT051_CFLAGS)		\
>  	$(PULSE_CFLAGS)			\
> @@ -175,20 +162,21 @@ libspice_client_glib_2_0_la_LDFLAGS =	\
>  	$(VERSION_LDFLAGS)		\
>  	$(NULL)
>  
> -libspice_client_glib_2_0_la_LIBADD =	\
> -	$(GLIB2_LIBS)			\
> -	$(GIO_LIBS)			\
> -	$(GOBJECT2_LIBS)		\
> -	$(CELT051_LIBS)			\
> -	$(JPEG_LIBS)			\
> -	$(Z_LIBS)			\
> -	$(PIXMAN_LIBS)			\
> -	$(SSL_LIBS)			\
> -	$(PULSE_LIBS)			\
> -	$(GST_LIBS)			\
> -	$(SASL_LIBS)			\
> -	$(SMARTCARD_LIBS)		\
> -	$(USBREDIR_LIBS)		\
> +libspice_client_glib_2_0_la_LIBADD =			\
> +	$(GLIB2_LIBS)					\
> +	$(GIO_LIBS)					\
> +	$(GOBJECT2_LIBS)				\
> +	$(CELT051_LIBS)					\
> +	$(JPEG_LIBS)					\
> +	$(Z_LIBS)					\
> +	$(PIXMAN_LIBS)					\
> +	$(SSL_LIBS)					\
> +	$(PULSE_LIBS)					\
> +	$(GST_LIBS)					\
> +	$(SASL_LIBS)					\
> +	$(SMARTCARD_LIBS)				\
> +	$(USBREDIR_LIBS)				\
> +	$(top_builddir)/spice-common/common/libspice-common.la	\
>  	$(NULL)
>  
>  if WITH_POLKIT
> @@ -248,36 +236,11 @@ libspice_client_glib_2_0_la_SOURCES =	\
>  	decode-jpeg.c			\
>  	decode-zlib.c			\
>  	\
> -	$(COMMON_DIR)/backtrace.c	\
> -	$(COMMON_DIR)/backtrace.h	\
> -	$(COMMON_DIR)/mem.c		\
> -	$(COMMON_DIR)/mem.h		\
> -	$(COMMON_DIR)/marshaller.c	\
> -	$(COMMON_DIR)/marshaller.h	\
> -	$(COMMON_DIR)/canvas_utils.c	\
> -	$(COMMON_DIR)/canvas_utils.h	\
> -	$(COMMON_DIR)/sw_canvas.c	\
> -	$(COMMON_DIR)/sw_canvas.h	\
> -	$(COMMON_DIR)/pixman_utils.c	\
> -	$(COMMON_DIR)/pixman_utils.h	\
> -	$(COMMON_DIR)/lines.c		\
> -	$(COMMON_DIR)/lines.h		\
> -	$(COMMON_DIR)/rop3.c		\
> -	$(COMMON_DIR)/rop3.h		\
> -	$(COMMON_DIR)/quic.c		\
> -	$(COMMON_DIR)/quic.h		\
> -	$(COMMON_DIR)/log.c		\
> -	$(COMMON_DIR)/log.h		\
> -	$(COMMON_DIR)/lz.c		\
> -	$(COMMON_DIR)/lz.h		\
> -	$(COMMON_DIR)/region.c		\
> -	$(COMMON_DIR)/region.h		\
> -	$(COMMON_DIR)/ssl_verify.c	\
> -	$(COMMON_DIR)/ssl_verify.h	\
> +	$(top_srcdir)/spice-common/common/sw_canvas.c	\
> +	$(top_srcdir)/spice-common/common/sw_canvas.h	\
>  	$(NULL)
>  
>  nodist_libspice_client_glib_2_0_la_SOURCES =	\
> -	$(MARSHALLERS)			\
>  	spice-glib-enums.c		\
>  	spice-marshal.c			\
>  	spice-marshal.h			\
> @@ -511,20 +474,6 @@ spice-widget-enums.h: spice-widget.h
>  		$< >  $@
>  
>  
> -# Note despite being autogenerated these are not part of CLEANFILES, they are
> -# actually a part of EXTRA_DIST, to avoid the need for pyparser by end users
> -generated_demarshallers.c: $(top_srcdir)/spice.proto
> -	$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include messages.h $< $@ >/dev/null
> -
> -generated_demarshallers1.c: $(top_srcdir)/spice1.proto
> -	$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include messages.h --prefix 1 --ptrsize 8 $< $@ >/dev/null
> -
> -generated_marshallers.c: $(top_srcdir)/spice.proto
> -	$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include client_marshallers.h --client $< $@ >/dev/null
> -
> -generated_marshallers1.c: $(top_srcdir)/spice1.proto
> -	$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include client_marshallers.h --client --prefix 1 --ptrsize 8 $< $@ >/dev/null
> -
>  vncdisplaykeymap.c: $(KEYMAPS)
>  
>  $(KEYMAPS): $(KEYMAP_GEN) keymaps.csv
> diff --git a/gtk/channel-display-priv.h b/gtk/channel-display-priv.h
> index eca1787..6fb624a 100644
> --- a/gtk/channel-display-priv.h
> +++ b/gtk/channel-display-priv.h
> @@ -26,13 +26,12 @@
>  #endif
>  #include <jpeglib.h>
>  
> -/* spice/common */
> -#include "canvas_base.h"
> -#include "canvas_utils.h"
> -#include "sw_canvas.h"
> -#include "ring.h"
> -#include "quic.h"
> -#include "rop3.h"
> +#include "common/canvas_base.h"
> +#include "common/canvas_utils.h"
> +#include "common/sw_canvas.h"
> +#include "common/ring.h"
> +#include "common/quic.h"
> +#include "common/rop3.h"
>  
>  G_BEGIN_DECLS
>  
> diff --git a/gtk/controller/Makefile.am b/gtk/controller/Makefile.am
> index 639a1e0..f1fb4af 100644
> --- a/gtk/controller/Makefile.am
> +++ b/gtk/controller/Makefile.am
> @@ -3,7 +3,7 @@ NULL =
>  AM_CPPFLAGS =					\
>  	-DG_LOG_DOMAIN=\"GSpiceController\"	\
>  	$(GIO_CFLAGS)				\
> -	$(PROTOCOL_CFLAGS)			\
> +	$(COMMON_CFLAGS)			\
>  	$(NULL)
>  
>  # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
> diff --git a/gtk/decode-glz.c b/gtk/decode-glz.c
> index 4033480..e2626ef 100644
> --- a/gtk/decode-glz.c
> +++ b/gtk/decode-glz.c
> @@ -25,8 +25,7 @@
>  #include "spice-util.h"
>  #include "decode.h"
>  
> -/* spice/common */
> -#include "canvas_utils.h"
> +#include "common/canvas_utils.h"
>  
>  struct glz_image_hdr {
>      uint64_t                id;
> diff --git a/gtk/decode.h b/gtk/decode.h
> index 9db6383..7af0760 100644
> --- a/gtk/decode.h
> +++ b/gtk/decode.h
> @@ -20,7 +20,7 @@
>  
>  #include <glib.h>
>  
> -#include "canvas_base.h"
> +#include "common/canvas_base.h"
>  
>  G_BEGIN_DECLS
>  
> diff --git a/gtk/spice-channel-cache.h b/gtk/spice-channel-cache.h
> index d8a40f3..3f39877 100644
> --- a/gtk/spice-channel-cache.h
> +++ b/gtk/spice-channel-cache.h
> @@ -18,10 +18,9 @@
>  #ifndef SPICE_CHANNEL_CACHE_H_
>  # define SPICE_CHANNEL_CACHE_H_
>  
> -/* spice/common */
>  #include <inttypes.h> /* For PRIx64 */
> -#include "mem.h"
> -#include "ring.h"
> +#include "common/mem.h"
> +#include "common/ring.h"
>  
>  G_BEGIN_DECLS
>  
> diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
> index 299b581..ac8bece 100644
> --- a/gtk/spice-channel-priv.h
> +++ b/gtk/spice-channel-priv.h
> @@ -33,10 +33,9 @@
>  #include "coroutine.h"
>  #include "gio-coroutine.h"
>  
> -#include "client_marshallers.h"
> -#include "client_demarshallers.h"
> -
> -#include "ssl_verify.h"
> +#include "common/client_marshallers.h"
> +#include "common/client_demarshallers.h"
> +#include "common/ssl_verify.h"
>  
>  G_BEGIN_DECLS
>  
> diff --git a/gtk/spice-common.h b/gtk/spice-common.h
> index cd8c4fc..8554f4c 100644
> --- a/gtk/spice-common.h
> +++ b/gtk/spice-common.h
> @@ -27,10 +27,9 @@
>  #include <errno.h>
>  #include <inttypes.h>
>  
> -/* spice/common */
> -#include "mem.h"
> -#include "messages.h"
> -#include "marshaller.h"
> +#include "common/mem.h"
> +#include "common/messages.h"
> +#include "common/marshaller.h"
>  
>  #include "spice-util.h"
>  
> diff --git a/gtk/spice-session.c b/gtk/spice-session.c
> index 745ccaf..e9c8b94 100644
> --- a/gtk/spice-session.c
> +++ b/gtk/spice-session.c
> @@ -17,16 +17,14 @@
>  */
>  #include <gio/gio.h>
>  #include <glib.h>
> +
> +#include "common/ring.h"
> +
>  #include "spice-client.h"
>  #include "spice-common.h"
>  #include "spice-channel-priv.h"
>  #include "spice-util-priv.h"
> -
>  #include "spice-session-priv.h"
> -
> -/* spice/common */
> -#include "ring.h"
> -
>  #include "gio-coroutine.h"
>  #include "glib-compat.h"
>  
> diff --git a/python_modules/Makefile.am b/python_modules/Makefile.am
> deleted file mode 100644
> index 95cb1c0..0000000
> --- a/python_modules/Makefile.am
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -NULL =
> -
> -PYTHON_MODULES = __init__.py codegen.py demarshal.py marshal.py ptypes.py spice_parser.py
> -
> -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 a2c010b..0000000
> --- a/python_modules/codegen.py
> +++ /dev/null
> @@ -1,374 +0,0 @@
> -from __future__ import with_statement
> -from cStringIO 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
> -
> -    def set_option(self, opt, value = True):
> -        self.options[opt] = value
> -
> -    def has_option(self, opt):
> -        return self.options.has_key(opt)
> -
> -    def set_is_generated(self, kind, name):
> -        if not self.generated.has_key(kind):
> -            v = {}
> -            self.generated[kind] = v
> -        else:
> -            v = self.generated[kind]
> -        v[name] = 1
> -
> -    def is_generated(self, kind, name):
> -        if not self.generated.has_key(kind):
> -            return False
> -        v = self.generated[kind]
> -        return v.has_key(name)
> -
> -    def getvalue(self):
> -        strs = map(lambda writer: writer.getvalue(), 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.generated = self.generated
> -        writer.options = self.options
> -        writer.public_prefix = self.public_prefix
> -
> -        return writer;
> -
> -    def write(self, s):
> -        # Ensure its a string
> -        s = str(s)
> -
> -        if len(s) == 0:
> -            return
> -
> -        if self.at_line_start:
> -            for i in range(self.indentation):
> -                self.out.write(" ")
> -            self.at_line_start = False
> -        self.out.write(s)
> -        return self
> -
> -    def newline(self):
> -        self.out.write("\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.indenttation = 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 self.function_variables.has_key(name):
> -            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("uint32_t", index)
> -        return index
> -
> -    def push_index(self):
> -        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 c999bd3..0000000
> --- a/python_modules/demarshal.py
> +++ /dev/null
> @@ -1,1257 +0,0 @@
> -from __future__ import with_statement
> -import ptypes
> -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, container, start):
> -        if not member.is_switch():
> -            self.type = member.member_type
> -        self.prefix = member.name
> -        self.subprefix = member.name
> -        self.position = "(%s + %s)" % (start, container.get_nw_offset(member, "", "__nw_size"))
> -        self.member = member
> -
> -def write_validate_switch_member(writer, 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, 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, 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, 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, container, start)
> -    with writer.block(prefix, newline=newline, comment=member.name) as scope:
> -        if member.is_switch():
> -            write_validate_switch_member(writer, 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):
> -    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"]
> -        if sub_want_nw_size:
> -            defs.append (m.name + "__nw_size")
> -        if sub_want_mem_size:
> -            defs.append (m.name + "__mem_size")
> -        if sub_want_extra_size:
> -            defs.append (m.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, 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:
> -            if not m.is_fixed_nw_size():
> -                nm_sum = nm_sum + " + " + m.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:
> -            if m.is_extra_size():
> -                mem_sum = mem_sum + " + " + m.name + "__mem_size"
> -            elif m.contains_extra_size():
> -                mem_sum = mem_sum + " + " + m.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:
> -            if m.is_extra_size():
> -                extra_sum.append(m.name + "__mem_size")
> -            elif m.contains_extra_size():
> -                extra_sum.append(m.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, uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, 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", "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, 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 ids2.has_key(end):
> -            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, 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 channel_parsers.has_key(i):
> -            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, 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 "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 d93f983..0000000
> --- a/python_modules/marshal.py
> +++ /dev/null
> @@ -1,424 +0,0 @@
> -from __future__ import with_statement
> -import ptypes
> -import codegen
> -
> -def write_includes(writer):
> -    writer.header.writeln("#include <spice/protocol.h>")
> -    writer.header.writeln("#include <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 <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):
> -    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 = map(lambda name: ", SpiceMarshaller **%s_out" % name, names)
> -        names_args = "".join(n)
> -
> -    header = writer.header
> -    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 "(%s * %s)" % (width_v, rows_v)
> -        elif bpp == 1:
> -            return "(((%s + 7) / 8 ) * %s)" % (width_v, rows_v)
> -        else:
> -            return "(((%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 = map(lambda name: ", SpiceMarshaller **%s_out" % name, 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",
> -                            "SpiceMarshaller *m, %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])
> -        if is_server:
> -            for m in channel.client_messages:
> -                message = m.message_type
> -                f = write_message_marshaller(writer, message, is_server, private_marshallers)
> -                if channel.has_attr("ifdef") and not functions.has_key(f):
> -                    functions[f] = channel.attributes["ifdef"][0]
> -                elif message.has_attr("ifdef") and not functions.has_key(f):
> -                    functions[f] = message.attributes["ifdef"][0]
> -                else:
> -                    functions[f] = True
> -        else:
> -            for m in channel.server_messages:
> -                message = m.message_type
> -                f = write_message_marshaller(writer, message, is_server, private_marshallers)
> -                if channel.has_attr("ifdef") and not functions.has_key(f):
> -                    functions[f] = channel.attributes["ifdef"][0]
> -                elif message.has_attr("ifdef") and not functions.has_key(f):
> -                    functions[f] = message.attributes["ifdef"][0]
> -                else:
> -                    functions[f] = True
> -        if channel.has_attr("ifdef"):
> -            writer.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 cdbe871..0000000
> --- a/python_modules/ptypes.py
> +++ /dev/null
> @@ -1,1034 +0,0 @@
> -import codegen
> -import types
> -
> -_types_by_name = {}
> -_types = []
> -
> -default_pointer_size = 4
> -
> -def type_exists(name):
> -    return _types_by_name.has_key(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, types.IntType):
> -            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"]
> -
> -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 _types_by_name.has_key(self.name):
> -            raise Exception, "Type %s already defined" % self.name
> -        _types.append(self)
> -        _types_by_name[self.name] = self
> -
> -    def has_attr(self, name):
> -        return self.attributes.has_key(name)
> -
> -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 not _types_by_name.has_key(self.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
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    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):
> -        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
> -
> -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 not names.has_key(value)
> -            names[value] = name
> -            values[name] = value
> -
> -        self.names = names
> -        self.values = values
> -
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    def __str__(self):
> -        return "enum %s" % self.name
> -
> -    def c_define(self, writer):
> -        writer.write("enum ")
> -        writer.write(self.c_name())
> -        writer.begin_block()
> -        values = 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(semicolon=True)
> -        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 not names.has_key(value)
> -            names[value] = name
> -            values[name] = value
> -
> -        self.names = names
> -        self.values = values
> -
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    def __str__(self):
> -        return "flags %s" % self.name
> -
> -    def c_define(self, writer):
> -        writer.write("enum ")
> -        writer.write(self.c_name())
> -        writer.begin_block()
> -        values = 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(semicolon=True)
> -        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, types.IntType)
> -
> -    def is_remaining_length(self):
> -        return isinstance(self.size, types.StringType) and len(self.size) == 0
> -
> -    def is_identifier_length(self):
> -        return isinstance(self.size, types.StringType) and len(self.size) > 0
> -
> -    def is_image_size_length(self):
> -        if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
> -            return False
> -        return self.size[0] == "image_size"
> -
> -    def is_bytes_length(self):
> -        if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
> -            return False
> -        return self.size[0] == "bytes"
> -
> -    def is_cstring_length(self):
> -        if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
> -            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):
> -        return self.attributes.has_key(name)
> -
> -    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
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    def resolve(self, container):
> -        self.container = container
> -        self.member_type = self.member_type.resolve()
> -        self.member_type.register()
> -        if self.has_attr("ptr32") and self.member_type.is_pointer():
> -            self.member_type.set_ptr_size(4)
> -        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 = map(lambda name: prefix + "_" + name, 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
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    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 = map(lambda c : c.resolve(self), 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 = map(lambda m : m.resolve(self), 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 self.members_by_name.has_key(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
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    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
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    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 = 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 = 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
> -        for attr in attribute_list:
> -            self.attributes[attr[0][1:]] = attr[1:]
> -
> -    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()
> -        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()
> -        assert(self.channel_type.member_name == None)
> -        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 f634800..0000000
> --- a/python_modules/spice_parser.py
> +++ /dev/null
> @@ -1,161 +0,0 @@
> -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:
> -    print "Module pyparsing not found."
> -    exit(1)
> -
> -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
> -        channel_   = Keyword("channel")
> -        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, err:
> -        print >> sys.stderr, err.line
> -        print >> sys.stderr, " "*(err.column-1) + "^"
> -        print >> sys.stderr, err
> -        return None
> -
> -    for t in types:
> -        t.resolve()
> -        t.register()
> -    protocol = types[-1]
> -    return protocol
> -
> diff --git a/spice-common b/spice-common
> new file mode 160000
> index 0000000..77cf70e
> --- /dev/null
> +++ b/spice-common
> @@ -0,0 +1 @@
> +Subproject commit 77cf70e4e6e8076250ca690246c6d89e1aa160c4
> diff --git a/spice-protocol b/spice-protocol
> deleted file mode 160000
> index 32da251..0000000
> --- a/spice-protocol
> +++ /dev/null
> @@ -1 +0,0 @@
> -Subproject commit 32da251a6572e3463cff040d106bb47a04e5a905
> diff --git a/spice.proto b/spice.proto
> deleted file mode 100644
> index da01a94..0000000
> --- a/spice.proto
> +++ /dev/null
> @@ -1,1205 +0,0 @@
> -/* built in types:
> -   int8, uint8, 16, 32, 64
> -*/
> -
> -typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4);
> -
> -struct Point {
> -    int32 x;
> -    int32 y;
> -};
> -
> -struct Point16 {
> -    int16 x;
> -    int16 y;
> -};
> -
> -struct PointFix {
> -    fixed28_4 x;
> -    fixed28_4 y;
> -};
> -
> -struct Rect {
> -    int32 top;
> -    int32 left;
> -    int32 bottom;
> -    int32 right;
> -};
> -
> -enum32 link_err {
> -    OK,
> -    ERROR,
> -    INVALID_MAGIC,
> -    INVALID_DATA,
> -    VERSION_MISMATCH,
> -    NEED_SECURED,
> -    NEED_UNSECURED,
> -    PERMISSION_DENIED,
> -    BAD_CONNECTION_ID,
> -    CHANNEL_NOT_AVAILABLE
> -};
> -
> -enum32 warn_code {
> -    WARN_GENERAL
> -} @prefix(SPICE_);
> -
> -enum32 info_code {
> -    INFO_GENERAL
> -} @prefix(SPICE_);
> -
> -flags32 migrate_flags {
> -    NEED_FLUSH,
> -    NEED_DATA_TRANSFER
> -} @prefix(SPICE_MIGRATE_);
> -
> -enum32 notify_severity {
> -    INFO,
> -    WARN,
> -    ERROR,
> -};
> -
> -enum32 notify_visibility {
> -    LOW,
> -    MEDIUM,
> -    HIGH,
> -};
> -
> -flags16 mouse_mode {
> -    SERVER,
> -    CLIENT,
> -};
> -
> -enum16 pubkey_type {
> -    INVALID,
> -    RSA,
> -    RSA2,
> -    DSA,
> -    DSA1,
> -    DSA2,
> -    DSA3,
> -    DSA4,
> -    DH,
> -    EC,
> -};
> -
> -message Empty {
> -};
> -
> -message Data {
> -    uint8 data[] @end @ctype(uint8_t);
> -} @nocopy;
> -
> -struct ChannelWait {
> -    uint8 channel_type;
> -    uint8 channel_id;
> -    uint64 message_serial;
> -} @ctype(SpiceWaitForChannel);
> -
> -channel BaseChannel {
> - server:
> -    message {
> -	migrate_flags flags;
> -    } migrate;
> -
> -    Data migrate_data;
> -
> -    message {
> -	uint32 generation;
> -	uint32 window;
> -    } set_ack;
> -
> -    message {
> -	uint32 id;
> -	uint64 timestamp;
> -	uint8 data[] @ctype(uint8_t) @as_ptr(data_len);
> -    } ping;
> -
> -    message {
> -	uint8 wait_count;
> -	ChannelWait wait_list[wait_count] @end;
> -    } wait_for_channels;
> -
> -    message {
> -	uint64 time_stamp;
> -	link_err reason;
> -    } @ctype(SpiceMsgDisconnect) disconnecting;
> -
> -    message {
> -	uint64 time_stamp;
> -	notify_severity severity;
> -	notify_visibility visibilty;
> -	uint32 what; /* error_code/warn_code/info_code */
> -	uint32 message_len;
> -	uint8 message[message_len] @end @nomarshal;
> -    } notify;
> -
> - client:
> -    message {
> -	uint32 generation;
> -    } ack_sync;
> -
> -    Empty ack;
> -
> -    message {
> -	uint32 id;
> -	uint64 timestamp;
> -    } @ctype(SpiceMsgPing) pong;
> -
> -    Empty migrate_flush_mark;
> -
> -    Data migrate_data;
> -
> -    message {
> -    	uint64 time_stamp;
> -	link_err reason;
> -    } @ctype(SpiceMsgDisconnect) disconnecting;
> -};
> -
> -struct ChannelId {
> -    uint8 type;
> -    uint8 id;
> -};
> -
> -channel MainChannel : BaseChannel {
> - server:
> -     message {
> -	uint16 port;
> -	uint16 sport;
> -	uint32 host_size;
> -	uint8 *host_data[host_size] @zero_terminated @marshall @nonnull;
> -	uint32 cert_subject_size;
> -	uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall;
> -    } @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101;
> -
> -    Empty migrate_cancel;
> -
> -    message {
> -	uint32 session_id;
> -	uint32 display_channels_hint;
> -	uint32 supported_mouse_modes;
> -	uint32 current_mouse_mode;
> -	uint32 agent_connected;
> -	uint32 agent_tokens;
> -	uint32 multi_media_time;
> -	uint32 ram_hint;
> -    } init;
> -
> -    message {
> -	uint32 num_of_channels;
> -	ChannelId channels[num_of_channels] @end;
> -    } @ctype(SpiceMsgChannels) channels_list;
> -
> -    message {
> -	mouse_mode supported_modes;
> -	mouse_mode current_mode @unique_flag;
> -    } mouse_mode;
> -
> -    message {
> -	uint32 time;
> -    } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time;
> -
> -    Empty agent_connected;
> -
> -    message {
> -	link_err error_code;
> -    } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected;
> -
> -    Data agent_data;
> -
> -    message {
> -	uint32 num_tokens;
> -    } @ctype(SpiceMsgMainAgentTokens) agent_token;
> -
> -    message {
> -      uint16 port;
> -      uint16 sport;
> -      uint32 host_size;
> -      uint8 *host_data[host_size] @zero_terminated @marshall;
> -      uint32 cert_subject_size;
> -      uint8 *cert_subject_data[cert_subject_size] @zero_terminated  @marshall;
> -    } @ctype(SpiceMsgMainMigrationSwitchHost) migrate_switch_host;
> -
> -    Empty migrate_end;
> -
> -    message {
> -       uint32 name_len;
> -       uint8 name[name_len];
> -    } name;
> -
> -    message {
> -       uint8 uuid[16];
> -    } uuid;
> -
> - client:
> -    message {
> -	uint64 cache_size;
> -    } @ctype(SpiceMsgcClientInfo) client_info = 101;
> -
> -    Empty migrate_connected;
> -
> -    Empty migrate_connect_error;
> -
> -    Empty attach_channels;
> -
> -    message {
> -	mouse_mode mode;
> -    } mouse_mode_request;
> -
> -    message {
> -	uint32 num_tokens;
> -    } agent_start;
> -
> -    Data agent_data;
> -
> -    message {
> -        uint32 num_tokens;
> -    } @ctype(SpiceMsgcMainAgentTokens) agent_token;
> -
> -    Empty migrate_end;
> -};
> -
> -enum8 clip_type {
> -    NONE,
> -    RECTS
> -};
> -
> -flags8 path_flags { /* TODO: C enum names changes */
> -    BEGIN = 0,
> -    END = 1,
> -    CLOSE = 3,
> -    BEZIER = 4,
> -} @prefix(SPICE_PATH_);
> -
> -enum8 video_codec_type {
> -    MJPEG = 1,
> -};
> -
> -flags8 stream_flags {
> -    TOP_DOWN = 0,
> -};
> -
> -enum8 brush_type {
> -    NONE,
> -    SOLID,
> -    PATTERN,
> -};
> -
> -flags8 mask_flags {
> -    INVERS,
> -};
> -
> -enum8 image_type {
> -    BITMAP,
> -    QUIC,
> -    RESERVED,
> -    LZ_PLT = 100,
> -    LZ_RGB,
> -    GLZ_RGB,
> -    FROM_CACHE,
> -    SURFACE,
> -    JPEG,
> -    FROM_CACHE_LOSSLESS,
> -    ZLIB_GLZ_RGB,
> -    JPEG_ALPHA,
> -};
> -
> -flags8 image_flags {
> -    CACHE_ME,
> -    HIGH_BITS_SET,
> -    CACHE_REPLACE_ME,
> -};
> -
> -enum8 bitmap_fmt {
> -    INVALID,
> -    1BIT_LE,
> -    1BIT_BE,
> -    4BIT_LE,
> -    4BIT_BE,
> -    8BIT /* 8bit indexed mode */,
> -    16BIT, /* 0555 mode */
> -    24BIT /* 3 byte, brg */,
> -    32BIT /* 4 byte, xrgb in little endian format */,
> -    RGBA /* 4 byte, argb in little endian format */
> -};
> -
> -flags8 bitmap_flags {
> -    PAL_CACHE_ME,
> -    PAL_FROM_CACHE,
> -    TOP_DOWN,
> -};
> -
> -flags8 jpeg_alpha_flags {
> -    TOP_DOWN,
> -};
> -
> -enum8 image_scale_mode {
> -    INTERPOLATE,
> -    NEAREST,
> -};
> -
> -flags16 ropd {
> -    INVERS_SRC,
> -    INVERS_BRUSH,
> -    INVERS_DEST,
> -    OP_PUT,
> -    OP_OR,
> -    OP_AND,
> -    OP_XOR,
> -    OP_BLACKNESS,
> -    OP_WHITENESS,
> -    OP_INVERS,
> -    INVERS_RES,
> -};
> -
> -flags8 line_flags {
> -    STYLED = 3,
> -    START_WITH_GAP = 2,
> -};
> -
> -flags8 string_flags {
> -    RASTER_A1,
> -    RASTER_A4,
> -    RASTER_A8,
> -    RASTER_TOP_DOWN,
> -};
> -
> -flags32 surface_flags {
> -    PRIMARY
> -};
> -
> -enum32 surface_fmt {
> -    INVALID,
> -    1_A     = 1,
> -    8_A     = 8,
> -    16_555  = 16 ,
> -    16_565  = 80,
> -    32_xRGB = 32,
> -    32_ARGB = 96
> -};
> -
> -flags8 alpha_flags {
> -    DEST_HAS_ALPHA,
> -    SRC_SURFACE_HAS_ALPHA
> -};
> -
> -enum8 resource_type {
> -      INVALID,
> -      PIXMAP
> -} @prefix(SPICE_RES_TYPE_);
> -
> -struct ClipRects {
> -    uint32 num_rects;
> -    Rect rects[num_rects] @end;
> -};
> -
> -struct PathSegment {
> -    path_flags flags;
> -    uint32 count;
> -    PointFix points[count] @end;
> -}  @ctype(SpicePathSeg);
> -
> -struct Path {
> -    uint32 num_segments;
> -    PathSegment segments[num_segments] @ptr_array;
> -};
> -
> -struct Clip {
> -    clip_type type;
> -    switch (type) {
> -    case RECTS:
> -        ClipRects rects @outvar(cliprects) @to_ptr;
> -    } u @anon;
> -};
> -
> -struct DisplayBase {
> -    uint32 surface_id;
> -    Rect box;
> -    Clip clip;
> -} @ctype(SpiceMsgDisplayBase);
> -
> -struct ResourceID {
> -    uint8 type;
> -    uint64 id;
> -};
> -
> -struct WaitForChannel {
> -    uint8 channel_type;
> -    uint8 channel_id;
> -    uint64 message_serial;
> -};
> -
> -struct Palette {
> -    uint64 unique;
> -    uint16 num_ents;
> -    uint32 ents[num_ents] @end;
> -};
> -
> -struct BitmapData {
> -    bitmap_fmt format;
> -    bitmap_flags flags;
> -    uint32 x;
> -    uint32 y;
> -    uint32 stride;
> -    switch (flags) {
> -    case PAL_FROM_CACHE:
> -	uint64 palette_id;
> -    default:
> -	Palette *palette @outvar(bitmap);
> -    } pal @anon;
> -    uint8 data[image_size(8, stride, y)] @chunk @nomarshal;
> -} @ctype(SpiceBitmap);
> -
> -struct BinaryData {
> -    uint32 data_size;
> -    uint8 data[data_size] @nomarshal @chunk;
> -} @ctype(SpiceQUICData);
> -
> -struct LZPLTData {
> -    bitmap_flags flags;
> -    uint32 data_size;
> -    switch (flags) {
> -    case PAL_FROM_CACHE:
> -	uint64 palette_id;
> -    default:
> -	Palette *palette @nonnull @outvar(lzplt);
> -    } pal @anon;
> -    uint8 data[data_size] @nomarshal @chunk;
> -};
> -
> -struct ZlibGlzRGBData {
> -    uint32 glz_data_size;
> -    uint32 data_size;
> -    uint8 data[data_size] @nomarshal @chunk;
> -} @ctype(SpiceZlibGlzRGBData);
> -
> -struct JPEGAlphaData {
> -    jpeg_alpha_flags flags;
> -    uint32 jpeg_size;
> -    uint32 data_size;
> -    uint8 data[data_size] @nomarshal @chunk;
> -} @ctype(SpiceJPEGAlphaData);
> -
> -struct Surface {
> -    uint32 surface_id;
> -};
> -
> -
> -struct Image {
> -    struct ImageDescriptor {
> -        uint64 id;
> -        image_type type;
> -        image_flags flags;
> -        uint32 width;
> -        uint32 height;
> -    } descriptor;
> -
> -    switch (descriptor.type) {
> -    case BITMAP:
> -        BitmapData bitmap;
> -    case QUIC:
> -        BinaryData quic;
> -    case LZ_RGB:
> -    case GLZ_RGB:
> -        BinaryData lz_rgb;
> -    case JPEG:
> -        BinaryData jpeg;
> -    case LZ_PLT:
> -        LZPLTData lz_plt;
> -    case ZLIB_GLZ_RGB:
> -        ZlibGlzRGBData zlib_glz;
> -    case JPEG_ALPHA:
> -        JPEGAlphaData jpeg_alpha;
> -    case SURFACE:
> -        Surface surface;
> -    } u;
> -};
> -
> -struct Pattern {
> -    Image *pat @nonnull;
> -    Point pos;
> -};
> -
> -struct Brush {
> -    brush_type type;
> -    switch (type) {
> -    case SOLID:
> -        uint32 color;
> -    case PATTERN:
> -        Pattern pattern;
> -    } u;
> -};
> -
> -struct QMask {
> -    mask_flags flags;
> -    Point pos;
> -    Image *bitmap;
> -};
> -
> -struct LineAttr {
> -    line_flags flags;
> -    switch (flags) {
> -    case STYLED:
> -        uint8 style_nseg;
> -   } u1 @anon;
> -   switch (flags) {
> -   case STYLED:
> -        fixed28_4 *style[style_nseg];
> -   } u2 @anon;
> -};
> -
> -struct RasterGlyphA1 {
> -    Point render_pos;
> -    Point glyph_origin;
> -    uint16 width;
> -    uint16 height;
> -    uint8 data[image_size(1, width, height)] @end;
> -} @ctype(SpiceRasterGlyph);
> -
> -struct RasterGlyphA4 {
> -    Point render_pos;
> -    Point glyph_origin;
> -    uint16 width;
> -    uint16 height;
> -    uint8 data[image_size(4, width, height)] @end;
> -} @ctype(SpiceRasterGlyph);
> -
> -struct RasterGlyphA8 {
> -    Point render_pos;
> -    Point glyph_origin;
> -    uint16 width;
> -    uint16 height;
> -    uint8 data[image_size(8, width, height)] @end;
> -} @ctype(SpiceRasterGlyph);
> -
> -struct String {
> -    uint16 length;
> -    string_flags flags; /* Special: Only one of a1/a4/a8 set */
> -    switch (flags) {
> -    case RASTER_A1:
> -	RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
> -    case RASTER_A4:
> -	RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
> -    case RASTER_A8:
> -	RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
> -    } u @anon;
> -};
> -
> -channel DisplayChannel : BaseChannel {
> - server:
> -    message {
> -	uint32 x_res;
> -	uint32 y_res;
> -	uint32 bits;
> -    } mode = 101;
> -
> -    Empty mark;
> -    Empty reset;
> -    message {
> -	DisplayBase base;
> -	Point src_pos;
> -    } copy_bits;
> -
> -    message {
> -	uint16 count;
> -	ResourceID resources[count] @end;
> -    } @ctype(SpiceResourceList) inval_list;
> -
> -    message {
> -	uint8 wait_count;
> -	WaitForChannel wait_list[wait_count] @end;
> -    } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps;
> -
> -    message {
> -	uint64 id;
> -    } @ctype(SpiceMsgDisplayInvalOne) inval_palette;
> -
> -    Empty inval_all_palettes;
> -
> -    message {
> -	uint32 surface_id;
> -	uint32 id;
> -	stream_flags flags;
> -	video_codec_type codec_type;
> -	uint64 stamp;
> -	uint32 stream_width;
> -	uint32 stream_height;
> -	uint32 src_width;
> -	uint32 src_height;
> -	Rect dest;
> -	Clip clip;
> -    } stream_create = 122;
> -
> -    message {
> -	uint32 id;
> -	uint32 multi_media_time;
> -	uint32 data_size;
> -	uint8 data[data_size] @end  @nomarshal;
> -    } stream_data;
> -
> -    message {
> -	uint32 id;
> -	Clip clip;
> -    } stream_clip;
> -
> -    message {
> -	uint32 id;
> -    } stream_destroy;
> -
> -    Empty stream_destroy_all;
> -
> -    message {
> -	DisplayBase base;
> -	struct Fill {
> -	    Brush brush @outvar(brush);
> -	    ropd rop_descriptor;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_fill = 302;
> -
> -    message {
> -	DisplayBase base;
> -	struct Opaque {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    Brush brush;
> -	    ropd rop_descriptor;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_opaque;
> -
> -    message {
> -	DisplayBase base;
> -	struct Copy {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    ropd rop_descriptor;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_copy;
> -
> -    message {
> -	DisplayBase base;
> -	struct Blend {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    ropd rop_descriptor;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} @ctype(SpiceCopy) data;
> -    } draw_blend;
> -
> -    message {
> -	DisplayBase base;
> -	struct Blackness {
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_blackness;
> -
> -    message {
> -	DisplayBase base;
> -	struct Whiteness {
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_whiteness;
> -
> -    message {
> -	DisplayBase base;
> -	struct Invers {
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_invers;
> -
> -    message {
> -	DisplayBase base;
> -	struct Rop3 {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    Brush brush;
> -	    uint8 rop3;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_rop3;
> -
> -    message {
> -	DisplayBase base;
> -	struct Stroke {
> -	    Path *path @marshall @nonnull;
> -	    LineAttr attr;
> -	    Brush brush;
> -	    uint16 fore_mode;
> -	    uint16 back_mode;
> -	} data;
> -    } draw_stroke;
> -
> -    message {
> -	DisplayBase base;
> -	struct Text {
> -	    String *str @marshall @nonnull;
> -	    Rect back_area;
> -	    Brush fore_brush @outvar(fore_brush);
> -	    Brush back_brush @outvar(back_brush);
> -	    uint16 fore_mode;
> -	    uint16 back_mode;
> -	} data;
> -    } draw_text;
> -
> -    message {
> -	DisplayBase base;
> -	struct Transparent {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    uint32 src_color;
> -	    uint32 true_color;
> -	} data;
> -    } draw_transparent;
> -
> -    message {
> -	DisplayBase base;
> -	struct AlphaBlend {
> -	    alpha_flags alpha_flags;
> -	    uint8 alpha;
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	} data;
> -    } draw_alpha_blend;
> -
> -    message {
> -	uint32 surface_id;
> -	uint32 width;
> -	uint32 height;
> -	surface_fmt format;
> -	surface_flags flags;
> -    } @ctype(SpiceMsgSurfaceCreate) surface_create;
> -
> -    message {
> -	uint32 surface_id;
> -    } @ctype(SpiceMsgSurfaceDestroy) surface_destroy;
> -
> - client:
> -    message {
> -	uint8 pixmap_cache_id;
> -	int64 pixmap_cache_size; //in pixels
> -	uint8 glz_dictionary_id;
> -	int32 glz_dictionary_window_size;  // in pixels
> -    } init = 101;
> -};
> -
> -flags16 keyboard_modifier_flags {
> -    SCROLL_LOCK,
> -    NUM_LOCK,
> -    CAPS_LOCK
> -};
> -
> -enum8 mouse_button {
> -    INVALID,
> -    LEFT,
> -    MIDDLE,
> -    RIGHT,
> -    UP,
> -    DOWN,
> -};
> -
> -flags16 mouse_button_mask {
> -    LEFT,
> -    MIDDLE,
> -    RIGHT
> -};
> -
> -channel InputsChannel : BaseChannel {
> - client:
> -    message {
> -	uint32 code;
> -    } @ctype(SpiceMsgcKeyDown) key_down = 101;
> -
> -    message {
> -	uint32 code;
> -    } @ctype(SpiceMsgcKeyUp) key_up;
> -
> -    message {
> -	keyboard_modifier_flags modifiers;
> -    } @ctype(SpiceMsgcKeyModifiers) key_modifiers;
> -
> -    message {
> -	int32 dx;
> -	int32 dy;
> -	mouse_button_mask buttons_state;
> -    } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111;
> -
> -    message {
> -	uint32 x;
> -	uint32 y;
> -	mouse_button_mask buttons_state;
> -	uint8 display_id;
> -    } @ctype(SpiceMsgcMousePosition) mouse_position;
> -
> -    message {
> -	mouse_button button;
> -	mouse_button_mask buttons_state;
> -    } @ctype(SpiceMsgcMousePress) mouse_press;
> -
> -    message {
> -	mouse_button button;
> -	mouse_button_mask buttons_state;
> -    } @ctype(SpiceMsgcMouseRelease) mouse_release;
> -
> - server:
> -    message {
> -	keyboard_modifier_flags keyboard_modifiers;
> -    } init = 101;
> -
> -    message {
> -	keyboard_modifier_flags modifiers;
> -    } key_modifiers;
> -
> -    Empty mouse_motion_ack = 111;
> -};
> -
> -enum8 cursor_type {
> -    ALPHA,
> -    MONO,
> -    COLOR4,
> -    COLOR8,
> -    COLOR16,
> -    COLOR24,
> -    COLOR32,
> -};
> -
> -flags16 cursor_flags {
> -    NONE, /* Means no cursor */
> -    CACHE_ME,
> -    FROM_CACHE,
> -};
> -
> -struct CursorHeader {
> -    uint64 unique;
> -    cursor_type type;
> -    uint16 width;
> -    uint16 height;
> -    uint16 hot_spot_x;
> -    uint16 hot_spot_y;
> -};
> -
> -struct Cursor {
> -    cursor_flags flags;
> -    switch (flags) {
> -    case !NONE:
> -        CursorHeader header;
> -    } u @anon;
> -    uint8 data[] @as_ptr(data_size);
> -};
> -
> -channel CursorChannel : BaseChannel {
> - server:
> -    message {
> -	Point16 position;
> -	uint16 trail_length;
> -	uint16 trail_frequency;
> -	uint8 visible;
> -	Cursor cursor;
> -    } init = 101;
> -
> -    Empty reset;
> -
> -    message {
> -	Point16 position;
> -	uint8 visible;
> -	Cursor cursor;
> -    } set;
> -
> -    message {
> -	Point16 position;
> -    } move;
> -
> -    Empty hide;
> -
> -    message {
> -	uint16 length;
> -	uint16 frequency;
> -    } trail;
> -
> -    message {
> -	uint64 id;
> -    } @ctype(SpiceMsgDisplayInvalOne) inval_one;
> -
> -    Empty inval_all;
> -};
> -
> -enum16 audio_data_mode {
> -    INVALID,
> -    RAW,
> -    CELT_0_5_1,
> -};
> -
> -enum16 audio_fmt {
> -    INVALID,
> -    S16,
> -};
> -
> -message AudioVolume {
> -    uint8 nchannels;
> -    uint16 volume[nchannels] @end;
> -};
> -
> -message AudioMute {
> -    uint8 mute;
> -};
> -
> -channel PlaybackChannel : BaseChannel {
> - server:
> -    message {
> -	uint32 time;
> -	uint8 data[] @as_ptr(data_size);
> -    } @ctype(SpiceMsgPlaybackPacket) data = 101;
> -
> -    message {
> -	uint32 time;
> -	audio_data_mode mode;
> -	uint8 data[] @as_ptr(data_size);
> -    } mode;
> -
> -    message {
> -       uint32 channels;
> -       audio_fmt format;
> -       uint32 frequency;
> -       uint32 time;
> -    } start;
> -
> -    Empty stop;
> -    AudioVolume volume;
> -    AudioMute mute;
> -};
> -
> -channel RecordChannel : BaseChannel {
> - server:
> -    message {
> -	uint32 channels;
> -	audio_fmt format;
> -	uint32 frequency;
> -    } start = 101;
> -
> -    Empty stop;
> -    AudioVolume volume;
> -    AudioMute mute;
> - client:
> -    message {
> -	uint32 time;
> -	uint8 data[] @nomarshal @as_ptr(data_size);
> -    } @ctype(SpiceMsgcRecordPacket) data = 101;
> -
> -    message {
> -	uint32 time;
> -	audio_data_mode mode;
> -	uint8 data[] @as_ptr(data_size);
> -    } mode;
> -
> -    message {
> -	uint32 time;
> -    } start_mark;
> -};
> -
> -enum16 tunnel_service_type {
> -    INVALID,
> -    GENERIC,
> -    IPP,
> -};
> -
> -enum16 tunnel_ip_type {
> -    INVALID,
> -    IPv4,
> -};
> -
> -struct TunnelIpInfo {
> -    tunnel_ip_type type;
> -    switch (type) {
> -    case IPv4:
> -	uint8 ipv4[4];
> -    } u;
> -} @ctype(SpiceMsgTunnelIpInfo);
> -
> -channel TunnelChannel : BaseChannel {
> - server:
> -    message {
> -	uint16 max_num_of_sockets;
> -	uint32 max_socket_data_size;
> -    } init = 101;
> -
> -    message {
> -	uint32 service_id;
> -	TunnelIpInfo virtual_ip;
> -    } service_ip_map;
> -
> -    message {
> -	uint16 connection_id;
> -	uint32 service_id;
> -	uint32 tokens;
> -    } socket_open;
> -
> -    message {
> -	uint16 connection_id;
> -    } socket_fin;
> -
> -    message {
> -	uint16 connection_id;
> -    } socket_close;
> -
> -    message {
> -	uint16 connection_id;
> -	uint8 data[] @end;
> -    } socket_data;
> -
> -    message {
> -	uint16 connection_id;
> -    } socket_closed_ack;
> -
> -    message {
> -	uint16 connection_id;
> -	uint32 num_tokens;
> -    } @ctype(SpiceMsgTunnelSocketTokens) socket_token;
> -
> - client:
> -    message {
> -	tunnel_service_type type;
> -	uint32 id;
> -	uint32 group;
> -	uint32 port;
> -	uint8 *name[cstring()] @nocopy;
> -	uint8 *description[cstring()] @nocopy;
> -	switch (type) {
> -	case IPP:
> -	    TunnelIpInfo ip @ctype(SpiceMsgTunnelIpInfo);
> -	} u;
> -    } @ctype(SpiceMsgcTunnelAddGenericService) service_add = 101;
> -
> -    message {
> -	uint32 id;
> -    } @ctype(SpiceMsgcTunnelRemoveService) service_remove;
> -
> -    message {
> -	uint16 connection_id;
> -	uint32 tokens;
> -    } socket_open_ack;
> -
> -    message {
> -	uint16 connection_id;
> -    } socket_open_nack;
> -
> -    message {
> -	uint16 connection_id;
> -    } socket_fin;
> -
> -    message {
> -	uint16 connection_id;
> -    } socket_closed;
> -
> -    message {
> -	uint16 connection_id;
> -    } socket_closed_ack;
> -
> -    message {
> -	uint16 connection_id;
> -	uint8 data[] @end;
> -    } socket_data;
> -
> -    message {
> -	uint16 connection_id;
> -	uint32 num_tokens;
> -    } @ctype(SpiceMsgcTunnelSocketTokens) socket_token;
> -};
> -
> -enum32 vsc_message_type {
> -    Init = 1,
> -    Error,
> -    ReaderAdd,
> -    ReaderRemove,
> -    ATR,
> -    CardRemove,
> -    APDU,
> -    Flush,
> -    FlushComplete
> -} @prefix(VSC_);
> -
> -struct VscMessageHeader {
> -    vsc_message_type type;
> -    uint32 reader_id;
> -    uint32 length;
> -} @ctype(VSCMsgHeader);
> -
> -struct VscMessageError {
> -    uint32 code;
> -} @ctype(VSCMsgError);
> -
> -struct VscMessageAPDU {
> -    uint8 data[];
> -} @ctype(VSCMsgAPDU);
> -
> -struct VscMessageATR {
> -    uint8 data[];
> -} @ctype(VSCMsgATR);
> -
> -struct VscMessageReaderAdd {
> -    int8 *reader_name[] @zero_terminated @nonnull @end @nomarshal;
> -} @ctype(VSCMsgReaderAdd);
> -
> -channel SmartcardChannel : BaseChannel {
> - server:
> -    message {
> -	vsc_message_type type;
> -	uint32 reader_id;
> -	uint32 length;
> -	uint8 data[] @end;
> -    } @ctype(SpiceMsgSmartcard) msg = 101;
> -
> - client:
> -    message {
> -	VscMessageHeader header;
> -	switch (header.type) {
> -	case ReaderAdd:
> -	    VscMessageReaderAdd add;
> -	case ATR:
> -	case APDU:
> -	    VscMessageATR atr_data;
> -	case Error:
> -	    VscMessageError error;
> -	} u @anon;
> -    } @ctype(SpiceMsgcSmartcard) msg = 101;
> -
> -    message {
> -	vsc_message_type type;
> -	uint32 reader_id;
> -	uint32 length;
> -    } @ctype(VSCMsgHeader) header = 101;
> -
> -    message {
> -	uint32 code;
> -    } @ctype(VSCMsgError) error = 101;
> -
> -    message {
> -	uint8 data[];
> -    } @ctype(VSCMsgATR) atr = 101;
> -
> -    message {
> -	int8 reader_name[] @zero_terminated @nonnull;
> -    } @ctype(VSCMsgReaderAdd) reader_add = 101;
> -} @ifdef(USE_SMARTCARD);
> -
> -channel UsbredirChannel : BaseChannel {
> -server:
> -    Data data = 101;
> -client:
> -    Data data = 101;
> -};
> -
> -protocol Spice {
> -    MainChannel main = 1;
> -    DisplayChannel display;
> -    InputsChannel inputs;
> -    CursorChannel cursor;
> -    PlaybackChannel playback;
> -    RecordChannel record;
> -    TunnelChannel tunnel;
> -    SmartcardChannel smartcard;
> -    UsbredirChannel usbredir;
> -};
> diff --git a/spice1.proto b/spice1.proto
> deleted file mode 100644
> index fa2524b..0000000
> --- a/spice1.proto
> +++ /dev/null
> @@ -1,934 +0,0 @@
> -/* built in types:
> -   int8, uint8, 16, 32, 64
> -*/
> -
> -typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4);
> -
> -struct Point {
> -    int32 x;
> -    int32 y;
> -};
> -
> -struct Point16 {
> -    int16 x;
> -    int16 y;
> -};
> -
> -struct PointFix {
> -    fixed28_4 x;
> -    fixed28_4 y;
> -};
> -
> -struct Rect {
> -    int32 top;
> -    int32 left;
> -    int32 bottom;
> -    int32 right;
> -};
> -
> -enum32 link_err {
> -    OK,
> -    ERROR,
> -    INVALID_MAGIC,
> -    INVALID_DATA,
> -    VERSION_MISMATCH,
> -    NEED_SECURED,
> -    NEED_UNSECURED,
> -    PERMISSION_DENIED,
> -    BAD_CONNECTION_ID,
> -    CHANNEL_NOT_AVAILABLE
> -};
> -
> -enum32 warn_code {
> -    WARN_GENERAL
> -} @prefix(SPICE_);
> -
> -enum32 info_code {
> -    INFO_GENERAL
> -} @prefix(SPICE_);
> -
> -flags32 migrate_flags {
> -    NEED_FLUSH,
> -    NEED_DATA_TRANSFER
> -} @prefix(SPICE_MIGRATE_);
> -
> -enum32 notify_severity {
> -    INFO,
> -    WARN,
> -    ERROR,
> -};
> -
> -enum32 notify_visibility {
> -    LOW,
> -    MEDIUM,
> -    HIGH,
> -};
> -
> -flags32 mouse_mode {
> -    SERVER,
> -    CLIENT,
> -};
> -
> -enum16 pubkey_type {
> -    INVALID,
> -    RSA,
> -    RSA2,
> -    DSA,
> -    DSA1,
> -    DSA2,
> -    DSA3,
> -    DSA4,
> -    DH,
> -    EC,
> -};
> -
> -message Empty {
> -};
> -
> -message Data {
> -    uint8 data[] @end @ctype(uint8_t);
> -} @nocopy;
> -
> -struct ChannelWait {
> -    uint8 channel_type;
> -    uint8 channel_id;
> -    uint64 message_serial;
> -} @ctype(SpiceWaitForChannel);
> -
> -channel BaseChannel {
> - server:
> -    message {
> -	migrate_flags flags;
> -    } migrate;
> -
> -    Data migrate_data;
> -
> -    message {
> -	uint32 generation;
> -	uint32 window;
> -    } set_ack;
> -
> -    message {
> -	uint32 id;
> -	uint64 timestamp;
> -	uint8 data[] @ctype(uint8_t) @as_ptr(data_len);
> -    } ping;
> -
> -    message {
> -	uint8 wait_count;
> -	ChannelWait wait_list[wait_count] @end;
> -    } wait_for_channels;
> -
> -    message {
> -	uint64 time_stamp;
> -	link_err reason;
> -    } @ctype(SpiceMsgDisconnect) disconnecting;
> -
> -    message {
> -	uint64 time_stamp;
> -	notify_severity severity;
> -	notify_visibility visibilty;
> -	uint32 what; /* error_code/warn_code/info_code */
> -	uint32 message_len;
> -	uint8 message[message_len] @end @nomarshal;
> -	uint8 zero @end @ctype(uint8_t) @nomarshal;
> -    } notify;
> -
> - client:
> -    message {
> -	uint32 generation;
> -    } ack_sync;
> -
> -    Empty ack;
> -
> -    message {
> -	uint32 id;
> -	uint64 timestamp;
> -    } @ctype(SpiceMsgPing) pong;
> -
> -    Empty migrate_flush_mark;
> -
> -    Data migrate_data;
> -
> -    message {
> -    	uint64 time_stamp;
> -	link_err reason;
> -    } @ctype(SpiceMsgDisconnect) disconnecting;
> -};
> -
> -struct ChannelId {
> -    uint8 type;
> -    uint8 id;
> -};
> -
> -channel MainChannel : BaseChannel {
> - server:
> -     message {
> -	uint16 port;
> -	uint16 sport;
> -	uint32 host_offset @zero;
> -	uint32 host_size;
> -	pubkey_type pub_key_type @minor(1);
> -	uint32 pub_key_offset @minor(1) @zero;
> -	uint32 pub_key_size @minor(1);
> -	uint8 host_data[host_size] @as_ptr @zero_terminated;
> -	uint8 pub_key_data[pub_key_size] @minor(1) @as_ptr @zero_terminated;
> -    } @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101;
> -
> -    Empty migrate_cancel;
> -
> -    message {
> -	uint32 session_id;
> -	uint32 display_channels_hint;
> -	uint32 supported_mouse_modes;
> -	uint32 current_mouse_mode;
> -	uint32 agent_connected;
> -	uint32 agent_tokens;
> -	uint32 multi_media_time;
> -	uint32 ram_hint;
> -    } init;
> -
> -    message {
> -	uint32 num_of_channels;
> -	ChannelId channels[num_of_channels] @end;
> -    } @ctype(SpiceMsgChannels) channels_list;
> -
> -    message {
> -	mouse_mode supported_modes;
> -	mouse_mode current_mode @unique_flag;
> -    } mouse_mode;
> -
> -    message {
> -	uint32 time;
> -    } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time;
> -
> -    Empty agent_connected;
> -
> -    message {
> -	link_err error_code;
> -    } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected;
> -
> -    Data agent_data;
> -
> -    message {
> -	uint32 num_tokens;
> -    } @ctype(SpiceMsgMainAgentTokens) agent_token;
> -
> -    message {
> -      uint16 port;
> -      uint16 sport;
> -      uint32 host_offset @zero;
> -      uint32 host_size;
> -      uint32 cert_subject_offset @zero;
> -      uint32 cert_subject_size;
> -      uint8 host_data[host_size] @as_ptr @zero_terminated;
> -      uint8 cert_subject_data[cert_subject_size] @as_ptr @zero_terminated;
> -    } @ctype(SpiceMsgMainMigrationSwitchHost) migrate_switch_host;
> -
> - client:
> -    message {
> -	uint64 cache_size;
> -    } @ctype(SpiceMsgcClientInfo) client_info = 101;
> -
> -    Empty migrate_connected;
> -
> -    Empty migrate_connect_error;
> -
> -    Empty attach_channels;
> -
> -    message {
> -	mouse_mode mode;
> -    } mouse_mode_request;
> -
> -    message {
> -	uint32 num_tokens;
> -    } agent_start;
> -
> -    Data agent_data;
> -
> -    message {
> -        uint32 num_tokens;
> -    } @ctype(SpiceMsgcMainAgentTokens) agent_token;
> -};
> -
> -enum32 clip_type {
> -    NONE,
> -    RECTS
> -};
> -
> -flags32 path_flags { /* TODO: C enum names changes */
> -    BEGIN = 0,
> -    END = 1,
> -    CLOSE = 3,
> -    BEZIER = 4,
> -} @prefix(SPICE_PATH_);
> -
> -enum32 video_codec_type {
> -    MJPEG = 1,
> -};
> -
> -flags32 stream_flags {
> -    TOP_DOWN = 0,
> -};
> -
> -enum32 brush_type {
> -    NONE,
> -    SOLID,
> -    PATTERN,
> -};
> -
> -flags8 mask_flags {
> -    INVERS,
> -};
> -
> -enum8 image_type {
> -    BITMAP,
> -    QUIC,
> -    RESERVED,
> -    LZ_PLT = 100,
> -    LZ_RGB,
> -    GLZ_RGB,
> -    FROM_CACHE,
> -};
> -
> -flags8 image_flags {
> -    CACHE_ME,
> -};
> -
> -enum8 bitmap_fmt {
> -    INVALID,
> -    1BIT_LE,
> -    1BIT_BE,
> -    4BIT_LE,
> -    4BIT_BE,
> -    8BIT /* 8bit indexed mode */,
> -    16BIT, /* 0555 mode */
> -    24BIT /* 3 byte, brg */,
> -    32BIT /* 4 byte, xrgb in little endian format */,
> -    RGBA /* 4 byte, argb in little endian format */
> -};
> -
> -flags8 bitmap_flags {
> -    PAL_CACHE_ME,
> -    PAL_FROM_CACHE,
> -    TOP_DOWN,
> -};
> -
> -enum8 image_scale_mode {
> -    INTERPOLATE,
> -    NEAREST,
> -};
> -
> -flags16 ropd {
> -    INVERS_SRC,
> -    INVERS_BRUSH,
> -    INVERS_DEST,
> -    OP_PUT,
> -    OP_OR,
> -    OP_AND,
> -    OP_XOR,
> -    OP_BLACKNESS,
> -    OP_WHITENESS,
> -    OP_INVERS,
> -    INVERS_RES,
> -};
> -
> -flags8 line_flags {
> -    STYLED = 3,
> -    START_WITH_GAP = 2,
> -};
> -
> -enum8 line_cap {
> -    ROUND,
> -    SQUARE,
> -    BUTT,
> -};
> -
> -enum8 line_join {
> -    ROUND,
> -    BEVEL,
> -    MITER,
> -};
> -
> -flags16 string_flags {
> -    RASTER_A1,
> -    RASTER_A4,
> -    RASTER_A8,
> -    RASTER_TOP_DOWN,
> -};
> -
> -enum8 resource_type {
> -      INVALID,
> -      PIXMAP
> -} @prefix(SPICE_RES_TYPE_);
> -
> -struct ClipRects {
> -    uint32 num_rects;
> -    Rect rects[num_rects] @end;
> -};
> -
> -struct PathSegment {
> -    path_flags flags;
> -    uint32 count;
> -    PointFix points[count] @end;
> -}  @ctype(SpicePathSeg);
> -
> -struct Path {
> -    uint32 segments_size @bytes_count(num_segments);
> -    PathSegment segments[bytes(segments_size, num_segments)] @ptr_array;
> -};
> -
> -struct Clip {
> -    clip_type type;
> -    switch (type) {
> -    case RECTS:
> -        ClipRects *rects @outvar(cliprects);
> -    default:
> -        uint64 data @zero;
> -    } u @anon;
> -};
> -
> -struct DisplayBase {
> -    uint32 surface_id @virtual(0);
> -    Rect box;
> -    Clip clip;
> -} @ctype(SpiceMsgDisplayBase);
> -
> -struct ResourceID {
> -    uint8 type;
> -    uint64 id;
> -};
> -
> -struct WaitForChannel {
> -    uint8 channel_type;
> -    uint8 channel_id;
> -    uint64 message_serial;
> -};
> -
> -struct Palette {
> -    uint64 unique;
> -    uint16 num_ents;
> -    uint32 ents[num_ents] @end;
> -};
> -
> -struct BitmapData {
> -    bitmap_fmt format;
> -    bitmap_flags flags;
> -    uint32 x;
> -    uint32 y;
> -    uint32 stride;
> -    switch (flags) {
> -    case PAL_FROM_CACHE:
> -	uint64 palette_id;
> -    default:
> -	Palette *palette @outvar(bitmap);
> -    } pal @anon;
> -    uint8 *data[image_size(8, stride, y)] @chunk; /* pointer to array, not array of pointers as in C */
> -} @ctype(SpiceBitmap);
> -
> -struct BinaryData {
> -    uint32 data_size;
> -    uint8 data[data_size] @nomarshal @chunk;
> -} @ctype(SpiceQUICData);
> -
> -struct LZPLTData {
> -    bitmap_flags flags;
> -    uint32 data_size;
> -    switch (flags) {
> -    case PAL_FROM_CACHE:
> -	uint64 palette_id;
> -    default:
> -	Palette *palette @nonnull @outvar(lzplt);
> -    } pal @anon;
> -    uint8 data[data_size] @nomarshal @chunk;
> -};
> -
> -struct Image {
> -    struct ImageDescriptor {
> -        uint64 id;
> -        image_type type;
> -        image_flags flags;
> -        uint32 width;
> -        uint32 height;
> -    } descriptor;
> -
> -    switch (descriptor.type) {
> -    case BITMAP:
> -        BitmapData bitmap;
> -    case QUIC:
> -        BinaryData quic;
> -    case LZ_RGB:
> -    case GLZ_RGB:
> -        BinaryData lz_rgb;
> -    case LZ_PLT:
> -        LZPLTData lz_plt;
> -    } u;
> -};
> -
> -struct Pattern {
> -    Image *pat @nonnull;
> -    Point pos;
> -};
> -
> -struct Brush {
> -    brush_type type;
> -    switch (type) {
> -    case SOLID:
> -        uint32 color;
> -    case PATTERN:
> -        Pattern pattern;
> -    } u @fixedsize;
> -};
> -
> -struct QMask {
> -    mask_flags flags;
> -    Point pos;
> -    Image *bitmap;
> -};
> -
> -struct LineAttr {
> -    line_flags flags;
> -    line_join join_style @zero;
> -    line_cap end_style @zero;
> -    uint8 style_nseg;
> -    fixed28_4 width @zero;
> -    fixed28_4 miter_limit @zero;
> -    fixed28_4 *style[style_nseg];
> -};
> -
> -struct RasterGlyphA1 {
> -    Point render_pos;
> -    Point glyph_origin;
> -    uint16 width;
> -    uint16 height;
> -    uint8 data[image_size(1, width, height)] @end;
> -} @ctype(SpiceRasterGlyph);
> -
> -struct RasterGlyphA4 {
> -    Point render_pos;
> -    Point glyph_origin;
> -    uint16 width;
> -    uint16 height;
> -    uint8 data[image_size(4, width, height)] @end;
> -} @ctype(SpiceRasterGlyph);
> -
> -struct RasterGlyphA8 {
> -    Point render_pos;
> -    Point glyph_origin;
> -    uint16 width;
> -    uint16 height;
> -    uint8 data[image_size(8, width, height)] @end;
> -} @ctype(SpiceRasterGlyph);
> -
> -struct String {
> -    uint16 length;
> -    string_flags flags; /* Special: Only one of a1/a4/a8 set */
> -    switch (flags) {
> -    case RASTER_A1:
> -	RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
> -    case RASTER_A4:
> -	RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
> -    case RASTER_A8:
> -	RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
> -    } u @anon;
> -};
> -
> -channel DisplayChannel : BaseChannel {
> - server:
> -    message {
> -	uint32 x_res;
> -	uint32 y_res;
> -	uint32 bits;
> -    } mode = 101;
> -
> -    Empty mark;
> -    Empty reset;
> -
> -    message {
> -	DisplayBase base;
> -	Point src_pos;
> -    } copy_bits;
> -
> -    message {
> -	uint16 count;
> -	ResourceID resources[count] @end;
> -    } @ctype(SpiceResourceList) inval_list;
> -
> -    message {
> -	uint8 wait_count;
> -	WaitForChannel wait_list[wait_count] @end;
> -    } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps;
> -
> -    message {
> -	uint64 id;
> -    } @ctype(SpiceMsgDisplayInvalOne) inval_palette;
> -
> -    Empty inval_all_palettes;
> -
> -    message {
> -	uint32 surface_id @virtual(0);
> -	uint32 id;
> -	stream_flags flags;
> -	video_codec_type codec_type;
> -	uint64 stamp;
> -	uint32 stream_width;
> -	uint32 stream_height;
> -	uint32 src_width;
> -	uint32 src_height;
> -	Rect dest;
> -	Clip clip;
> -    } stream_create = 122;
> -
> -    message {
> -	uint32 id;
> -	uint32 multi_media_time;
> -	uint32 data_size;
> -	uint32 pad_size @zero;
> -	uint8 data[data_size] @end  @nomarshal;
> -	/* Ignore: uint8 padding[pad_size] */
> -    } stream_data;
> -
> -    message {
> -	uint32 id;
> -	Clip clip;
> -    } stream_clip;
> -
> -    message {
> -	uint32 id;
> -    } stream_destroy;
> -
> -    Empty stream_destroy_all;
> -
> -    message {
> -	DisplayBase base;
> -	struct Fill {
> -	    Brush brush @outvar(brush);
> -	    uint16 rop_descriptor;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_fill = 302;
> -
> -    message {
> -	DisplayBase base;
> -	struct Opaque {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    Brush brush;
> -	    ropd rop_descriptor;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_opaque;
> -
> -    message {
> -	DisplayBase base;
> -	struct Copy {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    ropd rop_descriptor;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_copy;
> -
> -    message {
> -	DisplayBase base;
> -	struct Blend {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    ropd rop_descriptor;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} @ctype(SpiceCopy) data;
> -    } draw_blend;
> -
> -    message {
> -	DisplayBase base;
> -	struct Blackness {
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_blackness;
> -
> -    message {
> -	DisplayBase base;
> -	struct Whiteness {
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_whiteness;
> -
> -    message {
> -	DisplayBase base;
> -	struct Invers {
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_invers;
> -
> -    message {
> -	DisplayBase base;
> -	struct Rop3 {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    Brush brush;
> -	    uint8 rop3;
> -	    image_scale_mode scale_mode;
> -	    QMask mask @outvar(mask);
> -	} data;
> -    } draw_rop3;
> -
> -    message {
> -	DisplayBase base;
> -	struct Stroke {
> -	    Path *path;
> -	    LineAttr attr;
> -	    Brush brush;
> -	    uint16 fore_mode;
> -	    uint16 back_mode;
> -	} data;
> -    } draw_stroke;
> -
> -    message {
> -	DisplayBase base;
> -	struct Text {
> -	    String *str;
> -	    Rect back_area;
> -	    Brush fore_brush @outvar(fore_brush);
> -	    Brush back_brush @outvar(back_brush);
> -	    uint16 fore_mode;
> -	    uint16 back_mode;
> -	} data;
> -    } draw_text;
> -
> -    message {
> -	DisplayBase base;
> -	struct Transparent {
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	    uint32 src_color;
> -	    uint32 true_color;
> -	} data;
> -    } draw_transparent;
> -
> -    message {
> -	DisplayBase base;
> -	struct AlphaBlend {
> -	    int8 alpha_flags @virtual(0);
> -	    uint8 alpha;
> -	    Image *src_bitmap;
> -	    Rect src_area;
> -	} data;
> -    } draw_alpha_blend;
> -
> - client:
> -    message {
> -	uint8 pixmap_cache_id;
> -	int64 pixmap_cache_size; //in pixels
> -	uint8 glz_dictionary_id;
> -	int32 glz_dictionary_window_size;  // in pixels
> -    } init = 101;
> -};
> -
> -flags32 keyboard_modifier_flags {
> -    SCROLL_LOCK,
> -    NUM_LOCK,
> -    CAPS_LOCK
> -};
> -
> -enum32 mouse_button {
> -    INVALID,
> -    LEFT,
> -    MIDDLE,
> -    RIGHT,
> -    UP,
> -    DOWN,
> -};
> -
> -flags32 mouse_button_mask {
> -    LEFT,
> -    MIDDLE,
> -    RIGHT
> -};
> -
> -channel InputsChannel : BaseChannel {
> - client:
> -    message {
> -	uint32 code;
> -    } @ctype(SpiceMsgcKeyDown) key_down = 101;
> -
> -    message {
> -	uint32 code;
> -    } @ctype(SpiceMsgcKeyUp) key_up;
> -
> -    message {
> -	keyboard_modifier_flags modifiers;
> -    } @ctype(SpiceMsgcKeyModifiers) key_modifiers;
> -
> -    message {
> -	int32 dx;
> -	int32 dy;
> -	mouse_button_mask buttons_state;
> -    } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111;
> -
> -    message {
> -	uint32 x;
> -	uint32 y;
> -	mouse_button_mask buttons_state;
> -	uint8 display_id;
> -    } @ctype(SpiceMsgcMousePosition) mouse_position;
> -
> -    message {
> -	mouse_button button;
> -	mouse_button_mask buttons_state;
> -    } @ctype(SpiceMsgcMousePress) mouse_press;
> -
> -    message {
> -	mouse_button button;
> -	mouse_button_mask buttons_state;
> -    } @ctype(SpiceMsgcMouseRelease) mouse_release;
> -
> - server:
> -    message {
> -	keyboard_modifier_flags keyboard_modifiers;
> -    } init = 101;
> -
> -    message {
> -	keyboard_modifier_flags modifiers;
> -    } key_modifiers;
> -
> -    Empty mouse_motion_ack = 111;
> -};
> -
> -enum16 cursor_type {
> -    ALPHA,
> -    MONO,
> -    COLOR4,
> -    COLOR8,
> -    COLOR16,
> -    COLOR24,
> -    COLOR32,
> -};
> -
> -flags32 cursor_flags {
> -    NONE, /* Means no cursor */
> -    CACHE_ME,
> -    FROM_CACHE,
> -};
> -
> -struct CursorHeader {
> -    uint64 unique;
> -    cursor_type type;
> -    uint16 width;
> -    uint16 height;
> -    uint16 hot_spot_x;
> -    uint16 hot_spot_y;
> -};
> -
> -struct Cursor {
> -    cursor_flags flags;
> -    CursorHeader header;
> -    uint8 data[] @as_ptr(data_size);
> -};
> -
> -channel CursorChannel : BaseChannel {
> - server:
> -    message {
> -	Point16 position;
> -	uint16 trail_length;
> -	uint16 trail_frequency;
> -	uint8 visible;
> -	Cursor cursor;
> -    } init = 101;
> -
> -    Empty reset;
> -
> -    message {
> -	Point16 position;
> -	uint8 visible;
> -	Cursor cursor;
> -    } set;
> -
> -    message {
> -	Point16 position;
> -    } move;
> -
> -    Empty hide;
> -
> -    message {
> -	uint16 length;
> -	uint16 frequency;
> -    } trail;
> -
> -    message {
> -	uint64 id;
> -    } @ctype(SpiceMsgDisplayInvalOne) inval_one;
> -
> -    Empty inval_all;
> -};
> -
> -enum32 audio_data_mode {
> -    INVALID,
> -    RAW,
> -    CELT_0_5_1,
> -};
> -
> -enum32 audio_fmt {
> -    INVALID,
> -    S16,
> -};
> -
> -channel PlaybackChannel : BaseChannel {
> - server:
> -    message {
> -	uint32 time;
> -	uint8 data[] @as_ptr(data_size);
> -    } @ctype(SpiceMsgPlaybackPacket) data = 101;
> -
> -    message {
> -	uint32 time;
> -	audio_data_mode mode;
> -	uint8 data[] @as_ptr(data_size);
> -    } mode;
> -
> -    message {
> -       uint32 channels;
> -       audio_fmt format;
> -       uint32 frequency;
> -       uint32 time;
> -    } start;
> -
> -    Empty stop;
> -};
> -
> -channel RecordChannel : BaseChannel {
> - server:
> -    message {
> -	uint32 channels;
> -	audio_fmt format;
> -	uint32 frequency;
> -    } start = 101;
> -
> -    Empty stop;
> - client:
> -    message {
> -	uint32 time;
> -	uint8 data[] @nomarshal @as_ptr(data_size);
> -    } @ctype(SpiceMsgcRecordPacket) data = 101;
> -
> -    message {
> -	uint32 time;
> -	audio_data_mode mode;
> -	uint8 data[] @as_ptr(data_size);
> -    } mode;
> -
> -    message {
> -	uint32 time;
> -    } start_mark;
> -};
> -
> -protocol Spice {
> -    MainChannel main = 1;
> -    DisplayChannel display;
> -    InputsChannel inputs;
> -    CursorChannel cursor;
> -    PlaybackChannel playback;
> -    RecordChannel record;
> -};
> diff --git a/spice_codegen.py b/spice_codegen.py
> deleted file mode 100755
> index 3a9989d..0000000
> --- a/spice_codegen.py
> +++ /dev/null
> @@ -1,211 +0,0 @@
> -#!/usr/bin/env python
> -
> -import os
> -import sys
> -from optparse import OptionParser
> -import traceback
> -from python_modules import spice_parser
> -from python_modules import ptypes
> -from python_modules import codegen
> -from python_modules import demarshal
> -from python_modules import marshal
> -
> -def write_channel_enums(writer, channel, client):
> -    messages = filter(lambda m : m.channel == channel, \
> -                          channel.client_messages if client else channel.server_messages)
> -    if len(messages) == 0:
> -        return
> -    writer.begin_block("enum")
> -    i = 0;
> -    if client:
> -        prefix = [ "MSGC" ]
> -    else:
> -        prefix = [ "MSG" ]
> -    if channel.member_name:
> -        prefix.append(channel.member_name.upper())
> -    prefix.append(None) # To be replaced with name
> -    for m in messages:
> -        prefix[-1] = m.name.upper()
> -        enum = codegen.prefix_underscore_upper(*prefix)
> -        if m.value == i:
> -            writer.writeln("%s," % enum)
> -            i = i + 1
> -        else:
> -            writer.writeln("%s = %s," % (enum, m.value))
> -            i = m.value + 1
> -    if channel.member_name:
> -        prefix[-1] = prefix[-2]
> -        prefix[-2] = "END"
> -        writer.newline()
> -        writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix)))
> -    writer.end_block(semicolon=True)
> -    writer.newline()
> -
> -def write_enums(writer):
> -    writer.writeln("#ifndef _H_SPICE_ENUMS")
> -    writer.writeln("#define _H_SPICE_ENUMS")
> -    writer.newline()
> -    writer.comment("Generated from %s, don't edit" % writer.options["source"]).newline()
> -    writer.newline()
> -
> -    # Define enums
> -    for t in ptypes.get_named_types():
> -        if isinstance(t, ptypes.EnumBaseType):
> -            t.c_define(writer)
> -
> -    i = 0;
> -    writer.begin_block("enum")
> -    for c in proto.channels:
> -        enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
> -        if c.value == i:
> -            writer.writeln("%s," % enum)
> -            i = i + 1
> -        else:
> -            writer.writeln("%s = %s," % (enum, c.value))
> -            i = c.value + 1
> -    writer.newline()
> -    writer.writeln("SPICE_END_CHANNEL")
> -    writer.end_block(semicolon=True)
> -    writer.newline()
> -
> -    for c in ptypes.get_named_types():
> -        if not isinstance(c, ptypes.ChannelType):
> -            continue
> -        write_channel_enums(writer, c, False)
> -        write_channel_enums(writer, c, True)
> -
> -    writer.writeln("#endif /* _H_SPICE_ENUMS */")
> -
> -parser = OptionParser(usage="usage: %prog [options] <protocol_file> <destination file>")
> -parser.add_option("-e", "--generate-enums",
> -                  action="store_true", dest="generate_enums", default=False,
> -                  help="Generate enums")
> -parser.add_option("-d", "--generate-demarshallers",
> -                  action="store_true", dest="generate_demarshallers", default=False,
> -                  help="Generate demarshallers")
> -parser.add_option("-m", "--generate-marshallers",
> -                  action="store_true", dest="generate_marshallers", default=False,
> -                  help="Generate message marshallers")
> -parser.add_option("-P", "--private-marshallers",
> -                  action="store_true", dest="private_marshallers", default=False,
> -                  help="Generate private message marshallers")
> -parser.add_option("-M", "--generate-struct-marshaller",
> -                  action="append", dest="struct_marshallers",
> -                  help="Generate struct marshallers")
> -parser.add_option("-a", "--assert-on-error",
> -                  action="store_true", dest="assert_on_error", default=False,
> -                  help="Assert on error")
> -parser.add_option("-H", "--header",
> -                  action="store_true", dest="header", default=False,
> -                  help="Generate header")
> -parser.add_option("-p", "--print-error",
> -                  action="store_true", dest="print_error", default=False,
> -                  help="Print errors")
> -parser.add_option("-s", "--server",
> -                  action="store_true", dest="server", default=False,
> -                  help="Print errors")
> -parser.add_option("-c", "--client",
> -                  action="store_true", dest="client", default=False,
> -                  help="Print errors")
> -parser.add_option("-k", "--keep-identical-file",
> -                  action="store_true", dest="keep_identical_file", default=False,
> -                  help="Print errors")
> -parser.add_option("-i", "--include",
> -                  action="append", dest="includes", metavar="FILE",
> -                  help="Include FILE in generated code")
> -parser.add_option("--prefix", dest="prefix",
> -                  help="set public symbol prefix", default="")
> -parser.add_option("--ptrsize", dest="ptrsize",
> -                  help="set default pointer size", default="4")
> -
> -(options, args) = parser.parse_args()
> -
> -if len(args) == 0:
> -    parser.error("No protocol file specified")
> -
> -if len(args) == 1:
> -    parser.error("No destination file specified")
> -
> -ptypes.default_pointer_size = int(options.ptrsize)
> -
> -proto_file = args[0]
> -dest_file = args[1]
> -proto = spice_parser.parse(proto_file)
> -
> -if proto == None:
> -    exit(1)
> -
> -codegen.set_prefix(proto.name)
> -writer = codegen.CodeWriter()
> -writer.header = codegen.CodeWriter()
> -writer.set_option("source", os.path.basename(proto_file))
> -
> -writer.public_prefix = options.prefix
> -
> -if options.assert_on_error:
> -    writer.set_option("assert_on_error")
> -
> -if options.print_error:
> -    writer.set_option("print_error")
> -
> -if options.includes:
> -    for i in options.includes:
> -        writer.writeln('#include "%s"' % i)
> -
> -if options.generate_enums:
> -    write_enums(writer)
> -
> -if options.generate_demarshallers:
> -    if not options.server and not options.client:
> -        print >> sys.stderr, "Must specify client and/or server"
> -        sys.exit(1)
> -    demarshal.write_includes(writer)
> -
> -    if options.server:
> -        demarshal.write_protocol_parser(writer, proto, False)
> -    if options.client:
> -        demarshal.write_protocol_parser(writer, proto, True)
> -
> -if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0):
> -    marshal.write_includes(writer)
> -
> -if options.generate_marshallers:
> -    if not options.server and not options.client:
> -        print >> sys.stderr, "Must specify client and/or server"
> -        sys.exit(1)
> -    if options.server:
> -        marshal.write_protocol_marshaller(writer, proto, False, options.private_marshallers)
> -    if options.client:
> -        marshal.write_protocol_marshaller(writer, proto, True, options.private_marshallers)
> -
> -if options.struct_marshallers:
> -    for structname in options.struct_marshallers:
> -        t = ptypes.lookup_type(structname)
> -        marshal.write_marshal_ptr_function(writer, t)
> -
> -if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0):
> -    marshal.write_trailer(writer)
> -
> -if options.header:
> -    content = writer.header.getvalue()
> -else:
> -    content = writer.getvalue()
> -if options.keep_identical_file:
> -    try:
> -        f = open(dest_file, 'rb')
> -        old_content = f.read()
> -        f.close()
> -
> -        if content == old_content:
> -            print "No changes to %s" % dest_file
> -            sys.exit(0)
> -
> -    except IOError:
> -        pass
> -
> -f = open(dest_file, 'wb')
> -f.write(content)
> -f.close()
> -
> -print "Wrote %s" % dest_file
> -sys.exit(0)
> -- 
> 1.7.7.6
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list