From b1dc7fae2a95804948ba9eedca08d208cdd5f825 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 26 May 2010 12:19:58 +0200 Subject: Initial import of spice protocol description and demarshall generator The "spice.proto" file describes in detail the networking prototcol that spice uses and spice_codegen.py can parse this and generate demarshallers for such network messages. --- python_modules/demarshal.py | 1033 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1033 insertions(+) create mode 100644 python_modules/demarshal.py (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py new file mode 100644 index 0000000..fcd6850 --- /dev/null +++ b/python_modules/demarshal.py @@ -0,0 +1,1033 @@ +import ptypes +import codegen + + +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) + else: + writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr)))" % (type, 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.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 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)") + 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)") + + writer.newline() + writer.begin_block("struct PointerInfo") + writer.variable_def("uint64_t", "offset") + writer.variable_def("parse_func_t", "parse") + writer.variable_def("SPICE_ADDRESS *", "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) + scope.variable_def(m.member_type.c_type(), var) + writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type())) + 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) + 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.non_null = False + 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.non_null = member.has_attr("nonnull") + 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.non_null = c.member.has_attr("nonnull") + sub_want_extra_size = want_extra_size + if sub_want_extra_size and not m.contains_extra_size(): + writer.assign(item.extra_size(), 0) + sub_want_extra_size = False + + write_validate_item(writer, container, item, if_scope, scope, start, + want_nw_size, want_mem_size, sub_want_extra_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, "intptr_t", "uint8_t *message_start, uint8_t *message_end, SPICE_ADDRESS 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(), 8) + + if want_mem_size or want_extra_size: + target_type = item.type.target_type + + v = write_read_primitive_item(writer, item, scope) + if item.non_null: + 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()) + 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())) + writer.assign(array_item.mem_size(), array_item.nw_size()) + else: + write_validate_array_item(writer, container, array_item, scope, parent_scope, start, + True, True, 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("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) + 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) + 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 element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size: + # TODO: Overflow check the multiplication + 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() + scope.variable_def("uint32_t", element_nw_size) + scope.variable_def("uint32_t", element_mem_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: + 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: + 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)) + +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()) + assert not want_extra_size + +def write_validate_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + 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) + +def write_validate_member(writer, container, member, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + 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() + 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 + +def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False): + if array.is_bytes_length(): + nelements = "%s__nbytes" % prefix + else: + nelements = "%s__nelements" % prefix + if dest.is_toplevel(): + 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(): + if not handles_bytes: + raise NotImplementedError("handling of bytes() not supported here yet") + writer.assign(nelements, dest.get_ref(array.size[1])) + 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"): + 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 t.is_struct(): + write_container_parser(writer, t, dest2) + elif t.is_pointer(): + write_parse_pointer(writer, t, False, dest2, m.name, not m.has_attr("ptr32"), block) + elif t.is_primitive(): + 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) + write_array_parser(writer, nelements, t, dest, 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, "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, "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, nelements, array, dest, scope): + is_byte_size = array.is_bytes_length() + + element_type = array.element_type + if element_type == ptypes.uint8 or element_type == ptypes.int8: + writer.statement("memcpy(end, in, %s)" % (nelements)) + writer.increment("in", nelements) + writer.increment("end", nelements) + else: + if is_byte_size: + scope.variable_def("uint8_t *", "array_end") + writer.assign("array_end", "end + %s" % nelements) + with writer.index(no_block = is_byte_size) as index: + with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope: + if element_type.is_primitive(): + writer.statement("*(%s *)end = consume_%s(&in)" % (element_type.c_type(), element_type.primitive_type())) + writer.increment("end", element_type.sizeof()) + else: + dest2 = dest.child_at_end(writer, element_type) + dest2.reuse_scope = array_scope + write_container_parser(writer, element_type, dest2) + +def write_parse_pointer(writer, t, at_end, dest, member_name, is_64bit, scope): + target_type = t.target_type + if is_64bit: + writer.assign("ptr_info[n_ptr].offset", "consume_uint64(&in)") + else: + writer.assign("ptr_info[n_ptr].offset", "consume_uint32(&in)") + writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) + if at_end: + writer.assign("ptr_info[n_ptr].dest", "end") + writer.increment("end", "sizeof(SPICE_ADDRESS)"); + else: + writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name)) + if target_type.is_array(): + nelements = read_array_len(writer, member_name, target_type, dest, scope) + writer.assign("ptr_info[n_ptr].nelements", nelements) + + writer.statement("n_ptr++") + +def write_member_parser(writer, container, member, dest, scope): + if member.is_switch(): + write_switch_parser(writer, container, member, dest, scope) + return + + t = member.member_type + + if t.is_pointer(): + if member.has_attr("nocopy"): + writer.comment("Reuse data from network message").newline() + writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_uint64(&in))") + else: + write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, not member.has_attr("ptr32"), scope) + elif t.is_primitive(): + if member.has_end_attr(): + writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type())) + writer.increment("end", t.sizeof()) + else: + writer.assign(dest.get_ref(member.name), "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, handles_bytes = True) + write_array_parser(writer, 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.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, "0") + 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, "(size_t)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_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() + + writer.newline() + parent_scope = writer.function(function_name, + "uint8_t *", + "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size", 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", "mem_size", "nw_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, True, 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"): + writer.assign("data", "message_start") + writer.assign("*size", "message_end - message_start") + 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() + + 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.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, + "uint8_t *", + "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out") + + 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)" % (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" + else: + function_name = "spice_get_client_channel_parser" + + 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, + "uint8_t *", + "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, int minor, size_t *size_out") + scope.variable_def("spice_parse_channel_func_t", "func" ) + + if is_server: + writer.assign("func", "spice_get_server_channel_parser(channel, NULL)") + else: + writer.assign("func", "spice_get_client_channel_parser(channel, NULL)") + + with writer.if_block("func != NULL"): + writer.statement("return func(message_start, message_end, message_type, minor, size_out)") + + 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 ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.newline() + writer.writeln("#ifdef _MSC_VER") + writer.writeln("#pragma warning(disable:4101)") + writer.writeln("#endif") -- cgit From 41c07b938bfe53c61b28b4b9d87044766d237a10 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 18 Jun 2010 17:09:58 +0200 Subject: Support @as_ptr in demarshaller to avoid copying data unnecessary --- python_modules/demarshal.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index fcd6850..8b90458 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -760,7 +760,19 @@ def write_member_parser(writer, container, member, dest, scope): #TODO validate e.g. flags and enums elif t.is_array(): nelements = read_array_len(writer, member.name, t, dest, scope, handles_bytes = True) - write_array_parser(writer, nelements, t, dest, scope) + if 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, nelements, t, dest, scope) elif t.is_struct(): if member.has_end_attr(): dest2 = dest.child_at_end(writer, t) -- cgit From f9610c1a658d78660cfca01279350d2c235b8dba Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 22 Jun 2010 10:53:24 +0200 Subject: Add destructor for demarshalled messages This is required because we don't want to free messages that just refer to the unparsed message (like SpiceMsgData). Also, in the future we might need it for more complex demarshalling. --- python_modules/demarshal.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 8b90458..b1c4135 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -41,9 +41,10 @@ def write_parser_helpers(writer): 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)") - 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)") + 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") @@ -820,6 +821,13 @@ def write_ptr_info_check(writer): 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 @@ -833,7 +841,7 @@ def write_msg_parser(writer, message): writer.newline() parent_scope = writer.function(function_name, "uint8_t *", - "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size", True) + "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"); @@ -860,8 +868,10 @@ def write_msg_parser(writer, message): 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") @@ -882,6 +892,7 @@ def write_msg_parser(writer, message): writer.newline() writer.assign("*size", "end - data") + writer.assign("*free_message", "(message_destructor_t) free") writer.statement("return data") writer.newline() @@ -922,7 +933,7 @@ def write_channel_parser(writer, channel, server): writer.newline() scope = writer.function(function_name, "uint8_t *", - "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out") + "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() @@ -944,7 +955,7 @@ def write_channel_parser(writer, channel, server): 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)" % (d, r[0])) + 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") @@ -1006,7 +1017,7 @@ def write_full_protocol_parser(writer, is_server): function_name = "spice_parse_reply" scope = writer.function(function_name, "uint8_t *", - "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, int minor, size_t *size_out") + "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: @@ -1015,7 +1026,7 @@ def write_full_protocol_parser(writer, is_server): writer.assign("func", "spice_get_client_channel_parser(channel, NULL)") with writer.if_block("func != NULL"): - writer.statement("return func(message_start, message_end, message_type, minor, size_out)") + writer.statement("return func(message_start, message_end, message_type, minor, size_out, free_message)") writer.statement("return NULL") writer.end_block() -- cgit From 2523cec8c4890f977ee5569d9280d54108790674 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 22 Jun 2010 16:01:57 +0200 Subject: Support extra prefix in code generators This is require when we add a new spice.proto for the old (major 1) protocol description. --- python_modules/demarshal.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index b1c4135..8d86e84 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -966,9 +966,9 @@ def write_channel_parser(writer, channel, server): def write_get_channel_parser(writer, channel_parsers, max_channel, is_server): writer.newline() if is_server: - function_name = "spice_get_server_channel_parser" + function_name = "spice_get_server_channel_parser" + writer.public_prefix else: - function_name = "spice_get_client_channel_parser" + function_name = "spice_get_client_channel_parser" + writer.public_prefix scope = writer.function(function_name, "spice_parse_channel_func_t", @@ -1015,15 +1015,15 @@ def write_full_protocol_parser(writer, is_server): function_name = "spice_parse_msg" else: function_name = "spice_parse_reply" - scope = writer.function(function_name, + 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(channel, NULL)") + writer.assign("func", "spice_get_server_channel_parser%s(channel, NULL)" % writer.public_prefix) else: - writer.assign("func", "spice_get_client_channel_parser(channel, NULL)") + 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)") -- cgit From 9f3a36f3f939c14da4e2fa1f98f3ebfd50dcf9c7 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 22 Jun 2010 16:03:02 +0200 Subject: Make internal generated marshaller functions static --- python_modules/demarshal.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 8d86e84..eee659f 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -149,7 +149,7 @@ def write_validate_struct_function(writer, struct): writer.set_is_generated("validator", validate_function) writer = writer.function_helper() - scope = writer.function(validate_function, "intptr_t", "uint8_t *message_start, uint8_t *message_end, SPICE_ADDRESS offset, int minor") + scope = writer.function(validate_function, "static intptr_t", "uint8_t *message_start, uint8_t *message_end, SPICE_ADDRESS 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"); @@ -661,7 +661,7 @@ def write_parse_ptr_function(writer, target_type): writer.set_is_generated("parser", parse_function) writer = writer.function_helper() - scope = writer.function(parse_function, "uint8_t *", "uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, int minor") + 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") @@ -932,7 +932,7 @@ def write_channel_parser(writer, channel, server): function_name = "parse_%s_msgc" % channel.name writer.newline() scope = writer.function(function_name, - "uint8_t *", + "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() -- cgit From ee944c8314287a1037b9ede077583b1cec31ea07 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 22 Jun 2010 16:03:34 +0200 Subject: Add support for @virtual markup in spice protocol This means the member is not sent on the network at all. Instead its initialized to the attribute argument when demarshalled. This is useful for backwards compatibility support. --- python_modules/demarshal.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index eee659f..a0697a9 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -400,6 +400,9 @@ def write_validate_item(writer, container, item, scope, parent_scope, start, 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 @@ -740,6 +743,10 @@ def write_parse_pointer(writer, t, at_end, dest, member_name, is_64bit, scope): writer.statement("n_ptr++") 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 -- cgit From 1d5d5272e28f8d12f5b93e4d8e5f85561eafda25 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 23 Jun 2010 16:20:33 +0200 Subject: Make pointers 32bit in new protocol format --- python_modules/demarshal.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index a0697a9..0138ebe 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -184,7 +184,7 @@ def write_validate_struct_function(writer, struct): 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(), 8) + 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 @@ -636,7 +636,7 @@ def write_switch_parser(writer, container, switch, dest, scope): if t.is_struct(): write_container_parser(writer, t, dest2) elif t.is_pointer(): - write_parse_pointer(writer, t, False, dest2, m.name, not m.has_attr("ptr32"), block) + write_parse_pointer(writer, t, False, dest2, m.name, block) elif t.is_primitive(): writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type())) #TODO validate e.g. flags and enums @@ -724,12 +724,9 @@ def write_array_parser(writer, nelements, array, dest, scope): dest2.reuse_scope = array_scope write_container_parser(writer, element_type, dest2) -def write_parse_pointer(writer, t, at_end, dest, member_name, is_64bit, scope): +def write_parse_pointer(writer, t, at_end, dest, member_name, scope): target_type = t.target_type - if is_64bit: - writer.assign("ptr_info[n_ptr].offset", "consume_uint64(&in)") - else: - writer.assign("ptr_info[n_ptr].offset", "consume_uint32(&in)") + writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type()) writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) if at_end: writer.assign("ptr_info[n_ptr].dest", "end") @@ -756,9 +753,9 @@ def write_member_parser(writer, container, member, dest, scope): if t.is_pointer(): if member.has_attr("nocopy"): writer.comment("Reuse data from network message").newline() - writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_uint64(&in))") + 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, not member.has_attr("ptr32"), scope) + write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, scope) elif t.is_primitive(): if member.has_end_attr(): writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type())) -- cgit From dcaba909d3d68f7dcb3077de083724daf4b6fd29 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 29 Jun 2010 18:13:07 +0200 Subject: demarshaller: Don't parse @zero members These just write zeros at the right place in the network protocol typically for old back-compat things. We don't want to read these back in. --- python_modules/demarshal.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 0138ebe..d8b8ea9 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -638,7 +638,8 @@ def write_switch_parser(writer, container, switch, dest, scope): elif t.is_pointer(): write_parse_pointer(writer, t, False, dest2, m.name, block) elif t.is_primitive(): - writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type())) + if not m.has_attr("zero"): + 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) @@ -757,6 +758,8 @@ def write_member_parser(writer, container, member, dest, scope): else: write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, scope) elif t.is_primitive(): + if member.has_attr("zero"): + pass if member.has_end_attr(): writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type())) writer.increment("end", t.sizeof()) -- cgit From 13f8149daf9f38f76ec843599850c7fdea15f545 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 29 Jun 2010 18:14:49 +0200 Subject: demarshaller: Support @c_ptr attributes for pointers A @c_ptr pointer is stored in memory as a real pointer rather than a SPICE_ADDRESS. This is a temporary thing that will be removed again when all SPICE_ADDRESSes have been converted to real pointer. --- python_modules/demarshal.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index d8b8ea9..faaf862 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -50,8 +50,9 @@ def write_parser_helpers(writer): writer.begin_block("struct PointerInfo") writer.variable_def("uint64_t", "offset") writer.variable_def("parse_func_t", "parse") - writer.variable_def("SPICE_ADDRESS *", "dest") + writer.variable_def("void *", "dest") writer.variable_def("uint32_t", "nelements") + writer.variable_def("int", "is_ptr") writer.end_block(semicolon=True) def write_read_primitive(writer, start, container, name, scope): @@ -636,7 +637,7 @@ def write_switch_parser(writer, container, switch, dest, scope): if t.is_struct(): write_container_parser(writer, t, dest2) elif t.is_pointer(): - write_parse_pointer(writer, t, False, dest2, m.name, block) + write_parse_pointer(writer, t, False, m.has_attr("c_ptr"), dest2, m.name, block) elif t.is_primitive(): if not m.has_attr("zero"): writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type())) @@ -725,15 +726,16 @@ def write_array_parser(writer, nelements, array, dest, scope): dest2.reuse_scope = array_scope write_container_parser(writer, element_type, dest2) -def write_parse_pointer(writer, t, at_end, dest, member_name, scope): +def write_parse_pointer(writer, t, at_end, as_c_ptr, dest, member_name, scope): target_type = t.target_type writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type()) writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) if at_end: writer.assign("ptr_info[n_ptr].dest", "end") - writer.increment("end", "sizeof(SPICE_ADDRESS)"); + writer.increment("end", "sizeof(void *)" if as_c_ptr else "sizeof(SPICE_ADDRESS)"); else: writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name)) + writer.assign("ptr_info[n_ptr].is_ptr", "1" if as_c_ptr else "0") if target_type.is_array(): nelements = read_array_len(writer, member_name, target_type, dest, scope) writer.assign("ptr_info[n_ptr].nelements", nelements) @@ -756,7 +758,7 @@ def write_member_parser(writer, container, member, dest, scope): 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) + write_parse_pointer(writer, t, member.has_end_attr(), member.has_attr("c_ptr"), dest, member.name, scope) elif t.is_primitive(): if member.has_attr("zero"): pass @@ -817,13 +819,20 @@ def write_ptr_info_check(writer): with writer.for_loop(index, "n_ptr") as scope: offset = "ptr_info[%s].offset" % index function = "ptr_info[%s].parse" % index + is_ptr = "ptr_info[%s].is_ptr" % index dest = "ptr_info[%s].dest" % index with writer.if_block("%s == 0" % offset, newline=False): - writer.assign("*%s" % dest, "0") + with writer.if_block("%s == 0" % is_ptr, newline=False): + writer.assign("*(void **)(%s)" % dest, "NULL") + with writer.block(" else"): + writer.assign("*(SPICE_ADDRESS *)(%s)" % dest, "0") 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, "(size_t)end") + with writer.if_block("%s == 0" % is_ptr, newline=False): + writer.assign("*(void **)(%s)" % dest, "(void *)end") + with writer.block(" else"): + writer.assign("*(SPICE_ADDRESS *)(%s)" % dest, "(SPICE_ADDRESS)end") writer.assign("end", "%s(message_start, message_end, end, &ptr_info[%s], minor)" % (function, index)) writer.error_check("end == NULL") writer.newline() -- cgit From e42c910b5cb5e6de734064fb57832a6e73e34092 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 29 Jun 2010 21:42:59 +0200 Subject: Store SpicePath segment count rather than size Internally and in the network protocol (for the new version) we now store the actual number of segments rather than the size of the full segments array in bytes. This change consists of multiple changes to handle this: * Make the qxl parser calculate num_segments * Make the canvas stroke code handle the new SpicePath layout. * Fix up is_equal_path in red_worker.c for the new layout * replace multiple calls to spice_marshall_PathSegment with a single spice_marshall_Path call * Make the byte_size() array size handling do the conversion from network size to number of elements when marshalling/demarshalling. * Update the current spice protocol to send the segment count rather than the size * Update the old spice protocol to use the new byte_size functionallity to calculate the size sent and the number of elements recieved --- python_modules/demarshal.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index faaf862..48b4e73 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -604,7 +604,7 @@ def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False): elif array.is_bytes_length(): if not handles_bytes: raise NotImplementedError("handling of bytes() not supported here yet") - writer.assign(nelements, dest.get_ref(array.size[1])) + writer.assign(nelements, array.size[1]) else: raise NotImplementedError("TODO array size type not handled yet") return nelements @@ -714,10 +714,15 @@ def write_array_parser(writer, nelements, array, dest, scope): writer.increment("end", nelements) else: if is_byte_size: + real_nelements = nelements[:-len("nbytes")] + "nelements" scope.variable_def("uint8_t *", "array_end") + scope.variable_def("uint32_t", real_nelements) writer.assign("array_end", "end + %s" % nelements) + writer.assign(real_nelements, 0) with writer.index(no_block = is_byte_size) as index: with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope: + if is_byte_size: + writer.increment(real_nelements, 1) if element_type.is_primitive(): writer.statement("*(%s *)end = consume_%s(&in)" % (element_type.c_type(), element_type.primitive_type())) writer.increment("end", element_type.sizeof()) @@ -725,6 +730,8 @@ def write_array_parser(writer, nelements, array, dest, scope): dest2 = dest.child_at_end(writer, element_type) dest2.reuse_scope = array_scope write_container_parser(writer, element_type, dest2) + if is_byte_size: + writer.assign(dest.get_ref(array.size[2]), real_nelements) def write_parse_pointer(writer, t, at_end, as_c_ptr, dest, member_name, scope): target_type = t.target_type @@ -766,7 +773,12 @@ def write_member_parser(writer, container, member, dest, scope): writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type())) writer.increment("end", t.sizeof()) else: - writer.assign(dest.get_ref(member.name), "consume_%s(&in)" % (t.primitive_type())) + if member.has_attr("bytes_count"): + scope.variable_def("uint32_t", member.name); + dest_var = member.name + 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, handles_bytes = True) -- cgit From 6d38c4817f751f5f47dd1d22ba8319675bb57295 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 30 Jun 2010 16:49:50 +0200 Subject: Simplify SpiceLineAttr by removing unsed stuff Also in new protocol don't send style data if not needed. --- python_modules/demarshal.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 48b4e73..b819513 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -62,7 +62,8 @@ def write_read_primitive(writer, start, container, name, scope): writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size()) var = "%s__value" % (name) - scope.variable_def(m.member_type.c_type(), var) + 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 @@ -639,7 +640,9 @@ def write_switch_parser(writer, container, switch, dest, scope): elif t.is_pointer(): write_parse_pointer(writer, t, False, m.has_attr("c_ptr"), dest2, m.name, block) elif t.is_primitive(): - if not m.has_attr("zero"): + 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(): @@ -768,8 +771,8 @@ def write_member_parser(writer, container, member, dest, scope): write_parse_pointer(writer, t, member.has_end_attr(), member.has_attr("c_ptr"), dest, member.name, scope) elif t.is_primitive(): if member.has_attr("zero"): - pass - if member.has_end_attr(): + 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: -- cgit From 8ec1247dbe40ca7d0678e95c45f0d3a7b8908b77 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 1 Jul 2010 16:45:04 +0200 Subject: Fix 32bit failure in demarshaller Due to a typo we always read offsets as pointers, never as SPICE_ADDRESS. --- python_modules/demarshal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index b819513..023c3f6 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -837,14 +837,14 @@ def write_ptr_info_check(writer): is_ptr = "ptr_info[%s].is_ptr" % index dest = "ptr_info[%s].dest" % index with writer.if_block("%s == 0" % offset, newline=False): - with writer.if_block("%s == 0" % is_ptr, newline=False): + with writer.if_block(is_ptr, newline=False): writer.assign("*(void **)(%s)" % dest, "NULL") with writer.block(" else"): writer.assign("*(SPICE_ADDRESS *)(%s)" % dest, "0") with writer.block(" else"): writer.comment("Align to 32 bit").newline() writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)") - with writer.if_block("%s == 0" % is_ptr, newline=False): + with writer.if_block(is_ptr, newline=False): writer.assign("*(void **)(%s)" % dest, "(void *)end") with writer.block(" else"): writer.assign("*(SPICE_ADDRESS *)(%s)" % dest, "(SPICE_ADDRESS)end") -- cgit From 6228ae633e58f484f0da5cc20dcfbf42ead4859b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 30 Jun 2010 22:19:12 +0200 Subject: Properly parse and marshall SpiceString --- python_modules/demarshal.py | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 023c3f6..4d3e79b 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -125,7 +125,7 @@ def write_validate_switch_member(writer, container, switch_member, scope, parent item.subprefix = item.prefix + "_" + m.name item.non_null = c.member.has_attr("nonnull") sub_want_extra_size = want_extra_size - if sub_want_extra_size and not m.contains_extra_size(): + if sub_want_extra_size and not m.contains_extra_size() and not m.is_extra_size(): writer.assign(item.extra_size(), 0) sub_want_extra_size = False @@ -309,10 +309,13 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size: # TODO: Overflow check the multiplication - writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements)) + if array.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: + if not element_type.contains_extra_size() and not array.is_extra_size() and want_extra_size: writer.assign(extra_size, 0) want_extra_size = False @@ -329,14 +332,24 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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) + want_is_extra_size = False + want_element_mem_size = want_mem_size + if want_extra_size: + if array.is_extra_size(): + want_is_extra_size = True + want_extra_size = False + want_element_mem_size = True + else: + 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: + if want_extra_size or want_is_extra_size: writer.assign(extra_size, 0) want_element_nw_size = want_nw_size @@ -352,13 +365,19 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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: write_validate_item(writer, container, element_item, scope, parent_scope, start2, - want_element_nw_size, want_mem_size, want_extra_size) + want_element_nw_size, want_element_mem_size, want_extra_size) if want_nw_size: writer.increment(nw_size, element_nw_size) if want_mem_size: - writer.increment(mem_size, element_mem_size) - if want_extra_size: + if not array.is_extra_size(): + writer.increment(mem_size, element_mem_size) + if want_is_extra_size: + if array.ptr_array: + writer.increment(extra_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size) + else: + writer.increment(extra_size, "%s + %s" % (element_mem_size, element_extra_size)) + elif want_extra_size: writer.increment(extra_size, element_extra_size) writer.increment(start2, start_increment) @@ -722,8 +741,16 @@ def write_array_parser(writer, nelements, array, dest, scope): scope.variable_def("uint32_t", real_nelements) writer.assign("array_end", "end + %s" % nelements) writer.assign(real_nelements, 0) + if array.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 **)end") + writer.increment("end", "sizeof(void *) * %s" % nelements) with writer.index(no_block = is_byte_size) as index: with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope: + if array.ptr_array: + writer.statement("ptr_array[ptr_array_index++] = end") if is_byte_size: writer.increment(real_nelements, 1) if element_type.is_primitive(): @@ -733,6 +760,9 @@ def write_array_parser(writer, nelements, array, dest, scope): dest2 = dest.child_at_end(writer, element_type) dest2.reuse_scope = array_scope write_container_parser(writer, element_type, dest2) + if array.ptr_array: + writer.comment("Align ptr_array element to 4 bytes").newline() + writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)") if is_byte_size: writer.assign(dest.get_ref(array.size[2]), real_nelements) -- cgit From fefc89c6c45a5371be611c83e570d9f3fbc7fe75 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 5 Jul 2010 12:03:34 +0200 Subject: marshaller: Add generic way to handle propagating attributes Also switches @ptr_array to use this --- python_modules/demarshal.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 4d3e79b..5391e53 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -309,7 +309,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size: # TODO: Overflow check the multiplication - if array.ptr_array: + 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)) @@ -373,7 +373,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star if not array.is_extra_size(): writer.increment(mem_size, element_mem_size) if want_is_extra_size: - if array.ptr_array: + if array.has_attr("ptr_array"): writer.increment(extra_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size) else: writer.increment(extra_size, "%s + %s" % (element_mem_size, element_extra_size)) @@ -741,7 +741,7 @@ def write_array_parser(writer, nelements, array, dest, scope): scope.variable_def("uint32_t", real_nelements) writer.assign("array_end", "end + %s" % nelements) writer.assign(real_nelements, 0) - if array.ptr_array: + 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) @@ -749,7 +749,7 @@ def write_array_parser(writer, nelements, array, dest, scope): writer.increment("end", "sizeof(void *) * %s" % nelements) with writer.index(no_block = is_byte_size) as index: with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope: - if array.ptr_array: + if array.has_attr("ptr_array"): writer.statement("ptr_array[ptr_array_index++] = end") if is_byte_size: writer.increment(real_nelements, 1) @@ -760,7 +760,7 @@ def write_array_parser(writer, nelements, array, dest, scope): dest2 = dest.child_at_end(writer, element_type) dest2.reuse_scope = array_scope write_container_parser(writer, element_type, dest2) - if array.ptr_array: + 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)") if is_byte_size: -- cgit From f22381505d9ecc9fa6b5477d0a695b43957e93bb Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 5 Jul 2010 12:09:08 +0200 Subject: marshaller: Make @c_ptr a propagated attribute This simplifies some code --- python_modules/demarshal.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 5391e53..5a8f8ff 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -657,7 +657,7 @@ def write_switch_parser(writer, container, switch, dest, scope): if t.is_struct(): write_container_parser(writer, t, dest2) elif t.is_pointer(): - write_parse_pointer(writer, t, False, m.has_attr("c_ptr"), dest2, m.name, block) + write_parse_pointer(writer, t, False, dest2, m.name, block) elif t.is_primitive(): if m.has_attr("zero"): writer.statement("consume_%s(&in)" % (t.primitive_type())) @@ -766,21 +766,22 @@ def write_array_parser(writer, nelements, array, dest, scope): if is_byte_size: writer.assign(dest.get_ref(array.size[2]), real_nelements) -def write_parse_pointer(writer, t, at_end, as_c_ptr, dest, member_name, scope): - target_type = t.target_type - writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type()) - writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) - if at_end: - writer.assign("ptr_info[n_ptr].dest", "end") - writer.increment("end", "sizeof(void *)" if as_c_ptr else "sizeof(SPICE_ADDRESS)"); - else: - writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name)) - writer.assign("ptr_info[n_ptr].is_ptr", "1" if as_c_ptr else "0") - if target_type.is_array(): - nelements = read_array_len(writer, member_name, target_type, dest, scope) - writer.assign("ptr_info[n_ptr].nelements", nelements) +def write_parse_pointer(writer, t, at_end, dest, member_name, scope): + as_c_ptr = t.has_attr("c_ptr") + target_type = t.target_type + writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type()) + writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) + if at_end: + writer.assign("ptr_info[n_ptr].dest", "end") + writer.increment("end", "sizeof(void *)" if as_c_ptr else "sizeof(SPICE_ADDRESS)"); + else: + writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name)) + writer.assign("ptr_info[n_ptr].is_ptr", "1" if as_c_ptr else "0") + if target_type.is_array(): + nelements = read_array_len(writer, member_name, target_type, dest, scope) + writer.assign("ptr_info[n_ptr].nelements", nelements) - writer.statement("n_ptr++") + writer.statement("n_ptr++") def write_member_parser(writer, container, member, dest, scope): if member.has_attr("virtual"): @@ -798,7 +799,7 @@ def write_member_parser(writer, container, member, dest, scope): 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(), member.has_attr("c_ptr"), dest, member.name, scope) + 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()) -- cgit From 32481bf381f97cf99bee6df36afadbb213b61e3f Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 5 Jul 2010 12:13:45 +0200 Subject: marshaller: Make @nonnull a propagated attribute This cleans up some stuff --- python_modules/demarshal.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 5a8f8ff..5709567 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -82,7 +82,6 @@ class ItemInfo: self.prefix = prefix self.subprefix = prefix self.position = position - self.non_null = False self.member = None def nw_size(self): @@ -103,7 +102,6 @@ class MemberItemInfo(ItemInfo): self.type = member.member_type self.prefix = member.name self.subprefix = member.name - self.non_null = member.has_attr("nonnull") self.position = "(%s + %s)" % (start, container.get_nw_offset(member, "", "__nw_size")) self.member = member @@ -123,7 +121,6 @@ def write_validate_switch_member(writer, container, switch_member, scope, parent with writer.if_block(check, not first, False) as if_scope: item.type = c.member.member_type item.subprefix = item.prefix + "_" + m.name - item.non_null = c.member.has_attr("nonnull") sub_want_extra_size = want_extra_size if sub_want_extra_size and not m.contains_extra_size() and not m.is_extra_size(): writer.assign(item.extra_size(), 0) @@ -192,7 +189,7 @@ def write_validate_pointer_item(writer, container, item, scope, parent_scope, st target_type = item.type.target_type v = write_read_primitive_item(writer, item, scope) - if item.non_null: + if item.type.has_attr("nonnull"): writer.error_check("%s == 0" % v) # pointer target is struct, or array of primitives -- cgit From daaf4865d81bb3d05e6fe799fd9f87d9950a1136 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 5 Jul 2010 13:13:09 +0200 Subject: marshaller: Add some docs describing the types of sizes --- python_modules/demarshal.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 5709567..cf6fefd 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1,6 +1,35 @@ 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"): -- cgit From bb1d862989ae4d69145e1c8b97dc83a6b8fb450c Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 5 Jul 2010 13:13:39 +0200 Subject: Handle extra size for switch and array the right way Even for is_extra_size() we should calculate the mem_size for arrays, its just that the parent type (in this case switch) should request mem_size if the type is_extra_size. --- python_modules/demarshal.py | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index cf6fefd..606b926 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -150,13 +150,19 @@ def write_validate_switch_member(writer, container, switch_member, scope, parent with writer.if_block(check, not first, False) as if_scope: item.type = c.member.member_type item.subprefix = item.prefix + "_" + m.name - sub_want_extra_size = want_extra_size - if sub_want_extra_size and not m.contains_extra_size() and not m.is_extra_size(): - writer.assign(item.extra_size(), 0) - sub_want_extra_size = False + + 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, want_mem_size, sub_want_extra_size) + 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 @@ -341,7 +347,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements)) want_mem_size = False - if not element_type.contains_extra_size() and not array.is_extra_size() and want_extra_size: + if not element_type.contains_extra_size() and want_extra_size: writer.assign(extra_size, 0) want_extra_size = False @@ -361,21 +367,14 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star element_extra_size = element_item.extra_size() scope.variable_def("uint32_t", element_nw_size) scope.variable_def("uint32_t", element_mem_size) - want_is_extra_size = False - want_element_mem_size = want_mem_size if want_extra_size: - if array.is_extra_size(): - want_is_extra_size = True - want_extra_size = False - want_element_mem_size = True - else: - scope.variable_def("uint32_t", element_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 or want_is_extra_size: + if want_extra_size: writer.assign(extra_size, 0) want_element_nw_size = want_nw_size @@ -391,19 +390,16 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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: write_validate_item(writer, container, element_item, scope, parent_scope, start2, - want_element_nw_size, want_element_mem_size, want_extra_size) + 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 not array.is_extra_size(): - writer.increment(mem_size, element_mem_size) - if want_is_extra_size: if array.has_attr("ptr_array"): - writer.increment(extra_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size) + writer.increment(mem_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size) else: - writer.increment(extra_size, "%s + %s" % (element_mem_size, element_extra_size)) - elif want_extra_size: + writer.increment(mem_size, element_mem_size) + if want_extra_size: writer.increment(extra_size, element_extra_size) writer.increment(start2, start_increment) @@ -426,7 +422,8 @@ def write_validate_primitive_item(writer, container, item, scope, parent_scope, if want_mem_size: mem_size = item.mem_size() writer.assign(mem_size, item.type.sizeof()) - assert not want_extra_size + 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): -- cgit From 6ca5b39e6f2a6d82d0234cc2967ebfce2b9092d6 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 5 Jul 2010 20:45:13 +0200 Subject: Convert SpicePath.segments to a pointer array --- python_modules/demarshal.py | 51 +++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 606b926..bd7660d 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -47,13 +47,16 @@ def write_parser_helpers(writer): 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]: @@ -96,6 +99,15 @@ def write_read_primitive(writer, start, container, name, scope): 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()) @@ -280,6 +292,9 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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): @@ -315,6 +330,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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: @@ -389,6 +405,8 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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) @@ -405,6 +423,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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): @@ -613,11 +632,9 @@ class SubDemarshallingDestination(DemarshallingDestination): def get_ref(self, member): return self.parent_dest.get_ref(self.member) + "." + member -def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False): - if array.is_bytes_length(): - nelements = "%s__nbytes" % prefix - else: - nelements = "%s__nelements" % prefix +# Note: during parsing, byte_size types have been converted to count during validation +def read_array_len(writer, prefix, array, dest, scope): + nelements = "%s__nelements" % prefix if dest.is_toplevel(): return nelements # Already there for toplevel, need not recalculate element_type = array.element_type @@ -645,9 +662,7 @@ def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False): else: writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v)) elif array.is_bytes_length(): - if not handles_bytes: - raise NotImplementedError("handling of bytes() not supported here yet") - writer.assign(nelements, array.size[1]) + writer.assign(nelements, dest.get_ref(array.size[2])) else: raise NotImplementedError("TODO array size type not handled yet") return nelements @@ -758,24 +773,16 @@ def write_array_parser(writer, nelements, array, dest, scope): writer.increment("in", nelements) writer.increment("end", nelements) else: - if is_byte_size: - real_nelements = nelements[:-len("nbytes")] + "nelements" - scope.variable_def("uint8_t *", "array_end") - scope.variable_def("uint32_t", real_nelements) - writer.assign("array_end", "end + %s" % nelements) - writer.assign(real_nelements, 0) 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 **)end") writer.increment("end", "sizeof(void *) * %s" % nelements) - with writer.index(no_block = is_byte_size) as index: - with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope: + with writer.index() as index: + with writer.for_loop(index, nelements) as array_scope: if array.has_attr("ptr_array"): writer.statement("ptr_array[ptr_array_index++] = end") - if is_byte_size: - writer.increment(real_nelements, 1) if element_type.is_primitive(): writer.statement("*(%s *)end = consume_%s(&in)" % (element_type.c_type(), element_type.primitive_type())) writer.increment("end", element_type.sizeof()) @@ -786,8 +793,6 @@ def write_array_parser(writer, nelements, array, dest, scope): 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)") - if is_byte_size: - writer.assign(dest.get_ref(array.size[2]), real_nelements) def write_parse_pointer(writer, t, at_end, dest, member_name, scope): as_c_ptr = t.has_attr("c_ptr") @@ -831,14 +836,14 @@ def write_member_parser(writer, container, member, dest, scope): writer.increment("end", t.sizeof()) else: if member.has_attr("bytes_count"): - scope.variable_def("uint32_t", member.name); - dest_var = member.name + print member.attributes["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, handles_bytes = True) + nelements = read_array_len(writer, member.name, t, dest, scope) if 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()) -- cgit From 1b432de3b96c80e05287b6785b5be624baae8ba3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 6 Jul 2010 22:13:18 +0200 Subject: Add support for @chunk --- python_modules/demarshal.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index bd7660d..51dbe31 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -261,7 +261,9 @@ def write_validate_pointer_item(writer, container, item, scope, parent_scope, st 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("nocopy"): + 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: @@ -823,7 +825,20 @@ def write_member_parser(writer, container, member, dest, scope): t = member.member_type if t.is_pointer(): - if member.has_attr("nocopy"): + if member.has_attr("chunk"): + assert(t.target_type.is_array()) + nelements = read_array_len(writer, member.name, t.target_type, dest, scope) + 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") # spice_chunks_new_linear(message_start + consume_%s(&in), %s)" % (t.primitive_type(), nelements)) + 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: @@ -1140,6 +1155,7 @@ def write_includes(writer): writer.writeln("#include ") writer.writeln("#include ") writer.writeln("#include ") + writer.writeln("#include ") writer.newline() writer.writeln("#ifdef _MSC_VER") writer.writeln("#pragma warning(disable:4101)") -- cgit From 4a12b9c0dd555695177a017f4826557dde5fbe11 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 7 Jul 2010 20:40:06 +0200 Subject: codegen: support @chunk on non-pointer arrays This is similar to @as_ptr, but generates a single chunk of data. --- python_modules/demarshal.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 51dbe31..323fc70 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -357,6 +357,18 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star 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"): @@ -832,7 +844,7 @@ def write_member_parser(writer, container, member, dest, scope): 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") # spice_chunks_new_linear(message_start + consume_%s(&in), %s)" % (t.primitive_type(), nelements)) + 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) @@ -851,7 +863,6 @@ def write_member_parser(writer, container, member, dest, scope): writer.increment("end", t.sizeof()) else: if member.has_attr("bytes_count"): - print member.attributes["bytes_count"] dest_var = dest.get_ref(member.attributes["bytes_count"][0]) else: dest_var = dest.get_ref(member.name) @@ -859,7 +870,20 @@ def write_member_parser(writer, container, member, dest, scope): #TODO validate e.g. flags and enums elif t.is_array(): nelements = read_array_len(writer, member.name, t, dest, scope) - if member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size(): + 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"] -- cgit From 0ed056da99f2ee23da5600f76d5824c68918c1b5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 1 Jul 2010 17:55:33 +0200 Subject: Properly parse QXLImage to the new-world SpiceImage SpiceImage now replaces RedImage and has all image types in it. All image data are now chunked (and as such not copied when demarshalling). --- python_modules/demarshal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 323fc70..1ae1911 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -93,7 +93,7 @@ def write_read_primitive(writer, start, container, name, scope): 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) + 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())) @@ -112,7 +112,7 @@ 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) + 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 -- cgit From 74f9cd9f731f33c8c435fafcf3bada7ef0661470 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 8 Jul 2010 13:07:17 +0200 Subject: codegen: No SPICE_ADDRESS types left, drop @c_ptr --- python_modules/demarshal.py | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 1ae1911..e8afabb 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -82,9 +82,8 @@ def write_parser_helpers(writer): 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("void **", "dest") writer.variable_def("uint32_t", "nelements") - writer.variable_def("int", "is_ptr") writer.end_block(semicolon=True) def write_read_primitive(writer, start, container, name, scope): @@ -195,7 +194,7 @@ def write_validate_struct_function(writer, struct): 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, SPICE_ADDRESS offset, int minor") + 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"); @@ -809,16 +808,14 @@ def write_array_parser(writer, nelements, array, dest, scope): writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)") def write_parse_pointer(writer, t, at_end, dest, member_name, scope): - as_c_ptr = t.has_attr("c_ptr") target_type = t.target_type writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type()) writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) if at_end: - writer.assign("ptr_info[n_ptr].dest", "end") - writer.increment("end", "sizeof(void *)" if as_c_ptr else "sizeof(SPICE_ADDRESS)"); + writer.assign("ptr_info[n_ptr].dest", "(void **)end") + writer.increment("end", "sizeof(void *)"); else: - writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name)) - writer.assign("ptr_info[n_ptr].is_ptr", "1" if as_c_ptr else "0") + 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) writer.assign("ptr_info[n_ptr].nelements", nelements) @@ -932,20 +929,13 @@ def write_ptr_info_check(writer): with writer.for_loop(index, "n_ptr") as scope: offset = "ptr_info[%s].offset" % index function = "ptr_info[%s].parse" % index - is_ptr = "ptr_info[%s].is_ptr" % index dest = "ptr_info[%s].dest" % index with writer.if_block("%s == 0" % offset, newline=False): - with writer.if_block(is_ptr, newline=False): - writer.assign("*(void **)(%s)" % dest, "NULL") - with writer.block(" else"): - writer.assign("*(SPICE_ADDRESS *)(%s)" % dest, "0") + 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)") - with writer.if_block(is_ptr, newline=False): - writer.assign("*(void **)(%s)" % dest, "(void *)end") - with writer.block(" else"): - writer.assign("*(SPICE_ADDRESS *)(%s)" % dest, "(SPICE_ADDRESS)end") + 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() -- cgit From a09be53ea82e238183b117641d99ab3f89248bd0 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 8 Jul 2010 15:44:15 +0200 Subject: Fix inclusion of common files, no need for common/ part --- python_modules/demarshal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index e8afabb..96aa146 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1169,7 +1169,7 @@ def write_includes(writer): writer.writeln("#include ") writer.writeln("#include ") writer.writeln("#include ") - writer.writeln("#include ") + writer.writeln('#include "mem.h"') writer.newline() writer.writeln("#ifdef _MSC_VER") writer.writeln("#pragma warning(disable:4101)") -- cgit From d9629ca4e700cb35b77579bde4ab78ad7adbb30a Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 19 Jul 2010 14:10:16 +0200 Subject: codegen: Various cleanups Remove all uses of @end in the marshaller, instead just using the C struct array-at-end-of-struct. To make this work we also remove all use of @end for switches (making them C unions). We drop the zero member of the notify message so that we can avoid this use of @end for a primitive in the marshaller (plus its useless to send over the wire). We change the offsets and stuff in the migration messages to real pointers. --- python_modules/demarshal.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 96aa146..63f952b 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -646,8 +646,11 @@ class SubDemarshallingDestination(DemarshallingDestination): 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): - nelements = "%s__nelements" % prefix +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(): return nelements # Already there for toplevel, need not recalculate element_type = array.element_type @@ -716,8 +719,8 @@ def write_switch_parser(writer, container, switch, dest, scope): 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) - write_array_parser(writer, nelements, t, dest, block) + 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) @@ -759,7 +762,7 @@ def write_parse_ptr_function(writer, target_type): dest.is_helper = True dest.reuse_scope = scope if target_type.is_array(): - write_array_parser(writer, "this_ptr_info->nelements", target_type, dest, scope) + write_array_parser(writer, None, "this_ptr_info->nelements", target_type, dest, scope) else: write_container_parser(writer, target_type, dest) @@ -777,14 +780,17 @@ def write_parse_ptr_function(writer, target_type): return parse_function -def write_array_parser(writer, nelements, array, dest, scope): +def write_array_parser(writer, member, nelements, array, dest, scope): is_byte_size = array.is_bytes_length() element_type = array.element_type if element_type == ptypes.uint8 or element_type == ptypes.int8: - writer.statement("memcpy(end, in, %s)" % (nelements)) + if not member or member.has_attr("end"): + writer.statement("memcpy(end, in, %s)" % (nelements)) + writer.increment("end", nelements) + else: + writer.statement("memcpy(%s, in, %s)" % (dest.get_ref(member.name), nelements)) writer.increment("in", nelements) - writer.increment("end", nelements) else: if array.has_attr("ptr_array"): scope.variable_def("void **", "ptr_array") @@ -817,7 +823,7 @@ def write_parse_pointer(writer, t, at_end, dest, member_name, scope): 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) + nelements = read_array_len(writer, member_name, target_type, dest, scope, True) writer.assign("ptr_info[n_ptr].nelements", nelements) writer.statement("n_ptr++") @@ -836,7 +842,7 @@ def write_member_parser(writer, container, member, dest, scope): if 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) + 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") @@ -866,7 +872,7 @@ def write_member_parser(writer, container, member, dest, scope): 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) + 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() @@ -892,7 +898,7 @@ def write_member_parser(writer, container, member, dest, scope): else: writer.increment("in", "%s" % (nelements)) else: - write_array_parser(writer, nelements, t, dest, scope) + 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) @@ -915,7 +921,9 @@ def write_container_parser(writer, container, dest): 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.member_type.is_primitive(): + 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())) -- cgit From f008b7605df19ab5deb8f4f383837bef9416d7a1 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 19 Jul 2010 15:47:40 +0200 Subject: codegen: Allow @to_ptr to make inline structs demarshal as pointers --- python_modules/demarshal.py | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 63f952b..4aba7b0 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -161,6 +161,7 @@ def write_validate_switch_member(writer, container, switch_member, scope, parent 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()): @@ -459,6 +460,8 @@ def write_validate_primitive_item(writer, container, item, scope, parent_scope, 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) @@ -474,6 +477,11 @@ def write_validate_item(writer, container, item, scope, parent_scope, start, 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) + 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"): @@ -708,10 +716,12 @@ def write_switch_parser(writer, container, switch, dest, scope): dest2 = dest.child_sub(switch.name) dest2.reuse_scope = block - if t.is_struct(): - write_container_parser(writer, t, dest2) + 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())) @@ -813,9 +823,8 @@ def write_array_parser(writer, member, nelements, array, dest, scope): 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(writer, t, at_end, dest, member_name, scope): - target_type = t.target_type - writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type()) +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") @@ -828,6 +837,15 @@ def write_parse_pointer(writer, t, at_end, dest, member_name, scope): 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]) @@ -839,7 +857,9 @@ def write_member_parser(writer, container, member, dest, scope): t = member.member_type - if t.is_pointer(): + 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) -- cgit From 4702feb5b1958eeef9b4414a2fb7cac259394a52 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 19 Jul 2010 16:27:42 +0200 Subject: Don't send CursorHeader if cursor_flags is NONE --- python_modules/demarshal.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 4aba7b0..f259ead 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -708,7 +708,10 @@ def write_switch_parser(writer, container, switch, dest, scope): if switch.has_end_attr(): dest2 = dest.child_at_end(writer, m.member_type) elif switch.has_attr("anon"): - dest2 = dest + 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) -- cgit From 12bc82da5cc172df06cf1f5fbddd492e93e18fe6 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 19 Jul 2010 20:24:25 +0200 Subject: Fix uninitialized variable warnings --- python_modules/demarshal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index f259ead..a4345d4 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -479,7 +479,7 @@ def write_validate_item(writer, container, item, scope, parent_scope, start, 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) + 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, -- cgit From aae971c6abff7deacc9ffcde8aab87ded08b24c3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 20 Jul 2010 11:34:23 +0200 Subject: demarshaller: Fix palette marshalling It turns out that using base + sizeof(struct) is not a good way to access an array at the end of a struct. For SpicePalette sizeof is 16, but offset of ents is 12. Using this calculation in the demarshaller breaks things badly, so now we use the actual array member. --- python_modules/demarshal.py | 46 +++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index a4345d4..c588f98 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -797,29 +797,47 @@ 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: - if not member or member.has_attr("end"): - writer.statement("memcpy(end, in, %s)" % (nelements)) - writer.increment("end", nelements) - else: - writer.statement("memcpy(%s, in, %s)" % (dest.get_ref(member.name), nelements)) + writer.statement("memcpy(%s, in, %s)" % (array_start, nelements)) writer.increment("in", nelements) + if at_end: + writer.increment("end", nelements) else: - 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 **)end") - writer.increment("end", "sizeof(void *) * %s" % nelements) 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 *)end = consume_%s(&in)" % (element_type.c_type(), element_type.primitive_type())) - writer.increment("end", element_type.sizeof()) + writer.statement("%s = consume_%s(&in)" % (array_pos, element_type.primitive_type())) + if at_end: + writer.increment("end", element_type.sizeof()) else: - dest2 = dest.child_at_end(writer, element_type) + 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"): -- cgit From aa7a086933c8b03d2f7f78874342a53719a24fa5 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Thu, 29 Jul 2010 09:03:15 -0400 Subject: support python 2.5.4+ for marshaller/demarshallers Patch adds a "from __future__" import that doesn't affect newer python's but allows python 2.5.4 to run the code (tested under scratchbox, n900 build environment) --- python_modules/demarshal.py | 1 + 1 file changed, 1 insertion(+) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index c588f98..cbe3599 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1,3 +1,4 @@ +from __future__ import with_statement import ptypes import codegen -- cgit From d6f198b3f433100a7a212be03b059876ed33e598 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 24 Jan 2011 22:07:55 +0200 Subject: codegen: avoid creating out if not used (fix gcc 4.6.0 warning) --- python_modules/demarshal.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index cbe3599..48551c0 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1047,9 +1047,11 @@ def write_msg_parser(writer, message): writer.assign("end", "data + %s" % (msg_sizeof)) writer.assign("in", "start").newline() - dest = RootDemarshallingDestination(None, msg_type, msg_sizeof, "data") - dest.reuse_scope = parent_scope - write_container_parser(writer, message, dest) + # 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)") -- cgit From 3a6de6d6fb0362df9e78fa64942a45c02bdabe53 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 24 Jan 2011 23:32:43 +0200 Subject: demarshaller/marshaller fix gcc 4.6.0 python_modules/demarshal.py and marshal.py fixes for gcc 4.6.0 warning about set but unused variables. The fixes disable creating of variables mem_size when they are not used (demarshall) and declaring a src variable when the message doesn't use it (marshal). You need to touch *.proto after applying this (should add a Makefile dependency). --- python_modules/demarshal.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 48551c0..9d3b1e4 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -251,14 +251,18 @@ def write_validate_pointer_item(writer, container, item, scope, parent_scope, st array_item = ItemInfo(target_type, "%s__array" % item.prefix, start) scope.variable_def("uint32_t", array_item.nw_size()) - scope.variable_def("uint32_t", array_item.mem_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())) - writer.assign(array_item.mem_size(), array_item.nw_size()) else: write_validate_array_item(writer, container, array_item, scope, parent_scope, start, - True, True, False) + 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: @@ -524,7 +528,7 @@ def write_validate_member(writer, container, member, parent_scope, start, 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() + 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"] @@ -1007,6 +1011,9 @@ def write_msg_parser(writer, message): 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 *", @@ -1014,7 +1021,9 @@ def write_msg_parser(writer, message): 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", "mem_size", "nw_size"); + 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() @@ -1026,7 +1035,8 @@ def write_msg_parser(writer, message): write_parser_helpers(writer) - write_validate_container(writer, None, message, "start", parent_scope, True, True, False) + write_validate_container(writer, None, message, "start", parent_scope, True, + want_mem_size=want_mem_size, want_extra_size=False) writer.newline() -- cgit From bbd93cdb6b26e475bc7772a6b0c239082adfc153 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 21 Jun 2011 13:20:33 +0200 Subject: python: remove c-ism trailing ; --- python_modules/demarshal.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 9d3b1e4..3a0178e 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -74,7 +74,7 @@ def write_parser_helpers(writer): writer.newline() writer.statement("typedef struct PointerInfo PointerInfo") - writer.statement("typedef void (*message_destructor_t)(uint8_t *message)"); + 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)") @@ -198,11 +198,11 @@ def write_validate_struct_function(writer, struct): 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"); + 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"); + scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size") writer.newline() with writer.if_block("offset == 0"): @@ -766,8 +766,8 @@ def write_parse_ptr_function(writer, target_type): 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("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() @@ -854,7 +854,7 @@ def write_parse_pointer_core(writer, target_type, offset, at_end, dest, member_n 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 *)"); + 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(): @@ -890,7 +890,7 @@ def write_member_parser(writer, container, member, dest, scope): 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"); + 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") @@ -922,7 +922,7 @@ def write_member_parser(writer, container, member, dest, scope): 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"); + 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") @@ -1018,18 +1018,18 @@ def write_msg_parser(writer, message): 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("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"); + 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("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() @@ -1121,7 +1121,7 @@ def write_channel_parser(writer, channel, server): 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.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) -- cgit From 36ea49b68619a0d35c2887a1c7a3960dbc4d4fed Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Fri, 2 Mar 2012 13:42:10 +0100 Subject: demarshal: fixed-size array are missing __nelements A message with a fixed-size array, such as uint8 uuid[16] will generate an invalid code, missing the __nelements variable. Make sure that variable is defined. --- python_modules/demarshal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 3a0178e..541735a 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -664,7 +664,7 @@ def read_array_len(writer, prefix, array, dest, scope, is_ptr): nelements = "%s__array__nelements" % prefix else: nelements = "%s__nelements" % prefix - if dest.is_toplevel(): + 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) -- cgit From 12a5ce3dc5d9b130de1eba7038c9915428fac802 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Wed, 22 Jun 2011 13:26:15 +0200 Subject: handle @ifdef on messages and channels --- python_modules/demarshal.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 541735a..2381e7f 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1015,6 +1015,8 @@ def write_msg_parser(writer, message): or not message.members[0].is_array()) writer.newline() + if message.has_attr("ifdef"): + writer.ifdef(message.attributes["ifdef"][0]) parent_scope = writer.function(function_name, "uint8_t *", "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size, message_destructor_t *free_message", True) @@ -1084,6 +1086,9 @@ def write_msg_parser(writer, message): writer.statement("return NULL") writer.end_block() + if message.has_attr("ifdef"): + writer.endif(message.attributes["ifdef"][0]) + return function_name def write_channel_parser(writer, channel, server): @@ -1112,6 +1117,8 @@ def write_channel_parser(writer, channel, server): else: function_name = "parse_%s_msgc" % channel.name writer.newline() + if channel.has_attr("ifdef"): + writer.ifdef(channel.attributes["ifdef"][0]) scope = writer.function(function_name, "static uint8_t *", "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message") @@ -1141,6 +1148,8 @@ def write_channel_parser(writer, channel, server): writer.statement("return NULL") writer.end_block() + if channel.has_attr("ifdef"): + writer.endif(channel.attributes["ifdef"][0]) return function_name @@ -1157,13 +1166,16 @@ def write_get_channel_parser(writer, channel_parsers, max_channel, is_server): writer.write("static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[%d] = " % (max_channel+1)) writer.begin_block() + channel = None for i in range(0, max_channel + 1): - writer.write("{ ") if channel_parsers.has_key(i): + channel = channel_parsers[i][0] + if channel.has_attr("ifdef"): + writer.ifdef(channel.attributes["ifdef"][0]) + writer.write("{ ") writer.write(channel_parsers[i][1]) writer.write(", ") - channel = channel_parsers[i][0] max_msg = 0 if is_server: messages = channel.server_messages @@ -1172,13 +1184,15 @@ def write_get_channel_parser(writer, channel_parsers, max_channel, is_server): for m in messages: max_msg = max(max_msg, m.value) writer.write(max_msg) + writer.write("}") else: - writer.write("NULL, 0") - writer.write("}") + writer.write("{ NULL, 0 }") if i != max_channel: writer.write(",") writer.newline() + if channel and channel.has_attr("ifdef"): + writer.endif(channel.attributes["ifdef"][0]) writer.end_block(semicolon = True) with writer.if_block("channel < %d" % (max_channel + 1)): -- cgit From ca57afda341a1187a9c367e5be71744979dd7a86 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 30 Sep 2011 11:19:38 +0200 Subject: spice_codegen: Always write a channels entry for an ifdef-ed channel Before this patch, if a channel is defined conditionally in spice.proto (because it depends on external headers like the smartcard channel), spice_codegen would write an entry to the channels array in spice_get_*_channel_parser which would only take up a place in the array if the ifdef condition is true, thus moving up all other intializers one place when it is not true. This was causing issues (crashes) when building spice-gtk with the combination of usbredir support enabled and smartcard support disabled. This patch fixes this by adding #else { NULL, 0 }, to the generated code. Thanks to coolper chen for reporting this! Signed-off-by: Hans de Goede --- python_modules/demarshal.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 2381e7f..c8c6837 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1192,6 +1192,11 @@ def write_get_channel_parser(writer, channel_parsers, max_channel, is_server): writer.write(",") writer.newline() if channel and channel.has_attr("ifdef"): + writer.ifdef_else(channel.attributes["ifdef"][0]) + writer.write("{ NULL, 0 }") + if i != max_channel: + writer.write(",") + writer.newline() writer.endif(channel.attributes["ifdef"][0]) writer.end_block(semicolon = True) -- cgit From 725b5a9b53276aad505501e04f3d1cfbd7b6822f Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Fri, 6 Apr 2012 15:25:34 +0200 Subject: demarshall: add missing parens in BE read_xxx functions The missing parens causes build to fail on big-endian machines --- python_modules/demarshal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index c8c6837..cf48d74 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -50,7 +50,7 @@ def write_parser_helpers(writer): 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("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]: -- cgit From ef14521ac5218ca876e29173470fdb41a0cc821c Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Wed, 19 Mar 2014 15:41:07 +0100 Subject: Use #include "common/..." in (de)marshallers Now that they are created in $builddir, their includes will need to refer to files in $srcdir, which can be different. It's cleaner to add -I $(top_srcdir)/spice-common/ to modules using spice-common rather than having -I $(top_srcdir)/spice-common/common which would could create header collisions. --- python_modules/demarshal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index cf48d74..794cd25 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1250,7 +1250,7 @@ def write_includes(writer): writer.writeln("#include ") writer.writeln("#include ") writer.writeln("#include ") - writer.writeln('#include "mem.h"') + writer.writeln('#include "common/mem.h"') writer.newline() writer.writeln("#ifdef _MSC_VER") writer.writeln("#pragma warning(disable:4101)") -- cgit From 06a99ce30b113566b40453e42752d45582b3a9f7 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Tue, 25 Mar 2014 16:32:16 +0100 Subject: marshaller: Use #include <> for headers in $srcdir/common Since the (de)marshallers are now generated in $builddir and not in $srcdir, when these generated files include a file located in $srcdir/common, the compiler will find them thanks to a -I directive, so it makes more sense to use <> rather than "" when including them. --- python_modules/demarshal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 794cd25..b7e51dc 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1250,7 +1250,7 @@ def write_includes(writer): writer.writeln("#include ") writer.writeln("#include ") writer.writeln("#include ") - writer.writeln('#include "common/mem.h"') + writer.writeln('#include ') writer.newline() writer.writeln("#ifdef _MSC_VER") writer.writeln("#pragma warning(disable:4101)") -- cgit From 3916b9d813e716d0c8c03a2be82dd169e4461e90 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Wed, 16 Apr 2014 13:23:12 +0200 Subject: demarshal: prefix variable name with parent names Avoid naming clash if parent structures have the same name https://bugzilla.redhat.com/show_bug.cgi?id=1021995 --- python_modules/demarshal.py | 47 +++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index b7e51dc..ead776d 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -138,22 +138,25 @@ class ItemInfo: return self.position class MemberItemInfo(ItemInfo): - def __init__(self, member, container, start): + def __init__(self, member, mprefix, container, start): if not member.is_switch(): self.type = member.member_type self.prefix = member.name + if mprefix: + mprefix = mprefix + "_" + self.prefix = mprefix + self.prefix self.subprefix = member.name - self.position = "(%s + %s)" % (start, container.get_nw_offset(member, "", "__nw_size")) + self.position = "(%s + %s)" % (start, container.get_nw_offset(member, mprefix or "", "__nw_size")) self.member = member -def write_validate_switch_member(writer, container, switch_member, scope, parent_scope, start, +def write_validate_switch_member(writer, mprefix, container, switch_member, scope, parent_scope, start, want_nw_size, want_mem_size, want_extra_size): var = container.lookup_member(switch_member.variable) var_type = var.member_type v = write_read_primitive(writer, start, container, switch_member.variable, parent_scope) - item = MemberItemInfo(switch_member, container, start) + item = MemberItemInfo(switch_member, mprefix, container, start) first = True for c in switch_member.cases: @@ -487,7 +490,7 @@ def write_validate_item(writer, container, item, scope, parent_scope, start, 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, +def write_validate_member(writer, mprefix, container, member, parent_scope, start, want_nw_size, want_mem_size, want_extra_size): if member.has_attr("virtual"): return @@ -498,10 +501,10 @@ def write_validate_member(writer, container, member, parent_scope, start, else: prefix = "" newline = True - item = MemberItemInfo(member, container, start) + item = MemberItemInfo(member, mprefix, container, start) with writer.block(prefix, newline=newline, comment=member.name) as scope: if member.is_switch(): - write_validate_switch_member(writer, container, member, scope, parent_scope, start, + write_validate_switch_member(writer, mprefix, container, member, scope, parent_scope, start, want_nw_size, want_mem_size, want_extra_size) else: write_validate_item(writer, container, item, scope, parent_scope, start, @@ -526,22 +529,29 @@ def write_validate_member(writer, container, member, parent_scope, start, assert not want_extra_size def write_validate_container(writer, prefix, container, start, parent_scope, want_nw_size, want_mem_size, want_extra_size): + def prefix_m(prefix, m): + name = m.name + if prefix: + name = prefix + "_" + name + return name + for m in container.members: sub_want_nw_size = want_nw_size and not m.is_fixed_nw_size() sub_want_mem_size = m.is_extra_size() and want_mem_size sub_want_extra_size = not m.is_extra_size() and m.contains_extra_size() - defs = ["size_t"] + name = prefix_m(prefix, m) if sub_want_nw_size: - defs.append (m.name + "__nw_size") + + defs.append (name + "__nw_size") if sub_want_mem_size: - defs.append (m.name + "__mem_size") + defs.append (name + "__mem_size") if sub_want_extra_size: - defs.append (m.name + "__extra_size") + defs.append (name + "__extra_size") if sub_want_nw_size or sub_want_mem_size or sub_want_extra_size: parent_scope.variable_def(*defs) - write_validate_member(writer, container, m, parent_scope, start, + write_validate_member(writer, prefix, container, m, parent_scope, start, sub_want_nw_size, sub_want_mem_size, sub_want_extra_size) writer.newline() @@ -558,8 +568,9 @@ def write_validate_container(writer, prefix, container, start, parent_scope, wan nm_sum = str(size) for m in container.members: + name = prefix_m(prefix, m) if not m.is_fixed_nw_size(): - nm_sum = nm_sum + " + " + m.name + "__nw_size" + nm_sum = nm_sum + " + " + name + "__nw_size" writer.assign(nw_size, nm_sum) @@ -571,10 +582,11 @@ def write_validate_container(writer, prefix, container, start, parent_scope, wan mem_sum = container.sizeof() for m in container.members: + name = prefix_m(prefix, m) if m.is_extra_size(): - mem_sum = mem_sum + " + " + m.name + "__mem_size" + mem_sum = mem_sum + " + " + name + "__mem_size" elif m.contains_extra_size(): - mem_sum = mem_sum + " + " + m.name + "__extra_size" + mem_sum = mem_sum + " + " + name + "__extra_size" writer.assign(mem_size, mem_sum) @@ -586,10 +598,11 @@ def write_validate_container(writer, prefix, container, start, parent_scope, wan extra_sum = [] for m in container.members: + name = prefix_m(prefix, m) if m.is_extra_size(): - extra_sum.append(m.name + "__mem_size") + extra_sum.append(name + "__mem_size") elif m.contains_extra_size(): - extra_sum.append(m.name + "__extra_size") + extra_sum.append(name + "__extra_size") writer.assign(extra_size, codegen.sum_array(extra_sum)) class DemarshallingDestination: -- cgit From 744675b424a9db5e6fc26440dcfab961fd1d284e Mon Sep 17 00:00:00 2001 From: Fabiano Fidêncio Date: Wed, 3 Sep 2014 11:51:45 +0200 Subject: python: Fix -Wunused-parameter Although the most part of the parameters marked as unused are actually being used for a few functions, a bunch of warnings can be seen when the code is compiled with "-Wall -Wextra". As adding the unused attribute means that the variable/parameter is meant to be *possibly* unused, we're safe adding it in the generated code, even for used variables/parameters. --- python_modules/demarshal.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index ead776d..109f5e6 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -199,7 +199,7 @@ def write_validate_struct_function(writer, struct): 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 = writer.function(validate_function, "static intptr_t", "uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor") scope.variable_def("uint8_t *", "start = message_start + offset") scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos") scope.variable_def("size_t", "mem_size", "nw_size") @@ -773,7 +773,7 @@ def write_parse_ptr_function(writer, target_type): 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 = writer.function(parse_function, "static uint8_t *", "uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor") scope.variable_def("uint8_t *", "in = message_start + this_ptr_info->offset") scope.variable_def("uint8_t *", "end") @@ -1011,7 +1011,7 @@ def write_nofree(writer): if writer.is_generated("helper", "nofree"): return writer = writer.function_helper() - scope = writer.function("nofree", "static void", "uint8_t *data") + scope = writer.function("nofree", "static void", "SPICE_GNUC_UNUSED uint8_t *data") writer.end_block() def write_msg_parser(writer, message): @@ -1032,7 +1032,7 @@ def write_msg_parser(writer, message): writer.ifdef(message.attributes["ifdef"][0]) parent_scope = writer.function(function_name, "uint8_t *", - "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size, message_destructor_t *free_message", True) + "uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message", True) parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos") parent_scope.variable_def("uint8_t *", "start = message_start") parent_scope.variable_def("uint8_t *", "data = NULL") @@ -1134,7 +1134,7 @@ def write_channel_parser(writer, channel, server): writer.ifdef(channel.attributes["ifdef"][0]) scope = writer.function(function_name, "static uint8_t *", - "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message") + "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message") helpers = writer.function_helper() @@ -1230,7 +1230,7 @@ def write_full_protocol_parser(writer, is_server): 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") + "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message") scope.variable_def("spice_parse_channel_func_t", "func" ) if is_server: -- cgit From e919337980c45fb4bc907cf40cdd106fb8f32d92 Mon Sep 17 00:00:00 2001 From: Alexander Wauck Date: Tue, 31 Mar 2015 12:44:09 -0500 Subject: Make spice_codegen.py work on both Python 2 and 3 This is a new version of my previous patch that does not include six.py. It's still kind of big, but at least it's all spice-common changes now. There are also a few other fixes that Christophe brought to my attention. Note that six now needs to be installed on the system (python-six on Fedora and Debian, six on PyPI). This *should* be enough to make spice_codegen.py work on both Python 2 and Python 3. The major changes are as follows: * cStringIO.StringIO -> io.StringIO * str vs. unicode updates (io.StringIO doesn't like str) * integer division * foo.has_key(bar) -> bar in foo * import internal_thing -> from . import internal_thing * removed from __future__ import with_statement (might break Python 2.5?) * changed some lambdas to list comprehensions (done by 2to3) * cast some_dict.keys() to list where needed (e.g. for sorting) * use normal type names with isinstance instead of types.WhateverType Signed-off-by: Alexander Wauck --- python_modules/demarshal.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'python_modules/demarshal.py') diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py index 109f5e6..209eafc 100644 --- a/python_modules/demarshal.py +++ b/python_modules/demarshal.py @@ -1,6 +1,6 @@ -from __future__ import with_statement -import ptypes -import codegen + +from . import ptypes +from . import codegen # The handling of sizes is somewhat complex, as there are several types of size: # * nw_size @@ -68,7 +68,7 @@ def write_parser_helpers(writer): 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.increment("*ptr", size // 8) writer.statement("return val") writer.end_block() @@ -1119,7 +1119,7 @@ def write_channel_parser(writer, channel, server): ids2 = ids.copy() while len(ids2) > 0: end = start = min(ids2.keys()) - while ids2.has_key(end): + while end in ids2: del ids2[end] end = end + 1 @@ -1181,7 +1181,7 @@ def write_get_channel_parser(writer, channel_parsers, max_channel, is_server): writer.begin_block() channel = None for i in range(0, max_channel + 1): - if channel_parsers.has_key(i): + if i in channel_parsers: channel = channel_parsers[i][0] if channel.has_attr("ifdef"): writer.ifdef(channel.attributes["ifdef"][0]) -- cgit