mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-common
synced 2025-12-26 14:18:36 +00:00
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.
970 lines
26 KiB
Python
970 lines
26 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
|
|
|
|
def __str__(self):
|
|
return "%s*" % (str(self.target_type))
|
|
|
|
def resolve(self):
|
|
self.target_type = self.target_type.resolve()
|
|
return self
|
|
|
|
def get_fixed_size(self):
|
|
return 8 # offsets are 64bit
|
|
|
|
def is_fixed_nw_size(self):
|
|
return True
|
|
|
|
def is_primitive(self):
|
|
return True
|
|
|
|
def primitive_type(self):
|
|
return "uint64"
|
|
|
|
def get_fixed_nw_size(self):
|
|
return 8
|
|
|
|
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()
|
|
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
|
|
for c in self.cases:
|
|
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
|
|
return True
|
|
|
|
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)
|