summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2016-02-26 18:14:33 +0100
committerMarc-André Lureau <marcandre.lureau@gmail.com>2016-03-10 16:57:08 +0100
commit2a6e51c7ee867fe3f4b7dd07dee5517533a967be (patch)
tree84173a25e43d1d59fca616539ee570d214f4b6c7
parent7937915d67702a5c4b5147b277c432f5555e3852 (diff)
downloadspice-protocol-2a6e51c7ee867fe3f4b7dd07dee5517533a967be.tar.gz
spice-protocol-2a6e51c7ee867fe3f4b7dd07dee5517533a967be.tar.xz
spice-protocol-2a6e51c7ee867fe3f4b7dd07dee5517533a967be.zip
Remove codegen
Codegen generates code specific to spice-common submodule. It's not meant as a generic protocol header or specification. See discussion and commits about spice-common codegen re-import. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
-rw-r--r--Makefile.am14
-rwxr-xr-xautogen.sh2
-rw-r--r--configure.ac17
-rw-r--r--python_modules/Makefile.am15
-rw-r--r--python_modules/__init__.py0
-rw-r--r--python_modules/codegen.py380
-rw-r--r--python_modules/demarshal.py1274
-rw-r--r--python_modules/marshal.py420
-rw-r--r--python_modules/ptypes.py1138
-rw-r--r--python_modules/spice_parser.py163
-rw-r--r--spice-protocol.pc.in1
-rw-r--r--spice.proto1414
-rw-r--r--spice/Makefile.am24
-rw-r--r--spice1.proto943
-rwxr-xr-xspice_codegen.py275
15 files changed, 2 insertions, 6078 deletions
diff --git a/Makefile.am b/Makefile.am
index 4af20db..82f19e4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,18 +1,6 @@
NULL =
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = python_modules spice
-
-codegendir = $(datadir)/spice-protocol
-dist_codegen_DATA = \
- spice.proto \
- spice1.proto \
- $(NULL)
-
-dist_codegen_SCRIPTS = \
- spice_codegen.py \
- $(NULL)
-
-DISTCLEANFILES = *.pyc
+SUBDIRS = spice
pkgconfigdir = $(datadir)/pkgconfig
pkgconfig_DATA = spice-protocol.pc
diff --git a/autogen.sh b/autogen.sh
index 9e5365e..de6881d 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -11,7 +11,7 @@ test -z "$srcdir" && srcdir=.
autoreconf --verbose --force --install
)
-CONFIGURE_ARGS="--enable-maintainer-mode --enable-code-generator"
+CONFIGURE_ARGS="--enable-maintainer-mode"
if [ -z "$NOCONFIGURE" ]; then
echo "Running configure with $CONFIGURE_ARGS $@"
diff --git a/configure.ac b/configure.ac
index e8d118d..6d96f76 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,25 +14,8 @@ AM_MAINTAINER_MODE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
-dnl Enable generation of enums.h, mainly useful when building from git,
-dnl should not be needed for tarball users
-AC_ARG_ENABLE([code-generator],
- AS_HELP_STRING([--enable-code-generator=@<:@yes/no/auto@:>@],
- [Enable checks needed to use the Python code generator @<:@default=auto@:>@]),
- [],
- [enable_code_generator="auto"])
-if test "x$enable_code_generator" != "xno"; then
- AS_IF([test "x$enable_code_generator" = "xyes"], modules_required=[1], modules_required=[])
- AX_PYTHON_MODULE([six], $modules_required)
- AX_PYTHON_MODULE([pyparsing], $modules_required)
- AS_IF([test "x${HAVE_PYMOD_SIX}" = "xno"], enable_code_generator="no")
- AS_IF([test "x${HAVE_PYMOD_PYPARSING}" = "xno"], enable_code_generator="no")
-fi
-AM_CONDITIONAL([ENABLE_CODEGEN], [test "x$enable_code_generator" != "xno"])
-
AC_OUTPUT([
Makefile
spice-protocol.pc
spice/Makefile
-python_modules/Makefile
])
diff --git a/python_modules/Makefile.am b/python_modules/Makefile.am
deleted file mode 100644
index 98ab41f..0000000
--- a/python_modules/Makefile.am
+++ /dev/null
@@ -1,15 +0,0 @@
-NULL =
-
-python_codegendir = $(datadir)/spice-protocol/python_modules
-dist_python_codegen_DATA = \
- __init__.py \
- codegen.py \
- demarshal.py \
- marshal.py \
- ptypes.py \
- spice_parser.py \
- $(NULL)
-
-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
--- a/python_modules/__init__.py
+++ /dev/null
diff --git a/python_modules/codegen.py b/python_modules/codegen.py
deleted file mode 100644
index f7a2048..0000000
--- a/python_modules/codegen.py
+++ /dev/null
@@ -1,380 +0,0 @@
-
-import six
-from io import StringIO
-
-def camel_to_underscores(s, upper = False):
- res = ""
- for i in range(len(s)):
- c = s[i]
- if i > 0 and c.isupper():
- res = res + "_"
- if upper:
- res = res + c.upper()
- else:
- res = res + c.lower()
- return res
-
-def underscores_to_camel(s):
- res = ""
- do_upper = True
- for i in range(len(s)):
- c = s[i]
- if c == "_":
- do_upper = True
- else:
- if do_upper:
- res = res + c.upper()
- else:
- res = res + c
- do_upper = False
- return res
-
-proto_prefix = "Temp"
-
-def set_prefix(prefix):
- global proto_prefix
- global proto_prefix_upper
- global proto_prefix_lower
- proto_prefix = prefix
- proto_prefix_upper = prefix.upper()
- proto_prefix_lower = prefix.lower()
-
-def prefix_underscore_upper(*args):
- s = proto_prefix_upper
- for arg in args:
- s = s + "_" + arg
- return s
-
-def prefix_underscore_lower(*args):
- s = proto_prefix_lower
- for arg in args:
- s = s + "_" + arg
- return s
-
-def prefix_camel(*args):
- s = proto_prefix
- for arg in args:
- s = s + underscores_to_camel(arg)
- return s
-
-def increment_identifier(idf):
- v = idf[-1:]
- if v.isdigit():
- return idf[:-1] + str(int(v) + 1)
- return idf + "2"
-
-def sum_array(array):
- if len(array) == 0:
- return 0
- return " + ".join(array)
-
-class CodeWriter:
- def __init__(self):
- self.out = StringIO()
- self.contents = [self.out]
- self.indentation = 0
- self.at_line_start = True
- self.indexes = ["i", "j", "k", "ii", "jj", "kk"]
- self.current_index = 0
- self.generated = {}
- self.vars = []
- self.has_error_check = False
- self.options = {}
- self.function_helper_writer = None
- self.index_type = 'uint32_t'
-
- def set_option(self, opt, value = True):
- self.options[opt] = value
-
- def has_option(self, opt):
- return opt in self.options
-
- def set_is_generated(self, kind, name):
- if kind not in self.generated:
- v = {}
- self.generated[kind] = v
- else:
- v = self.generated[kind]
- v[name] = 1
-
- def is_generated(self, kind, name):
- if kind not in self.generated:
- return False
- v = self.generated[kind]
- return name in v
-
- def getvalue(self):
- strs = [writer.getvalue() for writer in self.contents]
- return "".join(strs)
-
- def get_subwriter(self):
- writer = CodeWriter()
- self.contents.append(writer)
- self.out = StringIO()
- self.contents.append(self.out)
- writer.indentation = self.indentation
- writer.at_line_start = self.at_line_start
- writer.index_type = self.index_type
- writer.generated = self.generated
- writer.options = self.options
- writer.public_prefix = self.public_prefix
-
- return writer
-
- def write(self, s):
- # Ensure its a unicode string
- if six.PY3:
- s = str(s)
- else:
- s = unicode(s)
-
- if len(s) == 0:
- return
-
- if self.at_line_start:
- self.out.write(u" " * self.indentation)
- self.at_line_start = False
- self.out.write(s)
- return self
-
- def newline(self):
- self.out.write(u"\n")
- self.at_line_start = True
- return self
-
- def writeln(self, s):
- self.write(s)
- self.newline()
- return self
-
- def label(self, s):
- self.indentation = self.indentation - 1
- self.write(s + ":")
- self.indentation = self.indentation + 1
- self.newline()
-
- def statement(self, s):
- self.write(s)
- self.write(";")
- self.newline()
- return self
-
- def assign(self, var, val):
- self.write("%s = %s" % (var, val))
- self.write(";")
- self.newline()
- return self
-
- def increment(self, var, val):
- self.write("%s += %s" % (var, val))
- self.write(";")
- self.newline()
- return self
-
- def comment(self, str):
- self.write("/* " + str + " */")
- return self
-
- def todo(self, str):
- self.comment("TODO: *** %s ***" % str).newline()
- return self
-
- def error_check(self, check, label = "error"):
- self.has_error_check = True
- with self.block("if (SPICE_UNLIKELY(%s))" % check):
- if self.has_option("print_error"):
- self.statement('printf("%%s: Caught error - %s", __PRETTY_FUNCTION__)' % check)
- if self.has_option("assert_on_error"):
- self.statement("assert(0)")
- self.statement("goto %s" % label)
-
- def indent(self):
- self.indentation += 4
-
- def unindent(self):
- self.indentation -= 4
- if self.indentation < 0:
- self.indentation = 0
-
- def begin_block(self, prefix= "", comment = ""):
- if len(prefix) > 0:
- self.write(prefix)
- if self.at_line_start:
- self.write("{")
- else:
- self.write(" {")
- if len(comment) > 0:
- self.write(" ")
- self.comment(comment)
- self.newline()
- self.indent()
-
- def end_block(self, semicolon=False, newline=True):
- self.unindent()
- if self.at_line_start:
- self.write("}")
- else:
- self.write(" }")
- if semicolon:
- self.write(";")
- if newline:
- self.newline()
-
- class Block:
- def __init__(self, writer, semicolon, newline):
- self.writer = writer
- self.semicolon = semicolon
- self.newline = newline
-
- def __enter__(self):
- return self.writer.get_subwriter()
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.writer.end_block(self.semicolon, self.newline)
-
- class PartialBlock:
- def __init__(self, writer, scope, semicolon, newline):
- self.writer = writer
- self.scope = scope
- self.semicolon = semicolon
- self.newline = newline
-
- def __enter__(self):
- return self.scope
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.writer.end_block(self.semicolon, self.newline)
-
- class NoBlock:
- def __init__(self, scope):
- self.scope = scope
-
- def __enter__(self):
- return self.scope
-
- def __exit__(self, exc_type, exc_value, traceback):
- pass
-
- def block(self, prefix= "", comment = "", semicolon=False, newline=True):
- self.begin_block(prefix, comment)
- return self.Block(self, semicolon, newline)
-
- def partial_block(self, scope, semicolon=False, newline=True):
- return self.PartialBlock(self, scope, semicolon, newline)
-
- def no_block(self, scope):
- return self.NoBlock(scope)
-
- def optional_block(self, scope):
- if scope != None:
- return self.NoBlock(scope)
- return self.block()
-
- def for_loop(self, index, limit):
- return self.block("for (%s = 0; %s < %s; %s++)" % (index, index, limit, index))
-
- def while_loop(self, expr):
- return self.block("while (%s)" % (expr))
-
- def if_block(self, check, elseif=False, newline=True):
- s = "if (%s)" % (check)
- if elseif:
- s = " else " + s
- self.begin_block(s, "")
- return self.Block(self, False, newline)
-
- def variable_defined(self, name):
- for n in self.vars:
- if n == name:
- return True
- return False
-
- def variable_def(self, ctype, *names):
- for n in names:
- # Strip away initialization
- i = n.find("=")
- if i != -1:
- n = n[0:i]
- self.vars.append(n.strip())
- # only add space for non-pointer types
- if ctype[-1] == "*":
- ctype = ctype[:-1].rstrip()
- self.writeln("%s *%s;"%(ctype, ", *".join(names)))
- else:
- self.writeln("%s %s;"%(ctype, ", ".join(names)))
- return self
-
- def function_helper(self):
- if self.function_helper_writer != None:
- writer = self.function_helper_writer.get_subwriter()
- self.function_helper_writer.newline()
- else:
- writer = self.get_subwriter()
- return writer
-
- def function(self, name, return_type, args, static = False):
- self.has_error_check = False
- self.function_helper_writer = self.get_subwriter()
- if static:
- self.write("static ")
- self.write(return_type)
- self.write(" %s(%s)"% (name, args)).newline()
- self.begin_block()
- self.function_variables_writer = self.get_subwriter()
- self.function_variables = {}
- return self.function_variables_writer
-
- def macro(self, name, args, define):
- self.write("#define %s(%s) %s" % (name, args, define)).newline()
-
- def ifdef(self, name):
- indentation = self.indentation
- self.indentation = 0;
- self.write("#ifdef %s" % (name)).newline()
- self.indentation = indentation
-
- def ifdef_else(self, name):
- indentation = self.indentation
- self.indentation = 0;
- self.write("#else /* %s */" % (name)).newline()
- self.indentation = indentation
-
- def endif(self, name):
- indentation = self.indentation
- self.indentation = 0;
- self.write("#endif /* %s */" % (name)).newline()
- self.indentation = indentation
-
- def add_function_variable(self, ctype, name):
- if name in self.function_variables:
- assert(self.function_variables[name] == ctype)
- else:
- self.function_variables[name] = ctype
- self.function_variables_writer.variable_def(ctype, name)
-
- def pop_index(self):
- index = self.indexes[self.current_index]
- self.current_index = self.current_index + 1
- self.add_function_variable(self.index_type, index)
- return index
-
- def push_index(self):
- assert self.current_index > 0
- self.current_index = self.current_index - 1
-
- class Index:
- def __init__(self, writer, val):
- self.writer = writer
- self.val = val
-
- def __enter__(self):
- return self.val
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.writer.push_index()
-
- def index(self, no_block = False):
- if no_block:
- return self.no_block(None)
- val = self.pop_index()
- return self.Index(self, val)
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
deleted file mode 100644
index 2252f37..0000000
--- a/python_modules/demarshal.py
+++ /dev/null
@@ -1,1274 +0,0 @@
-
-from . import ptypes
-from . import codegen
-
-# The handling of sizes is somewhat complex, as there are several types of size:
-# * nw_size
-# This is the network size, i.e. the number of bytes on the network
-#
-# * mem_size
-# The total amount of memory used for the representation of something inside
-# spice. This is generally sizeof(C struct), but can be larger if for instance
-# the type has a variable size array at the end or has a pointer in it that
-# points to another data chunk (which will be allocated after the main
-# data chunk). This is essentially how much memory you need to allocate to
-# contain the data type.
-#
-# * extra_size
-# This is the size of anything that is not part of the containing structure.
-# For instance, a primitive (say uint32_t) member has no extra size, because
-# when allocating its part of the sizeof(MessageStructType) struct. However
-# a variable array can be places at the end of a structure (@end) and its
-# size is then extra_size. Note that this extra_size is included in the
-# mem_size of the enclosing struct, and even if you request the mem_size
-# of the array itself. However, extra_size is typically not requested
-# when the full mem_size is also requested.
-#
-# extra sizes come in two flavours. contains_extra_size means that the item
-# has a normal presence in the parent container, but has some additional
-# extra_size it references. For instance via a pointer somewhere in it.
-# There is also is_extra_size(). This indicates that the whole elements
-# "normal" mem size should be considered extra size for the container, so
-# when computing the parent mem_size you should add the mem_size of this
-# part as extra_size
-
-def write_parser_helpers(writer):
- if writer.is_generated("helper", "demarshaller"):
- return
-
- writer.set_is_generated("helper", "demarshaller")
-
- writer = writer.function_helper()
-
- writer.writeln("#ifdef WORDS_BIGENDIAN")
- for size in [8, 16, 32, 64]:
- for sign in ["", "u"]:
- utype = "uint%d" % (size)
- type = "%sint%d" % (sign, size)
- swap = "SPICE_BYTESWAP%d" % size
- if size == 8:
- writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
- writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = val" % (type))
- else:
- writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr))))" % (type, swap, utype))
- writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = %s((%s_t)val)" % (utype, swap, utype))
- writer.writeln("#else")
- for size in [8, 16, 32, 64]:
- for sign in ["", "u"]:
- type = "%sint%d" % (sign, size)
- writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
- writer.macro("write_%s" % type, "ptr, val", "(*((%s_t *)(ptr))) = val" % type)
- writer.writeln("#endif")
-
- for size in [8, 16, 32, 64]:
- for sign in ["", "u"]:
- writer.newline()
- type = "%sint%d" % (sign, size)
- ctype = "%s_t" % type
- scope = writer.function("SPICE_GNUC_UNUSED consume_%s" % type, ctype, "uint8_t **ptr", True)
- scope.variable_def(ctype, "val")
- writer.assign("val", "read_%s(*ptr)" % type)
- writer.increment("*ptr", size // 8)
- writer.statement("return val")
- writer.end_block()
-
- writer.function("SPICE_GNUC_UNUSED consume_fd", "int", "uint8_t **ptr", True)
- writer.statement("return -1")
- writer.end_block()
-
- writer.newline()
- writer.statement("typedef struct PointerInfo PointerInfo")
- writer.statement("typedef void (*message_destructor_t)(uint8_t *message)")
- writer.statement("typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor)")
- writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message)")
- writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message)")
-
- writer.newline()
- writer.begin_block("struct PointerInfo")
- writer.variable_def("uint64_t", "offset")
- writer.variable_def("parse_func_t", "parse")
- writer.variable_def("void **", "dest")
- writer.variable_def("uint32_t", "nelements")
- writer.end_block(semicolon=True)
-
-def write_read_primitive(writer, start, container, name, scope):
- m = container.lookup_member(name)
- assert(m.is_primitive())
- writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
- writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size())
-
- var = "%s__value" % (name.replace(".", "_"))
- if not scope.variable_defined(var):
- scope.variable_def(m.member_type.c_type(), var)
- writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type()))
- return var
-
-def write_write_primitive(writer, start, container, name, val):
- m = container.lookup_member(name)
- assert(m.is_primitive())
- writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
-
- var = "%s__value" % (name)
- writer.statement("write_%s(pos, %s)" % (m.member_type.primitive_type(), val))
- return var
-
-def write_read_primitive_item(writer, item, scope):
- assert(item.type.is_primitive())
- writer.assign("pos", item.get_position())
- writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size())
- var = "%s__value" % (item.subprefix.replace(".", "_"))
- scope.variable_def(item.type.c_type(), var)
- writer.assign(var, "read_%s(pos)" % (item.type.primitive_type()))
- return var
-
-class ItemInfo:
- def __init__(self, type, prefix, position):
- self.type = type
- self.prefix = prefix
- self.subprefix = prefix
- self.position = position
- self.member = None
-
- def nw_size(self):
- return self.prefix + "__nw_size"
-
- def mem_size(self):
- return self.prefix + "__mem_size"
-
- def extra_size(self):
- return self.prefix + "__extra_size"
-
- def get_position(self):
- return self.position
-
-class MemberItemInfo(ItemInfo):
- def __init__(self, member, mprefix, container, start):
- if not member.is_switch():
- self.type = member.member_type
- self.prefix = member.name
- if mprefix:
- mprefix = mprefix + "_"
- self.prefix = mprefix + self.prefix
- self.subprefix = member.name
- self.position = "(%s + %s)" % (start, container.get_nw_offset(member, mprefix or "", "__nw_size"))
- self.member = member
-
-def write_validate_switch_member(writer, mprefix, container, switch_member, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size):
- var = container.lookup_member(switch_member.variable)
- var_type = var.member_type
-
- v = write_read_primitive(writer, start, container, switch_member.variable, parent_scope)
-
- item = MemberItemInfo(switch_member, mprefix, container, start)
-
- first = True
- for c in switch_member.cases:
- check = c.get_check(v, var_type)
- m = c.member
- with writer.if_block(check, not first, False) as if_scope:
- item.type = c.member.member_type
- item.subprefix = item.prefix + "_" + m.name
- item.member = c.member
-
- all_as_extra_size = m.is_extra_size() and want_extra_size
- if not want_mem_size and all_as_extra_size and not scope.variable_defined(item.mem_size()):
- scope.variable_def("uint32_t", item.mem_size())
-
- sub_want_mem_size = want_mem_size or all_as_extra_size
- sub_want_extra_size = want_extra_size and not all_as_extra_size
-
- write_validate_item(writer, container, item, if_scope, scope, start,
- want_nw_size, sub_want_mem_size, sub_want_extra_size)
-
- if all_as_extra_size:
- writer.assign(item.extra_size(), item.mem_size())
-
- first = False
-
- with writer.block(" else"):
- if want_nw_size:
- writer.assign(item.nw_size(), 0)
- if want_mem_size:
- writer.assign(item.mem_size(), 0)
- if want_extra_size:
- writer.assign(item.extra_size(), 0)
-
- writer.newline()
-
-def write_validate_struct_function(writer, struct):
- validate_function = "validate_%s" % struct.c_type()
- if writer.is_generated("validator", validate_function):
- return validate_function
-
- writer.set_is_generated("validator", validate_function)
- writer = writer.function_helper()
- scope = writer.function(validate_function, "static intptr_t", "uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor")
- scope.variable_def("uint8_t *", "start = message_start + offset")
- scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos")
- scope.variable_def("size_t", "mem_size", "nw_size")
- num_pointers = struct.get_num_pointers()
- if num_pointers != 0:
- scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
-
- writer.newline()
- with writer.if_block("offset == 0"):
- writer.statement("return 0")
-
- writer.newline()
- writer.error_check("start >= message_end")
-
- writer.newline()
- write_validate_container(writer, None, struct, "start", scope, True, True, False)
-
- writer.newline()
- writer.comment("Check if struct fits in reported side").newline()
- writer.error_check("start + nw_size > message_end")
-
- writer.statement("return mem_size")
-
- writer.newline()
- writer.label("error")
- writer.statement("return -1")
-
- writer.end_block()
-
- return validate_function
-
-def write_validate_pointer_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size):
- if want_nw_size:
- writer.assign(item.nw_size(), item.type.get_fixed_nw_size())
-
- if want_mem_size or want_extra_size:
- target_type = item.type.target_type
-
- v = write_read_primitive_item(writer, item, scope)
- if item.type.has_attr("nonnull"):
- writer.error_check("%s == 0" % v)
-
- # pointer target is struct, or array of primitives
- # if array, need no function check
-
- if target_type.is_array():
- writer.error_check("message_start + %s >= message_end" % v)
-
-
- assert target_type.element_type.is_primitive()
-
- array_item = ItemInfo(target_type, "%s__array" % item.prefix, start)
- scope.variable_def("uint32_t", array_item.nw_size())
- # don't create a variable that isn't used, fixes -Werror=unused-but-set-variable
- need_mem_size = want_mem_size or (
- want_extra_size and not item.member.has_attr("chunk")
- and not target_type.is_cstring_length())
- if need_mem_size:
- scope.variable_def("uint32_t", array_item.mem_size())
- if target_type.is_cstring_length():
- writer.assign(array_item.nw_size(), "spice_strnlen((char *)message_start + %s, message_end - (message_start + %s))" % (v, v))
- writer.error_check("*(message_start + %s + %s) != 0" % (v, array_item.nw_size()))
- else:
- write_validate_array_item(writer, container, array_item, scope, parent_scope, start,
- True, want_mem_size=need_mem_size, want_extra_size=False)
- writer.error_check("message_start + %s + %s > message_end" % (v, array_item.nw_size()))
-
- if want_extra_size:
- if item.member and item.member.has_attr("chunk"):
- writer.assign(item.extra_size(), "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
- elif item.member and item.member.has_attr("nocopy"):
- writer.comment("@nocopy, so no extra size").newline()
- writer.assign(item.extra_size(), 0)
- elif target_type.element_type.get_fixed_nw_size == 1:
- writer.assign(item.extra_size(), array_item.mem_size())
- # If not bytes or zero, add padding needed for alignment
- else:
- writer.assign(item.extra_size(), "%s + /* for alignment */ 3" % array_item.mem_size())
- if want_mem_size:
- writer.assign(item.mem_size(), "sizeof(void *) + %s" % array_item.mem_size())
-
- elif target_type.is_struct():
- validate_function = write_validate_struct_function(writer, target_type)
- writer.assign("ptr_size", "%s(message_start, message_end, %s, minor)" % (validate_function, v))
- writer.error_check("ptr_size < 0")
-
- if want_extra_size:
- writer.assign(item.extra_size(), "ptr_size + /* for alignment */ 3")
- if want_mem_size:
- writer.assign(item.mem_size(), "sizeof(void *) + ptr_size")
- else:
- raise NotImplementedError("pointer to unsupported type %s" % target_type)
-
-
-def write_validate_array_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size):
- array = item.type
- is_byte_size = False
- element_type = array.element_type
- if array.is_bytes_length():
- nelements = "%s__nbytes" %(item.prefix)
- real_nelements = "%s__nelements" %(item.prefix)
- if not parent_scope.variable_defined(real_nelements):
- parent_scope.variable_def("uint32_t", real_nelements)
- else:
- nelements = "%s__nelements" %(item.prefix)
- if not parent_scope.variable_defined(nelements):
- parent_scope.variable_def("uint32_t", nelements)
-
- if array.is_constant_length():
- writer.assign(nelements, array.size)
- elif array.is_remaining_length():
- if element_type.is_fixed_nw_size():
- if element_type.get_fixed_nw_size() == 1:
- writer.assign(nelements, "message_end - %s" % item.get_position())
- else:
- writer.assign(nelements, "(message_end - %s) / (%s)" %(item.get_position(), element_type.get_fixed_nw_size()))
- else:
- raise NotImplementedError("TODO array[] of dynamic element size not done yet")
- elif array.is_identifier_length():
- v = write_read_primitive(writer, start, container, array.size, scope)
- writer.assign(nelements, v)
- elif array.is_image_size_length():
- bpp = array.size[1]
- width = array.size[2]
- rows = array.size[3]
- width_v = write_read_primitive(writer, start, container, width, scope)
- rows_v = write_read_primitive(writer, start, container, rows, scope)
- # TODO: Handle multiplication overflow
- if bpp == 8:
- writer.assign(nelements, "%s * %s" % (width_v, rows_v))
- elif bpp == 1:
- writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v))
- else:
- writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
- elif array.is_bytes_length():
- is_byte_size = True
- v = write_read_primitive(writer, start, container, array.size[1], scope)
- writer.assign(nelements, v)
- writer.assign(real_nelements, 0)
- elif array.is_cstring_length():
- writer.todo("cstring array size type not handled yet")
- else:
- writer.todo("array size type not handled yet")
-
- writer.newline()
-
- nw_size = item.nw_size()
- mem_size = item.mem_size()
- extra_size = item.extra_size()
-
- if is_byte_size and want_nw_size:
- writer.assign(nw_size, nelements)
- want_nw_size = False
-
- if element_type.is_fixed_nw_size() and want_nw_size:
- element_size = element_type.get_fixed_nw_size()
- # TODO: Overflow check the multiplication
- if element_size == 1:
- writer.assign(nw_size, nelements)
- else:
- writer.assign(nw_size, "(%s) * %s" % (element_size, nelements))
- want_nw_size = False
-
- if array.has_attr("as_ptr") and want_mem_size:
- writer.assign(mem_size, "sizeof(void *)")
- want_mem_size = False
-
- if array.has_attr("chunk"):
- if want_mem_size:
- writer.assign(extra_size, "sizeof(SpiceChunks *)")
- want_mem_size = False
- if want_extra_size:
- writer.assign(extra_size, "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
- want_extra_size = False
-
- if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size:
- # TODO: Overflow check the multiplication
- if array.has_attr("ptr_array"):
- writer.assign(mem_size, "sizeof(void *) + SPICE_ALIGN(%s * %s, 4)" % (element_type.sizeof(), nelements))
- else:
- writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements))
- want_mem_size = False
-
- if not element_type.contains_extra_size() and want_extra_size:
- writer.assign(extra_size, 0)
- want_extra_size = False
-
- if not (want_mem_size or want_nw_size or want_extra_size):
- return
-
- start2 = codegen.increment_identifier(start)
- scope.variable_def("uint8_t *", "%s = %s" % (start2, item.get_position()))
- if is_byte_size:
- start2_end = "%s_array_end" % start2
- scope.variable_def("uint8_t *", start2_end)
-
- element_item = ItemInfo(element_type, "%s__element" % item.prefix, start2)
-
- element_nw_size = element_item.nw_size()
- element_mem_size = element_item.mem_size()
- element_extra_size = element_item.extra_size()
- scope.variable_def("uint32_t", element_nw_size)
- scope.variable_def("uint32_t", element_mem_size)
- if want_extra_size:
- scope.variable_def("uint32_t", element_extra_size)
-
- if want_nw_size:
- writer.assign(nw_size, 0)
- if want_mem_size:
- writer.assign(mem_size, 0)
- if want_extra_size:
- writer.assign(extra_size, 0)
-
- want_element_nw_size = want_nw_size
- if element_type.is_fixed_nw_size():
- start_increment = element_type.get_fixed_nw_size()
- else:
- want_element_nw_size = True
- start_increment = element_nw_size
-
- if is_byte_size:
- writer.assign(start2_end, "%s + %s" % (start2, nelements))
-
- with writer.index(no_block = is_byte_size) as index:
- with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope:
- if is_byte_size:
- writer.increment(real_nelements, 1)
- write_validate_item(writer, container, element_item, scope, parent_scope, start2,
- want_element_nw_size, want_mem_size, want_extra_size)
-
- if want_nw_size:
- writer.increment(nw_size, element_nw_size)
- if want_mem_size:
- if array.has_attr("ptr_array"):
- writer.increment(mem_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size)
- else:
- writer.increment(mem_size, element_mem_size)
- if want_extra_size:
- writer.increment(extra_size, element_extra_size)
-
- writer.increment(start2, start_increment)
- if is_byte_size:
- writer.error_check("%s != %s" % (start2, start2_end))
- write_write_primitive(writer, start, container, array.size[1], real_nelements)
-
-def write_validate_struct_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size):
- struct = item.type
- start2 = codegen.increment_identifier(start)
- scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", start2 + " = %s" % (item.get_position()))
-
- write_validate_container(writer, item.prefix, struct, start2, scope, want_nw_size, want_mem_size, want_extra_size)
-
-def write_validate_primitive_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size):
- if want_nw_size:
- nw_size = item.nw_size()
- writer.assign(nw_size, item.type.get_fixed_nw_size())
- if want_mem_size:
- mem_size = item.mem_size()
- writer.assign(mem_size, item.type.sizeof())
- if want_extra_size:
- writer.assign(item.extra_size(), 0)
-
-def write_validate_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size):
- if item.member and item.member.has_attr("to_ptr"):
- want_nw_size = True
- if item.type.is_pointer():
- write_validate_pointer_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size)
- elif item.type.is_array():
- write_validate_array_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size)
- elif item.type.is_struct():
- write_validate_struct_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size)
- elif item.type.is_primitive():
- write_validate_primitive_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size)
- else:
- writer.todo("Implement validation of %s" % item.type)
-
- if item.member and item.member.has_attr("to_ptr"):
- saved_size = "%s__saved_size" % item.member.name
- writer.add_function_variable("uint32_t", saved_size + " = 0")
- writer.assign(saved_size, item.nw_size())
-
-def write_validate_member(writer, mprefix, container, member, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size):
- if member.has_attr("virtual"):
- return
-
- if member.has_minor_attr():
- prefix = "if (minor >= %s)" % (member.get_minor_attr())
- newline = False
- else:
- prefix = ""
- newline = True
- item = MemberItemInfo(member, mprefix, container, start)
- with writer.block(prefix, newline=newline, comment=member.name) as scope:
- if member.is_switch():
- write_validate_switch_member(writer, mprefix, container, member, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size)
- else:
- write_validate_item(writer, container, item, scope, parent_scope, start,
- want_nw_size, want_mem_size, want_extra_size)
-
- if member.has_minor_attr():
- with writer.block(" else", comment = "minor < %s" % (member.get_minor_attr())):
- if member.is_array():
- nelements = "%s__nelements" %(item.prefix)
- writer.assign(nelements, 0)
- if want_nw_size:
- writer.assign(item.nw_size(), 0)
-
- if want_mem_size:
- if member.is_fixed_sizeof():
- writer.assign(item.mem_size(), member.sizeof())
- elif member.is_array():
- writer.assign(item.mem_size(), 0)
- else:
- raise NotImplementedError("TODO minor check for non-constant items")
-
- assert not want_extra_size
-
-def write_validate_container(writer, prefix, container, start, parent_scope, want_nw_size, want_mem_size, want_extra_size):
- def prefix_m(prefix, m):
- name = m.name
- if prefix:
- name = prefix + "_" + name
- return name
-
- for m in container.members:
- sub_want_nw_size = want_nw_size and not m.is_fixed_nw_size()
- sub_want_mem_size = m.is_extra_size() and want_mem_size
- sub_want_extra_size = not m.is_extra_size() and m.contains_extra_size()
- defs = ["size_t"]
- name = prefix_m(prefix, m)
- if sub_want_nw_size:
-
- defs.append (name + "__nw_size")
- if sub_want_mem_size:
- defs.append (name + "__mem_size")
- if sub_want_extra_size:
- defs.append (name + "__extra_size")
-
- if sub_want_nw_size or sub_want_mem_size or sub_want_extra_size:
- parent_scope.variable_def(*defs)
- write_validate_member(writer, prefix, container, m, parent_scope, start,
- sub_want_nw_size, sub_want_mem_size, sub_want_extra_size)
- writer.newline()
-
- if want_nw_size:
- if prefix:
- nw_size = prefix + "__nw_size"
- else:
- nw_size = "nw_size"
-
- size = 0
- for m in container.members:
- if m.is_fixed_nw_size():
- size = size + m.get_fixed_nw_size()
-
- nm_sum = str(size)
- for m in container.members:
- name = prefix_m(prefix, m)
- if not m.is_fixed_nw_size():
- nm_sum = nm_sum + " + " + name + "__nw_size"
-
- writer.assign(nw_size, nm_sum)
-
- if want_mem_size:
- if prefix:
- mem_size = prefix + "__mem_size"
- else:
- mem_size = "mem_size"
-
- mem_sum = container.sizeof()
- for m in container.members:
- name = prefix_m(prefix, m)
- if m.is_extra_size():
- mem_sum = mem_sum + " + " + name + "__mem_size"
- elif m.contains_extra_size():
- mem_sum = mem_sum + " + " + name + "__extra_size"
-
- writer.assign(mem_size, mem_sum)
-
- if want_extra_size:
- if prefix:
- extra_size = prefix + "__extra_size"
- else:
- extra_size = "extra_size"
-
- extra_sum = []
- for m in container.members:
- name = prefix_m(prefix, m)
- if m.is_extra_size():
- extra_sum.append(name + "__mem_size")
- elif m.contains_extra_size():
- extra_sum.append(name + "__extra_size")
- writer.assign(extra_size, codegen.sum_array(extra_sum))
-
-class DemarshallingDestination:
- def __init__(self):
- pass
-
- def child_at_end(self, writer, t):
- return RootDemarshallingDestination(self, t.c_type(), t.sizeof())
-
- def child_sub(self, member):
- return SubDemarshallingDestination(self, member)
-
- def declare(self, writer):
- return writer.optional_block(self.reuse_scope)
-
- def is_toplevel(self):
- return self.parent_dest == None and not self.is_helper
-
-class RootDemarshallingDestination(DemarshallingDestination):
- def __init__(self, parent_dest, c_type, sizeof, pointer = None):
- self.is_helper = False
- self.reuse_scope = None
- self.parent_dest = parent_dest
- if parent_dest:
- self.base_var = codegen.increment_identifier(parent_dest.base_var)
- else:
- self.base_var = "out"
- self.c_type = c_type
- self.sizeof = sizeof
- self.pointer = pointer # None == at "end"
-
- def get_ref(self, member):
- return self.base_var + "->" + member
-
- def declare(self, writer):
- if self.reuse_scope:
- scope = self.reuse_scope
- else:
- writer.begin_block()
- scope = writer.get_subwriter()
-
- scope.variable_def(self.c_type + " *", self.base_var)
- if not self.reuse_scope:
- scope.newline()
-
- if self.pointer:
- writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer))
- else:
- writer.assign(self.base_var, "(%s *)end" % (self.c_type))
- writer.increment("end", self.sizeof)
- writer.newline()
-
- if self.reuse_scope:
- return writer.no_block(self.reuse_scope)
- else:
- return writer.partial_block(scope)
-
-class SubDemarshallingDestination(DemarshallingDestination):
- def __init__(self, parent_dest, member):
- self.reuse_scope = None
- self.parent_dest = parent_dest
- self.base_var = parent_dest.base_var
- self.member = member
- self.is_helper = False
-
- def get_ref(self, member):
- return self.parent_dest.get_ref(self.member) + "." + member
-
-# Note: during parsing, byte_size types have been converted to count during validation
-def read_array_len(writer, prefix, array, dest, scope, is_ptr):
- if is_ptr:
- nelements = "%s__array__nelements" % prefix
- else:
- nelements = "%s__nelements" % prefix
- if dest.is_toplevel() and scope.variable_defined(nelements):
- return nelements # Already there for toplevel, need not recalculate
- element_type = array.element_type
- scope.variable_def("uint32_t", nelements)
- if array.is_constant_length():
- writer.assign(nelements, array.size)
- elif array.is_identifier_length():
- writer.assign(nelements, dest.get_ref(array.size))
- elif array.is_remaining_length():
- if element_type.is_fixed_nw_size():
- writer.assign(nelements, "(message_end - in) / (%s)" %(element_type.get_fixed_nw_size()))
- else:
- raise NotImplementedError("TODO array[] of dynamic element size not done yet")
- elif array.is_image_size_length():
- bpp = array.size[1]
- width = array.size[2]
- rows = array.size[3]
- width_v = dest.get_ref(width)
- rows_v = dest.get_ref(rows)
- # TODO: Handle multiplication overflow
- if bpp == 8:
- writer.assign(nelements, "%s * %s" % (width_v, rows_v))
- elif bpp == 1:
- writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v))
- else:
- writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
- elif array.is_bytes_length():
- writer.assign(nelements, dest.get_ref(array.size[2]))
- else:
- raise NotImplementedError("TODO array size type not handled yet")
- return nelements
-
-def write_switch_parser(writer, container, switch, dest, scope):
- var = container.lookup_member(switch.variable)
- var_type = var.member_type
-
- if switch.has_attr("fixedsize"):
- scope.variable_def("uint8_t *", "in_save")
- writer.assign("in_save", "in")
-
- first = True
- for c in switch.cases:
- check = c.get_check(dest.get_ref(switch.variable), var_type)
- m = c.member
- with writer.if_block(check, not first, False) as block:
- t = m.member_type
- if switch.has_end_attr():
- dest2 = dest.child_at_end(writer, m.member_type)
- elif switch.has_attr("anon"):
- if t.is_struct() and not m.has_attr("to_ptr"):
- dest2 = dest.child_sub(m.name)
- else:
- dest2 = dest
- else:
- if t.is_struct():
- dest2 = dest.child_sub(switch.name + "." + m.name)
- else:
- dest2 = dest.child_sub(switch.name)
- dest2.reuse_scope = block
-
- if m.has_attr("to_ptr"):
- write_parse_to_pointer(writer, t, False, dest2, m.name, block)
- elif t.is_pointer():
- write_parse_pointer(writer, t, False, dest2, m.name, block)
- elif t.is_struct():
- write_container_parser(writer, t, dest2)
- elif t.is_primitive():
- if m.has_attr("zero"):
- writer.statement("consume_%s(&in)" % (t.primitive_type()))
- else:
- writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type()))
- #TODO validate e.g. flags and enums
- elif t.is_array():
- nelements = read_array_len(writer, m.name, t, dest, block, False)
- write_array_parser(writer, m, nelements, t, dest2, block)
- else:
- writer.todo("Can't handle type %s" % m.member_type)
-
- first = False
-
- writer.newline()
-
- if switch.has_attr("fixedsize"):
- writer.assign("in", "in_save + %s" % switch.get_fixed_nw_size())
-
-def write_parse_ptr_function(writer, target_type):
- if target_type.is_array():
- parse_function = "parse_array_%s" % target_type.element_type.primitive_type()
- else:
- parse_function = "parse_struct_%s" % target_type.c_type()
- if writer.is_generated("parser", parse_function):
- return parse_function
-
- writer.set_is_generated("parser", parse_function)
-
- writer = writer.function_helper()
- scope = writer.function(parse_function, "static uint8_t *", "uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor")
- scope.variable_def("uint8_t *", "in = message_start + this_ptr_info->offset")
- scope.variable_def("uint8_t *", "end")
-
- num_pointers = target_type.get_num_pointers()
- if num_pointers != 0:
- scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
- scope.variable_def("uint32_t", "n_ptr=0")
- scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
-
- writer.newline()
- if target_type.is_array():
- writer.assign("end", "struct_data")
- else:
- writer.assign("end", "struct_data + %s" % (target_type.sizeof()))
-
- dest = RootDemarshallingDestination(None, target_type.c_type(), target_type.sizeof(), "struct_data")
- dest.is_helper = True
- dest.reuse_scope = scope
- if target_type.is_array():
- write_array_parser(writer, None, "this_ptr_info->nelements", target_type, dest, scope)
- else:
- write_container_parser(writer, target_type, dest)
-
- if num_pointers != 0:
- write_ptr_info_check(writer)
-
- writer.statement("return end")
-
- if writer.has_error_check:
- writer.newline()
- writer.label("error")
- writer.statement("return NULL")
-
- writer.end_block()
-
- return parse_function
-
-def write_array_parser(writer, member, nelements, array, dest, scope):
- is_byte_size = array.is_bytes_length()
-
- element_type = array.element_type
- if member:
- array_start = dest.get_ref(member.name)
- at_end = member.has_attr("end")
- else:
- array_start = "end"
- at_end = True
-
- if element_type == ptypes.uint8 or element_type == ptypes.int8:
- writer.statement("memcpy(%s, in, %s)" % (array_start, nelements))
- writer.increment("in", nelements)
- if at_end:
- writer.increment("end", nelements)
- else:
- with writer.index() as index:
- if member:
- array_pos = "%s[%s]" % (array_start, index)
- else:
- array_pos = "*(%s *)end" % (element_type.c_type())
-
- if array.has_attr("ptr_array"):
- scope.variable_def("void **", "ptr_array")
- scope.variable_def("int", "ptr_array_index")
- writer.assign("ptr_array_index", 0)
- writer.assign("ptr_array", "(void **)%s" % array_start)
- writer.increment("end", "sizeof(void *) * %s" % nelements)
- array_start = "end"
- array_pos = "*(%s *)end" % (element_type.c_type())
- at_end = True
-
- with writer.for_loop(index, nelements) as array_scope:
- if array.has_attr("ptr_array"):
- writer.statement("ptr_array[ptr_array_index++] = end")
- if element_type.is_primitive():
- writer.statement("%s = consume_%s(&in)" % (array_pos, element_type.primitive_type()))
- if at_end:
- writer.increment("end", element_type.sizeof())
- else:
- if at_end:
- dest2 = dest.child_at_end(writer, element_type)
- else:
- dest2 = RootDemarshallingDestination(dest, element_type.c_type(), element_type.c_type(), array_pos)
- dest2.reuse_scope = array_scope
- write_container_parser(writer, element_type, dest2)
- if array.has_attr("ptr_array"):
- writer.comment("Align ptr_array element to 4 bytes").newline()
- writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
-
-def write_parse_pointer_core(writer, target_type, offset, at_end, dest, member_name, scope):
- writer.assign("ptr_info[n_ptr].offset", offset)
- writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type))
- if at_end:
- writer.assign("ptr_info[n_ptr].dest", "(void **)end")
- writer.increment("end", "sizeof(void *)")
- else:
- writer.assign("ptr_info[n_ptr].dest", "(void **)&%s" % dest.get_ref(member_name))
- if target_type.is_array():
- nelements = read_array_len(writer, member_name, target_type, dest, scope, True)
- writer.assign("ptr_info[n_ptr].nelements", nelements)
-
- writer.statement("n_ptr++")
-
-def write_parse_pointer(writer, t, at_end, dest, member_name, scope):
- write_parse_pointer_core(writer, t.target_type, "consume_%s(&in)" % t.primitive_type(),
- at_end, dest, member_name, scope)
-
-def write_parse_to_pointer(writer, t, at_end, dest, member_name, scope):
- write_parse_pointer_core(writer, t, "in - start",
- at_end, dest, member_name, scope)
- writer.increment("in", "%s__saved_size" % member_name)
-
-def write_member_parser(writer, container, member, dest, scope):
- if member.has_attr("virtual"):
- writer.assign(dest.get_ref(member.name), member.attributes["virtual"][0])
- return
-
- if member.is_switch():
- write_switch_parser(writer, container, member, dest, scope)
- return
-
- t = member.member_type
-
- if member.has_attr("to_ptr"):
- write_parse_to_pointer(writer, t, member.has_end_attr(), dest, member.name, scope)
- elif t.is_pointer():
- if member.has_attr("chunk"):
- assert(t.target_type.is_array())
- nelements = read_array_len(writer, member.name, t.target_type, dest, scope, True)
- writer.comment("Reuse data from network message as chunk").newline()
- scope.variable_def("SpiceChunks *", "chunks")
- writer.assign("chunks", "(SpiceChunks *)end")
- writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
- writer.assign(dest.get_ref(member.name), "chunks")
- writer.assign("chunks->data_size", nelements)
- writer.assign("chunks->flags", 0)
- writer.assign("chunks->num_chunks", 1)
- writer.assign("chunks->chunk[0].len", nelements)
- writer.assign("chunks->chunk[0].data", "message_start + consume_%s(&in)" % t.primitive_type())
- elif member.has_attr("nocopy"):
- writer.comment("Reuse data from network message").newline()
- writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_%s(&in))" % t.primitive_type())
- else:
- write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, scope)
- elif t.is_primitive():
- if member.has_attr("zero"):
- writer.statement("consume_%s(&in)" % t.primitive_type())
- elif member.has_end_attr():
- writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type()))
- writer.increment("end", t.sizeof())
- else:
- if member.has_attr("bytes_count"):
- dest_var = dest.get_ref(member.attributes["bytes_count"][0])
- else:
- dest_var = dest.get_ref(member.name)
- writer.assign(dest_var, "consume_%s(&in)" % (t.primitive_type()))
- #TODO validate e.g. flags and enums
- elif t.is_array():
- nelements = read_array_len(writer, member.name, t, dest, scope, False)
- if member.has_attr("chunk") and t.element_type.is_fixed_nw_size() and t.element_type.get_fixed_nw_size() == 1:
- writer.comment("use array as chunk").newline()
-
- scope.variable_def("SpiceChunks *", "chunks")
- writer.assign("chunks", "(SpiceChunks *)end")
- writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
- writer.assign(dest.get_ref(member.name), "chunks")
- writer.assign("chunks->data_size", nelements)
- writer.assign("chunks->flags", 0)
- writer.assign("chunks->num_chunks", 1)
- writer.assign("chunks->chunk[0].len", nelements)
- writer.assign("chunks->chunk[0].data", "in")
- writer.increment("in", "%s" % (nelements))
- elif member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size():
- writer.comment("use array as pointer").newline()
- writer.assign(dest.get_ref(member.name), "(%s *)in" % t.element_type.c_type())
- len_var = member.attributes["as_ptr"]
- if len(len_var) > 0:
- writer.assign(dest.get_ref(len_var[0]), nelements)
- el_size = t.element_type.get_fixed_nw_size()
- if el_size != 1:
- writer.increment("in", "%s * %s" % (nelements, el_size))
- else:
- writer.increment("in", "%s" % (nelements))
- else:
- write_array_parser(writer, member, nelements, t, dest, scope)
- elif t.is_struct():
- if member.has_end_attr():
- dest2 = dest.child_at_end(writer, t)
- else:
- dest2 = dest.child_sub(member.name)
- writer.comment(member.name)
- write_container_parser(writer, t, dest2)
- else:
- raise NotImplementedError("TODO can't handle parsing of %s" % t)
-
-def write_container_parser(writer, container, dest):
- with dest.declare(writer) as scope:
- for m in container.members:
- if m.has_minor_attr():
- writer.begin_block("if (minor >= %s)" % m.get_minor_attr())
- write_member_parser(writer, container, m, dest, scope)
- if m.has_minor_attr():
- # We need to zero out the fixed part of all optional fields
- if not m.member_type.is_array():
- writer.end_block(newline=False)
- writer.begin_block(" else")
- # TODO: This is not right for fields that don't exist in the struct
- if m.has_attr("zero"):
- pass
- elif m.member_type.is_primitive():
- writer.assign(dest.get_ref(m.name), "0")
- elif m.is_fixed_sizeof():
- writer.statement("memset ((char *)&%s, 0, %s)" % (dest.get_ref(m.name), m.sizeof()))
- else:
- raise NotImplementedError("TODO Clear optional dynamic fields")
- writer.end_block()
-
-def write_ptr_info_check(writer):
- writer.newline()
- with writer.index() as index:
- with writer.for_loop(index, "n_ptr") as scope:
- offset = "ptr_info[%s].offset" % index
- function = "ptr_info[%s].parse" % index
- dest = "ptr_info[%s].dest" % index
- with writer.if_block("%s == 0" % offset, newline=False):
- writer.assign("*%s" % dest, "NULL")
- with writer.block(" else"):
- writer.comment("Align to 32 bit").newline()
- writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
- writer.assign("*%s" % dest, "(void *)end")
- writer.assign("end", "%s(message_start, message_end, end, &ptr_info[%s], minor)" % (function, index))
- writer.error_check("end == NULL")
- writer.newline()
-
-def write_nofree(writer):
- if writer.is_generated("helper", "nofree"):
- return
- writer = writer.function_helper()
- scope = writer.function("nofree", "static void", "SPICE_GNUC_UNUSED uint8_t *data")
- writer.end_block()
-
-def write_msg_parser(writer, message):
- msg_name = message.c_name()
- function_name = "parse_%s" % msg_name
- if writer.is_generated("demarshaller", function_name):
- return function_name
- writer.set_is_generated("demarshaller", function_name)
-
- msg_type = message.c_type()
- msg_sizeof = message.sizeof()
-
- want_mem_size = (len(message.members) != 1 or message.members[0].is_fixed_nw_size()
- or not message.members[0].is_array())
-
- writer.newline()
- if message.has_attr("ifdef"):
- writer.ifdef(message.attributes["ifdef"][0])
- parent_scope = writer.function(function_name,
- "uint8_t *",
- "uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message", True)
- parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos")
- parent_scope.variable_def("uint8_t *", "start = message_start")
- parent_scope.variable_def("uint8_t *", "data = NULL")
- parent_scope.variable_def("size_t", "nw_size")
- if want_mem_size:
- parent_scope.variable_def("size_t", "mem_size")
- if not message.has_attr("nocopy"):
- parent_scope.variable_def("uint8_t *", "in", "end")
- num_pointers = message.get_num_pointers()
- if num_pointers != 0:
- parent_scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
- parent_scope.variable_def("uint32_t", "n_ptr=0")
- parent_scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
- writer.newline()
-
- write_parser_helpers(writer)
-
- write_validate_container(writer, None, message, "start", parent_scope, True,
- want_mem_size=want_mem_size, want_extra_size=False)
-
- writer.newline()
-
- writer.comment("Check if message fits in reported side").newline()
- with writer.block("if (start + nw_size > message_end)"):
- writer.statement("return NULL")
-
- writer.newline().comment("Validated extents and calculated size").newline()
-
- if message.has_attr("nocopy"):
- write_nofree(writer)
- writer.assign("data", "message_start")
- writer.assign("*size", "message_end - message_start")
- writer.assign("*free_message", "nofree")
- else:
- writer.assign("data", "(uint8_t *)malloc(mem_size)")
- writer.error_check("data == NULL")
- writer.assign("end", "data + %s" % (msg_sizeof))
- writer.assign("in", "start").newline()
-
- # avoid defined and assigned but not used warnings of gcc 4.6.0+
- if message.is_extra_size() or not message.is_fixed_nw_size() or message.get_fixed_nw_size() > 0:
- dest = RootDemarshallingDestination(None, msg_type, msg_sizeof, "data")
- dest.reuse_scope = parent_scope
- write_container_parser(writer, message, dest)
-
- writer.newline()
- writer.statement("assert(in <= message_end)")
-
- if num_pointers != 0:
- write_ptr_info_check(writer)
-
- writer.statement("assert(end <= data + mem_size)")
-
- writer.newline()
- writer.assign("*size", "end - data")
- writer.assign("*free_message", "(message_destructor_t) free")
-
- writer.statement("return data")
- writer.newline()
- if writer.has_error_check:
- writer.label("error")
- with writer.block("if (data != NULL)"):
- writer.statement("free(data)")
- writer.statement("return NULL")
- writer.end_block()
-
- if message.has_attr("ifdef"):
- writer.endif(message.attributes["ifdef"][0])
-
- return function_name
-
-def write_channel_parser(writer, channel, server):
- writer.newline()
- ids = {}
- min_id = 1000000
- if server:
- messages = channel.server_messages
- else:
- messages = channel.client_messages
- for m in messages:
- ids[m.value] = m
-
- ranges = []
- ids2 = ids.copy()
- while len(ids2) > 0:
- end = start = min(ids2.keys())
- while end in ids2:
- del ids2[end]
- end = end + 1
-
- ranges.append( (start, end) )
-
- if server:
- function_name = "parse_%s_msg" % channel.name
- else:
- function_name = "parse_%s_msgc" % channel.name
- writer.newline()
- if channel.has_attr("ifdef"):
- writer.ifdef(channel.attributes["ifdef"][0])
- scope = writer.function(function_name,
- "static uint8_t *",
- "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message")
-
- helpers = writer.function_helper()
-
- d = 0
- for r in ranges:
- d = d + 1
- writer.write("static parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0]))
- writer.begin_block()
- for i in range(r[0], r[1]):
- func = write_msg_parser(helpers, ids[i].message_type)
- writer.write(func)
- if i != r[1] -1:
- writer.write(",")
- writer.newline()
-
- writer.end_block(semicolon = True)
-
- d = 0
- for r in ranges:
- d = d + 1
- with writer.if_block("message_type >= %d && message_type < %d" % (r[0], r[1]), d > 1, False):
- writer.statement("return funcs%d[message_type-%d](message_start, message_end, minor, size_out, free_message)" % (d, r[0]))
- writer.newline()
-
- writer.statement("return NULL")
- writer.end_block()
- if channel.has_attr("ifdef"):
- writer.endif(channel.attributes["ifdef"][0])
-
- return function_name
-
-def write_get_channel_parser(writer, channel_parsers, max_channel, is_server):
- writer.newline()
- if is_server:
- function_name = "spice_get_server_channel_parser" + writer.public_prefix
- else:
- function_name = "spice_get_client_channel_parser" + writer.public_prefix
-
- scope = writer.function(function_name,
- "spice_parse_channel_func_t",
- "uint32_t channel, unsigned int *max_message_type")
-
- writer.write("static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[%d] = " % (max_channel+1))
- writer.begin_block()
- channel = None
- for i in range(0, max_channel + 1):
- if i in channel_parsers:
- channel = channel_parsers[i][0]
- if channel.has_attr("ifdef"):
- writer.ifdef(channel.attributes["ifdef"][0])
- writer.write("{ ")
- writer.write(channel_parsers[i][1])
- writer.write(", ")
-
- max_msg = 0
- if is_server:
- messages = channel.server_messages
- else:
- messages = channel.client_messages
- for m in messages:
- max_msg = max(max_msg, m.value)
- writer.write(max_msg)
- writer.write("}")
- else:
- writer.write("{ NULL, 0 }")
-
- if i != max_channel:
- writer.write(",")
- writer.newline()
- if channel and channel.has_attr("ifdef"):
- writer.ifdef_else(channel.attributes["ifdef"][0])
- writer.write("{ NULL, 0 }")
- if i != max_channel:
- writer.write(",")
- writer.newline()
- writer.endif(channel.attributes["ifdef"][0])
- writer.end_block(semicolon = True)
-
- with writer.if_block("channel < %d" % (max_channel + 1)):
- with writer.if_block("max_message_type != NULL"):
- writer.assign("*max_message_type", "channels[channel].max_messages")
- writer.statement("return channels[channel].func")
-
- writer.statement("return NULL")
- writer.end_block()
-
-
-def write_full_protocol_parser(writer, is_server):
- writer.newline()
- if is_server:
- function_name = "spice_parse_msg"
- else:
- function_name = "spice_parse_reply"
- scope = writer.function(function_name + writer.public_prefix,
- "uint8_t *",
- "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message")
- scope.variable_def("spice_parse_channel_func_t", "func" )
-
- if is_server:
- writer.assign("func", "spice_get_server_channel_parser%s(channel, NULL)" % writer.public_prefix)
- else:
- writer.assign("func", "spice_get_client_channel_parser%s(channel, NULL)" % writer.public_prefix)
-
- with writer.if_block("func != NULL"):
- writer.statement("return func(message_start, message_end, message_type, minor, size_out, free_message)")
-
- writer.statement("return NULL")
- writer.end_block()
-
-def write_protocol_parser(writer, proto, is_server):
- max_channel = 0
- parsers = {}
-
- for channel in proto.channels:
- max_channel = max(max_channel, channel.value)
-
- parsers[channel.value] = (channel.channel_type, write_channel_parser(writer, channel.channel_type, is_server))
-
- write_get_channel_parser(writer, parsers, max_channel, is_server)
- write_full_protocol_parser(writer, is_server)
-
-def write_includes(writer):
- writer.writeln("#include <string.h>")
- writer.writeln("#include <assert.h>")
- writer.writeln("#include <stdlib.h>")
- writer.writeln("#include <stdio.h>")
- writer.writeln("#include <spice/protocol.h>")
- writer.writeln("#include <spice/macros.h>")
- writer.writeln('#include <common/mem.h>')
- writer.newline()
- writer.writeln("#ifdef _MSC_VER")
- writer.writeln("#pragma warning(disable:4101)")
- writer.writeln("#endif")
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
deleted file mode 100644
index 1d38d3d..0000000
--- a/python_modules/marshal.py
+++ /dev/null
@@ -1,420 +0,0 @@
-
-from . import ptypes
-from . import codegen
-
-def write_includes(writer):
- writer.header.writeln("#include <spice/protocol.h>")
- writer.header.writeln('#include "common/marshaller.h"')
- writer.header.newline()
- writer.header.writeln("#ifndef _GENERATED_HEADERS_H")
- writer.header.writeln("#define _GENERATED_HEADERS_H")
-
- writer.writeln("#include <string.h>")
- writer.writeln("#include <assert.h>")
- writer.writeln("#include <stdlib.h>")
- writer.writeln("#include <stdio.h>")
- writer.writeln("#include <spice/protocol.h>")
- writer.writeln("#include <spice/macros.h>")
- writer.writeln('#include "common/marshaller.h"')
- writer.newline()
- writer.writeln("#ifdef _MSC_VER")
- writer.writeln("#pragma warning(disable:4101)")
- writer.writeln("#pragma warning(disable:4018)")
- writer.writeln("#endif")
- writer.newline()
-
-class MarshallingSource:
- def __init__(self):
- pass
-
- def child_at_end(self, t):
- return RootMarshallingSource(self, t.c_type(), t.sizeof())
-
- def child_sub(self, containee):
- return SubMarshallingSource(self, containee)
-
- def declare(self, writer):
- return writer.optional_block(self.reuse_scope)
-
- def is_toplevel(self):
- return self.parent_src == None and not self.is_helper
-
-class RootMarshallingSource(MarshallingSource):
- def __init__(self, parent_src, c_type, sizeof, pointer = None):
- self.is_helper = False
- self.reuse_scope = None
- self.parent_src = parent_src
- if parent_src:
- self.base_var = codegen.increment_identifier(parent_src.base_var)
- else:
- self.base_var = "src"
- self.c_type = c_type
- self.sizeof = sizeof
- self.pointer = pointer
- assert pointer != None
-
- def get_self_ref(self):
- return self.base_var
-
- def get_ref(self, member):
- return self.base_var + "->" + member
-
- def declare(self, writer):
- if self.reuse_scope:
- scope = self.reuse_scope
- else:
- writer.begin_block()
- scope = writer.get_subwriter()
-
- scope.variable_def(self.c_type + " *", self.base_var)
- if not self.reuse_scope:
- scope.newline()
-
- writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer))
- writer.newline()
-
- if self.reuse_scope:
- return writer.no_block(self.reuse_scope)
- else:
- return writer.partial_block(scope)
-
-class SubMarshallingSource(MarshallingSource):
- def __init__(self, parent_src, containee):
- self.reuse_scope = None
- self.parent_src = parent_src
- self.base_var = parent_src.base_var
- self.containee = containee
- self.name = containee.name
- self.is_helper = False
-
- def get_self_ref(self):
- if self.containee.has_attr("to_ptr"):
- return "%s" % self.parent_src.get_ref(self.name)
- else:
- return "&%s" % self.parent_src.get_ref(self.name)
-
- def get_ref(self, member):
- if self.containee.has_attr("to_ptr"):
- return self.parent_src.get_ref(self.name) + "->" + member
- else:
- return self.parent_src.get_ref(self.name) + "." + member
-
-def write_marshal_ptr_function(writer, target_type, is_helper=True):
- if target_type.is_array():
- marshal_function = "spice_marshall_array_%s" % target_type.element_type.primitive_type()
- else:
- marshal_function = "spice_marshall_%s" % target_type.name
- if writer.is_generated("marshaller", marshal_function):
- return marshal_function
-
- writer.set_is_generated("marshaller", marshal_function)
-
- names = target_type.get_pointer_names(False)
- names_args = ""
- if len(names) > 0:
- n = [", SpiceMarshaller **%s_out" % name for name in names]
- names_args = "".join(n)
-
- header = writer.header
- if is_helper:
- writer = writer.function_helper()
- writer.header = header
- writer.out_prefix = ""
- if target_type.is_array():
- scope = writer.function(marshal_function, "SPICE_GNUC_UNUSED static void", "SpiceMarshaller *m, %s_t *ptr, unsigned count" % target_type.element_type.primitive_type() + names_args)
- else:
- scope = writer.function(marshal_function, "void", "SpiceMarshaller *m, %s *ptr" % target_type.c_type() + names_args)
- header.writeln("void " + marshal_function + "(SpiceMarshaller *m, %s *msg" % target_type.c_type() + names_args + ");")
- scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2")
-
- for n in names:
- writer.assign("*%s_out" % n, "NULL")
-
- writer.newline()
-
- if target_type.is_struct():
- src = RootMarshallingSource(None, target_type.c_type(), target_type.sizeof(), "ptr")
- src.reuse_scope = scope
- write_container_marshaller(writer, target_type, src)
- elif target_type.is_array() and target_type.element_type.is_primitive():
- with writer.index() as index:
- with writer.for_loop(index, "count") as array_scope:
- writer.statement("spice_marshaller_add_%s(m, *ptr++)" % (target_type.element_type.primitive_type()))
- else:
- writer.todo("Unsuppored pointer marshaller type")
-
- writer.end_block()
-
- return marshal_function
-
-def get_array_size(array, container_src):
- if array.is_constant_length():
- return array.size
- elif array.is_identifier_length():
- return container_src.get_ref(array.size)
- elif array.is_remaining_length():
- raise NotImplementedError("remaining size array sizes marshalling not supported")
- elif array.is_image_size_length():
- bpp = array.size[1]
- width = array.size[2]
- rows = array.size[3]
- width_v = container_src.get_ref(width)
- rows_v = container_src.get_ref(rows)
- # TODO: Handle multiplication overflow
- if bpp == 8:
- return "(unsigned) (%s * %s)" % (width_v, rows_v)
- elif bpp == 1:
- return "(unsigned) (((%s + 7) / 8 ) * %s)" % (width_v, rows_v)
- else:
- return "(unsigned) (((%s * %s + 7) / 8 ) * %s)" % (bpp, width_v, rows_v)
- elif array.is_bytes_length():
- return container_src.get_ref(array.size[2])
- else:
- raise NotImplementedError("TODO array size type not handled yet: %s" % array)
-
-def write_array_marshaller(writer, member, array, container_src, scope):
- element_type = array.element_type
-
- if array.is_remaining_length():
- writer.comment("Remaining data must be appended manually").newline()
- return
-
- nelements = get_array_size(array, container_src)
- is_byte_size = array.is_bytes_length()
-
- element = "%s__element" % member.name
-
- if not scope.variable_defined(element):
- if array.has_attr("ptr_array"):
- stars = " **"
- else:
- stars = " *"
- scope.variable_def(element_type.c_type() + stars, element)
- element_array = element
- if array.has_attr("ptr_array"):
- element = "*" + element
-
- writer.assign(element_array, container_src.get_ref(member.name))
-
- if is_byte_size:
- size_start_var = "%s__size_start" % member.name
- scope.variable_def("size_t", size_start_var)
- writer.assign(size_start_var, "spice_marshaller_get_size(m)")
-
- with writer.index() as index:
- with writer.for_loop(index, nelements) as array_scope:
- if element_type.is_primitive():
- writer.statement("spice_marshaller_add_%s(m, *%s)" % (element_type.primitive_type(), element))
- elif element_type.is_struct():
- src2 = RootMarshallingSource(container_src, element_type.c_type(), element_type.sizeof(), element)
- src2.reuse_scope = array_scope
- write_container_marshaller(writer, element_type, src2)
- else:
- writer.todo("array element unhandled type").newline()
-
- writer.statement("%s++" % element_array)
-
- if is_byte_size:
- size_var = member.container.lookup_member(array.size[1])
- size_var_type = size_var.member_type
- var = "%s__ref" % array.size[1]
- writer.statement("spice_marshaller_set_%s(m, %s, spice_marshaller_get_size(m) - %s)" % (size_var_type.primitive_type(), var, size_start_var))
-
-def write_pointer_marshaller(writer, member, src):
- t = member.member_type
- ptr_func = write_marshal_ptr_function(writer, t.target_type)
- submarshaller = "spice_marshaller_get_ptr_submarshaller(m, %d)" % (1 if member.get_fixed_nw_size() == 8 else 0)
- if member.has_attr("marshall"):
- rest_args = ""
- if t.target_type.is_array():
- rest_args = ", %s" % get_array_size(t.target_type, src)
- writer.assign("m2", submarshaller)
- if t.has_attr("nonnull"):
- writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args))
- else:
- with writer.if_block("%s != NULL" % src.get_ref(member.name)) as block:
- writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args))
- else:
- writer.assign("*%s_out" % (writer.out_prefix + member.name), submarshaller)
-
-def write_switch_marshaller(writer, container, switch, src, scope):
- var = container.lookup_member(switch.variable)
- var_type = var.member_type
-
- saved_out_prefix = writer.out_prefix
- first = True
- for c in switch.cases:
- check = c.get_check(src.get_ref(switch.variable), var_type)
- m = c.member
- writer.out_prefix = saved_out_prefix
- if m.has_attr("outvar"):
- writer.out_prefix = "%s_%s" % (m.attributes["outvar"][0], writer.out_prefix)
- with writer.if_block(check, not first, False) as block:
- t = m.member_type
- if switch.has_attr("anon"):
- if t.is_struct():
- src2 = src.child_sub(m)
- else:
- src2 = src
- else:
- if t.is_struct():
- src2 = src.child_sub(switch).child_sub(m)
- else:
- src2 = src.child_sub(switch)
- src2.reuse_scope = block
-
- if t.is_struct():
- write_container_marshaller(writer, t, src2)
- elif t.is_pointer():
- write_pointer_marshaller(writer, m, src2)
- elif t.is_primitive():
- if m.has_attr("zero"):
- writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type()))
- else:
- writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src2.get_ref(m.name)))
- #TODO validate e.g. flags and enums
- elif t.is_array():
- write_array_marshaller(writer, m, t, src2, scope)
- else:
- writer.todo("Can't handle type %s" % m.member_type)
-
- if switch.has_attr("fixedsize"):
- remaining = switch.get_fixed_nw_size() - t.get_fixed_nw_size()
- if remaining != 0:
- writer.statement("spice_marshaller_reserve_space(m, %s)" % remaining)
-
- first = False
- if switch.has_attr("fixedsize"):
- with writer.block(" else"):
- writer.statement("spice_marshaller_reserve_space(m, %s)" % switch.get_fixed_nw_size())
-
- writer.newline()
-
-def write_member_marshaller(writer, container, member, src, scope):
- if member.has_attr("outvar"):
- writer.out_prefix = "%s_%s" % (member.attributes["outvar"][0], writer.out_prefix)
- if member.has_attr("virtual"):
- writer.comment("Don't marshall @virtual %s" % member.name).newline()
- return
- if member.has_attr("nomarshal"):
- writer.comment("Don't marshall @nomarshal %s" % member.name).newline()
- return
- if member.is_switch():
- write_switch_marshaller(writer, container, member, src, scope)
- return
-
- t = member.member_type
-
- if t.is_pointer():
- write_pointer_marshaller(writer, member, src)
- elif t.is_primitive():
- if member.has_attr("zero"):
- writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type()))
- if member.has_attr("bytes_count"):
- var = "%s__ref" % member.name
- scope.variable_def("void *", var)
- writer.statement("%s = spice_marshaller_add_%s(m, %s)" % (var, t.primitive_type(), 0))
-
- else:
- writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src.get_ref(member.name)))
- elif t.is_array():
- write_array_marshaller(writer, member, t, src, scope)
- elif t.is_struct():
- src2 = src.child_sub(member)
- writer.comment(member.name)
- write_container_marshaller(writer, t, src2)
- else:
- raise NotImplementedError("TODO can't handle parsing of %s" % t)
-
-def write_container_marshaller(writer, container, src):
- saved_out_prefix = writer.out_prefix
- with src.declare(writer) as scope:
- for m in container.members:
- writer.out_prefix = saved_out_prefix
- write_member_marshaller(writer, container, m, src, scope)
-
-def write_message_marshaller(writer, message, is_server, private):
- if message.has_attr("ifdef"):
- writer.ifdef(message.attributes["ifdef"][0])
- writer.out_prefix = ""
- function_name = "spice_marshall_" + message.c_name()
- if writer.is_generated("marshaller", function_name):
- return function_name
- writer.set_is_generated("marshaller", function_name)
-
- names = message.get_pointer_names(False)
- names_args = ""
- if len(names) > 0:
- n = [", SpiceMarshaller **%s_out" % name for name in names]
- names_args = "".join(n)
-
- if not private:
- writer.header.writeln("void " + function_name + "(SpiceMarshaller *m, %s *msg" % message.c_type() + names_args + ");")
-
- scope = writer.function(function_name,
- "static void" if private else "void",
- "SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED %s *msg" % message.c_type() + names_args)
- scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2")
-
- for n in names:
- writer.assign("*%s_out" % n, "NULL")
-
- # fix warnings about unused variables by not creating body if no members to parse
- if any(x.is_fixed_nw_size() for x in message.members):
- src = RootMarshallingSource(None, message.c_type(), message.sizeof(), "msg")
- src.reuse_scope = scope
-
- write_container_marshaller(writer, message, src)
-
- writer.end_block()
- if message.has_attr("ifdef"):
- writer.endif(message.attributes["ifdef"][0])
- writer.newline()
- return function_name
-
-def write_protocol_marshaller(writer, proto, is_server, private_marshallers):
- functions = {}
- for c in proto.channels:
- channel = c.channel_type
- if channel.has_attr("ifdef"):
- writer.ifdef(channel.attributes["ifdef"][0])
- writer.header.ifdef(channel.attributes["ifdef"][0])
- if is_server:
- messages = channel.client_messages
- else:
- messages = channel.server_messages
- for m in messages:
- message = m.message_type
- f = write_message_marshaller(writer, message, is_server, private_marshallers)
- if channel.has_attr("ifdef") and f not in functions:
- functions[f] = channel.attributes["ifdef"][0]
- elif message.has_attr("ifdef") and f not in functions:
- functions[f] = message.attributes["ifdef"][0]
- else:
- functions[f] = True
- if channel.has_attr("ifdef"):
- writer.endif(channel.attributes["ifdef"][0])
- writer.header.endif(channel.attributes["ifdef"][0])
-
- if private_marshallers:
- scope = writer.function("spice_message_marshallers_get" + writer.public_prefix,
- "SpiceMessageMarshallers *",
- "void")
- writer.writeln("static SpiceMessageMarshallers marshallers = {NULL};").newline()
- for f in sorted(functions.keys()):
- member = f[len("spice_marshall_"):]
- if not member.startswith("msg"):
- member = "msg_" + member
- if functions[f] != True:
- writer.ifdef(functions[f])
- writer.assign("marshallers.%s" % member, f)
- if functions[f] != True:
- writer.endif(functions[f])
-
- writer.newline()
- writer.statement("return &marshallers")
- writer.end_block()
- writer.newline()
-
-def write_trailer(writer):
- writer.header.writeln("#endif")
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
deleted file mode 100644
index 753d363..0000000
--- a/python_modules/ptypes.py
+++ /dev/null
@@ -1,1138 +0,0 @@
-from . import codegen
-import types
-
-_types_by_name = {}
-_types = []
-
-default_pointer_size = 4
-
-def type_exists(name):
- return name in _types_by_name
-
-def lookup_type(name):
- return _types_by_name[name]
-
-def get_named_types():
- return _types
-
-class FixedSize:
- def __init__(self, val = 0, minor = 0):
- if isinstance(val, FixedSize):
- self.vals = val.vals
- else:
- self.vals = [0] * (minor + 1)
- self.vals[minor] = val
-
- def __add__(self, other):
- if isinstance(other, int):
- other = FixedSize(other)
-
- new = FixedSize()
- l = max(len(self.vals), len(other.vals))
- shared = min(len(self.vals), len(other.vals))
-
- new.vals = [0] * l
-
- for i in range(shared):
- new.vals[i] = self.vals[i] + other.vals[i]
-
- for i in range(shared,len(self.vals)):
- new.vals[i] = self.vals[i]
-
- for i in range(shared,len(other.vals)):
- new.vals[i] = new.vals[i] + other.vals[i]
-
- return new
-
- def __radd__(self, other):
- return self.__add__(other)
-
- def __str__(self):
- s = "%d" % (self.vals[0])
-
- for i in range(1,len(self.vals)):
- if self.vals[i] > 0:
- s = s + " + ((minor >= %d)?%d:0)" % (i, self.vals[i])
- return s
-
-# Some attribute are propagated from member to the type as they really
-# are part of the type definition, rather than the member. This applies
-# only to attributes that affect pointer or array attributes, as these
-# are member local types, unlike e.g. a Struct that may be used by
-# other members
-propagated_attributes=["ptr_array", "nonnull", "chunk"]
-
-valid_attributes=set([
- # embedded/appended at the end of the structure
- 'end',
- # the C structure contains a pointer to data
- # for instance we want to write an array to an allocated array
- 'to_ptr',
- # write output to this C structure
- 'ctype',
- # prefix for flags/values enumerations
- 'prefix',
- # used in demarshaller to use directly data from message without a copy
- 'nocopy',
- # store member array in a pointer
- # similar to to_ptr but has an additional argument which is the name of a C
- # field which will store the array length
- 'as_ptr',
- # do not generate marshall code
- # used for last members to be able to marshall them manually
- 'nomarshal',
- # ??? not used by python code
- 'zero_terminated',
- 'marshall',
- # this pointer member cannot be null
- 'nonnull',
- # this flag member contains only a single flag
- 'unique_flag',
- 'ptr_array',
- 'outvar',
- # C structure has an anonymous member (used in switch)
- 'anon',
- 'chunk',
- # this channel is contained in an #ifdef section
- # the argument specifies the preprocessor define to check
- 'ifdef',
- # write this member as zero on network
- 'zero',
- # specify minor version required for these members
- 'minor',
- # this member contains the byte count for an array.
- # the argument is the member name for item count (not bytes)
- 'bytes_count',
- # this attribute does not exist on the network, fill just structure with the value
- 'virtual',
- # for a switch this indicates that on network
- # it will occupy always the same size (maximum size required for all members)
- 'fixedsize',
-])
-
-attributes_with_arguments=set([
- 'ctype',
- 'prefix',
- 'as_ptr',
- 'outvar',
- 'ifdef',
- 'minor',
- 'bytes_count',
- 'virtual',
-])
-
-def fix_attributes(attribute_list):
- attrs = {}
- for attr in attribute_list:
- name = attr[0][1:]
- lst = attr[1:]
- if not name in valid_attributes:
- raise Exception("Attribute %s not recognized" % name)
- if not name in attributes_with_arguments:
- if len(lst) > 0:
- raise Exception("Attribute %s specified with options" % name)
- elif len(lst) > 1:
- raise Exception("Attribute %s has more than 1 argument" % name)
- attrs[name] = lst
- return attrs
-
-class Type:
- def __init__(self):
- self.attributes = {}
- self.registred = False
- self.name = None
-
- def has_name(self):
- return self.name != None
-
- def get_type(self, recursive=False):
- return self
-
- def is_primitive(self):
- return False
-
- def is_fixed_sizeof(self):
- return True
-
- def is_extra_size(self):
- return False
-
- def contains_extra_size(self):
- return False
-
- def is_fixed_nw_size(self):
- return True
-
- def is_array(self):
- return isinstance(self, ArrayType)
-
- def contains_member(self, member):
- return False
-
- def is_struct(self):
- return isinstance(self, StructType)
-
- def is_pointer(self):
- return isinstance(self, PointerType)
-
- def get_num_pointers(self):
- return 0
-
- def get_pointer_names(self, marshalled):
- return []
-
- def sizeof(self):
- return "sizeof(%s)" % (self.c_type())
-
- def __repr__(self):
- return self.__str__()
-
- def __str__(self):
- if self.name != None:
- return self.name
- return "anonymous type"
-
- def resolve(self):
- return self
-
- def register(self):
- if self.registred or self.name == None:
- return
- self.registred = True
- if self.name in _types_by_name:
- raise Exception("Type %s already defined" % self.name)
- _types.append(self)
- _types_by_name[self.name] = self
-
- def has_attr(self, name):
- if not name in valid_attributes:
- raise Exception('attribute %s not expected' % name)
- return name in self.attributes
-
-class TypeRef(Type):
- def __init__(self, name):
- Type.__init__(self)
- self.name = name
-
- def __str__(self):
- return "ref to %s" % (self.name)
-
- def resolve(self):
- if self.name not in _types_by_name:
- raise Exception("Unknown type %s" % self.name)
- return _types_by_name[self.name]
-
- def register(self):
- assert True, "Can't register TypeRef!"
-
-
-class IntegerType(Type):
- def __init__(self, bits, signed):
- Type.__init__(self)
- self.bits = bits
- self.signed = signed
-
- if signed:
- self.name = "int%d" % bits
- else:
- self.name = "uint%d" % bits
-
- def primitive_type(self):
- return self.name
-
- def c_type(self):
- return self.name + "_t"
-
- def get_fixed_nw_size(self):
- return self.bits // 8
-
- def is_primitive(self):
- return True
-
-class TypeAlias(Type):
- def __init__(self, name, the_type, attribute_list):
- Type.__init__(self)
- self.name = name
- self.the_type = the_type
- self.attributes = fix_attributes(attribute_list)
-
- def get_type(self, recursive=False):
- if recursive:
- return self.the_type.get_type(True)
- else:
- return self.the_type
-
- def primitive_type(self):
- return self.the_type.primitive_type()
-
- def resolve(self):
- self.the_type = self.the_type.resolve()
- return self
-
- def __str__(self):
- return "alias %s" % self.name
-
- def is_primitive(self):
- return self.the_type.is_primitive()
-
- def is_fixed_sizeof(self):
- return self.the_type.is_fixed_sizeof()
-
- def is_fixed_nw_size(self):
- return self.the_type.is_fixed_nw_size()
-
- def get_fixed_nw_size(self):
- return self.the_type.get_fixed_nw_size()
-
- def get_num_pointers(self):
- return self.the_type.get_num_pointers()
-
- def get_pointer_names(self, marshalled):
- return self.the_type.get_pointer_names(marshalled)
-
- def c_type(self):
- if self.has_attr("ctype"):
- return self.attributes["ctype"][0]
- return self.name
-
-class EnumBaseType(Type):
- def is_enum(self):
- return isinstance(self, EnumType)
-
- def primitive_type(self):
- return "uint%d" % (self.bits)
-
- def c_type(self):
- return "uint%d_t" % (self.bits)
-
- def c_name(self):
- return codegen.prefix_camel(self.name)
-
- def c_enumname(self, value):
- return self.c_enumname_by_name(self.names[value])
-
- def c_enumname_by_name(self, name):
- if self.has_attr("prefix"):
- return self.attributes["prefix"][0] + name
- return codegen.prefix_underscore_upper(self.name.upper(), name)
-
- def is_primitive(self):
- return True
-
- def get_fixed_nw_size(self):
- return self.bits // 8
-
- # generates a value-name table suitable for use with the wireshark protocol
- # dissector
- def c_describe(self, writer):
- writer.write("static const value_string %s_vs[] = " % codegen.prefix_underscore_lower(self.name))
- writer.begin_block()
- values = list(self.names.keys())
- values.sort()
- for i in values:
- writer.write("{ ")
- writer.write(self.c_enumname(i))
- writer.write(", \"%s\" }," % self.names[i])
- writer.newline()
- writer.write("{ 0, NULL }")
- writer.end_block(semicolon=True)
- writer.newline()
-
-
-class EnumType(EnumBaseType):
- def __init__(self, bits, name, enums, attribute_list):
- Type.__init__(self)
- self.bits = bits
- self.name = name
-
- last = -1
- names = {}
- values = {}
- for v in enums:
- name = v[0]
- if len(v) > 1:
- value = v[1]
- else:
- value = last + 1
- last = value
-
- assert value not in names
- names[value] = name
- values[name] = value
-
- self.names = names
- self.values = values
-
- self.attributes = fix_attributes(attribute_list)
-
- def __str__(self):
- return "enum %s" % self.name
-
- def c_define(self, writer):
- writer.write("typedef enum ")
- writer.write(self.c_name())
- writer.begin_block()
- values = list(self.names.keys())
- values.sort()
- current_default = 0
- for i in values:
- writer.write(self.c_enumname(i))
- if i != current_default:
- writer.write(" = %d" % (i))
- writer.write(",")
- writer.newline()
- current_default = i + 1
- writer.newline()
- writer.write(codegen.prefix_underscore_upper(self.name.upper(), "ENUM_END"))
- writer.newline()
- writer.end_block(newline=False)
- writer.write(" ")
- writer.write(self.c_name())
- writer.write(";")
- writer.newline()
- writer.newline()
-
-class FlagsType(EnumBaseType):
- def __init__(self, bits, name, flags, attribute_list):
- Type.__init__(self)
- self.bits = bits
- self.name = name
-
- last = -1
- names = {}
- values = {}
- for v in flags:
- name = v[0]
- if len(v) > 1:
- value = v[1]
- else:
- value = last + 1
- last = value
-
- assert value not in names
- names[value] = name
- values[name] = value
-
- self.names = names
- self.values = values
-
- self.attributes = fix_attributes(attribute_list)
-
- def __str__(self):
- return "flags %s" % self.name
-
- def c_define(self, writer):
- writer.write("typedef enum ")
- writer.write(self.c_name())
- writer.begin_block()
- values = list(self.names.keys())
- values.sort()
- mask = 0
- for i in values:
- writer.write(self.c_enumname(i))
- mask = mask | (1<<i)
- writer.write(" = (1 << %d)" % (i))
- writer.write(",")
- writer.newline()
- current_default = i + 1
- writer.newline()
- writer.write(codegen.prefix_underscore_upper(self.name.upper(), "MASK"))
- writer.write(" = 0x%x" % (mask))
- writer.newline()
- writer.end_block(newline=False)
- writer.write(" ")
- writer.write(self.c_name())
- writer.write(";")
- writer.newline()
- writer.newline()
-
-class ArrayType(Type):
- def __init__(self, element_type, size):
- Type.__init__(self)
- self.name = None
-
- self.element_type = element_type
- self.size = size
-
- def __str__(self):
- if self.size == None:
- return "%s[]" % (str(self.element_type))
- else:
- return "%s[%s]" % (str(self.element_type), str(self.size))
-
- def resolve(self):
- self.element_type = self.element_type.resolve()
- return self
-
- def is_constant_length(self):
- return isinstance(self.size, int)
-
- def is_remaining_length(self):
- return isinstance(self.size, str) and len(self.size) == 0
-
- def is_identifier_length(self):
- return isinstance(self.size, str) and len(self.size) > 0
-
- def is_image_size_length(self):
- if isinstance(self.size, int) or isinstance(self.size, str):
- return False
- return self.size[0] == "image_size"
-
- def is_bytes_length(self):
- if isinstance(self.size, int) or isinstance(self.size, str):
- return False
- return self.size[0] == "bytes"
-
- def is_cstring_length(self):
- if isinstance(self.size, int) or isinstance(self.size, str):
- return False
- return self.size[0] == "cstring"
-
- def is_fixed_sizeof(self):
- return self.is_constant_length() and self.element_type.is_fixed_sizeof()
-
- def is_fixed_nw_size(self):
- return self.is_constant_length() and self.element_type.is_fixed_nw_size()
-
- def get_fixed_nw_size(self):
- if not self.is_fixed_nw_size():
- raise Exception("Not a fixed size type")
-
- return self.element_type.get_fixed_nw_size() * self.size
-
- def get_num_pointers(self):
- element_count = self.element_type.get_num_pointers()
- if element_count == 0:
- return 0
- if self.is_constant_length(self):
- return element_count * self.size
- raise Exception("Pointers in dynamic arrays not supported")
-
- def get_pointer_names(self, marshalled):
- element_count = self.element_type.get_num_pointers()
- if element_count == 0:
- return []
- raise Exception("Pointer names in arrays not supported")
-
- def is_extra_size(self):
- return self.has_attr("ptr_array")
-
- def contains_extra_size(self):
- return self.element_type.contains_extra_size() or self.has_attr("chunk")
-
- def sizeof(self):
- return "%s * %s" % (self.element_type.sizeof(), self.size)
-
- def c_type(self):
- return self.element_type.c_type()
-
-class PointerType(Type):
- def __init__(self, target_type):
- Type.__init__(self)
- self.name = None
- self.target_type = target_type
- self.pointer_size = default_pointer_size
-
- def __str__(self):
- return "%s*" % (str(self.target_type))
-
- def resolve(self):
- self.target_type = self.target_type.resolve()
- return self
-
- def set_ptr_size(self, new_size):
- self.pointer_size = new_size
-
- def is_fixed_nw_size(self):
- return True
-
- def is_primitive(self):
- return True
-
- def primitive_type(self):
- if self.pointer_size == 4:
- return "uint32"
- else:
- return "uint64"
-
- def get_fixed_nw_size(self):
- return self.pointer_size
-
- def c_type(self):
- if self.pointer_size == 4:
- return "uint32_t"
- else:
- return "uint64_t"
-
- def contains_extra_size(self):
- return True
-
- def get_num_pointers(self):
- return 1
-
-class Containee:
- def __init__(self):
- self.attributes = {}
-
- def is_switch(self):
- return False
-
- def is_pointer(self):
- return not self.is_switch() and self.member_type.is_pointer()
-
- def is_array(self):
- return not self.is_switch() and self.member_type.is_array()
-
- def is_struct(self):
- return not self.is_switch() and self.member_type.is_struct()
-
- def is_primitive(self):
- return not self.is_switch() and self.member_type.is_primitive()
-
- def has_attr(self, name):
- if not name in valid_attributes:
- raise Exception('attribute %s not expected' % name)
- return name in self.attributes
-
- def has_minor_attr(self):
- return self.has_attr("minor")
-
- def has_end_attr(self):
- return self.has_attr("end")
-
- def get_minor_attr(self):
- return self.attributes["minor"][0]
-
-class Member(Containee):
- def __init__(self, name, member_type, attribute_list):
- Containee.__init__(self)
- self.name = name
- self.member_type = member_type
- self.attributes = fix_attributes(attribute_list)
-
- def resolve(self, container):
- self.container = container
- self.member_type = self.member_type.resolve()
- self.member_type.register()
- for i in propagated_attributes:
- if self.has_attr(i):
- self.member_type.attributes[i] = self.attributes[i]
- return self
-
- def contains_member(self, member):
- return self.member_type.contains_member(member)
-
- def is_primitive(self):
- return self.member_type.is_primitive()
-
- def is_fixed_sizeof(self):
- if self.has_end_attr():
- return False
- return self.member_type.is_fixed_sizeof()
-
- def is_extra_size(self):
- return self.has_end_attr() or self.has_attr("to_ptr") or self.member_type.is_extra_size()
-
- def is_fixed_nw_size(self):
- if self.has_attr("virtual"):
- return True
- return self.member_type.is_fixed_nw_size()
-
- def get_fixed_nw_size(self):
- if self.has_attr("virtual"):
- return 0
- size = self.member_type.get_fixed_nw_size()
- if self.has_minor_attr():
- minor = self.get_minor_attr()
- size = FixedSize(size, minor)
- return size
-
- def contains_extra_size(self):
- return self.member_type.contains_extra_size()
-
- def sizeof(self):
- return self.member_type.sizeof()
-
- def __repr__(self):
- return "%s (%s)" % (str(self.name), str(self.member_type))
-
- def get_num_pointers(self):
- if self.has_attr("to_ptr"):
- return 1
- return self.member_type.get_num_pointers()
-
- def get_pointer_names(self, marshalled):
- if self.member_type.is_pointer():
- if self.has_attr("marshall") == marshalled:
- names = [self.name]
- else:
- names = []
- else:
- names = self.member_type.get_pointer_names(marshalled)
- if self.has_attr("outvar"):
- prefix = self.attributes["outvar"][0]
- names = [prefix + "_" + name for name in names]
- return names
-
-class SwitchCase:
- def __init__(self, values, member):
- self.values = values
- self.member = member
- self.members = [member]
-
- def get_check(self, var_cname, var_type):
- checks = []
- for v in self.values:
- if v == None:
- return "1"
- elif var_type.is_enum():
- checks.append("%s == %s" % (var_cname, var_type.c_enumname_by_name(v[1])))
- else:
- checks.append("%s(%s & %s)" % (v[0], var_cname, var_type.c_enumname_by_name(v[1])))
- return " || ".join(checks)
-
- def resolve(self, container):
- self.switch = container
- self.member = self.member.resolve(self)
- return self
-
- def get_num_pointers(self):
- return self.member.get_num_pointers()
-
- def get_pointer_names(self, marshalled):
- return self.member.get_pointer_names(marshalled)
-
-class Switch(Containee):
- def __init__(self, variable, cases, name, attribute_list):
- Containee.__init__(self)
- self.variable = variable
- self.name = name
- self.cases = cases
- self.attributes = fix_attributes(attribute_list)
-
- def is_switch(self):
- return True
-
- def lookup_case_member(self, name):
- for c in self.cases:
- if c.member.name == name:
- return c.member
- return None
-
- def has_switch_member(self, member):
- for c in self.cases:
- if c.member == member:
- return True
- return False
-
- def resolve(self, container):
- self.container = container
- self.cases = [c.resolve(self) for c in self.cases]
- return self
-
- def __repr__(self):
- return "switch on %s %s" % (str(self.variable),str(self.name))
-
- def is_fixed_sizeof(self):
- # Kinda weird, but we're unlikely to have a real struct if there is an @end
- if self.has_end_attr():
- return False
- return True
-
- def is_fixed_nw_size(self):
- if self.has_attr("fixedsize"):
- return True
-
- size = None
- has_default = False
- for c in self.cases:
- for v in c.values:
- if v == None:
- has_default = True
- if not c.member.is_fixed_nw_size():
- return False
- if size == None:
- size = c.member.get_fixed_nw_size()
- elif size != c.member.get_fixed_nw_size():
- return False
- # Fixed size if all elements listed, or has default
- if has_default:
- return True
- key = self.container.lookup_member(self.variable)
- return len(self.cases) == len(key.member_type.values)
-
- def is_extra_size(self):
- return self.has_end_attr()
-
- def contains_extra_size(self):
- for c in self.cases:
- if c.member.is_extra_size():
- return True
- if c.member.contains_extra_size():
- return True
- return False
-
- def get_fixed_nw_size(self):
- if not self.is_fixed_nw_size():
- raise Exception("Not a fixed size type")
- size = 0
- for c in self.cases:
- size = max(size, c.member.get_fixed_nw_size())
- return size
-
- def sizeof(self):
- return "sizeof(((%s *)NULL)->%s)" % (self.container.c_type(),
- self.name)
-
- def contains_member(self, member):
- return False # TODO: Don't support switch deep member lookup yet
-
- def get_num_pointers(self):
- count = 0
- for c in self.cases:
- count = max(count, c.get_num_pointers())
- return count
-
- def get_pointer_names(self, marshalled):
- names = []
- for c in self.cases:
- names = names + c.get_pointer_names(marshalled)
- return names
-
-class ContainerType(Type):
- def is_fixed_sizeof(self):
- for m in self.members:
- if not m.is_fixed_sizeof():
- return False
- return True
-
- def contains_extra_size(self):
- for m in self.members:
- if m.is_extra_size():
- return True
- if m.contains_extra_size():
- return True
- return False
-
- def is_fixed_nw_size(self):
- for i in self.members:
- if not i.is_fixed_nw_size():
- return False
- return True
-
- def get_fixed_nw_size(self):
- size = 0
- for i in self.members:
- size = size + i.get_fixed_nw_size()
- return size
-
- def contains_member(self, member):
- for m in self.members:
- if m == member or m.contains_member(member):
- return True
- return False
-
- def get_fixed_nw_offset(self, member):
- size = 0
- for i in self.members:
- if i == member:
- break
- if i.contains_member(member):
- size = size + i.member_type.get_fixed_nw_offset(member)
- break
- if i.is_fixed_nw_size():
- size = size + i.get_fixed_nw_size()
- return size
-
- def resolve(self):
- self.members = [m.resolve(self) for m in self.members]
- return self
-
- def get_num_pointers(self):
- count = 0
- for m in self.members:
- count = count + m.get_num_pointers()
- return count
-
- def get_pointer_names(self, marshalled):
- names = []
- for m in self.members:
- names = names + m.get_pointer_names(marshalled)
- return names
-
- def get_nw_offset(self, member, prefix = "", postfix = ""):
- fixed = self.get_fixed_nw_offset(member)
- v = []
- container = self
- while container != None:
- members = container.members
- container = None
- for m in members:
- if m == member:
- break
- if m.contains_member(member):
- container = m.member_type
- break
- if m.is_switch() and m.has_switch_member(member):
- break
- if not m.is_fixed_nw_size():
- v.append(prefix + m.name + postfix)
- if len(v) > 0:
- return str(fixed) + " + " + (" + ".join(v))
- else:
- return str(fixed)
-
- def lookup_member(self, name):
- dot = name.find('.')
- rest = None
- if dot >= 0:
- rest = name[dot+1:]
- name = name[:dot]
-
- member = None
- if name in self.members_by_name:
- member = self.members_by_name[name]
- else:
- for m in self.members:
- if m.is_switch():
- member = m.lookup_case_member(name)
- if member != None:
- break
- if member != None:
- break
-
- if member == None:
- raise Exception("No member called %s found" % name)
-
- if rest != None:
- return member.member_type.lookup_member(rest)
-
- return member
-
-class StructType(ContainerType):
- def __init__(self, name, members, attribute_list):
- Type.__init__(self)
- self.name = name
- self.members = members
- self.members_by_name = {}
- for m in members:
- self.members_by_name[m.name] = m
- self.attributes = fix_attributes(attribute_list)
-
- def __str__(self):
- if self.name == None:
- return "anonymous struct"
- else:
- return "struct %s" % self.name
-
- def c_type(self):
- if self.has_attr("ctype"):
- return self.attributes["ctype"][0]
- return codegen.prefix_camel(self.name)
-
-class MessageType(ContainerType):
- def __init__(self, name, members, attribute_list):
- Type.__init__(self)
- self.name = name
- self.members = members
- self.members_by_name = {}
- for m in members:
- self.members_by_name[m.name] = m
- self.reverse_members = {} # ChannelMembers referencing this message
- self.attributes = fix_attributes(attribute_list)
-
- def __str__(self):
- if self.name == None:
- return "anonymous message"
- else:
- return "message %s" % self.name
-
- def c_name(self):
- if self.name == None:
- cms = list(self.reverse_members.keys())
- if len(cms) != 1:
- raise "Unknown typename for message"
- cm = cms[0]
- channelname = cm.channel.member_name
- if channelname == None:
- channelname = ""
- else:
- channelname = channelname + "_"
- if cm.is_server:
- return "msg_" + channelname + cm.name
- else:
- return "msgc_" + channelname + cm.name
- else:
- return codegen.prefix_camel("Msg", self.name)
-
- def c_type(self):
- if self.has_attr("ctype"):
- return self.attributes["ctype"][0]
- if self.name == None:
- cms = list(self.reverse_members.keys())
- if len(cms) != 1:
- raise "Unknown typename for message"
- cm = cms[0]
- channelname = cm.channel.member_name
- if channelname == None:
- channelname = ""
- if cm.is_server:
- return codegen.prefix_camel("Msg", channelname, cm.name)
- else:
- return codegen.prefix_camel("Msgc", channelname, cm.name)
- else:
- return codegen.prefix_camel("Msg", self.name)
-
-class ChannelMember(Containee):
- def __init__(self, name, message_type, value):
- Containee.__init__(self)
- self.name = name
- self.message_type = message_type
- self.value = value
-
- def resolve(self, channel):
- self.channel = channel
- self.message_type = self.message_type.resolve()
- self.message_type.reverse_members[self] = 1
-
- return self
-
- def __repr__(self):
- return "%s (%s)" % (str(self.name), str(self.message_type))
-
-class ChannelType(Type):
- def __init__(self, name, base, members, attribute_list):
- Type.__init__(self)
- self.name = name
- self.base = base
- self.member_name = None
- self.members = members
- self.attributes = fix_attributes(attribute_list)
-
- def __str__(self):
- if self.name == None:
- return "anonymous channel"
- else:
- return "channel %s" % self.name
-
- def is_fixed_nw_size(self):
- return False
-
- def get_client_message(self, name):
- return self.client_messages_byname[name]
-
- def get_server_message(self, name):
- return self.server_messages_byname[name]
-
- def resolve(self):
- if self.base != None:
- self.base = self.base.resolve()
-
- server_messages = self.base.server_messages[:]
- server_messages_byname = self.base.server_messages_byname.copy()
- client_messages = self.base.client_messages[:]
- client_messages_byname = self.base.client_messages_byname.copy()
-
- # Set default member_name, FooChannel -> foo
- self.member_name = self.name[:-7].lower()
- else:
- server_messages = []
- server_messages_byname = {}
- client_messages = []
- client_messages_byname = {}
-
- server_count = 1
- client_count = 1
-
- server = True
- for m in self.members:
- if m == "server":
- server = True
- elif m == "client":
- server = False
- elif server:
- m.is_server = True
- m = m.resolve(self)
- if m.value:
- server_count = m.value + 1
- else:
- m.value = server_count
- server_count = server_count + 1
- server_messages.append(m)
- server_messages_byname[m.name] = m
- else:
- m.is_server = False
- m = m.resolve(self)
- if m.value:
- client_count = m.value + 1
- else:
- m.value = client_count
- client_count = client_count + 1
- client_messages.append(m)
- client_messages_byname[m.name] = m
-
- self.server_messages = server_messages
- self.server_messages_byname = server_messages_byname
- self.client_messages = client_messages
- self.client_messages_byname = client_messages_byname
-
- return self
-
-class ProtocolMember:
- def __init__(self, name, channel_type, value):
- self.name = name
- self.channel_type = channel_type
- self.value = value
-
- def resolve(self, protocol):
- self.channel_type = self.channel_type.resolve()
- self.channel_type.member_name = self.name
- return self
-
- def __repr__(self):
- return "%s (%s)" % (str(self.name), str(self.channel_type))
-
-class ProtocolType(Type):
- def __init__(self, name, channels):
- Type.__init__(self)
- self.name = name
- self.channels = channels
-
- def __str__(self):
- if self.name == None:
- return "anonymous protocol"
- else:
- return "protocol %s" % self.name
-
- def is_fixed_nw_size(self):
- return False
-
- def resolve(self):
- count = 1
- for m in self.channels:
- m = m.resolve(self)
- if m.value:
- count = m.value + 1
- else:
- m.value = count
- count = count + 1
-
- return self
-
-class FdType(IntegerType):
- def __init__(self):
- IntegerType.__init__(self, 0, False)
- self.name = "fd"
-
- def c_type(self):
- return "int"
-
-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)
-unix_fd = FdType()
diff --git a/python_modules/spice_parser.py b/python_modules/spice_parser.py
deleted file mode 100644
index db3cc8d..0000000
--- a/python_modules/spice_parser.py
+++ /dev/null
@@ -1,163 +0,0 @@
-import six
-
-try:
- from pyparsing import Literal, CaselessLiteral, Word, OneOrMore, ZeroOrMore, \
- Forward, delimitedList, Group, Optional, Combine, alphas, nums, restOfLine, cStyleComment, \
- alphanums, ParseException, ParseResults, Keyword, StringEnd, replaceWith
-except ImportError:
- six.print_("Module pyparsing not found.")
- exit(1)
-
-
-from . import ptypes
-import sys
-
-cvtInt = lambda toks: int(toks[0])
-
-def parseVariableDef(toks):
- t = toks[0][0]
- pointer = toks[0][1]
- name = toks[0][2]
- array_size = toks[0][3]
- attributes = toks[0][4]
-
- if array_size != None:
- t = ptypes.ArrayType(t, array_size)
-
- if pointer != None:
- t = ptypes.PointerType(t)
-
- return ptypes.Member(name, t, attributes)
-
-bnf = None
-def SPICE_BNF():
- global bnf
-
- if not bnf:
-
- # punctuation
- colon = Literal(":").suppress()
- lbrace = Literal("{").suppress()
- rbrace = Literal("}").suppress()
- lbrack = Literal("[").suppress()
- rbrack = Literal("]").suppress()
- lparen = Literal("(").suppress()
- rparen = Literal(")").suppress()
- equals = Literal("=").suppress()
- comma = Literal(",").suppress()
- semi = Literal(";").suppress()
-
- # primitive types
- int8_ = Keyword("int8").setParseAction(replaceWith(ptypes.int8))
- uint8_ = Keyword("uint8").setParseAction(replaceWith(ptypes.uint8))
- int16_ = Keyword("int16").setParseAction(replaceWith(ptypes.int16))
- uint16_ = Keyword("uint16").setParseAction(replaceWith(ptypes.uint16))
- int32_ = Keyword("int32").setParseAction(replaceWith(ptypes.int32))
- uint32_ = Keyword("uint32").setParseAction(replaceWith(ptypes.uint32))
- int64_ = Keyword("int64").setParseAction(replaceWith(ptypes.int64))
- uint64_ = Keyword("uint64").setParseAction(replaceWith(ptypes.uint64))
- unix_fd_ = Keyword("unix_fd").setParseAction(replaceWith(ptypes.unix_fd))
-
- # keywords
- enum32_ = Keyword("enum32").setParseAction(replaceWith(32))
- enum16_ = Keyword("enum16").setParseAction(replaceWith(16))
- enum8_ = Keyword("enum8").setParseAction(replaceWith(8))
- flags32_ = Keyword("flags32").setParseAction(replaceWith(32))
- flags16_ = Keyword("flags16").setParseAction(replaceWith(16))
- flags8_ = Keyword("flags8").setParseAction(replaceWith(8))
- channel_ = Keyword("channel")
- server_ = Keyword("server")
- client_ = Keyword("client")
- protocol_ = Keyword("protocol")
- typedef_ = Keyword("typedef")
- struct_ = Keyword("struct")
- message_ = Keyword("message")
- image_size_ = Keyword("image_size")
- bytes_ = Keyword("bytes")
- cstring_ = Keyword("cstring")
- switch_ = Keyword("switch")
- default_ = Keyword("default")
- case_ = Keyword("case")
-
- identifier = Word( alphas, alphanums + "_" )
- enumname = Word( alphanums + "_" )
-
- integer = ( Combine( CaselessLiteral("0x") + Word( nums+"abcdefABCDEF" ) ) |
- Word( nums+"+-", nums ) ).setName("int").setParseAction(cvtInt)
-
- typename = identifier.copy().setParseAction(lambda toks : ptypes.TypeRef(str(toks[0])))
-
- # This is just normal "types", i.e. not channels or messages
- typeSpec = Forward()
-
- attributeValue = integer ^ identifier
- attribute = Group(Combine ("@" + identifier) + Optional(lparen + delimitedList(attributeValue) + rparen))
- attributes = Group(ZeroOrMore(attribute))
- arraySizeSpecImage = Group(image_size_ + lparen + integer + comma + identifier + comma + identifier + rparen)
- arraySizeSpecBytes = Group(bytes_ + lparen + identifier + comma + identifier + rparen)
- arraySizeSpecCString = Group(cstring_ + lparen + rparen)
- arraySizeSpec = lbrack + Optional(identifier ^ integer ^ arraySizeSpecImage ^ arraySizeSpecBytes ^arraySizeSpecCString, default="") + rbrack
- variableDef = Group(typeSpec + Optional("*", default=None) + identifier + Optional(arraySizeSpec, default=None) + attributes - semi) \
- .setParseAction(parseVariableDef)
-
- switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | Group(case_.suppress() + Optional("!", default="") + identifier) + colon)) + variableDef) \
- .setParseAction(lambda toks: ptypes.SwitchCase(toks[0][0], toks[0][1]))
- switchBody = Group(switch_ + lparen + delimitedList(identifier,delim='.', combine=True) + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \
- .setParseAction(lambda toks: ptypes.Switch(toks[0][1], toks[0][2], toks[0][3], toks[0][4]))
- messageBody = structBody = Group(lbrace + ZeroOrMore(variableDef | switchBody) + rbrace)
- structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))
-
- # have to use longest match for type, in case a user-defined type name starts with a keyword type, like "channel_type"
- typeSpec << ( structSpec ^ int8_ ^ uint8_ ^ int16_ ^ uint16_ ^
- int32_ ^ uint32_ ^ int64_ ^ uint64_ ^ unix_fd_ ^
- typename).setName("type")
-
- flagsBody = enumBody = Group(lbrace + delimitedList(Group (enumname + Optional(equals + integer))) + Optional(comma) + rbrace)
-
- messageSpec = Group(message_ + messageBody + attributes).setParseAction(lambda toks: ptypes.MessageType(None, toks[0][1], toks[0][2])) | typename
-
- channelParent = Optional(colon + typename, default=None)
- channelMessage = Group(messageSpec + identifier + Optional(equals + integer, default=None) + semi) \
- .setParseAction(lambda toks: ptypes.ChannelMember(toks[0][1], toks[0][0], toks[0][2]))
- channelBody = channelParent + Group(lbrace + ZeroOrMore( server_ + colon | client_ + colon | channelMessage) + rbrace)
-
- enum_ = (enum32_ | enum16_ | enum8_)
- flags_ = (flags32_ | flags16_ | flags8_)
- enumDef = Group(enum_ + identifier + enumBody + attributes - semi).setParseAction(lambda toks: ptypes.EnumType(toks[0][0], toks[0][1], toks[0][2], toks[0][3]))
- flagsDef = Group(flags_ + identifier + flagsBody + attributes - semi).setParseAction(lambda toks: ptypes.FlagsType(toks[0][0], toks[0][1], toks[0][2], toks[0][3]))
- messageDef = Group(message_ + identifier + messageBody + attributes - semi).setParseAction(lambda toks: ptypes.MessageType(toks[0][1], toks[0][2], toks[0][3]))
- channelDef = Group(channel_ + identifier + channelBody + attributes - semi).setParseAction(lambda toks: ptypes.ChannelType(toks[0][1], toks[0][2], toks[0][3], toks[0][4]))
- structDef = Group(struct_ + identifier + structBody + attributes - semi).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))
- typedefDef = Group(typedef_ + identifier + typeSpec + attributes - semi).setParseAction(lambda toks: ptypes.TypeAlias(toks[0][1], toks[0][2], toks[0][3]))
-
- definitions = typedefDef | structDef | enumDef | flagsDef | messageDef | channelDef
-
- protocolChannel = Group(typename + identifier + Optional(equals + integer, default=None) + semi) \
- .setParseAction(lambda toks: ptypes.ProtocolMember(toks[0][1], toks[0][0], toks[0][2]))
- protocolDef = Group(protocol_ + identifier + Group(lbrace + ZeroOrMore(protocolChannel) + rbrace) + semi) \
- .setParseAction(lambda toks: ptypes.ProtocolType(toks[0][1], toks[0][2]))
-
- bnf = ZeroOrMore (definitions) + protocolDef + StringEnd()
-
- singleLineComment = "//" + restOfLine
- bnf.ignore( singleLineComment )
- bnf.ignore( cStyleComment )
-
- return bnf
-
-
-def parse(filename):
- try:
- bnf = SPICE_BNF()
- types = bnf.parseFile(filename)
- except ParseException as err:
- six.print_(err.line, file=sys.stderr)
- six.print_(" "*(err.column-1) + "^", file=sys.stderr)
- six.print_(err, file=sys.stderr)
- return None
-
- for t in types:
- t.resolve()
- t.register()
- protocol = types[-1]
- return protocol
diff --git a/spice-protocol.pc.in b/spice-protocol.pc.in
index a55574f..f8b2669 100644
--- a/spice-protocol.pc.in
+++ b/spice-protocol.pc.in
@@ -1,7 +1,6 @@
prefix=@prefix@
includedir=@includedir@
datadir=${prefix}/share
-codegendir=${datadir}/spice-protocol
Name: spice-protocol
Description: SPICE protocol headers
diff --git a/spice.proto b/spice.proto
deleted file mode 100644
index 4a0778d..0000000
--- a/spice.proto
+++ /dev/null
@@ -1,1414 +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;
-};
-
-struct Transform {
- uint32 t00;
- uint32 t01;
- uint32 t02;
- uint32 t10;
- uint32 t11;
- uint32 t12;
-};
-
-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_);
-
-flags32 composite_flags {
- OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7,
- SRC_FILTER0, SRC_FILTER1, SRC_FILTER2,
- MASK_FILTER0, MASK_FITLER1, MASK_FILTER2,
-
- SRC_REPEAT0, SRC_REPEAT1,
- MASK_REPEAT0, MASK_REPEAT1,
- COMPONENT_ALPHA,
-
- HAS_MASK,
- HAS_SRC_TRANSFORM,
- HAS_MASK_TRANSFORM,
-
- /* These are used to override the formats given in the images. For
- * example, if the mask image has format a8r8g8b8, but MASK_OPAQUE
- * is set, the image should be treated as if it were x8r8g8b8
- */
- SOURCE_OPAQUE,
- MASK_OPAQUE,
- DEST_OPAQUE,
-} @prefix(SPICE_COMPOSITE_);
-
-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;
-
- Data list; /* the msg body is SpiceSubMessageList */
-
- Empty base_last = 100;
-
- 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;
-};
-
-struct DstInfo {
- 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(SpiceMigrationDstInfo);
-
-channel MainChannel : BaseChannel {
- server:
- message {
- DstInfo dst_info;
- } @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] @end;
- } name;
-
- message {
- uint8 uuid[16];
- } uuid;
-
- message {
- uint32 num_tokens;
- } agent_connected_tokens;
-
- message {
- DstInfo dst_info;
- uint32 src_mig_version;
- } migrate_begin_seamless;
-
- Empty migrate_dst_seamless_ack;
- Empty migrate_dst_seamless_nack;
-
- 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;
-
- message {
- uint32 src_version;
- } migrate_dst_do_seamless;
-
- Empty migrate_connected_seamless;
-};
-
-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,
- VP8,
- H264,
-};
-
-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,
- LZ4,
-};
-
-enum8 image_compression {
- INVALID = 0,
- OFF,
- AUTO_GLZ,
- AUTO_LZ,
- QUIC,
- GLZ,
- LZ,
- LZ4,
-};
-
-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 */,
- 8BIT_A /* 1 byte, alpha */
-};
-
-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,
-};
-
-/* This *must* remain with values identical to api/winddi.h
- LA_STYLED == 0x8 (log_2)=> 3
- LA_STARTGAP == 0x4 (log_2)=> 2
- This is used by the windows driver.
- */
-flags8 line_flags {
- STYLED = 3,
- START_WITH_GAP = 2,
-};
-
-flags8 string_flags {
- RASTER_A1,
- RASTER_A4,
- RASTER_A8,
- RASTER_TOP_DOWN,
-};
-
-flags32 surface_flags {
- /* Adding flags requires some caps check, since old clients only
- treat the value as an enum and not as a flag (flag == PRIMARY) */
- 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 LZ4:
- BinaryData lz4;
- 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;
-};
-
-struct StreamDataHeader {
- uint32 id;
- uint32 multi_media_time;
-};
-
-struct Head {
- uint32 id;
- uint32 surface_id;
- uint32 width;
- uint32 height;
- uint32 x;
- uint32 y;
- uint32 flags;
-};
-
-flags32 gl_scanout_flags {
- Y0TOP
-};
-
-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 {
- StreamDataHeader base;
- 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;
-
- message {
- StreamDataHeader base;
- uint32 width;
- uint32 height;
- Rect dest;
- uint32 data_size;
- uint8 data[data_size] @end @nomarshal;
- } stream_data_sized;
-
- message {
- uint16 count;
- uint16 max_allowed;
- Head heads[count] @end;
- } monitors_config;
-
- message {
- DisplayBase base;
- struct Composite {
- composite_flags flags;
- Image *src_bitmap;
- switch (flags) {
- case HAS_MASK:
- Image *mask_bitmap;
- } a @anon;
- switch (flags) {
- case HAS_SRC_TRANSFORM:
- Transform src_transform;
- } b @anon;
- switch (flags) {
- case HAS_MASK_TRANSFORM:
- Transform mask_transform;
- } c @anon;
- Point16 src_origin;
- Point16 mask_origin;
- } data;
- } draw_composite;
-
- message {
- uint32 stream_id;
- uint32 unique_id;
- uint32 max_window_size;
- uint32 timeout_ms;
- } stream_activate_report;
-
- message {
- unix_fd drm_dma_buf_fd;
- uint32 width;
- uint32 height;
- uint32 stride;
- /* specifies the format of drm_dma_buf_fd defined in drm_fourcc.h */
- uint32 drm_fourcc_format;
- gl_scanout_flags flags;
- } gl_scanout_unix;
-
- message {
- uint32 x;
- uint32 y;
- uint32 w;
- uint32 h;
- } gl_draw;
-
- 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;
-
- message {
- uint32 stream_id;
- uint32 unique_id;
- uint32 start_frame_mm_time;
- uint32 end_frame_mm_time;
- uint32 num_frames;
- uint32 num_drops;
- int32 last_frame_delay;
- uint32 audio_delay;
- } stream_report;
-
- message {
- image_compression image_compression;
- } preferred_compression;
-
- message {
- } gl_draw_done;
-};
-
-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;
-
- Data key_scancode;
-
- 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,
- OPUS,
-};
-
-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;
-
- message {
- uint32 latency_ms;
- } latency;
-};
-
-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
-};
-
-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) data = 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) data = 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 SpicevmcChannel : BaseChannel {
-server:
- Data data = 101;
-client:
- Data data = 101;
-};
-
-channel UsbredirChannel : SpicevmcChannel {
-};
-
-channel PortChannel : SpicevmcChannel {
- client:
- message {
- uint8 event;
- } event = 201;
- server:
- message {
- uint32 name_size;
- uint8 *name[name_size] @zero_terminated @marshall @nonnull;
- uint8 opened;
- } init = 201;
- message {
- uint8 event;
- } event;
-};
-
-channel WebDAVChannel : PortChannel {
-};
-
-protocol Spice {
- MainChannel main = 1;
- DisplayChannel display;
- InputsChannel inputs;
- CursorChannel cursor;
- PlaybackChannel playback;
- RecordChannel record;
- TunnelChannel tunnel;
- SmartcardChannel smartcard;
- UsbredirChannel usbredir;
- PortChannel port;
- WebDAVChannel webdav;
-};
diff --git a/spice/Makefile.am b/spice/Makefile.am
index 9be09ec..a54ae89 100644
--- a/spice/Makefile.am
+++ b/spice/Makefile.am
@@ -21,28 +21,4 @@ spice_protocol_include_HEADERS = \
vdi_dev.h \
$(NULL)
-# Using the python code generator requires some python modules
-# which might not be installed on the user computer. Given that
-# enums.h is stored in git, and should be up-to-date anyway,
-# we can make this part optional
-if ENABLE_CODEGEN
-MARSHALLERS_DEPS = \
- $(top_srcdir)/python_modules/__init__.py \
- $(top_srcdir)/python_modules/codegen.py \
- $(top_srcdir)/python_modules/demarshal.py \
- $(top_srcdir)/python_modules/marshal.py \
- $(top_srcdir)/python_modules/ptypes.py \
- $(top_srcdir)/python_modules/spice_parser.py \
- $(top_srcdir)/spice_codegen.py \
- $(NULL)
-
-BUILT_SOURCES = enums.h
-
-# this is going to upset automake distcheck, since we try to write to
-# readonly srcdir. To limit the fail chances, rebuild automatically
-# enums.h only if the spice.proto has changed.
-enums.h: $(top_srcdir)/spice.proto # $(MARSHALLERS_DEPS)
- $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-enums $< $@ >/dev/null
-endif
-
-include $(top_srcdir)/git.mk
diff --git a/spice1.proto b/spice1.proto
deleted file mode 100644
index 6adf312..0000000
--- a/spice1.proto
+++ /dev/null
@@ -1,943 +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;
-};
-
-struct DstInfo {
- 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(SpiceMigrationDstInfo);
-
-channel MainChannel : BaseChannel {
- server:
- message {
- DstInfo dst_info;
- } @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;
-};
-
-struct StreamDataHeader {
- uint32 id;
- uint32 multi_media_time;
-};
-
-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 {
- StreamDataHeader base;
- 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,
- OPUS,
-};
-
-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 569cccc..0000000
--- a/spice_codegen.py
+++ /dev/null
@@ -1,275 +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
-import six
-
-def write_channel_enums(writer, channel, client, describe):
- messages = list(filter(lambda m : m.channel == channel, \
- channel.client_messages if client else channel.server_messages))
- if len(messages) == 0:
- return
- if client:
- prefix = [ "MSGC" ]
- else:
- prefix = [ "MSG" ]
- if channel.member_name:
- prefix.append(channel.member_name.upper())
- if not describe:
- writer.begin_block("enum")
- else:
- writer.begin_block("static const value_string %s_vs[] = " % (codegen.prefix_underscore_lower(*[x.lower() for x in prefix])))
- i = 0
- prefix.append(None) # To be replaced with name
- for m in messages:
- prefix[-1] = m.name.upper()
- enum = codegen.prefix_underscore_upper(*prefix)
- if describe:
- writer.writeln("{ %s, \"%s %s\" }," % (enum, "Client" if client else "Server", m.name.upper()))
- else:
- if m.value == i:
- writer.writeln("%s," % enum)
- i = i + 1
- else:
- writer.writeln("%s = %s," % (enum, m.value))
- i = m.value + 1
- if describe:
- writer.writeln("{ 0, NULL }");
- else:
- 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_channel_type_enum(writer, describe=False):
- i = 0
- if describe:
- writer.begin_block("static const value_string channel_types_vs[] =")
- else:
- writer.begin_block("enum")
- for c in proto.channels:
- enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
- if describe:
- writer.writeln("{ %s, \"%s\" }," % (enum, c.name.upper()))
- else:
- 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()
- if describe:
- writer.writeln("{ 0, NULL }")
- else:
- writer.writeln("SPICE_END_CHANNEL")
- writer.end_block(semicolon=True)
- writer.newline()
-
-
-def write_enums(writer, describe=False):
- writer.writeln("#ifndef _H_SPICE_ENUMS")
- writer.writeln("#define _H_SPICE_ENUMS")
- writer.newline()
-
- # Define enums
- for t in ptypes.get_named_types():
- if isinstance(t, ptypes.EnumBaseType):
- t.c_define(writer)
- if describe:
- t.c_describe(writer)
-
- write_channel_type_enum(writer)
- if (describe):
- write_channel_type_enum(writer, True)
-
- for c in ptypes.get_named_types():
- if not isinstance(c, ptypes.ChannelType):
- continue
- write_channel_enums(writer, c, False, False)
- if describe:
- write_channel_enums(writer, c, False, describe)
- write_channel_enums(writer, c, True, False)
- if describe:
- write_channel_enums(writer, c, True, describe)
-
- 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("-w", "--generate-wireshark-dissector",
- action="store_true", dest="generate_dissector", default=False,
- help="Generate Wireshark dissector definitions")
-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))
-
-license = """/*
- Copyright (C) 2013 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-"""
-
-writer.public_prefix = options.prefix
-
-writer.writeln("/* this is a file autogenerated by spice_codegen.py */")
-writer.write(license)
-writer.header.writeln("/* this is a file autogenerated by spice_codegen.py */")
-writer.header.write(license)
-if not options.header and not options.generate_enums:
- writer.writeln("#ifdef HAVE_CONFIG_H")
- writer.writeln("#include <config.h>")
- writer.writeln("#endif")
-
-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.header.writeln('#include <%s>' % i)
- writer.writeln('#include <%s>' % i)
-
-if options.generate_enums or options.generate_dissector:
- write_enums(writer, options.generate_dissector)
-
-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, False)
-
-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:
- six.print_("No changes to %s" % dest_file)
- sys.exit(0)
-
- except IOError:
- pass
-
-f = open(dest_file, 'wb')
-if six.PY3:
- f.write(bytes(content, 'UTF-8'))
-else:
- f.write(content)
-f.close()
-
-six.print_("Wrote %s" % dest_file)
-sys.exit(0)