def __init__(self, name): ''' Default structure initializer. Sets up default fields. Public fields: name is a tuple of strings specifying the full type name. size is the size of the datatype in bytes, or None if variable-sized. nmemb is 1 for non-list types, None for variable-sized lists, otherwise number of elts. booleans for identifying subclasses, because I can't figure out isinstance(). ''' self.name = name self.size = None self.nmemb = None self.resolved = False # Screw isinstance(). self.is_simple = False self.is_list = False self.is_expr = False self.is_container = False self.is_reply = False self.is_union = False self.is_pad = False self.is_switch = False self.is_case_or_bitcase = False self.is_bitcase = False self.is_case = False self.required_start_align = Alignment() # the biggest align value of an align-pad contained in this type self.max_align_pad = 1
def __init__(self, name, size): Type.__init__(self, name) self.size = size self.nmemb = 1 # compute the required start_alignment based on the size of the type self.required_start_align = Alignment.for_primitive_type(self.size)
def calc_minimally_required_start_align(self, callstack, log): # calculate the minimally required start_align that causes no # align errors best_log = None best_failed_align = None for align in [1, 2, 4, 8]: for offset in range(0, align): align_candidate = Alignment(align, offset) if verbose_align_log: print("trying %s for %s" % (str(align_candidate), str(self))) my_log = AlignmentLog() if self.is_possible_start_align(align_candidate, callstack, my_log): log.append(my_log) if verbose_align_log: print("found start-align %s for %s" % (str(align_candidate), str(self))) return align_candidate else: my_ok_count = my_log.ok_count() if (best_log is None or my_ok_count > best_log.ok_count() or (my_ok_count == best_log.ok_count() and align_candidate.align > best_failed_align.align) and align_candidate.align != 8): best_log = my_log best_failed_align = align_candidate # none of the candidates applies # this type has illegal internal aligns for all possible start_aligns if verbose_align_log: print("didn't find start-align for %s" % str(self)) log.append(best_log) return None
def unchecked_get_alignment_after(self, start_align, callstack, log): if self.align <= 1: # fixed size pad after_align = start_align.align_after_fixed_size( self.get_total_size()) if log is not None: if after_align is None: log.fail( start_align, "", self, callstack, "align after fixed size pad of size %d failed" % self.size) else: log.ok(start_align, "", self, callstack, after_align) return after_align # align-pad assert self.align > 1 assert self.size == 1 assert self.nmemb == 1 if (start_align.offset == 0 and self.align <= start_align.align and start_align.align % self.align == 0): # the alignment pad is size 0 because the start_align # is already sufficiently aligned -> return the start_align after_align = start_align else: # the alignment pad has nonzero size -> return the alignment # that is guaranteed by it, independently of the start_align after_align = Alignment(self.align, 0) if log is not None: log.ok(start_align, "", self, callstack, after_align) return after_align
def __init__(self, name, elt): ComplexType.__init__(self, name, elt) self.is_reply = True self.doc = None if self.required_start_align is None: self.required_start_align = Alignment(4, 0) for child in list(elt): if child.tag == 'doc': self.doc = Doc(name, child)
def __init__(self, name, elt): ComplexType.__init__(self, name, elt) self.reply = None self.doc = None self.opcode = elt.get('opcode') if self.required_start_align is None: self.required_start_align = Alignment(4, 0) for child in list(elt): if child.tag == 'reply': self.reply = Reply(name, child) if child.tag == 'doc': self.doc = Doc(name, child)
def __init__(self, elt): Type.__init__(self, tcard8.name) self.is_pad = True self.size = 1 self.nmemb = 1 self.align = 1 if elt != None: self.nmemb = int(elt.get('bytes', "1"), 0) self.align = int(elt.get('align', "1"), 0) self.serialize = elt.get('serialize', "false").lower() in true_values # pads don't require any alignment at their start self.required_start_align = Alignment(1, 0)
def __init__(self, name, elt): ComplexType.__init__(self, name, elt) if self.required_start_align is None: self.required_start_align = Alignment(4, 0) self.opcodes = {} self.has_seq = not bool(elt.get('no-sequence-number')) self.is_ge_event = bool(elt.get('xge')) self.doc = None for item in list(elt): if item.tag == 'doc': self.doc = Doc(name, item)
def __init__(self, name, elt): Type.__init__(self, name) self.is_container = True self.elt = elt self.fields = [] self.nmemb = 1 self.size = 0 self.lenfield_parent = [self] self.fds = [] # get required_start_alignment required_start_align_element = elt.find("required_start_align") if required_start_align_element is None: # unknown -> mark for autocompute self.required_start_align = None else: self.required_start_align = Alignment( int(required_start_align_element.get('align', "4"), 0), int(required_start_align_element.get('offset', "0"), 0)) if verbose_align_log: print("Explicit start-align for %s: %s\n" % (self, self.required_start_align))
class Type(object): ''' Abstract base class for all XCB data types. Contains default fields, and some abstract methods. ''' def __init__(self, name): ''' Default structure initializer. Sets up default fields. Public fields: name is a tuple of strings specifying the full type name. size is the size of the datatype in bytes, or None if variable-sized. nmemb is 1 for non-list types, None for variable-sized lists, otherwise number of elts. booleans for identifying subclasses, because I can't figure out isinstance(). ''' self.name = name self.size = None self.nmemb = None self.resolved = False # Screw isinstance(). self.is_simple = False self.is_list = False self.is_expr = False self.is_container = False self.is_reply = False self.is_union = False self.is_pad = False self.is_switch = False self.is_case_or_bitcase = False self.is_bitcase = False self.is_case = False self.required_start_align = Alignment() # the biggest align value of an align-pad contained in this type self.max_align_pad = 1 def resolve(self, module): ''' Abstract method for resolving a type. This should make sure any referenced types are already declared. ''' raise Exception('abstract resolve method not overridden!') def out(self, name): ''' Abstract method for outputting code. These are declared in the language-specific modules, and there must be a dictionary containing them declared when this module is imported! ''' raise Exception('abstract out method not overridden!') def fixed_size(self): ''' Abstract method for determining if the data type is fixed-size. ''' raise Exception('abstract fixed_size method not overridden!') def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None): ''' Default method for making a data type a member of a structure. Extend this if the data type needs to add an additional length field or something. module is the global module object. complex_type is the structure object. see Field for the meaning of the other parameters. ''' new_field = Field(self, field_type, field_name, visible, wire, auto, enum) # We dump the _placeholder_byte if any fields are added. for (idx, field) in enumerate(complex_type.fields): if field == _placeholder_byte: complex_type.fields[idx] = new_field return complex_type.fields.append(new_field) new_field.parent = complex_type def make_fd_of(self, module, complex_type, fd_name): ''' Method for making a fd member of a structure. ''' new_fd = Field(self, module.get_type_name('INT32'), fd_name, True, False, False, None, True) # We dump the _placeholder_byte if any fields are added. for (idx, field) in enumerate(complex_type.fields): if field == _placeholder_byte: complex_type.fields[idx] = new_fd return complex_type.fields.append(new_fd) def get_total_size(self): ''' get the total size of this type if it is fixed-size, otherwise None ''' if self.fixed_size(): if self.nmemb is None: return self.size else: return self.size * self.nmemb else: return None def get_align_offset(self): if self.required_start_align is None: return 0 else: return self.required_start_align.offset def is_acceptable_start_align(self, start_align, callstack, log): return self.get_alignment_after(start_align, callstack, log) is not None def get_alignment_after(self, start_align, callstack, log): ''' get the alignment after this type based on the given start_align. the start_align is checked for compatibility with the internal start align. If it is not compatible, then None is returned ''' if self.required_start_align is None or self.required_start_align.is_guaranteed_at(start_align): return self.unchecked_get_alignment_after(start_align, callstack, log) else: if log is not None: log.fail(start_align, "", self, callstack + [self], "start_align is incompatible with required_start_align %s" % (str(self.required_start_align))) return None def unchecked_get_alignment_after(self, start_align, callstack, log): ''' Abstract method for geting the alignment after this type when the alignment at the start is given, and when this type has variable size. ''' raise Exception('abstract unchecked_get_alignment_after method not overridden!') @staticmethod def type_name_to_str(type_name): if isinstance(type_name, str): #already a string return type_name else: return ".".join(type_name) def __str__(self): return type(self).__name__ + " \"" + Type.type_name_to_str(self.name) + "\""
def __init__(self, name, elt): ComplexType.__init__(self, name, elt) self.opcodes = {} if self.required_start_align is None: self.required_start_align = Alignment(4, 0)
class Type(object): ''' Abstract base class for all XCB data types. Contains default fields, and some abstract methods. ''' def __init__(self, name): ''' Default structure initializer. Sets up default fields. Public fields: name is a tuple of strings specifying the full type name. size is the size of the datatype in bytes, or None if variable-sized. nmemb is 1 for non-list types, None for variable-sized lists, otherwise number of elts. booleans for identifying subclasses, because I can't figure out isinstance(). ''' self.name = name self.size = None self.nmemb = None self.resolved = False # Screw isinstance(). self.is_simple = False self.is_list = False self.is_expr = False self.is_container = False self.is_reply = False self.is_union = False self.is_pad = False self.is_switch = False self.is_case_or_bitcase = False self.is_bitcase = False self.is_case = False self.required_start_align = Alignment() # the biggest align value of an align-pad contained in this type self.max_align_pad = 1 def resolve(self, module): ''' Abstract method for resolving a type. This should make sure any referenced types are already declared. ''' raise Exception('abstract resolve method not overridden!') def out(self, name): ''' Abstract method for outputting code. These are declared in the language-specific modules, and there must be a dictionary containing them declared when this module is imported! ''' raise Exception('abstract out method not overridden!') def fixed_size(self): ''' Abstract method for determining if the data type is fixed-size. ''' raise Exception('abstract fixed_size method not overridden!') def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None): ''' Default method for making a data type a member of a structure. Extend this if the data type needs to add an additional length field or something. module is the global module object. complex_type is the structure object. see Field for the meaning of the other parameters. ''' new_field = Field(self, field_type, field_name, visible, wire, auto, enum) # We dump the _placeholder_byte if any fields are added. for (idx, field) in enumerate(complex_type.fields): if field == _placeholder_byte: complex_type.fields[idx] = new_field return complex_type.fields.append(new_field) new_field.parent = complex_type def make_fd_of(self, module, complex_type, fd_name): ''' Method for making a fd member of a structure. ''' new_fd = Field(self, module.get_type_name('INT32'), fd_name, True, False, False, None, True) # We dump the _placeholder_byte if any fields are added. for (idx, field) in enumerate(complex_type.fields): if field == _placeholder_byte: complex_type.fields[idx] = new_fd return complex_type.fields.append(new_fd) def get_total_size(self): ''' get the total size of this type if it is fixed-size, otherwise None ''' if self.fixed_size(): if self.nmemb is None: return self.size else: return self.size * self.nmemb else: return None def get_align_offset(self): if self.required_start_align is None: return 0 else: return self.required_start_align.offset def is_acceptable_start_align(self, start_align, callstack, log): return self.get_alignment_after(start_align, callstack, log) is not None def get_alignment_after(self, start_align, callstack, log): ''' get the alignment after this type based on the given start_align. the start_align is checked for compatibility with the internal start align. If it is not compatible, then None is returned ''' if self.required_start_align is None or self.required_start_align.is_guaranteed_at( start_align): return self.unchecked_get_alignment_after(start_align, callstack, log) else: if log is not None: log.fail( start_align, "", self, callstack + [self], "start_align is incompatible with required_start_align %s" % (str(self.required_start_align))) return None def unchecked_get_alignment_after(self, start_align, callstack, log): ''' Abstract method for geting the alignment after this type when the alignment at the start is given, and when this type has variable size. ''' raise Exception( 'abstract unchecked_get_alignment_after method not overridden!') @staticmethod def type_name_to_str(type_name): if isinstance(type_name, str): #already a string return type_name else: return ".".join(type_name) def __str__(self): return type(self).__name__ + " \"" + Type.type_name_to_str( self.name) + "\""