def _make_padding(self, members, padding_nb, offset, length, prev_member=None): """Make padding Fields for a specifed size.""" name = 'PADDING_%d' % padding_nb padding_nb += 1 log.debug("_make_padding: for %d bits", length) if (length % 8) != 0 or (prev_member is not None and prev_member.is_bitfield): # add a padding to align with the bitfield type # then multiple bytes if required. # pad_length = (length % 8) typename = prev_member.type.name padding = typedesc.Field( name, typedesc.FundamentalType(typename, 1, 1), # offset, pad_length, is_bitfield=True) offset, length, is_bitfield=True, is_padding=True) members.append(padding) # check for multiple bytes # if (length//8) > 0: # padding_nb = self._make_padding(members, padding_nb, offset+pad_length, # (length//8)*8, prev_member=padding) return padding_nb elif length > 8: pad_bytes = length / 8 padding = typedesc.Field(name, typedesc.ArrayType( typedesc.FundamentalType( self.get_ctypes_name( TypeKind.CHAR_U), length, 1), pad_bytes), offset, length, is_padding=True) members.append(padding) return padding_nb # simple char padding padding = typedesc.Field(name, typedesc.FundamentalType( self.get_ctypes_name(TypeKind.CHAR_U), 1, 1), offset, length, is_padding=True) members.append(padding) return padding_nb
def _VAR_DECL_type(self, cursor): """Generates a typedesc object from a Variable declaration.""" # Get the type _ctype = cursor.type.get_canonical() log.debug('VAR_DECL: _ctype: %s ', _ctype.kind) # FIXME: Need working int128, long_double, etc. if self.is_fundamental_type(_ctype): ctypesname = self.get_ctypes_name(_ctype.kind) _type = typedesc.FundamentalType(ctypesname, 0, 0) elif self.is_unexposed_type(_ctype): st = 'PATCH NEEDED: %s type is not exposed by clang' % ( self.get_unique_name(cursor)) log.error(st) raise RuntimeError(st) elif self.is_array_type(_ctype) or _ctype.kind == TypeKind.RECORD: _type = self.parse_cursor_type(_ctype) elif self.is_pointer_type(_ctype): # for example, extern Function pointer if self.is_unexposed_type(_ctype.get_pointee()): _type = self.parse_cursor_type( _ctype.get_canonical().get_pointee()) elif _ctype.get_pointee().kind == TypeKind.FUNCTIONPROTO: # Function pointers # Arguments are handled in here _type = self.parse_cursor_type(_ctype.get_pointee()) else: # Pointer to Fundamental types, structs.... _type = self.parse_cursor_type(_ctype) else: # What else ? raise NotImplementedError('What other type of variable? %s' % (_ctype.kind)) log.debug('VAR_DECL: _type: %s ', _type) return _type
def ELABORATED(self, _cursor_type): """ Handles ELABORATED """ # FIXME: function returning an enum type obj = typedesc.FundamentalType("c_int", 32, 32) return obj
def FundamentalType(self, attrs): name = attrs["name"] if name == "void": size = "" else: size = attrs["size"] align = attrs["align"] return typedesc.FundamentalType(name, size, align)
def _handle_fundamental_types(self, typ): """ Handles POD types nodes. see init_fundamental_types for the registration. """ ctypesname = self.get_ctypes_name(typ.kind) if typ.kind == TypeKind.VOID: size = align = 1 else: size = typ.get_size() align = typ.get_align() return typedesc.FundamentalType(ctypesname, size, align)
def _make_padding( self, members, padding_nb, offset, length, prev_member=None): """Make padding Fields for a specifed size.""" name = 'PADDING_%d' % padding_nb padding_nb += 1 log.debug("_make_padding: for %d bits", length) if (length % 8) != 0 or (prev_member is not None and prev_member.is_bitfield): if length > 32: typename = "c_uint64" elif length > 16: typename = "c_uint32" elif length > 8: typename = "c_uint16" else: typename = "c_uint8" padding = typedesc.Field(name, typedesc.FundamentalType(typename, 1, 1), offset, length, is_bitfield=True, is_padding=True) members.append(padding) return padding_nb elif length > 8: pad_bytes = length // 8 padding = typedesc.Field(name, typedesc.ArrayType( typedesc.FundamentalType( self.get_ctypes_name(TypeKind.CHAR_U), length, 1), pad_bytes), offset, length, is_padding=True) members.append(padding) return padding_nb # simple char padding padding = typedesc.Field(name, typedesc.FundamentalType( self.get_ctypes_name( TypeKind.CHAR_U), 1, 1), offset, length, is_padding=True) members.append(padding) return padding_nb
def ENUM(self, _cursor_type): """ Handles ENUM typedef. """ _decl = _cursor_type.get_declaration() name = self.get_unique_name(_decl) if self.is_registered(name): obj = self.get_registered(name) else: #log.warning('Was in ENUM but had to parse record declaration ') # FIXME: function returning an enum type # obj = self.parse_cursor(_decl) obj = typedesc.FundamentalType("c_int", 32, 32) return obj
def POINTER(self, _cursor_type): """ Handles POINTER types. """ # # FIXME catch InvalidDefinitionError and return a void * # # # we shortcut to canonical typedefs and to pointee canonical defs comment = None _type = _cursor_type.get_pointee().get_canonical() _p_type_name = self.get_unique_name(_type) # get pointer size size = _cursor_type.get_size() # not size of pointee align = _cursor_type.get_align() log.debug("POINTER: size:%d align:%d typ:%s" % (size, align, _type.kind)) if self.is_fundamental_type(_type): p_type = self.parse_cursor_type(_type) elif self.is_pointer_type(_type) or self.is_array_type(_type): p_type = self.parse_cursor_type(_type) elif _type.kind == TypeKind.FUNCTIONPROTO: p_type = self.parse_cursor_type(_type) elif _type.kind == TypeKind.FUNCTIONNOPROTO: p_type = self.parse_cursor_type(_type) else: #elif _type.kind == TypeKind.RECORD: # check registration decl = _type.get_declaration() decl_name = self.get_unique_name(decl) # Type is already defined OR will be defined later. if self.is_registered(decl_name): p_type = self.get_registered(decl_name) else: # forward declaration, without looping log.debug('POINTER: %s type was not previously declared' % (decl_name)) try: p_type = self.parse_cursor(decl) except InvalidDefinitionError as e: # no declaration in source file. Fake a void * p_type = typedesc.FundamentalType('None', 1, 1) comment = "InvalidDefinitionError" log.debug("POINTER: pointee type_name:'%s'" % (_p_type_name)) # return the pointer obj = typedesc.PointerType(p_type, size, align) obj.location = p_type.location if comment is not None: obj.comment = comment return obj
def VAR_DECL(self, cursor): """Handles Variable declaration.""" # get the name name = self.get_unique_name(cursor) # double declaration ? if self.is_registered(name): return self.get_registered(name) # Get the type _ctype = cursor.type.get_canonical() # FIXME: Need working int128, long_double, etc... if self.is_fundamental_type(_ctype): ctypesname = self.get_ctypes_name(_ctype.kind) _type = typedesc.FundamentalType(ctypesname, 0, 0) # FIXME: because c_long_double_t or c_unint128 are not real ctypes # we can make variable with them. # just write the value as-is. ### if literal_kind != CursorKind.DECL_REF_EXPR: ### init_value = '%s(%s)'%(ctypesname, init_value) elif self.is_unexposed_type(_ctype): # string are not exposed # FIXME recurse on child log.error('PATCH NEEDED: %s type is not exposed by clang' % (name)) raise RuntimeError('') ctypesname = self.get_ctypes_name(TypeKind.UCHAR) _type = typedesc.FundamentalType(ctypesname, 0, 0) elif self.is_array_type(_ctype) or _ctype.kind == TypeKind.RECORD: _type = self.parse_cursor_type(_ctype) elif self.is_pointer_type(_ctype): # extern Function pointer if self.is_unexposed_type(_ctype.get_pointee()): _type = self.parse_cursor_type( _ctype.get_canonical().get_pointee()) elif _ctype.get_pointee().kind == TypeKind.FUNCTIONPROTO: # Function pointers # cursor.type.get_pointee().kind == TypeKind.UNEXPOSED BUT # cursor.type.get_canonical().get_pointee().kind == TypeKind.FUNCTIONPROTO _type = self.parse_cursor_type(_ctype.get_pointee()) #_type = mth(_ctype.get_pointee()) else: # Fundamental types, structs.... _type = self.parse_cursor_type(_ctype) else: # What else ? raise NotImplementedError('What other type of variable? %s' % (_ctype.kind)) ## get the init_value and special cases init_value = self._get_var_decl_init_value(cursor.type, list(cursor.get_children())) if self.is_unexposed_type(_ctype): # string are not exposed init_value = '%s # UNEXPOSED TYPE. PATCH NEEDED.' % (init_value) elif (self.is_pointer_type(_ctype) and _ctype.get_pointee().kind == TypeKind.FUNCTIONPROTO): # Function pointers argument are handled inside if type(init_value) != list: init_value = [init_value] _type.arguments = init_value init_value = _type # finished log.debug('VAR_DECL: %s _ctype:%s _type:%s _init:%s location:%s' % (name, _ctype.kind.name, _type.name, init_value, getattr(cursor, 'location'))) obj = self.register(name, typedesc.Variable(name, _type, init_value)) self.set_location(obj, cursor) self.set_comment(obj, cursor) return True # dont parse literals again