mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-protocol
synced 2025-12-29 17:07:13 +00:00
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>
This commit is contained in:
parent
7937915d67
commit
2a6e51c7ee
14
Makefile.am
14
Makefile.am
@ -1,18 +1,6 @@
|
|||||||
NULL =
|
NULL =
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
SUBDIRS = python_modules spice
|
SUBDIRS = spice
|
||||||
|
|
||||||
codegendir = $(datadir)/spice-protocol
|
|
||||||
dist_codegen_DATA = \
|
|
||||||
spice.proto \
|
|
||||||
spice1.proto \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
dist_codegen_SCRIPTS = \
|
|
||||||
spice_codegen.py \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
DISTCLEANFILES = *.pyc
|
|
||||||
|
|
||||||
pkgconfigdir = $(datadir)/pkgconfig
|
pkgconfigdir = $(datadir)/pkgconfig
|
||||||
pkgconfig_DATA = spice-protocol.pc
|
pkgconfig_DATA = spice-protocol.pc
|
||||||
|
|||||||
@ -11,7 +11,7 @@ test -z "$srcdir" && srcdir=.
|
|||||||
autoreconf --verbose --force --install
|
autoreconf --verbose --force --install
|
||||||
)
|
)
|
||||||
|
|
||||||
CONFIGURE_ARGS="--enable-maintainer-mode --enable-code-generator"
|
CONFIGURE_ARGS="--enable-maintainer-mode"
|
||||||
|
|
||||||
if [ -z "$NOCONFIGURE" ]; then
|
if [ -z "$NOCONFIGURE" ]; then
|
||||||
echo "Running configure with $CONFIGURE_ARGS $@"
|
echo "Running configure with $CONFIGURE_ARGS $@"
|
||||||
|
|||||||
17
configure.ac
17
configure.ac
@ -14,25 +14,8 @@ AM_MAINTAINER_MODE
|
|||||||
|
|
||||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
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([
|
AC_OUTPUT([
|
||||||
Makefile
|
Makefile
|
||||||
spice-protocol.pc
|
spice-protocol.pc
|
||||||
spice/Makefile
|
spice/Makefile
|
||||||
python_modules/Makefile
|
|
||||||
])
|
])
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -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")
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -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
|
|
||||||
@ -1,7 +1,6 @@
|
|||||||
prefix=@prefix@
|
prefix=@prefix@
|
||||||
includedir=@includedir@
|
includedir=@includedir@
|
||||||
datadir=${prefix}/share
|
datadir=${prefix}/share
|
||||||
codegendir=${datadir}/spice-protocol
|
|
||||||
|
|
||||||
Name: spice-protocol
|
Name: spice-protocol
|
||||||
Description: SPICE protocol headers
|
Description: SPICE protocol headers
|
||||||
|
|||||||
1414
spice.proto
1414
spice.proto
File diff suppressed because it is too large
Load Diff
@ -21,28 +21,4 @@ spice_protocol_include_HEADERS = \
|
|||||||
vdi_dev.h \
|
vdi_dev.h \
|
||||||
$(NULL)
|
$(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
|
-include $(top_srcdir)/git.mk
|
||||||
|
|||||||
943
spice1.proto
943
spice1.proto
@ -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;
|
|
||||||
};
|
|
||||||
275
spice_codegen.py
275
spice_codegen.py
@ -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)
|
|
||||||
Loading…
Reference in New Issue
Block a user