mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-protocol
synced 2025-12-26 22:55:30 +00:00
Switches are fixed size only if all cases have the same size *and* it has a default case or all the valid cases are listed.
984 lines
27 KiB
Python
984 lines
27 KiB
Python
import codegen
|
|
import types
|
|
|
|
_types_by_name = {}
|
|
_types = []
|
|
|
|
def type_exists(name):
|
|
return _types_by_name.has_key(name)
|
|
|
|
def lookup_type(name):
|
|
return _types_by_name[name]
|
|
|
|
def get_named_types():
|
|
return _types
|
|
|
|
class FixedSize:
|
|
def __init__(self, val = 0, minor = 0):
|
|
if isinstance(val, FixedSize):
|
|
self.vals = val.vals
|
|
else:
|
|
self.vals = [0] * (minor + 1)
|
|
self.vals[minor] = val
|
|
|
|
def __add__(self, other):
|
|
if isinstance(other, types.IntType):
|
|
other = FixedSize(other)
|
|
|
|
new = FixedSize()
|
|
l = max(len(self.vals), len(other.vals))
|
|
shared = min(len(self.vals), len(other.vals))
|
|
|
|
new.vals = [0] * l
|
|
|
|
for i in range(shared):
|
|
new.vals[i] = self.vals[i] + other.vals[i]
|
|
|
|
for i in range(shared,len(self.vals)):
|
|
new.vals[i] = self.vals[i];
|
|
|
|
for i in range(shared,len(other.vals)):
|
|
new.vals[i] = new.vals[i] + other.vals[i];
|
|
|
|
return new
|
|
|
|
def __radd__(self, other):
|
|
return self.__add__(other)
|
|
|
|
def __str__(self):
|
|
s = "%d" % (self.vals[0])
|
|
|
|
for i in range(1,len(self.vals)):
|
|
if self.vals[i] > 0:
|
|
s = s + " + ((minor >= %d)?%d:0)" % (i, self.vals[i])
|
|
return s
|
|
|
|
class Type:
|
|
def __init__(self):
|
|
self.attributes = {}
|
|
self.registred = False
|
|
self.name = None
|
|
|
|
def has_name(self):
|
|
return self.name != None
|
|
|
|
def get_type(self, recursive=False):
|
|
return self
|
|
|
|
def is_primitive(self):
|
|
return False
|
|
|
|
def is_fixed_sizeof(self):
|
|
return True
|
|
|
|
def is_extra_size(self):
|
|
return False
|
|
|
|
def contains_extra_size(self):
|
|
return False
|
|
|
|
def is_fixed_nw_size(self):
|
|
return True
|
|
|
|
def is_array(self):
|
|
return isinstance(self, ArrayType)
|
|
|
|
def is_struct(self):
|
|
return isinstance(self, StructType)
|
|
|
|
def is_pointer(self):
|
|
return isinstance(self, PointerType)
|
|
|
|
def get_num_pointers(self):
|
|
return 0
|
|
|
|
def get_pointer_names(self):
|
|
return []
|
|
|
|
def sizeof(self):
|
|
return "sizeof(%s)" % (self.c_type())
|
|
|
|
def __repr__(self):
|
|
return self.__str__()
|
|
|
|
def __str__(self):
|
|
if self.name != None:
|
|
return self.name
|
|
return "anonymous type"
|
|
|
|
def resolve(self):
|
|
return self
|
|
|
|
def register(self):
|
|
if self.registred or self.name == None:
|
|
return
|
|
self.registred = True
|
|
if _types_by_name.has_key(self.name):
|
|
raise Exception, "Type %s already defined" % self.name
|
|
_types.append(self)
|
|
_types_by_name[self.name] = self
|
|
|
|
def has_pointer(self):
|
|
return False
|
|
|
|
def has_attr(self, name):
|
|
return self.attributes.has_key(name)
|
|
|
|
class TypeRef(Type):
|
|
def __init__(self, name):
|
|
Type.__init__(self)
|
|
self.name = name
|
|
|
|
def __str__(self):
|
|
return "ref to %s" % (self.name)
|
|
|
|
def resolve(self):
|
|
if not _types_by_name.has_key(self.name):
|
|
raise Exception, "Unknown type %s" % self.name
|
|
return _types_by_name[self.name]
|
|
|
|
def register(self):
|
|
assert True, "Can't register TypeRef!"
|
|
|
|
|
|
class IntegerType(Type):
|
|
def __init__(self, bits, signed):
|
|
Type.__init__(self)
|
|
self.bits = bits
|
|
self.signed = signed
|
|
|
|
if signed:
|
|
self.name = "int%d" % bits
|
|
else:
|
|
self.name = "uint%d" % bits
|
|
|
|
def primitive_type(self):
|
|
return self.name
|
|
|
|
def c_type(self):
|
|
return self.name + "_t"
|
|
|
|
def get_fixed_nw_size(self):
|
|
return self.bits / 8
|
|
|
|
def is_primitive(self):
|
|
return True
|
|
|
|
class TypeAlias(Type):
|
|
def __init__(self, name, the_type, attribute_list):
|
|
Type.__init__(self)
|
|
self.name = name
|
|
self.the_type = the_type
|
|
for attr in attribute_list:
|
|
self.attributes[attr[0][1:]] = attr[1:]
|
|
|
|
def get_type(self, recursive=False):
|
|
if recursive:
|
|
return self.the_type.get_type(True)
|
|
else:
|
|
return self.the_type
|
|
|
|
def primitive_type(self):
|
|
return self.the_type.primitive_type()
|
|
|
|
def resolve(self):
|
|
self.the_type = self.the_type.resolve()
|
|
return self
|
|
|
|
def __str__(self):
|
|
return "alias %s" % self.name
|
|
|
|
def is_primitive(self):
|
|
return self.the_type.is_primitive()
|
|
|
|
def is_fixed_sizeof(self):
|
|
return self.the_type.is_fixed_sizeof()
|
|
|
|
def is_fixed_nw_size(self):
|
|
return self.the_type.is_fixed_nw_size()
|
|
|
|
def get_fixed_nw_size(self):
|
|
return self.the_type.get_fixed_nw_size()
|
|
|
|
def get_num_pointers(self):
|
|
return self.the_type.get_num_pointers()
|
|
|
|
def get_pointer_names(self):
|
|
return self.the_type.get_pointer_names()
|
|
|
|
def c_type(self):
|
|
if self.has_attr("ctype"):
|
|
return self.attributes["ctype"][0]
|
|
return self.name
|
|
|
|
def has_pointer(self):
|
|
return self.the_type.has_pointer()
|
|
|
|
class EnumBaseType(Type):
|
|
def is_enum(self):
|
|
return isinstance(self, EnumType)
|
|
|
|
def primitive_type(self):
|
|
return "uint%d" % (self.bits)
|
|
|
|
def c_type(self):
|
|
return "uint%d_t" % (self.bits)
|
|
|
|
def c_name(self):
|
|
return codegen.prefix_camel(self.name)
|
|
|
|
def c_enumname(self, value):
|
|
if self.has_attr("prefix"):
|
|
return self.attributes["prefix"][0] + self.names[value]
|
|
return codegen.prefix_underscore_upper(self.name.upper(), self.names[value])
|
|
|
|
def c_enumname_by_name(self, name):
|
|
if self.has_attr("prefix"):
|
|
return self.attributes["prefix"][0] + self.names[value]
|
|
return codegen.prefix_underscore_upper(self.name.upper(), name)
|
|
|
|
def is_primitive(self):
|
|
return True
|
|
|
|
def get_fixed_nw_size(self):
|
|
return self.bits / 8
|
|
|
|
class EnumType(EnumBaseType):
|
|
def __init__(self, bits, name, enums, attribute_list):
|
|
Type.__init__(self)
|
|
self.bits = bits
|
|
self.name = name
|
|
|
|
last = -1
|
|
names = {}
|
|
values = {}
|
|
for v in enums:
|
|
name = v[0]
|
|
if len(v) > 1:
|
|
value = v[1]
|
|
else:
|
|
value = last + 1
|
|
last = value
|
|
|
|
assert not names.has_key(value)
|
|
names[value] = name
|
|
values[name] = value
|
|
|
|
self.names = names
|
|
self.values = values
|
|
|
|
for attr in attribute_list:
|
|
self.attributes[attr[0][1:]] = attr[1:]
|
|
|
|
def __str__(self):
|
|
return "enum %s" % self.name
|
|
|
|
def c_define(self, writer):
|
|
writer.write("enum ")
|
|
writer.write(self.c_name())
|
|
writer.begin_block()
|
|
values = self.names.keys()
|
|
values.sort()
|
|
current_default = 0
|
|
for i in values:
|
|
writer.write(self.c_enumname(i))
|
|
if i != current_default:
|
|
writer.write(" = %d" % (i))
|
|
writer.write(",")
|
|
writer.newline()
|
|
current_default = i + 1
|
|
writer.newline()
|
|
writer.write(codegen.prefix_underscore_upper(self.name.upper(), "ENUM_END"))
|
|
writer.newline()
|
|
writer.end_block(semicolon=True)
|
|
writer.newline()
|
|
|
|
class FlagsType(EnumBaseType):
|
|
def __init__(self, bits, name, flags, attribute_list):
|
|
Type.__init__(self)
|
|
self.bits = bits
|
|
self.name = name
|
|
|
|
last = -1
|
|
names = {}
|
|
values = {}
|
|
for v in flags:
|
|
name = v[0]
|
|
if len(v) > 1:
|
|
value = v[1]
|
|
else:
|
|
value = last + 1
|
|
last = value
|
|
|
|
assert not names.has_key(value)
|
|
names[value] = name
|
|
values[name] = value
|
|
|
|
self.names = names
|
|
self.values = values
|
|
|
|
for attr in attribute_list:
|
|
self.attributes[attr[0][1:]] = attr[1:]
|
|
|
|
def __str__(self):
|
|
return "flags %s" % self.name
|
|
|
|
def c_define(self, writer):
|
|
writer.write("enum ")
|
|
writer.write(self.c_name())
|
|
writer.begin_block()
|
|
values = self.names.keys()
|
|
values.sort()
|
|
mask = 0
|
|
for i in values:
|
|
writer.write(self.c_enumname(i))
|
|
mask = mask | (1<<i)
|
|
writer.write(" = (1 << %d)" % (i))
|
|
writer.write(",")
|
|
writer.newline()
|
|
current_default = i + 1
|
|
writer.newline()
|
|
writer.write(codegen.prefix_underscore_upper(self.name.upper(), "MASK"))
|
|
writer.write(" = 0x%x" % (mask))
|
|
writer.newline()
|
|
writer.end_block(semicolon=True)
|
|
writer.newline()
|
|
|
|
class ArrayType(Type):
|
|
def __init__(self, element_type, size):
|
|
Type.__init__(self)
|
|
self.name = None
|
|
|
|
self.element_type = element_type
|
|
self.size = size
|
|
|
|
def __str__(self):
|
|
if self.size == None:
|
|
return "%s[]" % (str(self.element_type))
|
|
else:
|
|
return "%s[%s]" % (str(self.element_type), str(self.size))
|
|
|
|
def resolve(self):
|
|
self.element_type = self.element_type.resolve()
|
|
return self
|
|
|
|
def is_constant_length(self):
|
|
return isinstance(self.size, types.IntType)
|
|
|
|
def is_remaining_length(self):
|
|
return isinstance(self.size, types.StringType) and len(self.size) == 0
|
|
|
|
def is_identifier_length(self):
|
|
return isinstance(self.size, types.StringType) and len(self.size) > 0
|
|
|
|
def is_image_size_length(self):
|
|
if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
|
|
return False
|
|
return self.size[0] == "image_size"
|
|
|
|
def is_bytes_length(self):
|
|
if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
|
|
return False
|
|
return self.size[0] == "bytes"
|
|
|
|
def is_cstring_length(self):
|
|
if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
|
|
return False
|
|
return self.size[0] == "cstring"
|
|
|
|
def is_fixed_sizeof(self):
|
|
return self.is_constant_length() and self.element_type.is_fixed_sizeof()
|
|
|
|
def is_fixed_nw_size(self):
|
|
return self.is_constant_length() and self.element_type.is_fixed_nw_size()
|
|
|
|
def get_fixed_nw_size(self):
|
|
if not self.is_fixed_nw_size():
|
|
raise Exception, "Not a fixed size type"
|
|
|
|
return self.element_type.get_fixed_nw_size() * self.size
|
|
|
|
def get_num_pointers(self):
|
|
element_count = self.element_type.get_num_pointers()
|
|
if element_count == 0:
|
|
return 0
|
|
if self.is_constant_length(self):
|
|
return element_count * self.size
|
|
raise Exception, "Pointers in dynamic arrays not supported"
|
|
|
|
def get_pointer_names(self):
|
|
element_count = self.element_type.get_num_pointers()
|
|
if element_count == 0:
|
|
return []
|
|
raise Exception, "Pointer names in arrays not supported"
|
|
|
|
def contains_extra_size(self):
|
|
return self.element_type.contains_extra_size()
|
|
|
|
def sizeof(self):
|
|
return "%s * %s" % (self.element_type.sizeof(), self.size)
|
|
|
|
def c_type(self):
|
|
return self.element_type.c_type()
|
|
|
|
class PointerType(Type):
|
|
def __init__(self, target_type):
|
|
Type.__init__(self)
|
|
self.name = None
|
|
self.target_type = target_type
|
|
self.pointer_size = 8
|
|
|
|
def __str__(self):
|
|
return "%s*" % (str(self.target_type))
|
|
|
|
def resolve(self):
|
|
self.target_type = self.target_type.resolve()
|
|
return self
|
|
|
|
def set_ptr_size(self, new_size):
|
|
self.pointer_size = new_size
|
|
|
|
def is_fixed_nw_size(self):
|
|
return True
|
|
|
|
def is_primitive(self):
|
|
return True
|
|
|
|
def primitive_type(self):
|
|
if self.pointer_size == 4:
|
|
return "uint32"
|
|
else:
|
|
return "uint64"
|
|
|
|
def get_fixed_nw_size(self):
|
|
return self.pointer_size
|
|
|
|
def c_type(self):
|
|
return "SPICE_ADDRESS"
|
|
|
|
def has_pointer(self):
|
|
return True
|
|
|
|
def contains_extra_size(self):
|
|
return True
|
|
|
|
def get_num_pointers(self):
|
|
return 1
|
|
|
|
class Containee:
|
|
def __init__(self):
|
|
self.attributes = {}
|
|
|
|
def is_switch(self):
|
|
return False
|
|
|
|
def is_pointer(self):
|
|
return not self.is_switch() and self.member_type.is_pointer()
|
|
|
|
def is_array(self):
|
|
return not self.is_switch() and self.member_type.is_array()
|
|
|
|
def is_struct(self):
|
|
return not self.is_switch() and self.member_type.is_struct()
|
|
|
|
def is_primitive(self):
|
|
return not self.is_switch() and self.member_type.is_primitive()
|
|
|
|
def has_attr(self, name):
|
|
return self.attributes.has_key(name)
|
|
|
|
def has_minor_attr(self):
|
|
return self.has_attr("minor")
|
|
|
|
def has_end_attr(self):
|
|
return self.has_attr("end")
|
|
|
|
def get_minor_attr(self):
|
|
return self.attributes["minor"][0]
|
|
|
|
class Member(Containee):
|
|
def __init__(self, name, member_type, attribute_list):
|
|
Containee.__init__(self)
|
|
self.name = name
|
|
self.member_type = member_type
|
|
for attr in attribute_list:
|
|
self.attributes[attr[0][1:]] = attr[1:]
|
|
|
|
def resolve(self, container):
|
|
self.container = container
|
|
self.member_type = self.member_type.resolve()
|
|
self.member_type.register()
|
|
if self.has_attr("ptr32") and self.member_type.is_pointer():
|
|
self.member_type.set_ptr_size(4)
|
|
return self
|
|
|
|
def is_primitive(self):
|
|
return self.member_type.is_primitive()
|
|
|
|
def is_fixed_sizeof(self):
|
|
if self.has_end_attr():
|
|
return False
|
|
return self.member_type.is_fixed_sizeof()
|
|
|
|
def is_extra_size(self):
|
|
return self.has_end_attr()
|
|
|
|
def is_fixed_nw_size(self):
|
|
if self.has_attr("virtual"):
|
|
return True
|
|
return self.member_type.is_fixed_nw_size()
|
|
|
|
def get_fixed_nw_size(self):
|
|
if self.has_attr("virtual"):
|
|
return 0
|
|
size = self.member_type.get_fixed_nw_size()
|
|
if self.has_minor_attr():
|
|
minor = self.get_minor_attr()
|
|
size = FixedSize(size, minor)
|
|
return size
|
|
|
|
def contains_extra_size(self):
|
|
return self.member_type.contains_extra_size()
|
|
|
|
def sizeof(self):
|
|
return self.member_type.sizeof()
|
|
|
|
def __repr__(self):
|
|
return "%s (%s)" % (str(self.name), str(self.member_type))
|
|
|
|
def has_pointer(self):
|
|
return self.member_type.has_pointer()
|
|
|
|
def get_num_pointers(self):
|
|
return self.member_type.get_num_pointers()
|
|
|
|
def get_pointer_names(self):
|
|
if self.member_type.is_pointer():
|
|
names = [self.name + "_out"]
|
|
else:
|
|
names = self.member_type.get_pointer_names()
|
|
if self.has_attr("outvar"):
|
|
prefix = self.attributes["outvar"][0]
|
|
names = map(lambda name: prefix + "_" + name, names)
|
|
return names
|
|
|
|
class SwitchCase:
|
|
def __init__(self, values, member):
|
|
self.values = values
|
|
self.member = member
|
|
self.members = [member]
|
|
|
|
def get_check(self, var_cname, var_type):
|
|
checks = []
|
|
for v in self.values:
|
|
if v == None:
|
|
return "1"
|
|
elif var_type.is_enum():
|
|
checks.append("%s == %s" % (var_cname, var_type.c_enumname_by_name(v)))
|
|
else:
|
|
checks.append("(%s & %s)" % (var_cname, var_type.c_enumname_by_name(v)))
|
|
return " || ".join(checks)
|
|
|
|
def resolve(self, container):
|
|
self.switch = container
|
|
self.member = self.member.resolve(self)
|
|
return self
|
|
|
|
def has_pointer(self):
|
|
return self.member.has_pointer()
|
|
|
|
def get_num_pointers(self):
|
|
return self.member.get_num_pointers()
|
|
|
|
def get_pointer_names(self):
|
|
return self.member.get_pointer_names()
|
|
|
|
class Switch(Containee):
|
|
def __init__(self, variable, cases, name, attribute_list):
|
|
Containee.__init__(self)
|
|
self.variable = variable
|
|
self.name = name
|
|
self.cases = cases
|
|
for attr in attribute_list:
|
|
self.attributes[attr[0][1:]] = attr[1:]
|
|
|
|
def is_switch(self):
|
|
return True
|
|
|
|
def has_switch_member(self, member):
|
|
for c in self.cases:
|
|
if c.member == member:
|
|
return True
|
|
return False
|
|
|
|
def resolve(self, container):
|
|
self.container = container
|
|
self.cases = map(lambda c : c.resolve(self), self.cases)
|
|
return self
|
|
|
|
def __repr__(self):
|
|
return "switch on %s %s" % (str(self.variable),str(self.name))
|
|
|
|
def is_fixed_sizeof(self):
|
|
# Kinda weird, but we're unlikely to have a real struct if there is an @end
|
|
if self.has_end_attr():
|
|
return False
|
|
return True
|
|
|
|
def is_fixed_nw_size(self):
|
|
if self.has_attr("fixedsize"):
|
|
return True
|
|
|
|
size = None
|
|
has_default = False
|
|
for c in self.cases:
|
|
for v in c.values:
|
|
if v == None:
|
|
has_default = True
|
|
if not c.member.is_fixed_nw_size():
|
|
return False
|
|
if size == None:
|
|
size = c.member.get_fixed_nw_size()
|
|
elif size != c.member.get_fixed_nw_size():
|
|
return False
|
|
# Fixed size if all elements listed, or has default
|
|
if has_default:
|
|
return True
|
|
key = self.container.lookup_member(self.variable)
|
|
return len(self.cases) == len(key.member_type.values)
|
|
|
|
def is_extra_size(self):
|
|
return self.has_end_attr()
|
|
|
|
def contains_extra_size(self):
|
|
for c in self.cases:
|
|
if c.member.is_extra_size():
|
|
return True
|
|
if c.member.contains_extra_size():
|
|
return True
|
|
return False
|
|
|
|
def get_fixed_nw_size(self):
|
|
if not self.is_fixed_nw_size():
|
|
raise Exception, "Not a fixed size type"
|
|
size = 0;
|
|
for c in self.cases:
|
|
size = max(size, c.member.get_fixed_nw_size())
|
|
return size
|
|
|
|
def sizeof(self):
|
|
return "sizeof(((%s *)NULL)->%s)" % (self.container.c_type(),
|
|
self.name)
|
|
|
|
def has_pointer(self):
|
|
for c in self.cases:
|
|
if c.has_pointer():
|
|
return True
|
|
return False
|
|
|
|
def get_num_pointers(self):
|
|
count = 0
|
|
for c in self.cases:
|
|
count = max(count, c.get_num_pointers())
|
|
return count
|
|
|
|
def get_pointer_names(self):
|
|
names = []
|
|
for c in self.cases:
|
|
names = names + c.get_pointer_names()
|
|
return names
|
|
|
|
class ContainerType(Type):
|
|
def is_fixed_sizeof(self):
|
|
for m in self.members:
|
|
if not m.is_fixed_sizeof():
|
|
return False
|
|
return True
|
|
|
|
def contains_extra_size(self):
|
|
for m in self.members:
|
|
if m.is_extra_size():
|
|
return True
|
|
if m.contains_extra_size():
|
|
return True
|
|
return False
|
|
|
|
def is_fixed_nw_size(self):
|
|
for i in self.members:
|
|
if not i.is_fixed_nw_size():
|
|
return False
|
|
return True
|
|
|
|
def get_fixed_nw_size(self):
|
|
size = 0
|
|
for i in self.members:
|
|
size = size + i.get_fixed_nw_size()
|
|
return size
|
|
|
|
def get_fixed_nw_offset(self, member):
|
|
size = 0
|
|
for i in self.members:
|
|
if i == member:
|
|
break
|
|
if i.is_fixed_nw_size():
|
|
size = size + i.get_fixed_nw_size()
|
|
return size
|
|
|
|
def resolve(self):
|
|
self.members = map(lambda m : m.resolve(self), self.members)
|
|
return self
|
|
|
|
def get_num_pointers(self):
|
|
count = 0
|
|
for m in self.members:
|
|
count = count + m.get_num_pointers()
|
|
return count
|
|
|
|
def get_pointer_names(self):
|
|
names = []
|
|
for m in self.members:
|
|
names = names + m.get_pointer_names()
|
|
return names
|
|
|
|
def has_pointer(self):
|
|
for m in self.members:
|
|
if m.has_pointer():
|
|
return True
|
|
return False
|
|
|
|
def get_nw_offset(self, member, prefix = "", postfix = ""):
|
|
fixed = self.get_fixed_nw_offset(member)
|
|
v = []
|
|
for m in self.members:
|
|
if m == member:
|
|
break
|
|
if m.is_switch() and m.has_switch_member(member):
|
|
break
|
|
if not m.is_fixed_nw_size():
|
|
v.append(prefix + m.name + postfix)
|
|
if len(v) > 0:
|
|
return str(fixed) + " + " + (" + ".join(v))
|
|
else:
|
|
return str(fixed)
|
|
|
|
def lookup_member(self, name):
|
|
return self.members_by_name[name]
|
|
|
|
class StructType(ContainerType):
|
|
def __init__(self, name, members, attribute_list):
|
|
Type.__init__(self)
|
|
self.name = name
|
|
self.members = members
|
|
self.members_by_name = {}
|
|
for m in members:
|
|
self.members_by_name[m.name] = m
|
|
for attr in attribute_list:
|
|
self.attributes[attr[0][1:]] = attr[1:]
|
|
|
|
def __str__(self):
|
|
if self.name == None:
|
|
return "anonymous struct"
|
|
else:
|
|
return "struct %s" % self.name
|
|
|
|
def c_type(self):
|
|
if self.has_attr("ctype"):
|
|
return self.attributes["ctype"][0]
|
|
return codegen.prefix_camel(self.name)
|
|
|
|
class MessageType(ContainerType):
|
|
def __init__(self, name, members, attribute_list):
|
|
Type.__init__(self)
|
|
self.name = name
|
|
self.members = members
|
|
self.members_by_name = {}
|
|
for m in members:
|
|
self.members_by_name[m.name] = m
|
|
self.reverse_members = {} # ChannelMembers referencing this message
|
|
for attr in attribute_list:
|
|
self.attributes[attr[0][1:]] = attr[1:]
|
|
|
|
def __str__(self):
|
|
if self.name == None:
|
|
return "anonymous message"
|
|
else:
|
|
return "message %s" % self.name
|
|
|
|
def c_name(self):
|
|
if self.name == None:
|
|
cms = self.reverse_members.keys()
|
|
if len(cms) != 1:
|
|
raise "Unknown typename for message"
|
|
cm = cms[0]
|
|
channelname = cm.channel.member_name
|
|
if channelname == None:
|
|
channelname = ""
|
|
else:
|
|
channelname = channelname + "_"
|
|
if cm.is_server:
|
|
return "msg_" + channelname + cm.name
|
|
else:
|
|
return "msgc_" + channelname + cm.name
|
|
else:
|
|
return codegen.prefix_camel("Msg", self.name)
|
|
|
|
def c_type(self):
|
|
if self.has_attr("ctype"):
|
|
return self.attributes["ctype"][0]
|
|
if self.name == None:
|
|
cms = self.reverse_members.keys()
|
|
if len(cms) != 1:
|
|
raise "Unknown typename for message"
|
|
cm = cms[0]
|
|
channelname = cm.channel.member_name
|
|
if channelname == None:
|
|
channelname = ""
|
|
if cm.is_server:
|
|
return codegen.prefix_camel("Msg", channelname, cm.name)
|
|
else:
|
|
return codegen.prefix_camel("Msgc", channelname, cm.name)
|
|
else:
|
|
return codegen.prefix_camel("Msg", self.name)
|
|
|
|
class ChannelMember(Containee):
|
|
def __init__(self, name, message_type, value):
|
|
Containee.__init__(self)
|
|
self.name = name
|
|
self.message_type = message_type
|
|
self.value = value
|
|
|
|
def resolve(self, channel):
|
|
self.channel = channel
|
|
self.message_type = self.message_type.resolve()
|
|
self.message_type.reverse_members[self] = 1
|
|
|
|
return self
|
|
|
|
def __repr__(self):
|
|
return "%s (%s)" % (str(self.name), str(self.message_type))
|
|
|
|
class ChannelType(Type):
|
|
def __init__(self, name, base, members):
|
|
Type.__init__(self)
|
|
self.name = name
|
|
self.base = base
|
|
self.member_name = None
|
|
self.members = members
|
|
|
|
def __str__(self):
|
|
if self.name == None:
|
|
return "anonymous channel"
|
|
else:
|
|
return "channel %s" % self.name
|
|
|
|
def is_fixed_nw_size(self):
|
|
return False
|
|
|
|
def get_client_message(self, name):
|
|
return self.client_messages_byname[name]
|
|
|
|
def get_server_message(self, name):
|
|
return self.server_messages_byname[name]
|
|
|
|
def resolve(self):
|
|
if self.base != None:
|
|
self.base = self.base.resolve()
|
|
|
|
server_messages = self.base.server_messages[:]
|
|
server_messages_byname = self.base.server_messages_byname.copy()
|
|
client_messages = self.base.client_messages[:]
|
|
client_messages_byname = self.base.client_messages_byname.copy()
|
|
else:
|
|
server_messages = []
|
|
server_messages_byname = {}
|
|
client_messages = []
|
|
client_messages_byname = {}
|
|
|
|
server_count = 1
|
|
client_count = 1
|
|
|
|
server = True
|
|
for m in self.members:
|
|
if m == "server":
|
|
server = True
|
|
elif m == "client":
|
|
server = False
|
|
elif server:
|
|
m.is_server = True
|
|
m = m.resolve(self)
|
|
if m.value:
|
|
server_count = m.value + 1
|
|
else:
|
|
m.value = server_count
|
|
server_count = server_count + 1
|
|
server_messages.append(m)
|
|
server_messages_byname[m.name] = m
|
|
else:
|
|
m.is_server = False
|
|
m = m.resolve(self)
|
|
if m.value:
|
|
client_count = m.value + 1
|
|
else:
|
|
m.value = client_count
|
|
client_count = client_count + 1
|
|
client_messages.append(m)
|
|
client_messages_byname[m.name] = m
|
|
|
|
self.server_messages = server_messages
|
|
self.server_messages_byname = server_messages_byname
|
|
self.client_messages = client_messages
|
|
self.client_messages_byname = client_messages_byname
|
|
|
|
return self
|
|
|
|
class ProtocolMember:
|
|
def __init__(self, name, channel_type, value):
|
|
self.name = name
|
|
self.channel_type = channel_type
|
|
self.value = value
|
|
|
|
def resolve(self, protocol):
|
|
self.channel_type = self.channel_type.resolve()
|
|
assert(self.channel_type.member_name == None)
|
|
self.channel_type.member_name = self.name
|
|
return self
|
|
|
|
def __repr__(self):
|
|
return "%s (%s)" % (str(self.name), str(self.channel_type))
|
|
|
|
class ProtocolType(Type):
|
|
def __init__(self, name, channels):
|
|
Type.__init__(self)
|
|
self.name = name
|
|
self.channels = channels
|
|
|
|
def __str__(self):
|
|
if self.name == None:
|
|
return "anonymous protocol"
|
|
else:
|
|
return "protocol %s" % self.name
|
|
|
|
def is_fixed_nw_size(self):
|
|
return False
|
|
|
|
def resolve(self):
|
|
count = 1
|
|
for m in self.channels:
|
|
m = m.resolve(self)
|
|
if m.value:
|
|
count = m.value + 1
|
|
else:
|
|
m.value = count
|
|
count = count + 1
|
|
|
|
return self
|
|
|
|
int8 = IntegerType(8, True)
|
|
uint8 = IntegerType(8, False)
|
|
int16 = IntegerType(16, True)
|
|
uint16 = IntegerType(16, False)
|
|
int32 = IntegerType(32, True)
|
|
uint32 = IntegerType(32, False)
|
|
int64 = IntegerType(64, True)
|
|
uint64 = IntegerType(64, False)
|