diff options
-rw-r--r-- | python_modules/Makefile.am | 5 | ||||
-rw-r--r-- | python_modules/__init__.py | 0 | ||||
-rw-r--r-- | python_modules/codegen.py | 356 | ||||
-rw-r--r-- | python_modules/demarshal.py | 1238 | ||||
-rw-r--r-- | python_modules/marshal.py | 402 | ||||
-rw-r--r-- | python_modules/ptypes.py | 1044 | ||||
-rw-r--r-- | python_modules/spice_parser.py | 161 | ||||
-rw-r--r-- | spice.proto | 1146 | ||||
-rw-r--r-- | spice1.proto | 934 | ||||
-rwxr-xr-x | spice_codegen.py | 218 |
10 files changed, 0 insertions, 5504 deletions
diff --git a/python_modules/Makefile.am b/python_modules/Makefile.am deleted file mode 100644 index 7d416dfc..00000000 --- a/python_modules/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -NULL = - -PYTHON_MODULES = __init__.py codegen.py demarshal.py marshal.py ptypes.py spice_parser.py - -EXTRA_DIST = $(PYTHON_MODULES) diff --git a/python_modules/__init__.py b/python_modules/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/python_modules/__init__.py +++ /dev/null diff --git a/python_modules/codegen.py b/python_modules/codegen.py deleted file mode 100644 index 116760c8..00000000 --- a/python_modules/codegen.py +++ /dev/null @@ -1,356 +0,0 @@ -from __future__ import with_statement -from cStringIO import StringIO - -def camel_to_underscores(s, upper = False): - res = "" - for i in range(len(s)): - c = s[i] - if i > 0 and c.isupper(): - res = res + "_" - if upper: - res = res + c.upper() - else: - res = res + c.lower() - return res - -def underscores_to_camel(s): - res = "" - do_upper = True - for i in range(len(s)): - c = s[i] - if c == "_": - do_upper = True - else: - if do_upper: - res = res + c.upper() - else: - res = res + c - do_upper = False - return res - -proto_prefix = "Temp" - -def set_prefix(prefix): - global proto_prefix - global proto_prefix_upper - global proto_prefix_lower - proto_prefix = prefix - proto_prefix_upper = prefix.upper() - proto_prefix_lower = prefix.lower() - -def prefix_underscore_upper(*args): - s = proto_prefix_upper - for arg in args: - s = s + "_" + arg - return s - -def prefix_underscore_lower(*args): - s = proto_prefix_lower - for arg in args: - s = s + "_" + arg - return s - -def prefix_camel(*args): - s = proto_prefix - for arg in args: - s = s + underscores_to_camel(arg) - return s - -def increment_identifier(idf): - v = idf[-1:] - if v.isdigit(): - return idf[:-1] + str(int(v) + 1) - return idf + "2" - -def sum_array(array): - if len(array) == 0: - return 0 - return " + ".join(array) - -class CodeWriter: - def __init__(self): - self.out = StringIO() - self.contents = [self.out] - self.indentation = 0 - self.at_line_start = True - self.indexes = ["i", "j", "k", "ii", "jj", "kk"] - self.current_index = 0 - self.generated = {} - self.vars = [] - self.has_error_check = False - self.options = {} - self.function_helper_writer = None - - def set_option(self, opt, value = True): - self.options[opt] = value - - def has_option(self, opt): - return self.options.has_key(opt) - - def set_is_generated(self, kind, name): - if not self.generated.has_key(kind): - v = {} - self.generated[kind] = v - else: - v = self.generated[kind] - v[name] = 1 - - def is_generated(self, kind, name): - if not self.generated.has_key(kind): - return False - v = self.generated[kind] - return v.has_key(name) - - def getvalue(self): - strs = map(lambda writer: writer.getvalue(), self.contents) - return "".join(strs) - - def get_subwriter(self): - writer = CodeWriter() - self.contents.append(writer) - self.out = StringIO() - self.contents.append(self.out) - writer.indentation = self.indentation - writer.at_line_start = self.at_line_start - writer.generated = self.generated - writer.options = self.options - writer.public_prefix = self.public_prefix - - return writer - - def write(self, s): - # Ensure its a string - s = str(s) - - if len(s) == 0: - return - - if self.at_line_start: - for i in range(self.indentation): - self.out.write(" ") - self.at_line_start = False - self.out.write(s) - return self - - def newline(self): - self.out.write("\n") - self.at_line_start = True - return self - - def writeln(self, s): - self.write(s) - self.newline() - return self - - def label(self, s): - self.indentation = self.indentation - 1 - self.write(s + ":") - self.indentation = self.indentation + 1 - self.newline() - - def statement(self, s): - self.write(s) - self.write(";") - self.newline() - return self - - def assign(self, var, val): - self.write("%s = %s" % (var, val)) - self.write(";") - self.newline() - return self - - def increment(self, var, val): - self.write("%s += %s" % (var, val)) - self.write(";") - self.newline() - return self - - def comment(self, str): - self.write("/* " + str + " */") - return self - - def todo(self, str): - self.comment("TODO: *** %s ***" % str).newline() - return self - - def error_check(self, check, label = "error"): - self.has_error_check = True - with self.block("if (SPICE_UNLIKELY(%s))" % check): - if self.has_option("print_error"): - self.statement('printf("%%s: Caught error - %s", __PRETTY_FUNCTION__)' % check) - if self.has_option("assert_on_error"): - self.statement("assert(0)") - self.statement("goto %s" % label) - - def indent(self): - self.indentation += 4 - - def unindent(self): - self.indentation -= 4 - if self.indentation < 0: - self.indenttation = 0 - - def begin_block(self, prefix= "", comment = ""): - if len(prefix) > 0: - self.write(prefix) - if self.at_line_start: - self.write("{") - else: - self.write(" {") - if len(comment) > 0: - self.write(" ") - self.comment(comment) - self.newline() - self.indent() - - def end_block(self, semicolon=False, newline=True): - self.unindent() - if self.at_line_start: - self.write("}") - else: - self.write(" }") - if semicolon: - self.write(";") - if newline: - self.newline() - - class Block: - def __init__(self, writer, semicolon, newline): - self.writer = writer - self.semicolon = semicolon - self.newline = newline - - def __enter__(self): - return self.writer.get_subwriter() - - def __exit__(self, exc_type, exc_value, traceback): - self.writer.end_block(self.semicolon, self.newline) - - class PartialBlock: - def __init__(self, writer, scope, semicolon, newline): - self.writer = writer - self.scope = scope - self.semicolon = semicolon - self.newline = newline - - def __enter__(self): - return self.scope - - def __exit__(self, exc_type, exc_value, traceback): - self.writer.end_block(self.semicolon, self.newline) - - class NoBlock: - def __init__(self, scope): - self.scope = scope - - def __enter__(self): - return self.scope - - def __exit__(self, exc_type, exc_value, traceback): - pass - - def block(self, prefix= "", comment = "", semicolon=False, newline=True): - self.begin_block(prefix, comment) - return self.Block(self, semicolon, newline) - - def partial_block(self, scope, semicolon=False, newline=True): - return self.PartialBlock(self, scope, semicolon, newline) - - def no_block(self, scope): - return self.NoBlock(scope) - - def optional_block(self, scope): - if scope != None: - return self.NoBlock(scope) - return self.block() - - def for_loop(self, index, limit): - return self.block("for (%s = 0; %s < %s; %s++)" % (index, index, limit, index)) - - def while_loop(self, expr): - return self.block("while (%s)" % (expr)) - - def if_block(self, check, elseif=False, newline=True): - s = "if (%s)" % (check) - if elseif: - s = " else " + s - self.begin_block(s, "") - return self.Block(self, False, newline) - - def variable_defined(self, name): - for n in self.vars: - if n == name: - return True - return False - - def variable_def(self, ctype, *names): - for n in names: - # Strip away initialization - i = n.find("=") - if i != -1: - n = n[0:i] - self.vars.append(n.strip()) - # only add space for non-pointer types - if ctype[-1] == "*": - ctype = ctype[:-1].rstrip() - self.writeln("%s *%s;"%(ctype, ", *".join(names))) - else: - self.writeln("%s %s;"%(ctype, ", ".join(names))) - return self - - def function_helper(self): - if self.function_helper_writer != None: - writer = self.function_helper_writer.get_subwriter() - self.function_helper_writer.newline() - else: - writer = self.get_subwriter() - return writer - - def function(self, name, return_type, args, static = False): - self.has_error_check = False - self.function_helper_writer = self.get_subwriter() - if static: - self.write("static ") - self.write(return_type) - self.write(" %s(%s)"% (name, args)).newline() - self.begin_block() - self.function_variables_writer = self.get_subwriter() - self.function_variables = {} - return self.function_variables_writer - - def macro(self, name, args, define): - self.write("#define %s(%s) %s" % (name, args, define)).newline() - - def add_function_variable(self, ctype, name): - if self.function_variables.has_key(name): - assert(self.function_variables[name] == ctype) - else: - self.function_variables[name] = ctype - self.function_variables_writer.variable_def(ctype, name) - - def pop_index(self): - index = self.indexes[self.current_index] - self.current_index = self.current_index + 1 - self.add_function_variable("uint32_t", index) - return index - - def push_index(self): - self.current_index = self.current_index - 1 - - class Index: - def __init__(self, writer, val): - self.writer = writer - self.val = val - - def __enter__(self): - return self.val - - def __exit__(self, exc_type, exc_value, traceback): - self.writer.push_index() - - def index(self, no_block = False): - if no_block: - return self.no_block(None) - val = self.pop_index() - return self.Index(self, val) diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py deleted file mode 100644 index 541735a5..00000000 --- a/python_modules/demarshal.py +++ /dev/null @@ -1,1238 +0,0 @@ -from __future__ import with_statement -import ptypes -import codegen - -# The handling of sizes is somewhat complex, as there are several types of size: -# * nw_size -# This is the network size, i.e. the number of bytes on the network -# -# * mem_size -# The total amount of memory used for the representation of something inside -# spice. This is generally sizeof(C struct), but can be larger if for instance -# the type has a variable size array at the end or has a pointer in it that -# points to another data chunk (which will be allocated after the main -# data chunk). This is essentially how much memory you need to allocate to -# contain the data type. -# -# * extra_size -# This is the size of anything that is not part of the containing structure. -# For instance, a primitive (say uint32_t) member has no extra size, because -# when allocating its part of the sizeof(MessageStructType) struct. However -# a variable array can be places at the end of a structure (@end) and its -# size is then extra_size. Note that this extra_size is included in the -# mem_size of the enclosing struct, and even if you request the mem_size -# of the array itself. However, extra_size is typically not requested -# when the full mem_size is also requested. -# -# extra sizes come in two flavours. contains_extra_size means that the item -# has a normal presence in the parent container, but has some additional -# extra_size it references. For instance via a pointer somewhere in it. -# There is also is_extra_size(). This indicates that the whole elements -# "normal" mem size should be considered extra size for the container, so -# when computing the parent mem_size you should add the mem_size of this -# part as extra_size - -def write_parser_helpers(writer): - if writer.is_generated("helper", "demarshaller"): - return - - writer.set_is_generated("helper", "demarshaller") - - writer = writer.function_helper() - - writer.writeln("#ifdef WORDS_BIGENDIAN") - for size in [8, 16, 32, 64]: - for sign in ["", "u"]: - utype = "uint%d" % (size) - type = "%sint%d" % (sign, size) - swap = "SPICE_BYTESWAP%d" % size - if size == 8: - writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type) - writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = val" % (type)) - else: - writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr)))" % (type, swap, utype)) - writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = %s((%s_t)val)" % (utype, swap, utype)) - writer.writeln("#else") - for size in [8, 16, 32, 64]: - for sign in ["", "u"]: - type = "%sint%d" % (sign, size) - writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type) - writer.macro("write_%s" % type, "ptr, val", "(*((%s_t *)(ptr))) = val" % type) - writer.writeln("#endif") - - for size in [8, 16, 32, 64]: - for sign in ["", "u"]: - writer.newline() - type = "%sint%d" % (sign, size) - ctype = "%s_t" % type - scope = writer.function("SPICE_GNUC_UNUSED consume_%s" % type, ctype, "uint8_t **ptr", True) - scope.variable_def(ctype, "val") - writer.assign("val", "read_%s(*ptr)" % type) - writer.increment("*ptr", size / 8) - writer.statement("return val") - writer.end_block() - - writer.newline() - writer.statement("typedef struct PointerInfo PointerInfo") - writer.statement("typedef void (*message_destructor_t)(uint8_t *message)") - writer.statement("typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor)") - writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message)") - writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message)") - - writer.newline() - writer.begin_block("struct PointerInfo") - writer.variable_def("uint64_t", "offset") - writer.variable_def("parse_func_t", "parse") - writer.variable_def("void **", "dest") - writer.variable_def("uint32_t", "nelements") - writer.end_block(semicolon=True) - -def write_read_primitive(writer, start, container, name, scope): - m = container.lookup_member(name) - assert(m.is_primitive()) - writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size")) - writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size()) - - var = "%s__value" % (name.replace(".", "_")) - if not scope.variable_defined(var): - scope.variable_def(m.member_type.c_type(), var) - writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type())) - return var - -def write_write_primitive(writer, start, container, name, val): - m = container.lookup_member(name) - assert(m.is_primitive()) - writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size")) - - var = "%s__value" % (name) - writer.statement("write_%s(pos, %s)" % (m.member_type.primitive_type(), val)) - return var - -def write_read_primitive_item(writer, item, scope): - assert(item.type.is_primitive()) - writer.assign("pos", item.get_position()) - writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size()) - var = "%s__value" % (item.subprefix.replace(".", "_")) - scope.variable_def(item.type.c_type(), var) - writer.assign(var, "read_%s(pos)" % (item.type.primitive_type())) - return var - -class ItemInfo: - def __init__(self, type, prefix, position): - self.type = type - self.prefix = prefix - self.subprefix = prefix - self.position = position - self.member = None - - def nw_size(self): - return self.prefix + "__nw_size" - - def mem_size(self): - return self.prefix + "__mem_size" - - def extra_size(self): - return self.prefix + "__extra_size" - - def get_position(self): - return self.position - -class MemberItemInfo(ItemInfo): - def __init__(self, member, container, start): - if not member.is_switch(): - self.type = member.member_type - self.prefix = member.name - self.subprefix = member.name - self.position = "(%s + %s)" % (start, container.get_nw_offset(member, "", "__nw_size")) - self.member = member - -def write_validate_switch_member(writer, container, switch_member, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size): - var = container.lookup_member(switch_member.variable) - var_type = var.member_type - - v = write_read_primitive(writer, start, container, switch_member.variable, parent_scope) - - item = MemberItemInfo(switch_member, container, start) - - first = True - for c in switch_member.cases: - check = c.get_check(v, var_type) - m = c.member - with writer.if_block(check, not first, False) as if_scope: - item.type = c.member.member_type - item.subprefix = item.prefix + "_" + m.name - item.member = c.member - - all_as_extra_size = m.is_extra_size() and want_extra_size - if not want_mem_size and all_as_extra_size and not scope.variable_defined(item.mem_size()): - scope.variable_def("uint32_t", item.mem_size()) - - sub_want_mem_size = want_mem_size or all_as_extra_size - sub_want_extra_size = want_extra_size and not all_as_extra_size - - write_validate_item(writer, container, item, if_scope, scope, start, - want_nw_size, sub_want_mem_size, sub_want_extra_size) - - if all_as_extra_size: - writer.assign(item.extra_size(), item.mem_size()) - - first = False - - with writer.block(" else"): - if want_nw_size: - writer.assign(item.nw_size(), 0) - if want_mem_size: - writer.assign(item.mem_size(), 0) - if want_extra_size: - writer.assign(item.extra_size(), 0) - - writer.newline() - -def write_validate_struct_function(writer, struct): - validate_function = "validate_%s" % struct.c_type() - if writer.is_generated("validator", validate_function): - return validate_function - - writer.set_is_generated("validator", validate_function) - writer = writer.function_helper() - scope = writer.function(validate_function, "static intptr_t", "uint8_t *message_start, uint8_t *message_end, uint64_t offset, int minor") - scope.variable_def("uint8_t *", "start = message_start + offset") - scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos") - scope.variable_def("size_t", "mem_size", "nw_size") - num_pointers = struct.get_num_pointers() - if num_pointers != 0: - scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size") - - writer.newline() - with writer.if_block("offset == 0"): - writer.statement("return 0") - - writer.newline() - writer.error_check("start >= message_end") - - writer.newline() - write_validate_container(writer, None, struct, "start", scope, True, True, False) - - writer.newline() - writer.comment("Check if struct fits in reported side").newline() - writer.error_check("start + nw_size > message_end") - - writer.statement("return mem_size") - - writer.newline() - writer.label("error") - writer.statement("return -1") - - writer.end_block() - - return validate_function - -def write_validate_pointer_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size): - if want_nw_size: - writer.assign(item.nw_size(), item.type.get_fixed_nw_size()) - - if want_mem_size or want_extra_size: - target_type = item.type.target_type - - v = write_read_primitive_item(writer, item, scope) - if item.type.has_attr("nonnull"): - writer.error_check("%s == 0" % v) - - # pointer target is struct, or array of primitives - # if array, need no function check - - if target_type.is_array(): - writer.error_check("message_start + %s >= message_end" % v) - - - assert target_type.element_type.is_primitive() - - array_item = ItemInfo(target_type, "%s__array" % item.prefix, start) - scope.variable_def("uint32_t", array_item.nw_size()) - # don't create a variable that isn't used, fixes -Werror=unused-but-set-variable - need_mem_size = want_mem_size or ( - want_extra_size and not item.member.has_attr("chunk") - and not target_type.is_cstring_length()) - if need_mem_size: - scope.variable_def("uint32_t", array_item.mem_size()) - if target_type.is_cstring_length(): - writer.assign(array_item.nw_size(), "spice_strnlen((char *)message_start + %s, message_end - (message_start + %s))" % (v, v)) - writer.error_check("*(message_start + %s + %s) != 0" % (v, array_item.nw_size())) - else: - write_validate_array_item(writer, container, array_item, scope, parent_scope, start, - True, want_mem_size=need_mem_size, want_extra_size=False) - writer.error_check("message_start + %s + %s > message_end" % (v, array_item.nw_size())) - - if want_extra_size: - if item.member and item.member.has_attr("chunk"): - writer.assign(item.extra_size(), "sizeof(SpiceChunks) + sizeof(SpiceChunk)") - elif item.member and item.member.has_attr("nocopy"): - writer.comment("@nocopy, so no extra size").newline() - writer.assign(item.extra_size(), 0) - elif target_type.element_type.get_fixed_nw_size == 1: - writer.assign(item.extra_size(), array_item.mem_size()) - # If not bytes or zero, add padding needed for alignment - else: - writer.assign(item.extra_size(), "%s + /* for alignment */ 3" % array_item.mem_size()) - if want_mem_size: - writer.assign(item.mem_size(), "sizeof(void *) + %s" % array_item.mem_size()) - - elif target_type.is_struct(): - validate_function = write_validate_struct_function(writer, target_type) - writer.assign("ptr_size", "%s(message_start, message_end, %s, minor)" % (validate_function, v)) - writer.error_check("ptr_size < 0") - - if want_extra_size: - writer.assign(item.extra_size(), "ptr_size + /* for alignment */ 3") - if want_mem_size: - writer.assign(item.mem_size(), "sizeof(void *) + ptr_size") - else: - raise NotImplementedError("pointer to unsupported type %s" % target_type) - - -def write_validate_array_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size): - array = item.type - is_byte_size = False - element_type = array.element_type - if array.is_bytes_length(): - nelements = "%s__nbytes" %(item.prefix) - real_nelements = "%s__nelements" %(item.prefix) - if not parent_scope.variable_defined(real_nelements): - parent_scope.variable_def("uint32_t", real_nelements) - else: - nelements = "%s__nelements" %(item.prefix) - if not parent_scope.variable_defined(nelements): - parent_scope.variable_def("uint32_t", nelements) - - if array.is_constant_length(): - writer.assign(nelements, array.size) - elif array.is_remaining_length(): - if element_type.is_fixed_nw_size(): - if element_type.get_fixed_nw_size() == 1: - writer.assign(nelements, "message_end - %s" % item.get_position()) - else: - writer.assign(nelements, "(message_end - %s) / (%s)" %(item.get_position(), element_type.get_fixed_nw_size())) - else: - raise NotImplementedError("TODO array[] of dynamic element size not done yet") - elif array.is_identifier_length(): - v = write_read_primitive(writer, start, container, array.size, scope) - writer.assign(nelements, v) - elif array.is_image_size_length(): - bpp = array.size[1] - width = array.size[2] - rows = array.size[3] - width_v = write_read_primitive(writer, start, container, width, scope) - rows_v = write_read_primitive(writer, start, container, rows, scope) - # TODO: Handle multiplication overflow - if bpp == 8: - writer.assign(nelements, "%s * %s" % (width_v, rows_v)) - elif bpp == 1: - writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v)) - else: - writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v)) - elif array.is_bytes_length(): - is_byte_size = True - v = write_read_primitive(writer, start, container, array.size[1], scope) - writer.assign(nelements, v) - writer.assign(real_nelements, 0) - elif array.is_cstring_length(): - writer.todo("cstring array size type not handled yet") - else: - writer.todo("array size type not handled yet") - - writer.newline() - - nw_size = item.nw_size() - mem_size = item.mem_size() - extra_size = item.extra_size() - - if is_byte_size and want_nw_size: - writer.assign(nw_size, nelements) - want_nw_size = False - - if element_type.is_fixed_nw_size() and want_nw_size: - element_size = element_type.get_fixed_nw_size() - # TODO: Overflow check the multiplication - if element_size == 1: - writer.assign(nw_size, nelements) - else: - writer.assign(nw_size, "(%s) * %s" % (element_size, nelements)) - want_nw_size = False - - if array.has_attr("as_ptr") and want_mem_size: - writer.assign(mem_size, "sizeof(void *)") - want_mem_size = False - - if array.has_attr("chunk"): - if want_mem_size: - writer.assign(extra_size, "sizeof(SpiceChunks *)") - want_mem_size = False - if want_extra_size: - writer.assign(extra_size, "sizeof(SpiceChunks) + sizeof(SpiceChunk)") - want_extra_size = False - - if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size: - # TODO: Overflow check the multiplication - if array.has_attr("ptr_array"): - writer.assign(mem_size, "sizeof(void *) + SPICE_ALIGN(%s * %s, 4)" % (element_type.sizeof(), nelements)) - else: - writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements)) - want_mem_size = False - - if not element_type.contains_extra_size() and want_extra_size: - writer.assign(extra_size, 0) - want_extra_size = False - - if not (want_mem_size or want_nw_size or want_extra_size): - return - - start2 = codegen.increment_identifier(start) - scope.variable_def("uint8_t *", "%s = %s" % (start2, item.get_position())) - if is_byte_size: - start2_end = "%s_array_end" % start2 - scope.variable_def("uint8_t *", start2_end) - - element_item = ItemInfo(element_type, "%s__element" % item.prefix, start2) - - element_nw_size = element_item.nw_size() - element_mem_size = element_item.mem_size() - element_extra_size = element_item.extra_size() - scope.variable_def("uint32_t", element_nw_size) - scope.variable_def("uint32_t", element_mem_size) - if want_extra_size: - scope.variable_def("uint32_t", element_extra_size) - - if want_nw_size: - writer.assign(nw_size, 0) - if want_mem_size: - writer.assign(mem_size, 0) - if want_extra_size: - writer.assign(extra_size, 0) - - want_element_nw_size = want_nw_size - if element_type.is_fixed_nw_size(): - start_increment = element_type.get_fixed_nw_size() - else: - want_element_nw_size = True - start_increment = element_nw_size - - if is_byte_size: - writer.assign(start2_end, "%s + %s" % (start2, nelements)) - - with writer.index(no_block = is_byte_size) as index: - with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope: - if is_byte_size: - writer.increment(real_nelements, 1) - write_validate_item(writer, container, element_item, scope, parent_scope, start2, - want_element_nw_size, want_mem_size, want_extra_size) - - if want_nw_size: - writer.increment(nw_size, element_nw_size) - if want_mem_size: - if array.has_attr("ptr_array"): - writer.increment(mem_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size) - else: - writer.increment(mem_size, element_mem_size) - if want_extra_size: - writer.increment(extra_size, element_extra_size) - - writer.increment(start2, start_increment) - if is_byte_size: - writer.error_check("%s != %s" % (start2, start2_end)) - write_write_primitive(writer, start, container, array.size[1], real_nelements) - -def write_validate_struct_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size): - struct = item.type - start2 = codegen.increment_identifier(start) - scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", start2 + " = %s" % (item.get_position())) - - write_validate_container(writer, item.prefix, struct, start2, scope, want_nw_size, want_mem_size, want_extra_size) - -def write_validate_primitive_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size): - if want_nw_size: - nw_size = item.nw_size() - writer.assign(nw_size, item.type.get_fixed_nw_size()) - if want_mem_size: - mem_size = item.mem_size() - writer.assign(mem_size, item.type.sizeof()) - if want_extra_size: - writer.assign(item.extra_size(), 0) - -def write_validate_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size): - if item.member and item.member.has_attr("to_ptr"): - want_nw_size = True - if item.type.is_pointer(): - write_validate_pointer_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size) - elif item.type.is_array(): - write_validate_array_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size) - elif item.type.is_struct(): - write_validate_struct_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size) - elif item.type.is_primitive(): - write_validate_primitive_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size) - else: - writer.todo("Implement validation of %s" % item.type) - - if item.member and item.member.has_attr("to_ptr"): - saved_size = "%s__saved_size" % item.member.name - writer.add_function_variable("uint32_t", saved_size + " = 0") - writer.assign(saved_size, item.nw_size()) - -def write_validate_member(writer, container, member, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size): - if member.has_attr("virtual"): - return - - if member.has_minor_attr(): - prefix = "if (minor >= %s)" % (member.get_minor_attr()) - newline = False - else: - prefix = "" - newline = True - item = MemberItemInfo(member, container, start) - with writer.block(prefix, newline=newline, comment=member.name) as scope: - if member.is_switch(): - write_validate_switch_member(writer, container, member, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size) - else: - write_validate_item(writer, container, item, scope, parent_scope, start, - want_nw_size, want_mem_size, want_extra_size) - - if member.has_minor_attr(): - with writer.block(" else", comment = "minor < %s" % (member.get_minor_attr())): - if member.is_array(): - nelements = "%s__nelements" %(item.prefix) - writer.assign(nelements, 0) - if want_nw_size: - writer.assign(item.nw_size(), 0) - - if want_mem_size: - if member.is_fixed_sizeof(): - writer.assign(item.mem_size(), member.sizeof()) - elif member.is_array(): - writer.assign(item.mem_size(), 0) - else: - raise NotImplementedError("TODO minor check for non-constant items") - - assert not want_extra_size - -def write_validate_container(writer, prefix, container, start, parent_scope, want_nw_size, want_mem_size, want_extra_size): - for m in container.members: - sub_want_nw_size = want_nw_size and not m.is_fixed_nw_size() - sub_want_mem_size = m.is_extra_size() and want_mem_size - sub_want_extra_size = not m.is_extra_size() and m.contains_extra_size() - - defs = ["size_t"] - if sub_want_nw_size: - defs.append (m.name + "__nw_size") - if sub_want_mem_size: - defs.append (m.name + "__mem_size") - if sub_want_extra_size: - defs.append (m.name + "__extra_size") - - if sub_want_nw_size or sub_want_mem_size or sub_want_extra_size: - parent_scope.variable_def(*defs) - write_validate_member(writer, container, m, parent_scope, start, - sub_want_nw_size, sub_want_mem_size, sub_want_extra_size) - writer.newline() - - if want_nw_size: - if prefix: - nw_size = prefix + "__nw_size" - else: - nw_size = "nw_size" - - size = 0 - for m in container.members: - if m.is_fixed_nw_size(): - size = size + m.get_fixed_nw_size() - - nm_sum = str(size) - for m in container.members: - if not m.is_fixed_nw_size(): - nm_sum = nm_sum + " + " + m.name + "__nw_size" - - writer.assign(nw_size, nm_sum) - - if want_mem_size: - if prefix: - mem_size = prefix + "__mem_size" - else: - mem_size = "mem_size" - - mem_sum = container.sizeof() - for m in container.members: - if m.is_extra_size(): - mem_sum = mem_sum + " + " + m.name + "__mem_size" - elif m.contains_extra_size(): - mem_sum = mem_sum + " + " + m.name + "__extra_size" - - writer.assign(mem_size, mem_sum) - - if want_extra_size: - if prefix: - extra_size = prefix + "__extra_size" - else: - extra_size = "extra_size" - - extra_sum = [] - for m in container.members: - if m.is_extra_size(): - extra_sum.append(m.name + "__mem_size") - elif m.contains_extra_size(): - extra_sum.append(m.name + "__extra_size") - writer.assign(extra_size, codegen.sum_array(extra_sum)) - -class DemarshallingDestination: - def __init__(self): - pass - - def child_at_end(self, writer, t): - return RootDemarshallingDestination(self, t.c_type(), t.sizeof()) - - def child_sub(self, member): - return SubDemarshallingDestination(self, member) - - def declare(self, writer): - return writer.optional_block(self.reuse_scope) - - def is_toplevel(self): - return self.parent_dest == None and not self.is_helper - -class RootDemarshallingDestination(DemarshallingDestination): - def __init__(self, parent_dest, c_type, sizeof, pointer = None): - self.is_helper = False - self.reuse_scope = None - self.parent_dest = parent_dest - if parent_dest: - self.base_var = codegen.increment_identifier(parent_dest.base_var) - else: - self.base_var = "out" - self.c_type = c_type - self.sizeof = sizeof - self.pointer = pointer # None == at "end" - - def get_ref(self, member): - return self.base_var + "->" + member - - def declare(self, writer): - if self.reuse_scope: - scope = self.reuse_scope - else: - writer.begin_block() - scope = writer.get_subwriter() - - scope.variable_def(self.c_type + " *", self.base_var) - if not self.reuse_scope: - scope.newline() - - if self.pointer: - writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer)) - else: - writer.assign(self.base_var, "(%s *)end" % (self.c_type)) - writer.increment("end", self.sizeof) - writer.newline() - - if self.reuse_scope: - return writer.no_block(self.reuse_scope) - else: - return writer.partial_block(scope) - -class SubDemarshallingDestination(DemarshallingDestination): - def __init__(self, parent_dest, member): - self.reuse_scope = None - self.parent_dest = parent_dest - self.base_var = parent_dest.base_var - self.member = member - self.is_helper = False - - def get_ref(self, member): - return self.parent_dest.get_ref(self.member) + "." + member - -# Note: during parsing, byte_size types have been converted to count during validation -def read_array_len(writer, prefix, array, dest, scope, is_ptr): - if is_ptr: - nelements = "%s__array__nelements" % prefix - else: - nelements = "%s__nelements" % prefix - if dest.is_toplevel() and scope.variable_defined(nelements): - return nelements # Already there for toplevel, need not recalculate - element_type = array.element_type - scope.variable_def("uint32_t", nelements) - if array.is_constant_length(): - writer.assign(nelements, array.size) - elif array.is_identifier_length(): - writer.assign(nelements, dest.get_ref(array.size)) - elif array.is_remaining_length(): - if element_type.is_fixed_nw_size(): - writer.assign(nelements, "(message_end - in) / (%s)" %(element_type.get_fixed_nw_size())) - else: - raise NotImplementedError("TODO array[] of dynamic element size not done yet") - elif array.is_image_size_length(): - bpp = array.size[1] - width = array.size[2] - rows = array.size[3] - width_v = dest.get_ref(width) - rows_v = dest.get_ref(rows) - # TODO: Handle multiplication overflow - if bpp == 8: - writer.assign(nelements, "%s * %s" % (width_v, rows_v)) - elif bpp == 1: - writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v)) - else: - writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v)) - elif array.is_bytes_length(): - writer.assign(nelements, dest.get_ref(array.size[2])) - else: - raise NotImplementedError("TODO array size type not handled yet") - return nelements - -def write_switch_parser(writer, container, switch, dest, scope): - var = container.lookup_member(switch.variable) - var_type = var.member_type - - if switch.has_attr("fixedsize"): - scope.variable_def("uint8_t *", "in_save") - writer.assign("in_save", "in") - - first = True - for c in switch.cases: - check = c.get_check(dest.get_ref(switch.variable), var_type) - m = c.member - with writer.if_block(check, not first, False) as block: - t = m.member_type - if switch.has_end_attr(): - dest2 = dest.child_at_end(writer, m.member_type) - elif switch.has_attr("anon"): - if t.is_struct() and not m.has_attr("to_ptr"): - dest2 = dest.child_sub(m.name) - else: - dest2 = dest - else: - if t.is_struct(): - dest2 = dest.child_sub(switch.name + "." + m.name) - else: - dest2 = dest.child_sub(switch.name) - dest2.reuse_scope = block - - if m.has_attr("to_ptr"): - write_parse_to_pointer(writer, t, False, dest2, m.name, block) - elif t.is_pointer(): - write_parse_pointer(writer, t, False, dest2, m.name, block) - elif t.is_struct(): - write_container_parser(writer, t, dest2) - elif t.is_primitive(): - if m.has_attr("zero"): - writer.statement("consume_%s(&in)" % (t.primitive_type())) - else: - writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type())) - #TODO validate e.g. flags and enums - elif t.is_array(): - nelements = read_array_len(writer, m.name, t, dest, block, False) - write_array_parser(writer, m, nelements, t, dest2, block) - else: - writer.todo("Can't handle type %s" % m.member_type) - - first = False - - writer.newline() - - if switch.has_attr("fixedsize"): - writer.assign("in", "in_save + %s" % switch.get_fixed_nw_size()) - -def write_parse_ptr_function(writer, target_type): - if target_type.is_array(): - parse_function = "parse_array_%s" % target_type.element_type.primitive_type() - else: - parse_function = "parse_struct_%s" % target_type.c_type() - if writer.is_generated("parser", parse_function): - return parse_function - - writer.set_is_generated("parser", parse_function) - - writer = writer.function_helper() - scope = writer.function(parse_function, "static uint8_t *", "uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, int minor") - scope.variable_def("uint8_t *", "in = message_start + this_ptr_info->offset") - scope.variable_def("uint8_t *", "end") - - num_pointers = target_type.get_num_pointers() - if num_pointers != 0: - scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size") - scope.variable_def("uint32_t", "n_ptr=0") - scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers) - - writer.newline() - if target_type.is_array(): - writer.assign("end", "struct_data") - else: - writer.assign("end", "struct_data + %s" % (target_type.sizeof())) - - dest = RootDemarshallingDestination(None, target_type.c_type(), target_type.sizeof(), "struct_data") - dest.is_helper = True - dest.reuse_scope = scope - if target_type.is_array(): - write_array_parser(writer, None, "this_ptr_info->nelements", target_type, dest, scope) - else: - write_container_parser(writer, target_type, dest) - - if num_pointers != 0: - write_ptr_info_check(writer) - - writer.statement("return end") - - if writer.has_error_check: - writer.newline() - writer.label("error") - writer.statement("return NULL") - - writer.end_block() - - return parse_function - -def write_array_parser(writer, member, nelements, array, dest, scope): - is_byte_size = array.is_bytes_length() - - element_type = array.element_type - if member: - array_start = dest.get_ref(member.name) - at_end = member.has_attr("end") - else: - array_start = "end" - at_end = True - - if element_type == ptypes.uint8 or element_type == ptypes.int8: - writer.statement("memcpy(%s, in, %s)" % (array_start, nelements)) - writer.increment("in", nelements) - if at_end: - writer.increment("end", nelements) - else: - with writer.index() as index: - if member: - array_pos = "%s[%s]" % (array_start, index) - else: - array_pos = "*(%s *)end" % (element_type.c_type()) - - if array.has_attr("ptr_array"): - scope.variable_def("void **", "ptr_array") - scope.variable_def("int", "ptr_array_index") - writer.assign("ptr_array_index", 0) - writer.assign("ptr_array", "(void **)%s" % array_start) - writer.increment("end", "sizeof(void *) * %s" % nelements) - array_start = "end" - array_pos = "*(%s *)end" % (element_type.c_type()) - at_end = True - - with writer.for_loop(index, nelements) as array_scope: - if array.has_attr("ptr_array"): - writer.statement("ptr_array[ptr_array_index++] = end") - if element_type.is_primitive(): - writer.statement("%s = consume_%s(&in)" % (array_pos, element_type.primitive_type())) - if at_end: - writer.increment("end", element_type.sizeof()) - else: - if at_end: - dest2 = dest.child_at_end(writer, element_type) - else: - dest2 = RootDemarshallingDestination(dest, element_type.c_type(), element_type.c_type(), array_pos) - dest2.reuse_scope = array_scope - write_container_parser(writer, element_type, dest2) - if array.has_attr("ptr_array"): - writer.comment("Align ptr_array element to 4 bytes").newline() - writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)") - -def write_parse_pointer_core(writer, target_type, offset, at_end, dest, member_name, scope): - writer.assign("ptr_info[n_ptr].offset", offset) - writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) - if at_end: - writer.assign("ptr_info[n_ptr].dest", "(void **)end") - writer.increment("end", "sizeof(void *)") - else: - writer.assign("ptr_info[n_ptr].dest", "(void **)&%s" % dest.get_ref(member_name)) - if target_type.is_array(): - nelements = read_array_len(writer, member_name, target_type, dest, scope, True) - writer.assign("ptr_info[n_ptr].nelements", nelements) - - writer.statement("n_ptr++") - -def write_parse_pointer(writer, t, at_end, dest, member_name, scope): - write_parse_pointer_core(writer, t.target_type, "consume_%s(&in)" % t.primitive_type(), - at_end, dest, member_name, scope) - -def write_parse_to_pointer(writer, t, at_end, dest, member_name, scope): - write_parse_pointer_core(writer, t, "in - start", - at_end, dest, member_name, scope) - writer.increment("in", "%s__saved_size" % member_name) - -def write_member_parser(writer, container, member, dest, scope): - if member.has_attr("virtual"): - writer.assign(dest.get_ref(member.name), member.attributes["virtual"][0]) - return - - if member.is_switch(): - write_switch_parser(writer, container, member, dest, scope) - return - - t = member.member_type - - if member.has_attr("to_ptr"): - write_parse_to_pointer(writer, t, member.has_end_attr(), dest, member.name, scope) - elif t.is_pointer(): - if member.has_attr("chunk"): - assert(t.target_type.is_array()) - nelements = read_array_len(writer, member.name, t.target_type, dest, scope, True) - writer.comment("Reuse data from network message as chunk").newline() - scope.variable_def("SpiceChunks *", "chunks") - writer.assign("chunks", "(SpiceChunks *)end") - writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)") - writer.assign(dest.get_ref(member.name), "chunks") - writer.assign("chunks->data_size", nelements) - writer.assign("chunks->flags", 0) - writer.assign("chunks->num_chunks", 1) - writer.assign("chunks->chunk[0].len", nelements) - writer.assign("chunks->chunk[0].data", "message_start + consume_%s(&in)" % t.primitive_type()) - elif member.has_attr("nocopy"): - writer.comment("Reuse data from network message").newline() - writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_%s(&in))" % t.primitive_type()) - else: - write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, scope) - elif t.is_primitive(): - if member.has_attr("zero"): - writer.statement("consume_%s(&in)" % t.primitive_type()) - elif member.has_end_attr(): - writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type())) - writer.increment("end", t.sizeof()) - else: - if member.has_attr("bytes_count"): - dest_var = dest.get_ref(member.attributes["bytes_count"][0]) - else: - dest_var = dest.get_ref(member.name) - writer.assign(dest_var, "consume_%s(&in)" % (t.primitive_type())) - #TODO validate e.g. flags and enums - elif t.is_array(): - nelements = read_array_len(writer, member.name, t, dest, scope, False) - if member.has_attr("chunk") and t.element_type.is_fixed_nw_size() and t.element_type.get_fixed_nw_size() == 1: - writer.comment("use array as chunk").newline() - - scope.variable_def("SpiceChunks *", "chunks") - writer.assign("chunks", "(SpiceChunks *)end") - writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)") - writer.assign(dest.get_ref(member.name), "chunks") - writer.assign("chunks->data_size", nelements) - writer.assign("chunks->flags", 0) - writer.assign("chunks->num_chunks", 1) - writer.assign("chunks->chunk[0].len", nelements) - writer.assign("chunks->chunk[0].data", "in") - writer.increment("in", "%s" % (nelements)) - elif member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size(): - writer.comment("use array as pointer").newline() - writer.assign(dest.get_ref(member.name), "(%s *)in" % t.element_type.c_type()) - len_var = member.attributes["as_ptr"] - if len(len_var) > 0: - writer.assign(dest.get_ref(len_var[0]), nelements) - el_size = t.element_type.get_fixed_nw_size() - if el_size != 1: - writer.increment("in", "%s * %s" % (nelements, el_size)) - else: - writer.increment("in", "%s" % (nelements)) - else: - write_array_parser(writer, member, nelements, t, dest, scope) - elif t.is_struct(): - if member.has_end_attr(): - dest2 = dest.child_at_end(writer, t) - else: - dest2 = dest.child_sub(member.name) - writer.comment(member.name) - write_container_parser(writer, t, dest2) - else: - raise NotImplementedError("TODO can't handle parsing of %s" % t) - -def write_container_parser(writer, container, dest): - with dest.declare(writer) as scope: - for m in container.members: - if m.has_minor_attr(): - writer.begin_block("if (minor >= %s)" % m.get_minor_attr()) - write_member_parser(writer, container, m, dest, scope) - if m.has_minor_attr(): - # We need to zero out the fixed part of all optional fields - if not m.member_type.is_array(): - writer.end_block(newline=False) - writer.begin_block(" else") - # TODO: This is not right for fields that don't exist in the struct - if m.has_attr("zero"): - pass - elif m.member_type.is_primitive(): - writer.assign(dest.get_ref(m.name), "0") - elif m.is_fixed_sizeof(): - writer.statement("memset ((char *)&%s, 0, %s)" % (dest.get_ref(m.name), m.sizeof())) - else: - raise NotImplementedError("TODO Clear optional dynamic fields") - writer.end_block() - -def write_ptr_info_check(writer): - writer.newline() - with writer.index() as index: - with writer.for_loop(index, "n_ptr") as scope: - offset = "ptr_info[%s].offset" % index - function = "ptr_info[%s].parse" % index - dest = "ptr_info[%s].dest" % index - with writer.if_block("%s == 0" % offset, newline=False): - writer.assign("*%s" % dest, "NULL") - with writer.block(" else"): - writer.comment("Align to 32 bit").newline() - writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)") - writer.assign("*%s" % dest, "(void *)end") - writer.assign("end", "%s(message_start, message_end, end, &ptr_info[%s], minor)" % (function, index)) - writer.error_check("end == NULL") - writer.newline() - -def write_nofree(writer): - if writer.is_generated("helper", "nofree"): - return - writer = writer.function_helper() - scope = writer.function("nofree", "static void", "uint8_t *data") - writer.end_block() - -def write_msg_parser(writer, message): - msg_name = message.c_name() - function_name = "parse_%s" % msg_name - if writer.is_generated("demarshaller", function_name): - return function_name - writer.set_is_generated("demarshaller", function_name) - - msg_type = message.c_type() - msg_sizeof = message.sizeof() - - want_mem_size = (len(message.members) != 1 or message.members[0].is_fixed_nw_size() - or not message.members[0].is_array()) - - writer.newline() - parent_scope = writer.function(function_name, - "uint8_t *", - "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size, message_destructor_t *free_message", True) - parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos") - parent_scope.variable_def("uint8_t *", "start = message_start") - parent_scope.variable_def("uint8_t *", "data = NULL") - parent_scope.variable_def("size_t", "nw_size") - if want_mem_size: - parent_scope.variable_def("size_t", "mem_size") - if not message.has_attr("nocopy"): - parent_scope.variable_def("uint8_t *", "in", "end") - num_pointers = message.get_num_pointers() - if num_pointers != 0: - parent_scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size") - parent_scope.variable_def("uint32_t", "n_ptr=0") - parent_scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers) - writer.newline() - - write_parser_helpers(writer) - - write_validate_container(writer, None, message, "start", parent_scope, True, - want_mem_size=want_mem_size, want_extra_size=False) - - writer.newline() - - writer.comment("Check if message fits in reported side").newline() - with writer.block("if (start + nw_size > message_end)"): - writer.statement("return NULL") - - writer.newline().comment("Validated extents and calculated size").newline() - - if message.has_attr("nocopy"): - write_nofree(writer) - writer.assign("data", "message_start") - writer.assign("*size", "message_end - message_start") - writer.assign("*free_message", "nofree") - else: - writer.assign("data", "(uint8_t *)malloc(mem_size)") - writer.error_check("data == NULL") - writer.assign("end", "data + %s" % (msg_sizeof)) - writer.assign("in", "start").newline() - - # avoid defined and assigned but not used warnings of gcc 4.6.0+ - if message.is_extra_size() or not message.is_fixed_nw_size() or message.get_fixed_nw_size() > 0: - dest = RootDemarshallingDestination(None, msg_type, msg_sizeof, "data") - dest.reuse_scope = parent_scope - write_container_parser(writer, message, dest) - - writer.newline() - writer.statement("assert(in <= message_end)") - - if num_pointers != 0: - write_ptr_info_check(writer) - - writer.statement("assert(end <= data + mem_size)") - - writer.newline() - writer.assign("*size", "end - data") - writer.assign("*free_message", "(message_destructor_t) free") - - writer.statement("return data") - writer.newline() - if writer.has_error_check: - writer.label("error") - with writer.block("if (data != NULL)"): - writer.statement("free(data)") - writer.statement("return NULL") - writer.end_block() - - return function_name - -def write_channel_parser(writer, channel, server): - writer.newline() - ids = {} - min_id = 1000000 - if server: - messages = channel.server_messages - else: - messages = channel.client_messages - for m in messages: - ids[m.value] = m - - ranges = [] - ids2 = ids.copy() - while len(ids2) > 0: - end = start = min(ids2.keys()) - while ids2.has_key(end): - del ids2[end] - end = end + 1 - - ranges.append( (start, end) ) - - if server: - function_name = "parse_%s_msg" % channel.name - else: - function_name = "parse_%s_msgc" % channel.name - writer.newline() - scope = writer.function(function_name, - "static uint8_t *", - "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message") - - helpers = writer.function_helper() - - d = 0 - for r in ranges: - d = d + 1 - writer.write("static parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0])) - writer.begin_block() - for i in range(r[0], r[1]): - func = write_msg_parser(helpers, ids[i].message_type) - writer.write(func) - if i != r[1] -1: - writer.write(",") - writer.newline() - - writer.end_block(semicolon = True) - - d = 0 - for r in ranges: - d = d + 1 - with writer.if_block("message_type >= %d && message_type < %d" % (r[0], r[1]), d > 1, False): - writer.statement("return funcs%d[message_type-%d](message_start, message_end, minor, size_out, free_message)" % (d, r[0])) - writer.newline() - - writer.statement("return NULL") - writer.end_block() - - 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() - for i in range(0, max_channel + 1): - writer.write("{ ") - if channel_parsers.has_key(i): - writer.write(channel_parsers[i][1]) - writer.write(", ") - - channel = channel_parsers[i][0] - 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) - else: - writer.write("NULL, 0") - writer.write("}") - - if i != max_channel: - writer.write(",") - writer.newline() - writer.end_block(semicolon = True) - - with writer.if_block("channel < %d" % (max_channel + 1)): - with writer.if_block("max_message_type != NULL"): - writer.assign("*max_message_type", "channels[channel].max_messages") - writer.statement("return channels[channel].func") - - writer.statement("return NULL") - writer.end_block() - - -def write_full_protocol_parser(writer, is_server): - writer.newline() - if is_server: - function_name = "spice_parse_msg" - else: - function_name = "spice_parse_reply" - scope = writer.function(function_name + writer.public_prefix, - "uint8_t *", - "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message") - scope.variable_def("spice_parse_channel_func_t", "func" ) - - if is_server: - writer.assign("func", "spice_get_server_channel_parser%s(channel, NULL)" % writer.public_prefix) - else: - writer.assign("func", "spice_get_client_channel_parser%s(channel, NULL)" % writer.public_prefix) - - with writer.if_block("func != NULL"): - writer.statement("return func(message_start, message_end, message_type, minor, size_out, free_message)") - - writer.statement("return NULL") - writer.end_block() - -def write_protocol_parser(writer, proto, is_server): - max_channel = 0 - parsers = {} - - for channel in proto.channels: - max_channel = max(max_channel, channel.value) - - parsers[channel.value] = (channel.channel_type, write_channel_parser(writer, channel.channel_type, is_server)) - - write_get_channel_parser(writer, parsers, max_channel, is_server) - write_full_protocol_parser(writer, is_server) - -def write_includes(writer): - writer.writeln("#include <string.h>") - writer.writeln("#include <assert.h>") - writer.writeln("#include <stdlib.h>") - writer.writeln("#include <stdio.h>") - writer.writeln("#include <spice/protocol.h>") - writer.writeln("#include <spice/macros.h>") - writer.writeln('#include "mem.h"') - writer.newline() - writer.writeln("#ifdef _MSC_VER") - writer.writeln("#pragma warning(disable:4101)") - writer.writeln("#endif") diff --git a/python_modules/marshal.py b/python_modules/marshal.py deleted file mode 100644 index 5b4dfdd7..00000000 --- a/python_modules/marshal.py +++ /dev/null @@ -1,402 +0,0 @@ -from __future__ import with_statement -import ptypes -import codegen - -def write_includes(writer): - writer.header.writeln("#include <spice/protocol.h>") - writer.header.writeln("#include <marshaller.h>") - writer.header.newline() - writer.header.writeln("#ifndef _GENERATED_HEADERS_H") - writer.header.writeln("#define _GENERATED_HEADERS_H") - - writer.writeln("#include <string.h>") - writer.writeln("#include <assert.h>") - writer.writeln("#include <stdlib.h>") - writer.writeln("#include <stdio.h>") - writer.writeln("#include <spice/protocol.h>") - writer.writeln("#include <spice/macros.h>") - writer.writeln("#include <marshaller.h>") - writer.newline() - writer.writeln("#ifdef _MSC_VER") - writer.writeln("#pragma warning(disable:4101)") - writer.writeln("#pragma warning(disable:4018)") - writer.writeln("#endif") - writer.newline() - -class MarshallingSource: - def __init__(self): - pass - - def child_at_end(self, t): - return RootMarshallingSource(self, t.c_type(), t.sizeof()) - - def child_sub(self, containee): - return SubMarshallingSource(self, containee) - - def declare(self, writer): - return writer.optional_block(self.reuse_scope) - - def is_toplevel(self): - return self.parent_src == None and not self.is_helper - -class RootMarshallingSource(MarshallingSource): - def __init__(self, parent_src, c_type, sizeof, pointer = None): - self.is_helper = False - self.reuse_scope = None - self.parent_src = parent_src - if parent_src: - self.base_var = codegen.increment_identifier(parent_src.base_var) - else: - self.base_var = "src" - self.c_type = c_type - self.sizeof = sizeof - self.pointer = pointer - assert pointer != None - - def get_self_ref(self): - return self.base_var - - def get_ref(self, member): - return self.base_var + "->" + member - - def declare(self, writer): - if self.reuse_scope: - scope = self.reuse_scope - else: - writer.begin_block() - scope = writer.get_subwriter() - - scope.variable_def(self.c_type + " *", self.base_var) - if not self.reuse_scope: - scope.newline() - - writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer)) - writer.newline() - - if self.reuse_scope: - return writer.no_block(self.reuse_scope) - else: - return writer.partial_block(scope) - -class SubMarshallingSource(MarshallingSource): - def __init__(self, parent_src, containee): - self.reuse_scope = None - self.parent_src = parent_src - self.base_var = parent_src.base_var - self.containee = containee - self.name = containee.name - self.is_helper = False - - def get_self_ref(self): - if self.containee.has_attr("to_ptr"): - return "%s" % self.parent_src.get_ref(self.name) - else: - return "&%s" % self.parent_src.get_ref(self.name) - - def get_ref(self, member): - if self.containee.has_attr("to_ptr"): - return self.parent_src.get_ref(self.name) + "->" + member - else: - return self.parent_src.get_ref(self.name) + "." + member - -def write_marshal_ptr_function(writer, target_type): - if target_type.is_array(): - marshal_function = "spice_marshall_array_%s" % target_type.element_type.primitive_type() - else: - marshal_function = "spice_marshall_%s" % target_type.name - if writer.is_generated("marshaller", marshal_function): - return marshal_function - - writer.set_is_generated("marshaller", marshal_function) - - names = target_type.get_pointer_names(False) - names_args = "" - if len(names) > 0: - n = map(lambda name: ", SpiceMarshaller **%s_out" % name, names) - names_args = "".join(n) - - header = writer.header - writer = writer.function_helper() - writer.header = header - writer.out_prefix = "" - if target_type.is_array(): - scope = writer.function(marshal_function, "SPICE_GNUC_UNUSED static void", "SpiceMarshaller *m, %s_t *ptr, unsigned count" % target_type.element_type.primitive_type() + names_args) - else: - scope = writer.function(marshal_function, "void", "SpiceMarshaller *m, %s *ptr" % target_type.c_type() + names_args) - header.writeln("void " + marshal_function + "(SpiceMarshaller *m, %s *msg" % target_type.c_type() + names_args + ");") - scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2") - - for n in names: - writer.assign("*%s_out" % n, "NULL") - - writer.newline() - - if target_type.is_struct(): - src = RootMarshallingSource(None, target_type.c_type(), target_type.sizeof(), "ptr") - src.reuse_scope = scope - write_container_marshaller(writer, target_type, src) - elif target_type.is_array() and target_type.element_type.is_primitive(): - with writer.index() as index: - with writer.for_loop(index, "count") as array_scope: - writer.statement("spice_marshaller_add_%s(m, *ptr++)" % (target_type.element_type.primitive_type())) - else: - writer.todo("Unsuppored pointer marshaller type") - - writer.end_block() - - return marshal_function - -def get_array_size(array, container_src): - if array.is_constant_length(): - return array.size - elif array.is_identifier_length(): - return container_src.get_ref(array.size) - elif array.is_remaining_length(): - raise NotImplementedError("remaining size array sizes marshalling not supported") - elif array.is_image_size_length(): - bpp = array.size[1] - width = array.size[2] - rows = array.size[3] - width_v = container_src.get_ref(width) - rows_v = container_src.get_ref(rows) - # TODO: Handle multiplication overflow - if bpp == 8: - return "(%s * %s)" % (width_v, rows_v) - elif bpp == 1: - return "(((%s + 7) / 8 ) * %s)" % (width_v, rows_v) - else: - return "(((%s * %s + 7) / 8 ) * %s)" % (bpp, width_v, rows_v) - elif array.is_bytes_length(): - return container_src.get_ref(array.size[2]) - else: - raise NotImplementedError("TODO array size type not handled yet: %s" % array) - -def write_array_marshaller(writer, member, array, container_src, scope): - element_type = array.element_type - - if array.is_remaining_length(): - writer.comment("Remaining data must be appended manually").newline() - return - - nelements = get_array_size(array, container_src) - is_byte_size = array.is_bytes_length() - - element = "%s__element" % member.name - - if not scope.variable_defined(element): - if array.has_attr("ptr_array"): - stars = " **" - else: - stars = " *" - scope.variable_def(element_type.c_type() + stars, element) - element_array = element - if array.has_attr("ptr_array"): - element = "*" + element - - writer.assign(element_array, container_src.get_ref(member.name)) - - if is_byte_size: - size_start_var = "%s__size_start" % member.name - scope.variable_def("size_t", size_start_var) - writer.assign(size_start_var, "spice_marshaller_get_size(m)") - - with writer.index() as index: - with writer.for_loop(index, nelements) as array_scope: - if element_type.is_primitive(): - writer.statement("spice_marshaller_add_%s(m, *%s)" % (element_type.primitive_type(), element)) - elif element_type.is_struct(): - src2 = RootMarshallingSource(container_src, element_type.c_type(), element_type.sizeof(), element) - src2.reuse_scope = array_scope - write_container_marshaller(writer, element_type, src2) - else: - writer.todo("array element unhandled type").newline() - - writer.statement("%s++" % element_array) - - if is_byte_size: - size_var = member.container.lookup_member(array.size[1]) - size_var_type = size_var.member_type - var = "%s__ref" % array.size[1] - writer.statement("spice_marshaller_set_%s(m, %s, spice_marshaller_get_size(m) - %s)" % (size_var_type.primitive_type(), var, size_start_var)) - -def write_pointer_marshaller(writer, member, src): - t = member.member_type - ptr_func = write_marshal_ptr_function(writer, t.target_type) - submarshaller = "spice_marshaller_get_ptr_submarshaller(m, %d)" % (1 if member.get_fixed_nw_size() == 8 else 0) - if member.has_attr("marshall"): - rest_args = "" - if t.target_type.is_array(): - rest_args = ", %s" % get_array_size(t.target_type, src) - writer.assign("m2", submarshaller) - if t.has_attr("nonnull"): - writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args)) - else: - with writer.if_block("%s != NULL" % src.get_ref(member.name)) as block: - writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args)) - else: - writer.assign("*%s_out" % (writer.out_prefix + member.name), submarshaller) - -def write_switch_marshaller(writer, container, switch, src, scope): - var = container.lookup_member(switch.variable) - var_type = var.member_type - - saved_out_prefix = writer.out_prefix - first = True - for c in switch.cases: - check = c.get_check(src.get_ref(switch.variable), var_type) - m = c.member - writer.out_prefix = saved_out_prefix - if m.has_attr("outvar"): - writer.out_prefix = "%s_%s" % (m.attributes["outvar"][0], writer.out_prefix) - with writer.if_block(check, not first, False) as block: - t = m.member_type - if switch.has_attr("anon"): - if t.is_struct(): - src2 = src.child_sub(m) - else: - src2 = src - else: - if t.is_struct(): - src2 = src.child_sub(switch).child_sub(m) - else: - src2 = src.child_sub(switch) - src2.reuse_scope = block - - if t.is_struct(): - write_container_marshaller(writer, t, src2) - elif t.is_pointer(): - write_pointer_marshaller(writer, m, src2) - elif t.is_primitive(): - if m.has_attr("zero"): - writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type())) - else: - writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src2.get_ref(m.name))) - #TODO validate e.g. flags and enums - elif t.is_array(): - write_array_marshaller(writer, m, t, src2, scope) - else: - writer.todo("Can't handle type %s" % m.member_type) - - if switch.has_attr("fixedsize"): - remaining = switch.get_fixed_nw_size() - t.get_fixed_nw_size() - if remaining != 0: - writer.statement("spice_marshaller_reserve_space(m, %s)" % remaining) - - first = False - if switch.has_attr("fixedsize"): - with writer.block(" else"): - writer.statement("spice_marshaller_reserve_space(m, %s)" % switch.get_fixed_nw_size()) - - writer.newline() - -def write_member_marshaller(writer, container, member, src, scope): - if member.has_attr("outvar"): - writer.out_prefix = "%s_%s" % (member.attributes["outvar"][0], writer.out_prefix) - if member.has_attr("virtual"): - writer.comment("Don't marshall @virtual %s" % member.name).newline() - return - if member.has_attr("nomarshal"): - writer.comment("Don't marshall @nomarshal %s" % member.name).newline() - return - if member.is_switch(): - write_switch_marshaller(writer, container, member, src, scope) - return - - t = member.member_type - - if t.is_pointer(): - write_pointer_marshaller(writer, member, src) - elif t.is_primitive(): - if member.has_attr("zero"): - writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type())) - if member.has_attr("bytes_count"): - var = "%s__ref" % member.name - scope.variable_def("void *", var) - writer.statement("%s = spice_marshaller_add_%s(m, %s)" % (var, t.primitive_type(), 0)) - - else: - writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src.get_ref(member.name))) - elif t.is_array(): - write_array_marshaller(writer, member, t, src, scope) - elif t.is_struct(): - src2 = src.child_sub(member) - writer.comment(member.name) - write_container_marshaller(writer, t, src2) - else: - raise NotImplementedError("TODO can't handle parsing of %s" % t) - -def write_container_marshaller(writer, container, src): - saved_out_prefix = writer.out_prefix - with src.declare(writer) as scope: - for m in container.members: - writer.out_prefix = saved_out_prefix - write_member_marshaller(writer, container, m, src, scope) - -def write_message_marshaller(writer, message, is_server, private): - writer.out_prefix = "" - function_name = "spice_marshall_" + message.c_name() - if writer.is_generated("marshaller", function_name): - return function_name - writer.set_is_generated("marshaller", function_name) - - names = message.get_pointer_names(False) - names_args = "" - if len(names) > 0: - n = map(lambda name: ", SpiceMarshaller **%s_out" % name, names) - names_args = "".join(n) - - if not private: - writer.header.writeln("void " + function_name + "(SpiceMarshaller *m, %s *msg" % message.c_type() + names_args + ");") - - scope = writer.function(function_name, - "static void" if private else "void", - "SpiceMarshaller *m, %s *msg" % message.c_type() + names_args) - scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2") - - for n in names: - writer.assign("*%s_out" % n, "NULL") - - # fix warnings about unused variables by not creating body if no members to parse - if any(x.is_fixed_nw_size() for x in message.members): - src = RootMarshallingSource(None, message.c_type(), message.sizeof(), "msg") - src.reuse_scope = scope - - write_container_marshaller(writer, message, src) - - writer.end_block() - 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 is_server: - for m in channel.client_messages: - message = m.message_type - f = write_message_marshaller(writer, message, is_server, private_marshallers) - functions[f] = True - else: - for m in channel.server_messages: - message = m.message_type - f= write_message_marshaller(writer, message, is_server, private_marshallers) - functions[f] = True - - 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 - writer.assign("marshallers.%s" % member, 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 45859498..00000000 --- a/python_modules/ptypes.py +++ /dev/null @@ -1,1044 +0,0 @@ -import codegen -import types - -_types_by_name = {} -_types = [] - -default_pointer_size = 4 - -def type_exists(name): - return _types_by_name.has_key(name) - -def lookup_type(name): - return _types_by_name[name] - -def get_named_types(): - return _types - -class FixedSize: - def __init__(self, val = 0, minor = 0): - if isinstance(val, FixedSize): - self.vals = val.vals - else: - self.vals = [0] * (minor + 1) - self.vals[minor] = val - - def __add__(self, other): - if isinstance(other, types.IntType): - other = FixedSize(other) - - new = FixedSize() - l = max(len(self.vals), len(other.vals)) - shared = min(len(self.vals), len(other.vals)) - - new.vals = [0] * l - - for i in range(shared): - new.vals[i] = self.vals[i] + other.vals[i] - - for i in range(shared,len(self.vals)): - new.vals[i] = self.vals[i] - - for i in range(shared,len(other.vals)): - new.vals[i] = new.vals[i] + other.vals[i] - - return new - - def __radd__(self, other): - return self.__add__(other) - - def __str__(self): - s = "%d" % (self.vals[0]) - - for i in range(1,len(self.vals)): - if self.vals[i] > 0: - s = s + " + ((minor >= %d)?%d:0)" % (i, self.vals[i]) - return s - -# Some attribute are propagated from member to the type as they really -# are part of the type definition, rather than the member. This applies -# only to attributes that affect pointer or array attributes, as these -# are member local types, unlike e.g. a Struct that may be used by -# other members -propagated_attributes=["ptr_array", "nonnull", "chunk"] - -class Type: - def __init__(self): - self.attributes = {} - self.registred = False - self.name = None - - def has_name(self): - return self.name != None - - def get_type(self, recursive=False): - return self - - def is_primitive(self): - return False - - def is_fixed_sizeof(self): - return True - - def is_extra_size(self): - return False - - def contains_extra_size(self): - return False - - def is_fixed_nw_size(self): - return True - - def is_array(self): - return isinstance(self, ArrayType) - - def contains_member(self, member): - return False - - def is_struct(self): - return isinstance(self, StructType) - - def is_pointer(self): - return isinstance(self, PointerType) - - def get_num_pointers(self): - return 0 - - def get_pointer_names(self, marshalled): - return [] - - def sizeof(self): - return "sizeof(%s)" % (self.c_type()) - - def __repr__(self): - return self.__str__() - - def __str__(self): - if self.name != None: - return self.name - return "anonymous type" - - def resolve(self): - return self - - def register(self): - if self.registred or self.name == None: - return - self.registred = True - if _types_by_name.has_key(self.name): - raise Exception, "Type %s already defined" % self.name - _types.append(self) - _types_by_name[self.name] = self - - def has_attr(self, name): - return self.attributes.has_key(name) - -class TypeRef(Type): - def __init__(self, name): - Type.__init__(self) - self.name = name - - def __str__(self): - return "ref to %s" % (self.name) - - def resolve(self): - if not _types_by_name.has_key(self.name): - raise Exception, "Unknown type %s" % self.name - return _types_by_name[self.name] - - def register(self): - assert True, "Can't register TypeRef!" - - -class IntegerType(Type): - def __init__(self, bits, signed): - Type.__init__(self) - self.bits = bits - self.signed = signed - - if signed: - self.name = "int%d" % bits - else: - self.name = "uint%d" % bits - - def primitive_type(self): - return self.name - - def c_type(self): - return self.name + "_t" - - def get_fixed_nw_size(self): - return self.bits / 8 - - def is_primitive(self): - return True - -class TypeAlias(Type): - def __init__(self, name, the_type, attribute_list): - Type.__init__(self) - self.name = name - self.the_type = the_type - for attr in attribute_list: - self.attributes[attr[0][1:]] = attr[1:] - - def get_type(self, recursive=False): - if recursive: - return self.the_type.get_type(True) - else: - return self.the_type - - def primitive_type(self): - return self.the_type.primitive_type() - - def resolve(self): - self.the_type = self.the_type.resolve() - return self - - def __str__(self): - return "alias %s" % self.name - - def is_primitive(self): - return self.the_type.is_primitive() - - def is_fixed_sizeof(self): - return self.the_type.is_fixed_sizeof() - - def is_fixed_nw_size(self): - return self.the_type.is_fixed_nw_size() - - def get_fixed_nw_size(self): - return self.the_type.get_fixed_nw_size() - - def get_num_pointers(self): - return self.the_type.get_num_pointers() - - def get_pointer_names(self, marshalled): - return self.the_type.get_pointer_names(marshalled) - - def c_type(self): - if self.has_attr("ctype"): - return self.attributes["ctype"][0] - return self.name - -class EnumBaseType(Type): - def is_enum(self): - return isinstance(self, EnumType) - - def primitive_type(self): - return "uint%d" % (self.bits) - - def c_type(self): - return "uint%d_t" % (self.bits) - - def c_name(self): - return codegen.prefix_camel(self.name) - - def c_enumname(self, value): - if self.has_attr("prefix"): - return self.attributes["prefix"][0] + self.names[value] - return codegen.prefix_underscore_upper(self.name.upper(), self.names[value]) - - def c_enumname_by_name(self, name): - if self.has_attr("prefix"): - return self.attributes["prefix"][0] + name - return codegen.prefix_underscore_upper(self.name.upper(), name) - - def is_primitive(self): - return True - - def get_fixed_nw_size(self): - return self.bits / 8 - -class EnumType(EnumBaseType): - def __init__(self, bits, name, enums, attribute_list): - Type.__init__(self) - self.bits = bits - self.name = name - - last = -1 - names = {} - values = {} - for v in enums: - name = v[0] - if len(v) > 1: - value = v[1] - else: - value = last + 1 - last = value - - assert not names.has_key(value) - names[value] = name - values[name] = value - - self.names = names - self.values = values - - for attr in attribute_list: - self.attributes[attr[0][1:]] = attr[1:] - - def __str__(self): - return "enum %s" % self.name - - def c_define(self, writer): - writer.write("typedef enum ") - writer.write(self.c_name()) - writer.begin_block() - values = self.names.keys() - values.sort() - current_default = 0 - for i in values: - writer.write(self.c_enumname(i)) - if i != current_default: - writer.write(" = %d" % (i)) - writer.write(",") - writer.newline() - current_default = i + 1 - writer.newline() - writer.write(codegen.prefix_underscore_upper(self.name.upper(), "ENUM_END")) - writer.newline() - writer.end_block(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 not names.has_key(value) - names[value] = name - values[name] = value - - self.names = names - self.values = values - - for attr in attribute_list: - self.attributes[attr[0][1:]] = attr[1:] - - def __str__(self): - return "flags %s" % self.name - - def c_define(self, writer): - writer.write("typedef enum ") - writer.write(self.c_name()) - writer.begin_block() - values = self.names.keys() - values.sort() - mask = 0 - for i in values: - writer.write(self.c_enumname(i)) - mask = mask | (1<<i) - writer.write(" = (1 << %d)" % (i)) - writer.write(",") - writer.newline() - current_default = i + 1 - writer.newline() - writer.write(codegen.prefix_underscore_upper(self.name.upper(), "MASK")) - writer.write(" = 0x%x" % (mask)) - writer.newline() - writer.end_block(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, types.IntType) - - def is_remaining_length(self): - return isinstance(self.size, types.StringType) and len(self.size) == 0 - - def is_identifier_length(self): - return isinstance(self.size, types.StringType) and len(self.size) > 0 - - def is_image_size_length(self): - if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType): - return False - return self.size[0] == "image_size" - - def is_bytes_length(self): - if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType): - return False - return self.size[0] == "bytes" - - def is_cstring_length(self): - if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType): - return False - return self.size[0] == "cstring" - - def is_fixed_sizeof(self): - return self.is_constant_length() and self.element_type.is_fixed_sizeof() - - def is_fixed_nw_size(self): - return self.is_constant_length() and self.element_type.is_fixed_nw_size() - - def get_fixed_nw_size(self): - if not self.is_fixed_nw_size(): - raise Exception, "Not a fixed size type" - - return self.element_type.get_fixed_nw_size() * self.size - - def get_num_pointers(self): - element_count = self.element_type.get_num_pointers() - if element_count == 0: - return 0 - if self.is_constant_length(self): - return element_count * self.size - raise Exception, "Pointers in dynamic arrays not supported" - - def get_pointer_names(self, marshalled): - element_count = self.element_type.get_num_pointers() - if element_count == 0: - return [] - raise Exception, "Pointer names in arrays not supported" - - def is_extra_size(self): - return self.has_attr("ptr_array") - - def contains_extra_size(self): - return self.element_type.contains_extra_size() or self.has_attr("chunk") - - def sizeof(self): - return "%s * %s" % (self.element_type.sizeof(), self.size) - - def c_type(self): - return self.element_type.c_type() - -class PointerType(Type): - def __init__(self, target_type): - Type.__init__(self) - self.name = None - self.target_type = target_type - self.pointer_size = default_pointer_size - - def __str__(self): - return "%s*" % (str(self.target_type)) - - def resolve(self): - self.target_type = self.target_type.resolve() - return self - - def set_ptr_size(self, new_size): - self.pointer_size = new_size - - def is_fixed_nw_size(self): - return True - - def is_primitive(self): - return True - - def primitive_type(self): - if self.pointer_size == 4: - return "uint32" - else: - return "uint64" - - def get_fixed_nw_size(self): - return self.pointer_size - - def c_type(self): - if self.pointer_size == 4: - return "uint32_t" - else: - return "uint64_t" - - def contains_extra_size(self): - return True - - def get_num_pointers(self): - return 1 - -class Containee: - def __init__(self): - self.attributes = {} - - def is_switch(self): - return False - - def is_pointer(self): - return not self.is_switch() and self.member_type.is_pointer() - - def is_array(self): - return not self.is_switch() and self.member_type.is_array() - - def is_struct(self): - return not self.is_switch() and self.member_type.is_struct() - - def is_primitive(self): - return not self.is_switch() and self.member_type.is_primitive() - - def has_attr(self, name): - return self.attributes.has_key(name) - - def has_minor_attr(self): - return self.has_attr("minor") - - def has_end_attr(self): - return self.has_attr("end") - - def get_minor_attr(self): - return self.attributes["minor"][0] - -class Member(Containee): - def __init__(self, name, member_type, attribute_list): - Containee.__init__(self) - self.name = name - self.member_type = member_type - for attr in attribute_list: - self.attributes[attr[0][1:]] = attr[1:] - - def resolve(self, container): - self.container = container - self.member_type = self.member_type.resolve() - self.member_type.register() - if self.has_attr("ptr32") and self.member_type.is_pointer(): - self.member_type.set_ptr_size(4) - for i in propagated_attributes: - if self.has_attr(i): - self.member_type.attributes[i] = self.attributes[i] - return self - - def contains_member(self, member): - return self.member_type.contains_member(member) - - def is_primitive(self): - return self.member_type.is_primitive() - - def is_fixed_sizeof(self): - if self.has_end_attr(): - return False - return self.member_type.is_fixed_sizeof() - - def is_extra_size(self): - return self.has_end_attr() or self.has_attr("to_ptr") or self.member_type.is_extra_size() - - def is_fixed_nw_size(self): - if self.has_attr("virtual"): - return True - return self.member_type.is_fixed_nw_size() - - def get_fixed_nw_size(self): - if self.has_attr("virtual"): - return 0 - size = self.member_type.get_fixed_nw_size() - if self.has_minor_attr(): - minor = self.get_minor_attr() - size = FixedSize(size, minor) - return size - - def contains_extra_size(self): - return self.member_type.contains_extra_size() - - def sizeof(self): - return self.member_type.sizeof() - - def __repr__(self): - return "%s (%s)" % (str(self.name), str(self.member_type)) - - def get_num_pointers(self): - if self.has_attr("to_ptr"): - return 1 - return self.member_type.get_num_pointers() - - def get_pointer_names(self, marshalled): - if self.member_type.is_pointer(): - if self.has_attr("marshall") == marshalled: - names = [self.name] - else: - names = [] - else: - names = self.member_type.get_pointer_names(marshalled) - if self.has_attr("outvar"): - prefix = self.attributes["outvar"][0] - names = map(lambda name: prefix + "_" + name, names) - return names - -class SwitchCase: - def __init__(self, values, member): - self.values = values - self.member = member - self.members = [member] - - def get_check(self, var_cname, var_type): - checks = [] - for v in self.values: - if v == None: - return "1" - elif var_type.is_enum(): - checks.append("%s == %s" % (var_cname, var_type.c_enumname_by_name(v[1]))) - else: - checks.append("%s(%s & %s)" % (v[0], var_cname, var_type.c_enumname_by_name(v[1]))) - return " || ".join(checks) - - def resolve(self, container): - self.switch = container - self.member = self.member.resolve(self) - return self - - def get_num_pointers(self): - return self.member.get_num_pointers() - - def get_pointer_names(self, marshalled): - return self.member.get_pointer_names(marshalled) - -class Switch(Containee): - def __init__(self, variable, cases, name, attribute_list): - Containee.__init__(self) - self.variable = variable - self.name = name - self.cases = cases - for attr in attribute_list: - self.attributes[attr[0][1:]] = attr[1:] - - def is_switch(self): - return True - - def lookup_case_member(self, name): - for c in self.cases: - if c.member.name == name: - return c.member - return None - - def has_switch_member(self, member): - for c in self.cases: - if c.member == member: - return True - return False - - def resolve(self, container): - self.container = container - self.cases = map(lambda c : c.resolve(self), self.cases) - return self - - def __repr__(self): - return "switch on %s %s" % (str(self.variable),str(self.name)) - - def is_fixed_sizeof(self): - # Kinda weird, but we're unlikely to have a real struct if there is an @end - if self.has_end_attr(): - return False - return True - - def is_fixed_nw_size(self): - if self.has_attr("fixedsize"): - return True - - size = None - has_default = False - for c in self.cases: - for v in c.values: - if v == None: - has_default = True - if not c.member.is_fixed_nw_size(): - return False - if size == None: - size = c.member.get_fixed_nw_size() - elif size != c.member.get_fixed_nw_size(): - return False - # Fixed size if all elements listed, or has default - if has_default: - return True - key = self.container.lookup_member(self.variable) - return len(self.cases) == len(key.member_type.values) - - def is_extra_size(self): - return self.has_end_attr() - - def contains_extra_size(self): - for c in self.cases: - if c.member.is_extra_size(): - return True - if c.member.contains_extra_size(): - return True - return False - - def get_fixed_nw_size(self): - if not self.is_fixed_nw_size(): - raise Exception, "Not a fixed size type" - size = 0 - for c in self.cases: - size = max(size, c.member.get_fixed_nw_size()) - return size - - def sizeof(self): - return "sizeof(((%s *)NULL)->%s)" % (self.container.c_type(), - self.name) - - def contains_member(self, member): - return False # TODO: Don't support switch deep member lookup yet - - def get_num_pointers(self): - count = 0 - for c in self.cases: - count = max(count, c.get_num_pointers()) - return count - - def get_pointer_names(self, marshalled): - names = [] - for c in self.cases: - names = names + c.get_pointer_names(marshalled) - return names - -class ContainerType(Type): - def is_fixed_sizeof(self): - for m in self.members: - if not m.is_fixed_sizeof(): - return False - return True - - def contains_extra_size(self): - for m in self.members: - if m.is_extra_size(): - return True - if m.contains_extra_size(): - return True - return False - - def is_fixed_nw_size(self): - for i in self.members: - if not i.is_fixed_nw_size(): - return False - return True - - def get_fixed_nw_size(self): - size = 0 - for i in self.members: - size = size + i.get_fixed_nw_size() - return size - - def contains_member(self, member): - for m in self.members: - if m == member or m.contains_member(member): - return True - return False - - def get_fixed_nw_offset(self, member): - size = 0 - for i in self.members: - if i == member: - break - if i.contains_member(member): - size = size + i.member_type.get_fixed_nw_offset(member) - break - if i.is_fixed_nw_size(): - size = size + i.get_fixed_nw_size() - return size - - def resolve(self): - self.members = map(lambda m : m.resolve(self), self.members) - return self - - def get_num_pointers(self): - count = 0 - for m in self.members: - count = count + m.get_num_pointers() - return count - - def get_pointer_names(self, marshalled): - names = [] - for m in self.members: - names = names + m.get_pointer_names(marshalled) - return names - - def get_nw_offset(self, member, prefix = "", postfix = ""): - fixed = self.get_fixed_nw_offset(member) - v = [] - container = self - while container != None: - members = container.members - container = None - for m in members: - if m == member: - break - if m.contains_member(member): - container = m.member_type - break - if m.is_switch() and m.has_switch_member(member): - break - if not m.is_fixed_nw_size(): - v.append(prefix + m.name + postfix) - if len(v) > 0: - return str(fixed) + " + " + (" + ".join(v)) - else: - return str(fixed) - - def lookup_member(self, name): - dot = name.find('.') - rest = None - if dot >= 0: - rest = name[dot+1:] - name = name[:dot] - - member = None - if self.members_by_name.has_key(name): - member = self.members_by_name[name] - else: - for m in self.members: - if m.is_switch(): - member = m.lookup_case_member(name) - if member != None: - break - if member != None: - break - - if member == None: - raise Exception, "No member called %s found" % name - - if rest != None: - return member.member_type.lookup_member(rest) - - return member - -class StructType(ContainerType): - def __init__(self, name, members, attribute_list): - Type.__init__(self) - self.name = name - self.members = members - self.members_by_name = {} - for m in members: - self.members_by_name[m.name] = m - for attr in attribute_list: - self.attributes[attr[0][1:]] = attr[1:] - - def __str__(self): - if self.name == None: - return "anonymous struct" - else: - return "struct %s" % self.name - - def c_type(self): - if self.has_attr("ctype"): - return self.attributes["ctype"][0] - return codegen.prefix_camel(self.name) - -class MessageType(ContainerType): - def __init__(self, name, members, attribute_list): - Type.__init__(self) - self.name = name - self.members = members - self.members_by_name = {} - for m in members: - self.members_by_name[m.name] = m - self.reverse_members = {} # ChannelMembers referencing this message - for attr in attribute_list: - self.attributes[attr[0][1:]] = attr[1:] - - def __str__(self): - if self.name == None: - return "anonymous message" - else: - return "message %s" % self.name - - def c_name(self): - if self.name == None: - cms = self.reverse_members.keys() - if len(cms) != 1: - raise "Unknown typename for message" - cm = cms[0] - channelname = cm.channel.member_name - if channelname == None: - channelname = "" - else: - channelname = channelname + "_" - if cm.is_server: - return "msg_" + channelname + cm.name - else: - return "msgc_" + channelname + cm.name - else: - return codegen.prefix_camel("Msg", self.name) - - def c_type(self): - if self.has_attr("ctype"): - return self.attributes["ctype"][0] - if self.name == None: - cms = self.reverse_members.keys() - if len(cms) != 1: - raise "Unknown typename for message" - cm = cms[0] - channelname = cm.channel.member_name - if channelname == None: - channelname = "" - if cm.is_server: - return codegen.prefix_camel("Msg", channelname, cm.name) - else: - return codegen.prefix_camel("Msgc", channelname, cm.name) - else: - return codegen.prefix_camel("Msg", self.name) - -class ChannelMember(Containee): - def __init__(self, name, message_type, value): - Containee.__init__(self) - self.name = name - self.message_type = message_type - self.value = value - - def resolve(self, channel): - self.channel = channel - self.message_type = self.message_type.resolve() - self.message_type.reverse_members[self] = 1 - - return self - - def __repr__(self): - return "%s (%s)" % (str(self.name), str(self.message_type)) - -class ChannelType(Type): - def __init__(self, name, base, members): - Type.__init__(self) - self.name = name - self.base = base - self.member_name = None - self.members = members - - def __str__(self): - if self.name == None: - return "anonymous channel" - else: - return "channel %s" % self.name - - def is_fixed_nw_size(self): - return False - - def get_client_message(self, name): - return self.client_messages_byname[name] - - def get_server_message(self, name): - return self.server_messages_byname[name] - - def resolve(self): - if self.base != None: - self.base = self.base.resolve() - - server_messages = self.base.server_messages[:] - server_messages_byname = self.base.server_messages_byname.copy() - client_messages = self.base.client_messages[:] - client_messages_byname = self.base.client_messages_byname.copy() - - # Set default member_name, FooChannel -> foo - self.member_name = self.name[:-7].lower() - else: - server_messages = [] - server_messages_byname = {} - client_messages = [] - client_messages_byname = {} - - server_count = 1 - client_count = 1 - - server = True - for m in self.members: - if m == "server": - server = True - elif m == "client": - server = False - elif server: - m.is_server = True - m = m.resolve(self) - if m.value: - server_count = m.value + 1 - else: - m.value = server_count - server_count = server_count + 1 - server_messages.append(m) - server_messages_byname[m.name] = m - else: - m.is_server = False - m = m.resolve(self) - if m.value: - client_count = m.value + 1 - else: - m.value = client_count - client_count = client_count + 1 - client_messages.append(m) - client_messages_byname[m.name] = m - - self.server_messages = server_messages - self.server_messages_byname = server_messages_byname - self.client_messages = client_messages - self.client_messages_byname = client_messages_byname - - return self - -class ProtocolMember: - def __init__(self, name, channel_type, value): - self.name = name - self.channel_type = channel_type - self.value = value - - def resolve(self, protocol): - self.channel_type = self.channel_type.resolve() - self.channel_type.member_name = self.name - return self - - def __repr__(self): - return "%s (%s)" % (str(self.name), str(self.channel_type)) - -class ProtocolType(Type): - def __init__(self, name, channels): - Type.__init__(self) - self.name = name - self.channels = channels - - def __str__(self): - if self.name == None: - return "anonymous protocol" - else: - return "protocol %s" % self.name - - def is_fixed_nw_size(self): - return False - - def resolve(self): - count = 1 - for m in self.channels: - m = m.resolve(self) - if m.value: - count = m.value + 1 - else: - m.value = count - count = count + 1 - - return self - -int8 = IntegerType(8, True) -uint8 = IntegerType(8, False) -int16 = IntegerType(16, True) -uint16 = IntegerType(16, False) -int32 = IntegerType(32, True) -uint32 = IntegerType(32, False) -int64 = IntegerType(64, True) -uint64 = IntegerType(64, False) diff --git a/python_modules/spice_parser.py b/python_modules/spice_parser.py deleted file mode 100644 index d0aabb09..00000000 --- a/python_modules/spice_parser.py +++ /dev/null @@ -1,161 +0,0 @@ -try: - from pyparsing import Literal, CaselessLiteral, Word, OneOrMore, ZeroOrMore, \ - Forward, delimitedList, Group, Optional, Combine, alphas, nums, restOfLine, cStyleComment, \ - alphanums, ParseException, ParseResults, Keyword, StringEnd, replaceWith -except ImportError: - print "Module pyparsing not found." - exit(1) - - -import ptypes -import sys - -cvtInt = lambda toks: int(toks[0]) - -def parseVariableDef(toks): - t = toks[0][0] - pointer = toks[0][1] - name = toks[0][2] - array_size = toks[0][3] - attributes = toks[0][4] - - if array_size != None: - t = ptypes.ArrayType(t, array_size) - - if pointer != None: - t = ptypes.PointerType(t) - - return ptypes.Member(name, t, attributes) - -bnf = None -def SPICE_BNF(): - global bnf - - if not bnf: - - # punctuation - colon = Literal(":").suppress() - lbrace = Literal("{").suppress() - rbrace = Literal("}").suppress() - lbrack = Literal("[").suppress() - rbrack = Literal("]").suppress() - lparen = Literal("(").suppress() - rparen = Literal(")").suppress() - equals = Literal("=").suppress() - comma = Literal(",").suppress() - semi = Literal(";").suppress() - - # primitive types - int8_ = Keyword("int8").setParseAction(replaceWith(ptypes.int8)) - uint8_ = Keyword("uint8").setParseAction(replaceWith(ptypes.uint8)) - int16_ = Keyword("int16").setParseAction(replaceWith(ptypes.int16)) - uint16_ = Keyword("uint16").setParseAction(replaceWith(ptypes.uint16)) - int32_ = Keyword("int32").setParseAction(replaceWith(ptypes.int32)) - uint32_ = Keyword("uint32").setParseAction(replaceWith(ptypes.uint32)) - int64_ = Keyword("int64").setParseAction(replaceWith(ptypes.int64)) - uint64_ = Keyword("uint64").setParseAction(replaceWith(ptypes.uint64)) - - # keywords - channel_ = Keyword("channel") - enum32_ = Keyword("enum32").setParseAction(replaceWith(32)) - enum16_ = Keyword("enum16").setParseAction(replaceWith(16)) - enum8_ = Keyword("enum8").setParseAction(replaceWith(8)) - flags32_ = Keyword("flags32").setParseAction(replaceWith(32)) - flags16_ = Keyword("flags16").setParseAction(replaceWith(16)) - flags8_ = Keyword("flags8").setParseAction(replaceWith(8)) - channel_ = Keyword("channel") - server_ = Keyword("server") - client_ = Keyword("client") - protocol_ = Keyword("protocol") - typedef_ = Keyword("typedef") - struct_ = Keyword("struct") - message_ = Keyword("message") - image_size_ = Keyword("image_size") - bytes_ = Keyword("bytes") - cstring_ = Keyword("cstring") - switch_ = Keyword("switch") - default_ = Keyword("default") - case_ = Keyword("case") - - identifier = Word( alphas, alphanums + "_" ) - enumname = Word( alphanums + "_" ) - - integer = ( Combine( CaselessLiteral("0x") + Word( nums+"abcdefABCDEF" ) ) | - Word( nums+"+-", nums ) ).setName("int").setParseAction(cvtInt) - - typename = identifier.copy().setParseAction(lambda toks : ptypes.TypeRef(str(toks[0]))) - - # This is just normal "types", i.e. not channels or messages - typeSpec = Forward() - - attributeValue = integer ^ identifier - attribute = Group(Combine ("@" + identifier) + Optional(lparen + delimitedList(attributeValue) + rparen)) - attributes = Group(ZeroOrMore(attribute)) - arraySizeSpecImage = Group(image_size_ + lparen + integer + comma + identifier + comma + identifier + rparen) - arraySizeSpecBytes = Group(bytes_ + lparen + identifier + comma + identifier + rparen) - arraySizeSpecCString = Group(cstring_ + lparen + rparen) - arraySizeSpec = lbrack + Optional(identifier ^ integer ^ arraySizeSpecImage ^ arraySizeSpecBytes ^arraySizeSpecCString, default="") + rbrack - variableDef = Group(typeSpec + Optional("*", default=None) + identifier + Optional(arraySizeSpec, default=None) + attributes - semi) \ - .setParseAction(parseVariableDef) - - switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | Group(case_.suppress() + Optional("!", default="") + identifier) + colon)) + variableDef) \ - .setParseAction(lambda toks: ptypes.SwitchCase(toks[0][0], toks[0][1])) - switchBody = Group(switch_ + lparen + delimitedList(identifier,delim='.', combine=True) + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \ - .setParseAction(lambda toks: ptypes.Switch(toks[0][1], toks[0][2], toks[0][3], toks[0][4])) - messageBody = structBody = Group(lbrace + ZeroOrMore(variableDef | switchBody) + rbrace) - structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3])) - - # have to use longest match for type, in case a user-defined type name starts with a keyword type, like "channel_type" - typeSpec << ( structSpec ^ int8_ ^ uint8_ ^ int16_ ^ uint16_ ^ - int32_ ^ uint32_ ^ int64_ ^ uint64_ ^ - typename).setName("type") - - flagsBody = enumBody = Group(lbrace + delimitedList(Group (enumname + Optional(equals + integer))) + Optional(comma) + rbrace) - - messageSpec = Group(message_ + messageBody + attributes).setParseAction(lambda toks: ptypes.MessageType(None, toks[0][1], toks[0][2])) | typename - - channelParent = Optional(colon + typename, default=None) - channelMessage = Group(messageSpec + identifier + Optional(equals + integer, default=None) + semi) \ - .setParseAction(lambda toks: ptypes.ChannelMember(toks[0][1], toks[0][0], toks[0][2])) - channelBody = channelParent + Group(lbrace + ZeroOrMore( server_ + colon | client_ + colon | channelMessage) + rbrace) - - enum_ = (enum32_ | enum16_ | enum8_) - flags_ = (flags32_ | flags16_ | flags8_) - enumDef = Group(enum_ + identifier + enumBody + attributes - semi).setParseAction(lambda toks: ptypes.EnumType(toks[0][0], toks[0][1], toks[0][2], toks[0][3])) - flagsDef = Group(flags_ + identifier + flagsBody + attributes - semi).setParseAction(lambda toks: ptypes.FlagsType(toks[0][0], toks[0][1], toks[0][2], toks[0][3])) - messageDef = Group(message_ + identifier + messageBody + attributes - semi).setParseAction(lambda toks: ptypes.MessageType(toks[0][1], toks[0][2], toks[0][3])) - channelDef = Group(channel_ + identifier + channelBody - semi).setParseAction(lambda toks: ptypes.ChannelType(toks[0][1], toks[0][2], toks[0][3])) - structDef = Group(struct_ + identifier + structBody + attributes - semi).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3])) - typedefDef = Group(typedef_ + identifier + typeSpec + attributes - semi).setParseAction(lambda toks: ptypes.TypeAlias(toks[0][1], toks[0][2], toks[0][3])) - - definitions = typedefDef | structDef | enumDef | flagsDef | messageDef | channelDef - - protocolChannel = Group(typename + identifier + Optional(equals + integer, default=None) + semi) \ - .setParseAction(lambda toks: ptypes.ProtocolMember(toks[0][1], toks[0][0], toks[0][2])) - protocolDef = Group(protocol_ + identifier + Group(lbrace + ZeroOrMore(protocolChannel) + rbrace) + semi) \ - .setParseAction(lambda toks: ptypes.ProtocolType(toks[0][1], toks[0][2])) - - bnf = ZeroOrMore (definitions) + protocolDef + StringEnd() - - singleLineComment = "//" + restOfLine - bnf.ignore( singleLineComment ) - bnf.ignore( cStyleComment ) - - return bnf - - -def parse(filename): - try: - bnf = SPICE_BNF() - types = bnf.parseFile(filename) - except ParseException, err: - print >> sys.stderr, err.line - print >> sys.stderr, " "*(err.column-1) + "^" - print >> sys.stderr, err - return None - - for t in types: - t.resolve() - t.register() - protocol = types[-1] - return protocol diff --git a/spice.proto b/spice.proto deleted file mode 100644 index ae27c8d0..00000000 --- a/spice.proto +++ /dev/null @@ -1,1146 +0,0 @@ -/* built in types: - int8, uint8, 16, 32, 64 -*/ - -typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4); - -struct Point { - int32 x; - int32 y; -}; - -struct Point16 { - int16 x; - int16 y; -}; - -struct PointFix { - fixed28_4 x; - fixed28_4 y; -}; - -struct Rect { - int32 top; - int32 left; - int32 bottom; - int32 right; -}; - -enum32 link_err { - OK, - ERROR, - INVALID_MAGIC, - INVALID_DATA, - VERSION_MISMATCH, - NEED_SECURED, - NEED_UNSECURED, - PERMISSION_DENIED, - BAD_CONNECTION_ID, - CHANNEL_NOT_AVAILABLE -}; - -enum32 warn_code { - WARN_GENERAL -} @prefix(SPICE_); - -enum32 info_code { - INFO_GENERAL -} @prefix(SPICE_); - -flags32 migrate_flags { - NEED_FLUSH, - NEED_DATA_TRANSFER -} @prefix(SPICE_MIGRATE_); - -enum32 notify_severity { - INFO, - WARN, - ERROR, -}; - -enum32 notify_visibility { - LOW, - MEDIUM, - HIGH, -}; - -flags16 mouse_mode { - SERVER, - CLIENT, -}; - -enum16 pubkey_type { - INVALID, - RSA, - RSA2, - DSA, - DSA1, - DSA2, - DSA3, - DSA4, - DH, - EC, -}; - -message Empty { -}; - -message Data { - uint8 data[] @end @ctype(uint8_t); -} @nocopy; - -struct ChannelWait { - uint8 channel_type; - uint8 channel_id; - uint64 message_serial; -} @ctype(SpiceWaitForChannel); - -channel BaseChannel { - server: - message { - migrate_flags flags; - } migrate; - - Data migrate_data; - - message { - uint32 generation; - uint32 window; - } set_ack; - - message { - uint32 id; - uint64 timestamp; - uint8 data[] @ctype(uint8_t) @as_ptr(data_len); - } ping; - - message { - uint8 wait_count; - ChannelWait wait_list[wait_count] @end; - } wait_for_channels; - - message { - uint64 time_stamp; - link_err reason; - } @ctype(SpiceMsgDisconnect) disconnecting; - - message { - uint64 time_stamp; - notify_severity severity; - notify_visibility visibilty; - uint32 what; /* error_code/warn_code/info_code */ - uint32 message_len; - uint8 message[message_len] @end @nomarshal; - } notify; - - Data list; /* the msg body is SpiceSubMessageList */ - - client: - message { - uint32 generation; - } ack_sync; - - Empty ack; - - message { - uint32 id; - uint64 timestamp; - } @ctype(SpiceMsgPing) pong; - - Empty migrate_flush_mark; - - Data migrate_data; - - message { - uint64 time_stamp; - link_err reason; - } @ctype(SpiceMsgDisconnect) disconnecting; -}; - -struct ChannelId { - uint8 type; - uint8 id; -}; - -channel MainChannel : BaseChannel { - server: - message { - uint16 port; - uint16 sport; - uint32 host_size; - uint8 *host_data[host_size] @zero_terminated @marshall @nonnull; - uint32 cert_subject_size; - uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall; - } @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101; - - Empty migrate_cancel; - - message { - uint32 session_id; - uint32 display_channels_hint; - uint32 supported_mouse_modes; - uint32 current_mouse_mode; - uint32 agent_connected; - uint32 agent_tokens; - uint32 multi_media_time; - uint32 ram_hint; - } init; - - message { - uint32 num_of_channels; - ChannelId channels[num_of_channels] @end; - } @ctype(SpiceMsgChannels) channels_list; - - message { - mouse_mode supported_modes; - mouse_mode current_mode @unique_flag; - } mouse_mode; - - message { - uint32 time; - } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time; - - Empty agent_connected; - - message { - link_err error_code; - } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected; - - Data agent_data; - - message { - uint32 num_tokens; - } @ctype(SpiceMsgMainAgentTokens) agent_token; - - message { - uint16 port; - uint16 sport; - uint32 host_size; - uint8 *host_data[host_size] @zero_terminated @marshall; - uint32 cert_subject_size; - uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall; - } @ctype(SpiceMsgMainMigrationSwitchHost) migrate_switch_host; - - Empty migrate_end; - - message { - uint32 name_len; - uint8 name[name_len]; - } name; - - message { - uint8 uuid[16]; - } uuid; - - client: - message { - uint64 cache_size; - } @ctype(SpiceMsgcClientInfo) client_info = 101; - - Empty migrate_connected; - - Empty migrate_connect_error; - - Empty attach_channels; - - message { - mouse_mode mode; - } mouse_mode_request; - - message { - uint32 num_tokens; - } agent_start; - - Data agent_data; - - message { - uint32 num_tokens; - } @ctype(SpiceMsgcMainAgentTokens) agent_token; - - Empty migrate_end; -}; - -enum8 clip_type { - NONE, - RECTS -}; - -flags8 path_flags { /* TODO: C enum names changes */ - BEGIN = 0, - END = 1, - CLOSE = 3, - BEZIER = 4, -} @prefix(SPICE_PATH_); - -enum8 video_codec_type { - MJPEG = 1, -}; - -flags8 stream_flags { - TOP_DOWN = 0, -}; - -enum8 brush_type { - NONE, - SOLID, - PATTERN, -}; - -flags8 mask_flags { - INVERS, -}; - -enum8 image_type { - BITMAP, - QUIC, - RESERVED, - LZ_PLT = 100, - LZ_RGB, - GLZ_RGB, - FROM_CACHE, - SURFACE, - JPEG, - FROM_CACHE_LOSSLESS, - ZLIB_GLZ_RGB, - JPEG_ALPHA, -}; - -flags8 image_flags { - CACHE_ME, - HIGH_BITS_SET, - CACHE_REPLACE_ME, -}; - -enum8 bitmap_fmt { - INVALID, - 1BIT_LE, - 1BIT_BE, - 4BIT_LE, - 4BIT_BE, - 8BIT /* 8bit indexed mode */, - 16BIT, /* 0555 mode */ - 24BIT /* 3 byte, brg */, - 32BIT /* 4 byte, xrgb in little endian format */, - RGBA /* 4 byte, argb in little endian format */ -}; - -flags8 bitmap_flags { - PAL_CACHE_ME, - PAL_FROM_CACHE, - TOP_DOWN, -}; - -flags8 jpeg_alpha_flags { - TOP_DOWN, -}; - -enum8 image_scale_mode { - INTERPOLATE, - NEAREST, -}; - -flags16 ropd { - INVERS_SRC, - INVERS_BRUSH, - INVERS_DEST, - OP_PUT, - OP_OR, - OP_AND, - OP_XOR, - OP_BLACKNESS, - OP_WHITENESS, - OP_INVERS, - INVERS_RES, -}; - -/* 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 { - PRIMARY -}; - -enum32 surface_fmt { - INVALID, - 1_A = 1, - 8_A = 8, - 16_555 = 16 , - 16_565 = 80, - 32_xRGB = 32, - 32_ARGB = 96 -}; - -flags8 alpha_flags { - DEST_HAS_ALPHA, - SRC_SURFACE_HAS_ALPHA -}; - -enum8 resource_type { - INVALID, - PIXMAP -} @prefix(SPICE_RES_TYPE_); - -struct ClipRects { - uint32 num_rects; - Rect rects[num_rects] @end; -}; - -struct PathSegment { - path_flags flags; - uint32 count; - PointFix points[count] @end; -} @ctype(SpicePathSeg); - -struct Path { - uint32 num_segments; - PathSegment segments[num_segments] @ptr_array; -}; - -struct Clip { - clip_type type; - switch (type) { - case RECTS: - ClipRects rects @outvar(cliprects) @to_ptr; - } u @anon; -}; - -struct DisplayBase { - uint32 surface_id; - Rect box; - Clip clip; -} @ctype(SpiceMsgDisplayBase); - -struct ResourceID { - uint8 type; - uint64 id; -}; - -struct WaitForChannel { - uint8 channel_type; - uint8 channel_id; - uint64 message_serial; -}; - -struct Palette { - uint64 unique; - uint16 num_ents; - uint32 ents[num_ents] @end; -}; - -struct BitmapData { - bitmap_fmt format; - bitmap_flags flags; - uint32 x; - uint32 y; - uint32 stride; - switch (flags) { - case PAL_FROM_CACHE: - uint64 palette_id; - default: - Palette *palette @outvar(bitmap); - } pal @anon; - uint8 data[image_size(8, stride, y)] @chunk @nomarshal; -} @ctype(SpiceBitmap); - -struct BinaryData { - uint32 data_size; - uint8 data[data_size] @nomarshal @chunk; -} @ctype(SpiceQUICData); - -struct LZPLTData { - bitmap_flags flags; - uint32 data_size; - switch (flags) { - case PAL_FROM_CACHE: - uint64 palette_id; - default: - Palette *palette @nonnull @outvar(lzplt); - } pal @anon; - uint8 data[data_size] @nomarshal @chunk; -}; - -struct ZlibGlzRGBData { - uint32 glz_data_size; - uint32 data_size; - uint8 data[data_size] @nomarshal @chunk; -} @ctype(SpiceZlibGlzRGBData); - -struct JPEGAlphaData { - jpeg_alpha_flags flags; - uint32 jpeg_size; - uint32 data_size; - uint8 data[data_size] @nomarshal @chunk; -} @ctype(SpiceJPEGAlphaData); - -struct Surface { - uint32 surface_id; -}; - - -struct Image { - struct ImageDescriptor { - uint64 id; - image_type type; - image_flags flags; - uint32 width; - uint32 height; - } descriptor; - - switch (descriptor.type) { - case BITMAP: - BitmapData bitmap; - case QUIC: - BinaryData quic; - case LZ_RGB: - case GLZ_RGB: - BinaryData lz_rgb; - case JPEG: - BinaryData jpeg; - case LZ_PLT: - LZPLTData lz_plt; - case ZLIB_GLZ_RGB: - ZlibGlzRGBData zlib_glz; - case JPEG_ALPHA: - JPEGAlphaData jpeg_alpha; - case SURFACE: - Surface surface; - } u; -}; - -struct Pattern { - Image *pat @nonnull; - Point pos; -}; - -struct Brush { - brush_type type; - switch (type) { - case SOLID: - uint32 color; - case PATTERN: - Pattern pattern; - } u; -}; - -struct QMask { - mask_flags flags; - Point pos; - Image *bitmap; -}; - -struct LineAttr { - line_flags flags; - switch (flags) { - case STYLED: - uint8 style_nseg; - } u1 @anon; - switch (flags) { - case STYLED: - fixed28_4 *style[style_nseg]; - } u2 @anon; -}; - -struct RasterGlyphA1 { - Point render_pos; - Point glyph_origin; - uint16 width; - uint16 height; - uint8 data[image_size(1, width, height)] @end; -} @ctype(SpiceRasterGlyph); - -struct RasterGlyphA4 { - Point render_pos; - Point glyph_origin; - uint16 width; - uint16 height; - uint8 data[image_size(4, width, height)] @end; -} @ctype(SpiceRasterGlyph); - -struct RasterGlyphA8 { - Point render_pos; - Point glyph_origin; - uint16 width; - uint16 height; - uint8 data[image_size(8, width, height)] @end; -} @ctype(SpiceRasterGlyph); - -struct String { - uint16 length; - string_flags flags; /* Special: Only one of a1/a4/a8 set */ - switch (flags) { - case RASTER_A1: - RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; - case RASTER_A4: - RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; - case RASTER_A8: - RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; - } u @anon; -}; - -channel DisplayChannel : BaseChannel { - server: - message { - uint32 x_res; - uint32 y_res; - uint32 bits; - } mode = 101; - - Empty mark; - Empty reset; - message { - DisplayBase base; - Point src_pos; - } copy_bits; - - message { - uint16 count; - ResourceID resources[count] @end; - } @ctype(SpiceResourceList) inval_list; - - message { - uint8 wait_count; - WaitForChannel wait_list[wait_count] @end; - } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps; - - message { - uint64 id; - } @ctype(SpiceMsgDisplayInvalOne) inval_palette; - - Empty inval_all_palettes; - - message { - uint32 surface_id; - uint32 id; - stream_flags flags; - video_codec_type codec_type; - uint64 stamp; - uint32 stream_width; - uint32 stream_height; - uint32 src_width; - uint32 src_height; - Rect dest; - Clip clip; - } stream_create = 122; - - message { - uint32 id; - uint32 multi_media_time; - uint32 data_size; - uint8 data[data_size] @end @nomarshal; - } stream_data; - - message { - uint32 id; - Clip clip; - } stream_clip; - - message { - uint32 id; - } stream_destroy; - - Empty stream_destroy_all; - - message { - DisplayBase base; - struct Fill { - Brush brush @outvar(brush); - ropd rop_descriptor; - QMask mask @outvar(mask); - } data; - } draw_fill = 302; - - message { - DisplayBase base; - struct Opaque { - Image *src_bitmap; - Rect src_area; - Brush brush; - ropd rop_descriptor; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } data; - } draw_opaque; - - message { - DisplayBase base; - struct Copy { - Image *src_bitmap; - Rect src_area; - ropd rop_descriptor; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } data; - } draw_copy; - - message { - DisplayBase base; - struct Blend { - Image *src_bitmap; - Rect src_area; - ropd rop_descriptor; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } @ctype(SpiceCopy) data; - } draw_blend; - - message { - DisplayBase base; - struct Blackness { - QMask mask @outvar(mask); - } data; - } draw_blackness; - - message { - DisplayBase base; - struct Whiteness { - QMask mask @outvar(mask); - } data; - } draw_whiteness; - - message { - DisplayBase base; - struct Invers { - QMask mask @outvar(mask); - } data; - } draw_invers; - - message { - DisplayBase base; - struct Rop3 { - Image *src_bitmap; - Rect src_area; - Brush brush; - uint8 rop3; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } data; - } draw_rop3; - - message { - DisplayBase base; - struct Stroke { - Path *path @marshall @nonnull; - LineAttr attr; - Brush brush; - uint16 fore_mode; - uint16 back_mode; - } data; - } draw_stroke; - - message { - DisplayBase base; - struct Text { - String *str @marshall @nonnull; - Rect back_area; - Brush fore_brush @outvar(fore_brush); - Brush back_brush @outvar(back_brush); - uint16 fore_mode; - uint16 back_mode; - } data; - } draw_text; - - message { - DisplayBase base; - struct Transparent { - Image *src_bitmap; - Rect src_area; - uint32 src_color; - uint32 true_color; - } data; - } draw_transparent; - - message { - DisplayBase base; - struct AlphaBlend { - alpha_flags alpha_flags; - uint8 alpha; - Image *src_bitmap; - Rect src_area; - } data; - } draw_alpha_blend; - - message { - uint32 surface_id; - uint32 width; - uint32 height; - surface_fmt format; - surface_flags flags; - } @ctype(SpiceMsgSurfaceCreate) surface_create; - - message { - uint32 surface_id; - } @ctype(SpiceMsgSurfaceDestroy) surface_destroy; - - client: - message { - uint8 pixmap_cache_id; - int64 pixmap_cache_size; //in pixels - uint8 glz_dictionary_id; - int32 glz_dictionary_window_size; // in pixels - } init = 101; -}; - -flags16 keyboard_modifier_flags { - SCROLL_LOCK, - NUM_LOCK, - CAPS_LOCK -}; - -enum8 mouse_button { - INVALID, - LEFT, - MIDDLE, - RIGHT, - UP, - DOWN, -}; - -flags16 mouse_button_mask { - LEFT, - MIDDLE, - RIGHT -}; - -channel InputsChannel : BaseChannel { - client: - message { - uint32 code; - } @ctype(SpiceMsgcKeyDown) key_down = 101; - - message { - uint32 code; - } @ctype(SpiceMsgcKeyUp) key_up; - - message { - keyboard_modifier_flags modifiers; - } @ctype(SpiceMsgcKeyModifiers) key_modifiers; - - message { - int32 dx; - int32 dy; - mouse_button_mask buttons_state; - } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111; - - message { - uint32 x; - uint32 y; - mouse_button_mask buttons_state; - uint8 display_id; - } @ctype(SpiceMsgcMousePosition) mouse_position; - - message { - mouse_button button; - mouse_button_mask buttons_state; - } @ctype(SpiceMsgcMousePress) mouse_press; - - message { - mouse_button button; - mouse_button_mask buttons_state; - } @ctype(SpiceMsgcMouseRelease) mouse_release; - - server: - message { - keyboard_modifier_flags keyboard_modifiers; - } init = 101; - - message { - keyboard_modifier_flags modifiers; - } key_modifiers; - - Empty mouse_motion_ack = 111; -}; - -enum8 cursor_type { - ALPHA, - MONO, - COLOR4, - COLOR8, - COLOR16, - COLOR24, - COLOR32, -}; - -flags16 cursor_flags { - NONE, /* Means no cursor */ - CACHE_ME, - FROM_CACHE, -}; - -struct CursorHeader { - uint64 unique; - cursor_type type; - uint16 width; - uint16 height; - uint16 hot_spot_x; - uint16 hot_spot_y; -}; - -struct Cursor { - cursor_flags flags; - switch (flags) { - case !NONE: - CursorHeader header; - } u @anon; - uint8 data[] @as_ptr(data_size); -}; - -channel CursorChannel : BaseChannel { - server: - message { - Point16 position; - uint16 trail_length; - uint16 trail_frequency; - uint8 visible; - Cursor cursor; - } init = 101; - - Empty reset; - - message { - Point16 position; - uint8 visible; - Cursor cursor; - } set; - - message { - Point16 position; - } move; - - Empty hide; - - message { - uint16 length; - uint16 frequency; - } trail; - - message { - uint64 id; - } @ctype(SpiceMsgDisplayInvalOne) inval_one; - - Empty inval_all; -}; - -enum16 audio_data_mode { - INVALID, - RAW, - CELT_0_5_1, -}; - -enum16 audio_fmt { - INVALID, - S16, -}; - -message AudioVolume { - uint8 nchannels; - uint16 volume[nchannels] @end; -}; - -message AudioMute { - uint8 mute; -}; - -channel PlaybackChannel : BaseChannel { - server: - message { - uint32 time; - uint8 data[] @as_ptr(data_size); - } @ctype(SpiceMsgPlaybackPacket) data = 101; - - message { - uint32 time; - audio_data_mode mode; - uint8 data[] @as_ptr(data_size); - } mode; - - message { - uint32 channels; - audio_fmt format; - uint32 frequency; - uint32 time; - } start; - - Empty stop; - AudioVolume volume; - AudioMute mute; -}; - -channel RecordChannel : BaseChannel { - server: - message { - uint32 channels; - audio_fmt format; - uint32 frequency; - } start = 101; - - Empty stop; - AudioVolume volume; - AudioMute mute; - client: - message { - uint32 time; - uint8 data[] @nomarshal @as_ptr(data_size); - } @ctype(SpiceMsgcRecordPacket) data = 101; - - message { - uint32 time; - audio_data_mode mode; - uint8 data[] @as_ptr(data_size); - } mode; - - message { - uint32 time; - } start_mark; -}; - -enum16 tunnel_service_type { - INVALID, - GENERIC, - IPP, -}; - -enum16 tunnel_ip_type { - INVALID, - IPv4, -}; - -struct TunnelIpInfo { - tunnel_ip_type type; - switch (type) { - case IPv4: - uint8 ipv4[4]; - } u; -} @ctype(SpiceMsgTunnelIpInfo); - -channel TunnelChannel : BaseChannel { - server: - message { - uint16 max_num_of_sockets; - uint32 max_socket_data_size; - } init = 101; - - message { - uint32 service_id; - TunnelIpInfo virtual_ip; - } service_ip_map; - - message { - uint16 connection_id; - uint32 service_id; - uint32 tokens; - } socket_open; - - message { - uint16 connection_id; - } socket_fin; - - message { - uint16 connection_id; - } socket_close; - - message { - uint16 connection_id; - uint8 data[] @end; - } socket_data; - - message { - uint16 connection_id; - } socket_closed_ack; - - message { - uint16 connection_id; - uint32 num_tokens; - } @ctype(SpiceMsgTunnelSocketTokens) socket_token; - - client: - message { - tunnel_service_type type; - uint32 id; - uint32 group; - uint32 port; - uint8 *name[cstring()] @nocopy; - uint8 *description[cstring()] @nocopy; - switch (type) { - case IPP: - TunnelIpInfo ip @ctype(SpiceMsgTunnelIpInfo); - } u; - } @ctype(SpiceMsgcTunnelAddGenericService) service_add = 101; - - message { - uint32 id; - } @ctype(SpiceMsgcTunnelRemoveService) service_remove; - - message { - uint16 connection_id; - uint32 tokens; - } socket_open_ack; - - message { - uint16 connection_id; - } socket_open_nack; - - message { - uint16 connection_id; - } socket_fin; - - message { - uint16 connection_id; - } socket_closed; - - message { - uint16 connection_id; - } socket_closed_ack; - - message { - uint16 connection_id; - uint8 data[] @end; - } socket_data; - - message { - uint16 connection_id; - uint32 num_tokens; - } @ctype(SpiceMsgcTunnelSocketTokens) socket_token; -}; - -channel SmartcardChannel : BaseChannel { -server: - Data data = 101; -client: - Data data = 101; -}; - -channel SpicevmcChannel : BaseChannel { -server: - Data data = 101; -client: - Data data = 101; -}; - -channel UsbredirChannel : SpicevmcChannel { -}; - -protocol Spice { - MainChannel main = 1; - DisplayChannel display; - InputsChannel inputs; - CursorChannel cursor; - PlaybackChannel playback; - RecordChannel record; - TunnelChannel tunnel; - SmartcardChannel smartcard; - UsbredirChannel usbredir; -}; diff --git a/spice1.proto b/spice1.proto deleted file mode 100644 index fa2524bb..00000000 --- a/spice1.proto +++ /dev/null @@ -1,934 +0,0 @@ -/* built in types: - int8, uint8, 16, 32, 64 -*/ - -typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4); - -struct Point { - int32 x; - int32 y; -}; - -struct Point16 { - int16 x; - int16 y; -}; - -struct PointFix { - fixed28_4 x; - fixed28_4 y; -}; - -struct Rect { - int32 top; - int32 left; - int32 bottom; - int32 right; -}; - -enum32 link_err { - OK, - ERROR, - INVALID_MAGIC, - INVALID_DATA, - VERSION_MISMATCH, - NEED_SECURED, - NEED_UNSECURED, - PERMISSION_DENIED, - BAD_CONNECTION_ID, - CHANNEL_NOT_AVAILABLE -}; - -enum32 warn_code { - WARN_GENERAL -} @prefix(SPICE_); - -enum32 info_code { - INFO_GENERAL -} @prefix(SPICE_); - -flags32 migrate_flags { - NEED_FLUSH, - NEED_DATA_TRANSFER -} @prefix(SPICE_MIGRATE_); - -enum32 notify_severity { - INFO, - WARN, - ERROR, -}; - -enum32 notify_visibility { - LOW, - MEDIUM, - HIGH, -}; - -flags32 mouse_mode { - SERVER, - CLIENT, -}; - -enum16 pubkey_type { - INVALID, - RSA, - RSA2, - DSA, - DSA1, - DSA2, - DSA3, - DSA4, - DH, - EC, -}; - -message Empty { -}; - -message Data { - uint8 data[] @end @ctype(uint8_t); -} @nocopy; - -struct ChannelWait { - uint8 channel_type; - uint8 channel_id; - uint64 message_serial; -} @ctype(SpiceWaitForChannel); - -channel BaseChannel { - server: - message { - migrate_flags flags; - } migrate; - - Data migrate_data; - - message { - uint32 generation; - uint32 window; - } set_ack; - - message { - uint32 id; - uint64 timestamp; - uint8 data[] @ctype(uint8_t) @as_ptr(data_len); - } ping; - - message { - uint8 wait_count; - ChannelWait wait_list[wait_count] @end; - } wait_for_channels; - - message { - uint64 time_stamp; - link_err reason; - } @ctype(SpiceMsgDisconnect) disconnecting; - - message { - uint64 time_stamp; - notify_severity severity; - notify_visibility visibilty; - uint32 what; /* error_code/warn_code/info_code */ - uint32 message_len; - uint8 message[message_len] @end @nomarshal; - uint8 zero @end @ctype(uint8_t) @nomarshal; - } notify; - - client: - message { - uint32 generation; - } ack_sync; - - Empty ack; - - message { - uint32 id; - uint64 timestamp; - } @ctype(SpiceMsgPing) pong; - - Empty migrate_flush_mark; - - Data migrate_data; - - message { - uint64 time_stamp; - link_err reason; - } @ctype(SpiceMsgDisconnect) disconnecting; -}; - -struct ChannelId { - uint8 type; - uint8 id; -}; - -channel MainChannel : BaseChannel { - server: - message { - uint16 port; - uint16 sport; - uint32 host_offset @zero; - uint32 host_size; - pubkey_type pub_key_type @minor(1); - uint32 pub_key_offset @minor(1) @zero; - uint32 pub_key_size @minor(1); - uint8 host_data[host_size] @as_ptr @zero_terminated; - uint8 pub_key_data[pub_key_size] @minor(1) @as_ptr @zero_terminated; - } @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101; - - Empty migrate_cancel; - - message { - uint32 session_id; - uint32 display_channels_hint; - uint32 supported_mouse_modes; - uint32 current_mouse_mode; - uint32 agent_connected; - uint32 agent_tokens; - uint32 multi_media_time; - uint32 ram_hint; - } init; - - message { - uint32 num_of_channels; - ChannelId channels[num_of_channels] @end; - } @ctype(SpiceMsgChannels) channels_list; - - message { - mouse_mode supported_modes; - mouse_mode current_mode @unique_flag; - } mouse_mode; - - message { - uint32 time; - } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time; - - Empty agent_connected; - - message { - link_err error_code; - } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected; - - Data agent_data; - - message { - uint32 num_tokens; - } @ctype(SpiceMsgMainAgentTokens) agent_token; - - message { - uint16 port; - uint16 sport; - uint32 host_offset @zero; - uint32 host_size; - uint32 cert_subject_offset @zero; - uint32 cert_subject_size; - uint8 host_data[host_size] @as_ptr @zero_terminated; - uint8 cert_subject_data[cert_subject_size] @as_ptr @zero_terminated; - } @ctype(SpiceMsgMainMigrationSwitchHost) migrate_switch_host; - - client: - message { - uint64 cache_size; - } @ctype(SpiceMsgcClientInfo) client_info = 101; - - Empty migrate_connected; - - Empty migrate_connect_error; - - Empty attach_channels; - - message { - mouse_mode mode; - } mouse_mode_request; - - message { - uint32 num_tokens; - } agent_start; - - Data agent_data; - - message { - uint32 num_tokens; - } @ctype(SpiceMsgcMainAgentTokens) agent_token; -}; - -enum32 clip_type { - NONE, - RECTS -}; - -flags32 path_flags { /* TODO: C enum names changes */ - BEGIN = 0, - END = 1, - CLOSE = 3, - BEZIER = 4, -} @prefix(SPICE_PATH_); - -enum32 video_codec_type { - MJPEG = 1, -}; - -flags32 stream_flags { - TOP_DOWN = 0, -}; - -enum32 brush_type { - NONE, - SOLID, - PATTERN, -}; - -flags8 mask_flags { - INVERS, -}; - -enum8 image_type { - BITMAP, - QUIC, - RESERVED, - LZ_PLT = 100, - LZ_RGB, - GLZ_RGB, - FROM_CACHE, -}; - -flags8 image_flags { - CACHE_ME, -}; - -enum8 bitmap_fmt { - INVALID, - 1BIT_LE, - 1BIT_BE, - 4BIT_LE, - 4BIT_BE, - 8BIT /* 8bit indexed mode */, - 16BIT, /* 0555 mode */ - 24BIT /* 3 byte, brg */, - 32BIT /* 4 byte, xrgb in little endian format */, - RGBA /* 4 byte, argb in little endian format */ -}; - -flags8 bitmap_flags { - PAL_CACHE_ME, - PAL_FROM_CACHE, - TOP_DOWN, -}; - -enum8 image_scale_mode { - INTERPOLATE, - NEAREST, -}; - -flags16 ropd { - INVERS_SRC, - INVERS_BRUSH, - INVERS_DEST, - OP_PUT, - OP_OR, - OP_AND, - OP_XOR, - OP_BLACKNESS, - OP_WHITENESS, - OP_INVERS, - INVERS_RES, -}; - -flags8 line_flags { - STYLED = 3, - START_WITH_GAP = 2, -}; - -enum8 line_cap { - ROUND, - SQUARE, - BUTT, -}; - -enum8 line_join { - ROUND, - BEVEL, - MITER, -}; - -flags16 string_flags { - RASTER_A1, - RASTER_A4, - RASTER_A8, - RASTER_TOP_DOWN, -}; - -enum8 resource_type { - INVALID, - PIXMAP -} @prefix(SPICE_RES_TYPE_); - -struct ClipRects { - uint32 num_rects; - Rect rects[num_rects] @end; -}; - -struct PathSegment { - path_flags flags; - uint32 count; - PointFix points[count] @end; -} @ctype(SpicePathSeg); - -struct Path { - uint32 segments_size @bytes_count(num_segments); - PathSegment segments[bytes(segments_size, num_segments)] @ptr_array; -}; - -struct Clip { - clip_type type; - switch (type) { - case RECTS: - ClipRects *rects @outvar(cliprects); - default: - uint64 data @zero; - } u @anon; -}; - -struct DisplayBase { - uint32 surface_id @virtual(0); - Rect box; - Clip clip; -} @ctype(SpiceMsgDisplayBase); - -struct ResourceID { - uint8 type; - uint64 id; -}; - -struct WaitForChannel { - uint8 channel_type; - uint8 channel_id; - uint64 message_serial; -}; - -struct Palette { - uint64 unique; - uint16 num_ents; - uint32 ents[num_ents] @end; -}; - -struct BitmapData { - bitmap_fmt format; - bitmap_flags flags; - uint32 x; - uint32 y; - uint32 stride; - switch (flags) { - case PAL_FROM_CACHE: - uint64 palette_id; - default: - Palette *palette @outvar(bitmap); - } pal @anon; - uint8 *data[image_size(8, stride, y)] @chunk; /* pointer to array, not array of pointers as in C */ -} @ctype(SpiceBitmap); - -struct BinaryData { - uint32 data_size; - uint8 data[data_size] @nomarshal @chunk; -} @ctype(SpiceQUICData); - -struct LZPLTData { - bitmap_flags flags; - uint32 data_size; - switch (flags) { - case PAL_FROM_CACHE: - uint64 palette_id; - default: - Palette *palette @nonnull @outvar(lzplt); - } pal @anon; - uint8 data[data_size] @nomarshal @chunk; -}; - -struct Image { - struct ImageDescriptor { - uint64 id; - image_type type; - image_flags flags; - uint32 width; - uint32 height; - } descriptor; - - switch (descriptor.type) { - case BITMAP: - BitmapData bitmap; - case QUIC: - BinaryData quic; - case LZ_RGB: - case GLZ_RGB: - BinaryData lz_rgb; - case LZ_PLT: - LZPLTData lz_plt; - } u; -}; - -struct Pattern { - Image *pat @nonnull; - Point pos; -}; - -struct Brush { - brush_type type; - switch (type) { - case SOLID: - uint32 color; - case PATTERN: - Pattern pattern; - } u @fixedsize; -}; - -struct QMask { - mask_flags flags; - Point pos; - Image *bitmap; -}; - -struct LineAttr { - line_flags flags; - line_join join_style @zero; - line_cap end_style @zero; - uint8 style_nseg; - fixed28_4 width @zero; - fixed28_4 miter_limit @zero; - fixed28_4 *style[style_nseg]; -}; - -struct RasterGlyphA1 { - Point render_pos; - Point glyph_origin; - uint16 width; - uint16 height; - uint8 data[image_size(1, width, height)] @end; -} @ctype(SpiceRasterGlyph); - -struct RasterGlyphA4 { - Point render_pos; - Point glyph_origin; - uint16 width; - uint16 height; - uint8 data[image_size(4, width, height)] @end; -} @ctype(SpiceRasterGlyph); - -struct RasterGlyphA8 { - Point render_pos; - Point glyph_origin; - uint16 width; - uint16 height; - uint8 data[image_size(8, width, height)] @end; -} @ctype(SpiceRasterGlyph); - -struct String { - uint16 length; - string_flags flags; /* Special: Only one of a1/a4/a8 set */ - switch (flags) { - case RASTER_A1: - RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; - case RASTER_A4: - RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; - case RASTER_A8: - RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; - } u @anon; -}; - -channel DisplayChannel : BaseChannel { - server: - message { - uint32 x_res; - uint32 y_res; - uint32 bits; - } mode = 101; - - Empty mark; - Empty reset; - - message { - DisplayBase base; - Point src_pos; - } copy_bits; - - message { - uint16 count; - ResourceID resources[count] @end; - } @ctype(SpiceResourceList) inval_list; - - message { - uint8 wait_count; - WaitForChannel wait_list[wait_count] @end; - } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps; - - message { - uint64 id; - } @ctype(SpiceMsgDisplayInvalOne) inval_palette; - - Empty inval_all_palettes; - - message { - uint32 surface_id @virtual(0); - uint32 id; - stream_flags flags; - video_codec_type codec_type; - uint64 stamp; - uint32 stream_width; - uint32 stream_height; - uint32 src_width; - uint32 src_height; - Rect dest; - Clip clip; - } stream_create = 122; - - message { - uint32 id; - uint32 multi_media_time; - uint32 data_size; - uint32 pad_size @zero; - uint8 data[data_size] @end @nomarshal; - /* Ignore: uint8 padding[pad_size] */ - } stream_data; - - message { - uint32 id; - Clip clip; - } stream_clip; - - message { - uint32 id; - } stream_destroy; - - Empty stream_destroy_all; - - message { - DisplayBase base; - struct Fill { - Brush brush @outvar(brush); - uint16 rop_descriptor; - QMask mask @outvar(mask); - } data; - } draw_fill = 302; - - message { - DisplayBase base; - struct Opaque { - Image *src_bitmap; - Rect src_area; - Brush brush; - ropd rop_descriptor; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } data; - } draw_opaque; - - message { - DisplayBase base; - struct Copy { - Image *src_bitmap; - Rect src_area; - ropd rop_descriptor; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } data; - } draw_copy; - - message { - DisplayBase base; - struct Blend { - Image *src_bitmap; - Rect src_area; - ropd rop_descriptor; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } @ctype(SpiceCopy) data; - } draw_blend; - - message { - DisplayBase base; - struct Blackness { - QMask mask @outvar(mask); - } data; - } draw_blackness; - - message { - DisplayBase base; - struct Whiteness { - QMask mask @outvar(mask); - } data; - } draw_whiteness; - - message { - DisplayBase base; - struct Invers { - QMask mask @outvar(mask); - } data; - } draw_invers; - - message { - DisplayBase base; - struct Rop3 { - Image *src_bitmap; - Rect src_area; - Brush brush; - uint8 rop3; - image_scale_mode scale_mode; - QMask mask @outvar(mask); - } data; - } draw_rop3; - - message { - DisplayBase base; - struct Stroke { - Path *path; - LineAttr attr; - Brush brush; - uint16 fore_mode; - uint16 back_mode; - } data; - } draw_stroke; - - message { - DisplayBase base; - struct Text { - String *str; - Rect back_area; - Brush fore_brush @outvar(fore_brush); - Brush back_brush @outvar(back_brush); - uint16 fore_mode; - uint16 back_mode; - } data; - } draw_text; - - message { - DisplayBase base; - struct Transparent { - Image *src_bitmap; - Rect src_area; - uint32 src_color; - uint32 true_color; - } data; - } draw_transparent; - - message { - DisplayBase base; - struct AlphaBlend { - int8 alpha_flags @virtual(0); - uint8 alpha; - Image *src_bitmap; - Rect src_area; - } data; - } draw_alpha_blend; - - client: - message { - uint8 pixmap_cache_id; - int64 pixmap_cache_size; //in pixels - uint8 glz_dictionary_id; - int32 glz_dictionary_window_size; // in pixels - } init = 101; -}; - -flags32 keyboard_modifier_flags { - SCROLL_LOCK, - NUM_LOCK, - CAPS_LOCK -}; - -enum32 mouse_button { - INVALID, - LEFT, - MIDDLE, - RIGHT, - UP, - DOWN, -}; - -flags32 mouse_button_mask { - LEFT, - MIDDLE, - RIGHT -}; - -channel InputsChannel : BaseChannel { - client: - message { - uint32 code; - } @ctype(SpiceMsgcKeyDown) key_down = 101; - - message { - uint32 code; - } @ctype(SpiceMsgcKeyUp) key_up; - - message { - keyboard_modifier_flags modifiers; - } @ctype(SpiceMsgcKeyModifiers) key_modifiers; - - message { - int32 dx; - int32 dy; - mouse_button_mask buttons_state; - } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111; - - message { - uint32 x; - uint32 y; - mouse_button_mask buttons_state; - uint8 display_id; - } @ctype(SpiceMsgcMousePosition) mouse_position; - - message { - mouse_button button; - mouse_button_mask buttons_state; - } @ctype(SpiceMsgcMousePress) mouse_press; - - message { - mouse_button button; - mouse_button_mask buttons_state; - } @ctype(SpiceMsgcMouseRelease) mouse_release; - - server: - message { - keyboard_modifier_flags keyboard_modifiers; - } init = 101; - - message { - keyboard_modifier_flags modifiers; - } key_modifiers; - - Empty mouse_motion_ack = 111; -}; - -enum16 cursor_type { - ALPHA, - MONO, - COLOR4, - COLOR8, - COLOR16, - COLOR24, - COLOR32, -}; - -flags32 cursor_flags { - NONE, /* Means no cursor */ - CACHE_ME, - FROM_CACHE, -}; - -struct CursorHeader { - uint64 unique; - cursor_type type; - uint16 width; - uint16 height; - uint16 hot_spot_x; - uint16 hot_spot_y; -}; - -struct Cursor { - cursor_flags flags; - CursorHeader header; - uint8 data[] @as_ptr(data_size); -}; - -channel CursorChannel : BaseChannel { - server: - message { - Point16 position; - uint16 trail_length; - uint16 trail_frequency; - uint8 visible; - Cursor cursor; - } init = 101; - - Empty reset; - - message { - Point16 position; - uint8 visible; - Cursor cursor; - } set; - - message { - Point16 position; - } move; - - Empty hide; - - message { - uint16 length; - uint16 frequency; - } trail; - - message { - uint64 id; - } @ctype(SpiceMsgDisplayInvalOne) inval_one; - - Empty inval_all; -}; - -enum32 audio_data_mode { - INVALID, - RAW, - CELT_0_5_1, -}; - -enum32 audio_fmt { - INVALID, - S16, -}; - -channel PlaybackChannel : BaseChannel { - server: - message { - uint32 time; - uint8 data[] @as_ptr(data_size); - } @ctype(SpiceMsgPlaybackPacket) data = 101; - - message { - uint32 time; - audio_data_mode mode; - uint8 data[] @as_ptr(data_size); - } mode; - - message { - uint32 channels; - audio_fmt format; - uint32 frequency; - uint32 time; - } start; - - Empty stop; -}; - -channel RecordChannel : BaseChannel { - server: - message { - uint32 channels; - audio_fmt format; - uint32 frequency; - } start = 101; - - Empty stop; - client: - message { - uint32 time; - uint8 data[] @nomarshal @as_ptr(data_size); - } @ctype(SpiceMsgcRecordPacket) data = 101; - - message { - uint32 time; - audio_data_mode mode; - uint8 data[] @as_ptr(data_size); - } mode; - - message { - uint32 time; - } start_mark; -}; - -protocol Spice { - MainChannel main = 1; - DisplayChannel display; - InputsChannel inputs; - CursorChannel cursor; - PlaybackChannel playback; - RecordChannel record; -}; diff --git a/spice_codegen.py b/spice_codegen.py deleted file mode 100755 index a9fdee98..00000000 --- a/spice_codegen.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -from optparse import OptionParser -import traceback -from python_modules import spice_parser -from python_modules import ptypes -from python_modules import codegen -from python_modules import demarshal -from python_modules import marshal - -def write_channel_enums(writer, channel, client): - messages = filter(lambda m : m.channel == channel, \ - channel.client_messages if client else channel.server_messages) - if len(messages) == 0: - return - writer.begin_block("enum") - i = 0 - if client: - prefix = [ "MSGC" ] - else: - prefix = [ "MSG" ] - if channel.member_name: - prefix.append(channel.member_name.upper()) - prefix.append(None) # To be replaced with name - for m in messages: - prefix[-1] = m.name.upper() - enum = codegen.prefix_underscore_upper(*prefix) - if m.value == i: - writer.writeln("%s," % enum) - i = i + 1 - else: - writer.writeln("%s = %s," % (enum, m.value)) - i = m.value + 1 - if channel.member_name: - prefix[-1] = prefix[-2] - prefix[-2] = "END" - writer.newline() - writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix))) - writer.end_block(semicolon=True) - writer.newline() - -def write_enums(writer): - writer.writeln("#ifndef _H_SPICE_ENUMS") - writer.writeln("#define _H_SPICE_ENUMS") - writer.newline() - writer.comment("Generated from %s, don't edit" % writer.options["source"]).newline() - writer.newline() - - # Define enums - for t in ptypes.get_named_types(): - if isinstance(t, ptypes.EnumBaseType): - t.c_define(writer) - - i = 0 - writer.begin_block("enum") - for c in proto.channels: - enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper()) - if c.value == i: - writer.writeln("%s," % enum) - i = i + 1 - else: - writer.writeln("%s = %s," % (enum, c.value)) - i = c.value + 1 - writer.newline() - writer.writeln("SPICE_END_CHANNEL") - writer.end_block(semicolon=True) - writer.newline() - - for c in ptypes.get_named_types(): - if not isinstance(c, ptypes.ChannelType): - continue - write_channel_enums(writer, c, False) - write_channel_enums(writer, c, True) - - writer.writeln("#endif /* _H_SPICE_ENUMS */") - -parser = OptionParser(usage="usage: %prog [options] <protocol_file> <destination file>") -parser.add_option("-e", "--generate-enums", - action="store_true", dest="generate_enums", default=False, - help="Generate enums") -parser.add_option("-d", "--generate-demarshallers", - action="store_true", dest="generate_demarshallers", default=False, - help="Generate demarshallers") -parser.add_option("-m", "--generate-marshallers", - action="store_true", dest="generate_marshallers", default=False, - help="Generate message marshallers") -parser.add_option("-P", "--private-marshallers", - action="store_true", dest="private_marshallers", default=False, - help="Generate private message marshallers") -parser.add_option("-M", "--generate-struct-marshaller", - action="append", dest="struct_marshallers", - help="Generate struct marshallers") -parser.add_option("-a", "--assert-on-error", - action="store_true", dest="assert_on_error", default=False, - help="Assert on error") -parser.add_option("-H", "--header", - action="store_true", dest="header", default=False, - help="Generate header") -parser.add_option("-p", "--print-error", - action="store_true", dest="print_error", default=False, - help="Print errors") -parser.add_option("-s", "--server", - action="store_true", dest="server", default=False, - help="Print errors") -parser.add_option("-c", "--client", - action="store_true", dest="client", default=False, - help="Print errors") -parser.add_option("-k", "--keep-identical-file", - action="store_true", dest="keep_identical_file", default=False, - help="Print errors") -parser.add_option("-i", "--include", - action="append", dest="includes", metavar="FILE", - help="Include FILE in generated code") -parser.add_option("--prefix", dest="prefix", - help="set public symbol prefix", default="") -parser.add_option("--ptrsize", dest="ptrsize", - help="set default pointer size", default="4") - -(options, args) = parser.parse_args() - -if len(args) == 0: - parser.error("No protocol file specified") - -if len(args) == 1: - parser.error("No destination file specified") - -ptypes.default_pointer_size = int(options.ptrsize) - -proto_file = args[0] -dest_file = args[1] -proto = spice_parser.parse(proto_file) - -if proto == None: - exit(1) - -codegen.set_prefix(proto.name) -writer = codegen.CodeWriter() -writer.header = codegen.CodeWriter() -writer.set_option("source", os.path.basename(proto_file)) - -writer.public_prefix = options.prefix - -writer.writeln("/* this is a file autogenerated by spice_codegen.py */") -writer.header.writeln("/* this is a file autogenerated by spice_codegen.py */") -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.writeln('#include "%s"' % i) - -if options.generate_enums: - write_enums(writer) - -if options.generate_demarshallers: - if not options.server and not options.client: - print >> sys.stderr, "Must specify client and/or server" - sys.exit(1) - demarshal.write_includes(writer) - - if options.server: - demarshal.write_protocol_parser(writer, proto, False) - if options.client: - demarshal.write_protocol_parser(writer, proto, True) - -if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0): - marshal.write_includes(writer) - -if options.generate_marshallers: - if not options.server and not options.client: - print >> sys.stderr, "Must specify client and/or server" - sys.exit(1) - if options.server: - marshal.write_protocol_marshaller(writer, proto, False, options.private_marshallers) - if options.client: - marshal.write_protocol_marshaller(writer, proto, True, options.private_marshallers) - -if options.struct_marshallers: - for structname in options.struct_marshallers: - t = ptypes.lookup_type(structname) - marshal.write_marshal_ptr_function(writer, t) - -if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0): - marshal.write_trailer(writer) - -if options.header: - content = writer.header.getvalue() -else: - content = writer.getvalue() -if options.keep_identical_file: - try: - f = open(dest_file, 'rb') - old_content = f.read() - f.close() - - if content == old_content: - print "No changes to %s" % dest_file - sys.exit(0) - - except IOError: - pass - -f = open(dest_file, 'wb') -f.write(content) -f.close() - -print "Wrote %s" % dest_file -sys.exit(0) |