def as_bitfield(self):
        """
            Take Enum entry type and convert into a bitfield type:
            uint64_t NameOfEnum : offset.num_bits;
        """
        if self.instance is None:
            return []

        result = []
        for enum in self.instance:
            type_val = 64
            bits = enum.origin.get('num_bits', -1)
            if enum.parent is not None:
                type_val = enum.parent.get('num_bits', type_val)

            e_name = enum.name.split('genz_')[-1]
            if int(bits) < 0:
                logging.warning('Enum entry "%s" has invalid bitfield value?' %
                                e_name)
            enum_entry = fields.CStructEntry(e_name,
                                             num_type=type_val,
                                             bitfield=bits)

            if enum_entry not in result:
                result.append(enum_entry)
        return result
示例#2
0
 def struct_meta(self):
     """
         A meta struct describing a <class> field.
     "raw_name" - is a name of the class as it appears in the xml file.
     "condensed_name" - is a trimmed class' name.
     "value" - a 'condensed' indexed ('hardware_types' enum defined in __init__).
     """
     entries = [
         fields.CStructEntry('raw_name', var_type='const char * const'),
         fields.CStructEntry('condensed_name', var_type='const char * const'),
         fields.CStructEntry('value', var_type='const enum %s' % self.enum.name), #name of the enum
     ]
     #FIXME: hardcoded index value!
     struct_instance = fields.CStruct(self.struct_name,
                                     entries=entries,
                                     ignore_ctrl_struct_enum=True)
     return struct_instance
示例#3
0
 def build_externs(cls, name, var_name=None):
     # name = 'genz_ctrl_struct_type_to_ptrs'
     if var_name is None:
         var_name = cls.ctr_ptr_info_struct_name
     array_type = 'extern struct %s' % var_name
     return [
         fields.CArrayEntry(name, array_type, is_allow_empty=False),
         fields.CStructEntry('%s_nelems' % var_name,
                             var_type='extern size_t',
                             l_space='')
     ]
示例#4
0
 def build_struct_sizes(cls, structs: list):
     """ """
     result = []
     for struct in structs:
         v_type = 'ssize_t %s_size' % struct.name.lower()
         field_name = '(struct %s *ci)' % cls.ctrl_info_name
         entry = fields.CStructEntry(field_name,
                                     var_type=v_type,
                                     l_space='')
         result.append(entry)
     return result
示例#5
0
    def build_ctrl_ptr_info_struct(cls):
        """
        struct genz_control_ptr_info {
            struct genz_control_structure_ptr *ptr;
            size_t num_ptrs;
            ssize_t struct_bytes;
            uint8_t vers;
            char *name;
        };
        """
        struct = fields.CStruct(cls.ctr_ptr_info_struct_name)

        entries = [
            fields.CStructEntry('* const ptr',
                                var_type='const struct %s' %
                                cls.ctrl_ptr_struct_name),
            fields.CStructEntry('num_ptrs', var_type='const size_t'),
            fields.CStructEntry('struct_bytes', var_type='const ssize_t'),
            fields.CStructEntry(
                'chained',
                var_type='const bool'),  #structure contains chained ptr
            fields.CStructEntry('vers', var_type='const uint8_t'),
            fields.CStructEntry('name', var_type='const char * const'),
        ]

        struct.extend(entries)
        return struct
示例#6
0
    def build_ctrl_struct_ptr_struct(cls):
        """
        struct genz_control_structure_ptr {
            const enum genz_control_ptr_flags ptr_type;
            const enum genz_pointer_size ptr_size;
            const uint32_t pointer_offset;
            const enum genz_control_structure_type struct_type;
            const char *ptr_name;
            ssize_t (*size_fn)(struct genz_control_info *ci);
        };
        """
        struct = fields.CStruct(cls.ctrl_ptr_struct_name)

        entries = [
            fields.CStructEntry('ptr_type',
                                var_type='const enum %s' %
                                cls.ctrl_ptr_flags_name),
            fields.CStructEntry('ptr_size',
                                var_type='const enum %s' %
                                cls.ptr_size_enum_name),
            fields.CStructEntry('pointer_offset', var_type='const uint32_t'),
            fields.CStructEntry('struct_type',
                                var_type='const enum %s' %
                                cls.ctrl_struct_type_enum_name),
            fields.CStructEntry('*ptr_name', var_type='const char'),
            fields.CStructEntry('(*size_fn)(struct %s *ci)' %
                                cls.ctrl_info_name,
                                var_type='ssize_t'),
        ]

        struct.extend(entries)
        return struct
示例#7
0
    def build_export_symbol(self, name):
        """
            EXPORT_SYMBOL(genz_struct_type_to_ptrs);

            size_t genz_struct_type_to_ptrs_nelems =
                sizeof(genz_struct_emtype_to_ptrs) /
                sizeof(genz_struct_type_to_ptrs[0]);

            EXPORT_SYMBOL(genz_struct_type_to_ptrs);
        """
        export_symbol = 'EXPORT_SYMBOL(%s)'
        value = 'sizeof({name}) / sizeof({name}[0])'.format(name=name)
        return [
            fields.CStructEntry(export_symbol % name, var_type='', l_space=''),
            fields.EStateEntry('size_t %s_nelems' % name,
                               value,
                               l_space='',
                               close_bracket=';'),
            fields.CStructEntry(export_symbol % (name + '_nelems'),
                                var_type='',
                                l_space=''),
        ]
示例#8
0
    def parse(self, root):
        """
            Generate a struct array of "meta" structs describing a Class. Refere
        to "struct_meta" property for documentation on the meta values.

            @param root: xml root tree to start parsing from.
        """
        if root is None:
            return

        if self._instance is None:
            self._instance = fields.CArrayEntry(self.name, 'struct %s' % self.struct_name)

        list_of_names = []
        longest_name_length = self._get_longest_name_length(root)

        for class_elem in root:
            raw_name = get_name(class_elem)

            trimmed_name = raw_name.lower().split('(')[0].strip()

            name = trim_name(trimmed_name, replaceable=' —[:](),=.\n', removable='\'|!<>@#$%^&*+–’-/')
            if 'switch' in name:
                name = 'switch'
            if 'bridge' in trimmed_name:
                name = 'bridge'

            if name not in list_of_names:
                list_of_names.append(name)

            enum_index =  len(self.enum.entries)
            estate = fields.EStateEntry('GENZ_%s' % name.upper(), enum_index)
            spaces = ' ' * (longest_name_length - len(raw_name))
            # { raw_name, condenced_name, condenced_enum_value }
            name = '"%s", %s"%s", %s' % (raw_name, spaces, name, estate.name)
            struct_entry = fields.CStructEntry(name, ignore_long_name_warning=True)
            struct_entry.l_space = '%s { ' % struct_entry.l_space
            struct_entry.str_close_symbol = ' },'

            self._instance.append(struct_entry)
            self.enum.append(estate)

        last_state = fields.EStateEntry('GENZ_NUM_HARDWARE_TYPES', None)
        self.enum.append(last_state)
        return self.instance
    def split_entry(self, entry: fields.CStructEntry, splitbit=64):
        """
            When struct entry bits exceeding offset_bits, the entry needs to be
        splitted in chunks.

        @param: dict or CStructEntry object to be splitted.
        """
        if entry.num_type == -1 or entry.bitfield == None or entry.bitfield == -1:
            #this is not a bitfield entry, so skip it.
            return entry
        max_bit = entry.origin.get('max_bit', -1)
        max_bit = int(max_bit)

        min_bit = entry.origin.get('min_bit', -1)
        min_bit = int(min_bit)

        result = []
        if not (min_bit < splitbit and max_bit >= splitbit):
            return [entry]

        split_bits = []
        split_bits.append(splitbit - min_bit)
        split_bits.append(entry.bitfield - split_bits[0])
        for index in range(len(split_bits)):
            bitfield = split_bits[index]
            name = entry.fields.get('name')
            entry_split = fields.CStructEntry(name=name,
                                              num_type=entry.num_type,
                                              bitfield=entry.bitfield)
            entry_split.name = '%s_%s' % (entry_split.name, index + 1)
            entry_split.definition = entry.definition
            entry_split.bitfield = bitfield
            entry_split.str_end = ' //NOTE: split bit'
            result.append(entry_split)

        return result
示例#10
0
    def _parse_structs(self, xml_structs):
        for struct_elem in xml_structs:
            struct_parser = parsers.StructBuilder(struct_elem)
            if struct_parser.instance not in self.structs:  #duplicates check
                self.structs.append(struct_parser.instance)

            union_builder = parsers.UnionBuilder(struct_elem)
            if union_builder is not None and union_builder.instance is not None:
                self.unions.extend(union_builder.instance)

            enum_builder = parsers.EnumBuilder(struct_elem)
            if enum_builder.instance is not None and len(
                    enum_builder.instance) > 0:
                for enum in enum_builder.instance:  #duplicates check
                    if enum not in self.enums:
                        self.enums.append(enum)

            pointer_parser = parsers.PointerBuilder(struct_elem,
                                                    data_types=self.DataTypes)
            if pointer_parser.instance is not None:
                if pointer_parser.instance not in self.pointers:
                    pointer_parser.instance.origin = struct_parser.instance
                    if pointer_parser.instance not in self.pointers:  #duplicates check
                        self.pointers.append(pointer_parser.instance)
                struct_parser.instance.child_pointers.extend(
                    pointer_parser.instance.entries)

            #Parsing a table is almost a recursive process. Each <table> or
            #<array> entry has almost the same structure as <struct> entry.
            table_parser = parsers.TableBuilder(struct_elem)
            if table_parser.instance is not None:
                for cgen in table_parser.instance:
                    for t_struct in cgen.structs:
                        table_entry_name = 'struct %s' % t_struct.name
                        struct_entry = fields.CStructEntry(
                            rm_prefix(cgen.structs[0].name, 'genz_') + '[]',
                            var_type=table_entry_name)

                        #Adding created Table entry to the current struct_parser
                        #entries list
                        if not struct_entry in struct_parser.instance.entries:
                            struct_parser.instance.append(struct_entry)

                        #loop through table's structs and only add those that are
                        #not already in the main structs list.
                        # These are the struct generated from <array> fields.
                        target = []
                        target.extend(cgen.structs)
                        for ms in target:
                            if ms not in self.struct_arrays:
                                self.struct_arrays.insert(0, ms)

                        struct_parser.instance.child_arrays.extend(
                            cgen.structs)

                        self._add_to_list(cgen.unions, self.unions)
                        self._add_to_list(cgen.enums, self.enums)
                        self._add_to_list(cgen.pointers, self.pointers)
                        self._add_to_list(cgen.struct_arrays,
                                          self.struct_arrays,
                                          is_push_front=True)
示例#11
0
    def entries(self):
        result = []
        result.append(self.DataTypes.table_index_define())

        ctrl_ptr_flags = self.DataTypes.build_ptr_flags_enum()
        ptr_sizes = self.DataTypes.build_ptr_sizes_enum()
        ctrl_ptr_struct = self.DataTypes.build_ctrl_struct_ptr_struct()
        ctrl_ptr_info_struct = self.DataTypes.build_ctrl_ptr_info_struct()

        externs = self.DataTypes.build_externs(self.struct_type_to_ptrs_name)
        # externs.extend(self.DataTypes.build_externs(self.table_type_to_ptrs_name))

        externs.extend(self.externs)

        externs.extend([
            fields.CArrayEntry(self.table_type_to_ptrs_name,
                               'extern struct genz_control_ptr_info',
                               is_allow_empty=False),
            fields.CStructEntry('genz_struct_type_to_ptrs_nelems',
                                var_type='extern size_t',
                                l_space=''),
            fields.CStructEntry('genz_table_type_to_ptrs_nelems',
                                var_type='extern size_t',
                                l_space='')
        ])

        result.append(ctrl_ptr_flags)
        result.append(ptr_sizes)
        result.append(ctrl_ptr_info_struct)
        result.append(self.structs_enum)
        result.append(ctrl_ptr_struct)

        # Order of adding things Matters for C file to compile.
        for union in self.unions:
            result.append(union)

        for enum in self.enums:
            if len(enum.entries) > 1:
                result.append(enum)

        structs = []

        # structs.append(
        #     fields.CStruct('genz_control_info', str_start='', open_bracket='', close_bracket=';')
        # )

        structs.extend(self.struct_arrays)
        structs.extend(self.structs)
        for struct in structs:
            if len(struct.entries) == 1:
                if '[]' in struct.entries[0].name:
                    continue
            result.append(struct)

        result.extend(externs)

        result.extend(self.struct_enum_size_t)

        #tentative declaration
        result.insert(
            0,
            fields.CStruct('genz_control_info',
                           str_start='',
                           open_bracket='',
                           close_bracket=';'))
        return result
示例#12
0
    def build_control_ptr_info_array(self):
        """
         This is a list of all the <struct>.
         Index by <struct> "type" number. There could be "gaps" in the type index -
        so add "null" entry and move on.

        Same thing should be created for <table>, except no need to have gaps.
        Assign index as you go.
        """
        array_type = self.DataTypes.ctr_ptr_info_struct_name
        array_name = 'genz_struct_type_to_ptrs'
        table_name = 'genz_table_type_to_ptrs'
        struct_array = fields.CArrayEntry(array_name, 'struct %s' % array_type)
        table_array = fields.CArrayEntry(table_name, 'struct %s' % array_type)
        pointers_count = len(self.pointers)

        #Need to know how big the pointers list is going to be, based of the
        #struct's highest "type" attribute's value which indicates its position
        #in the array that is built here.
        hIndex_struct = self.find_highest_struct_index()
        hIndex_tbl = self.find_highest_struct_index(tag='table')
        for idx in range(hIndex_struct + 1):
            struct = self.find_struct_by_index(idx)
            if struct is None:
                null_entry = fields.NullEntry(close_bracket=',')
            else:
                name_no_genz = rm_prefix(struct.name,
                                         'genz_').split('_structure')[0]
                offset = 'sizeof(struct {name})'.format(name=struct.name)
                name = 'NULL, 0, {offset}, {chained}, {vers}, "{stype}"'.format(
                    offset=offset,
                    vers=struct.vers if struct.vers is not None else '0x0',
                    stype=name_no_genz,
                    chained='true' if struct.is_chained else 'false')
                null_entry = fields.CStructEntry(name,
                                                 ignore_long_name_warning=True)
                null_entry.l_space = '%s { ' % null_entry.l_space
                null_entry.str_close_symbol = ' },'
            struct_array.append(null_entry)

        for idx in range(hIndex_tbl + 1):
            table = self.find_struct_by_index(idx, tag='table')
            name_no_genz = rm_prefix(table.name, 'genz_')
            name = 'NULL, 0, 0, {chained}, 0x0, "{stype}"'.format(
                stype=name_no_genz,
                chained='true' if table.is_chained else 'false')
            null_entry = fields.CStructEntry(name,
                                             ignore_long_name_warning=True)
            null_entry.l_space = '%s { ' % null_entry.l_space
            null_entry.str_close_symbol = ' },'
            table_array.append(null_entry)

        struct_enum = self.structs_enum
        for index in range(pointers_count):
            ptr = self.pointers[index]
            struct = ptr.origin
            if struct.tag not in ['struct', 'table']:
                continue

            if struct.index is None:
                msg = 'NOOOOOOO!! No "type" attr in struct -> %s' % struct.name
                logging.critical(msg)

            if not isinstance(struct, fields.cstruct.CStruct):
                msg = 'Pointer "%s" origin is not of type CStruct!' % ptr.name
                logging.critical(msg)
                continue

            if struct.origin is None:
                logging.critical('Pointer "%s" struct "%s" origin is None?!' %\
                                (ptr.name, struct.name))
                continue

            name_no_ptr = ptr.name.split('_ptrs')[0]
            name_no_genz = rm_prefix(name_no_ptr,
                                     'genz_').split('_structure')[0]

            ptr_size = 'sizeof({name})/sizeof({name}[0])'.format(name=ptr.name)
            ptr_offset = 'sizeof(struct genz_{name})'.format(name=name_no_ptr)

            name = '{ptype}, {size}, {offset}, {chained}, {vers}, "{stype}"'.format(
                ptype=ptr.name,
                size=ptr_size,
                offset=ptr_offset,
                vers=struct.vers if struct.vers is not None else '0x0',
                stype=name_no_genz,
                chained='true' if struct.is_chained else 'false')
            struct_entry = fields.CStructEntry(name,
                                               ignore_long_name_warning=True)
            struct_entry.l_space = '%s { ' % struct_entry.l_space
            struct_entry.str_close_symbol = ' },'

            if struct.tag == 'struct':
                struct_array.entries[int(struct.index, 0)] = struct_entry
            elif struct.tag == 'table':
                enum = self.find_enum_value_by_name(struct.name.upper(),
                                                    struct_enum)
                enum_val = enum.value.split('+')[-1].strip()
                if enum_val.isdigit(): enum_val = int(enum_val, 0)
                else: enum_val = 0
                table_array.entries[enum_val] = struct_entry

        return struct_array, table_array
    def create_entry(self, field, bits):
        """
            @param field: the xml field to create a struct entry from.
            @param bits: the 'num_bits' attr of the <offset> field (e.g. parent of field).
        """
        if field is None:
            logging.error('Failed parsing field (is None)! Root: %s' %
                          self.root)
            return

        s_entry = None
        name = get_name(field)

        field_name = trim_name(name)

        # If a field has <value> entries - it is an Enum, not a struct entry.
        if (len(field.findall('value')) > 0):
            logging.info('A "%s" field is an Enum...' % field_name)
            if (len(field.findall('subfield')) > 0):
                msg = 'Both <value> and <subfield> in the "%s" field!'
                msg += ' What is it? Struct entry or Enum?'
                logging.error(msg % (field_name))
            return

        props = field.attrib
        is_no_name = False

        if name is None:
            name = str(field.attrib)
            is_no_name = True

        if props.get('offset_bits', None) is None:
            props['offset_bits'] = bits

        var_type = None
        bitfield = props['num_bits']
        if 'uuid' in field_name and not field_name.endswith('ptr'):
            base_bit = props.get('base_bit', None)
            if base_bit is not None:  # ignore second half of split uuid
                return
            field_name = uuid_re.sub('', field_name)
            var_type = 'uuid_t'
            bitfield = -1

        s_entry = fields.CStructEntry(name=field_name,
                                      num_type=props['offset_bits'],
                                      bitfield=bitfield,
                                      var_type=var_type)

        s_entry.origin = field
        s_entry.parent = self.root
        if is_no_name:
            s_entry.str_start = '//'
            s_entry.str_end = ' //FIXME: entry had no name'

        #FIXME: we are ignoring ... entries for now, but will be fixed later
        if s_entry.name == '...':
            s_entry.str_start = '//'
            s_entry.str_end = ' //FIXME: name "..." entry'

        #FIXME: write this to a file, but comment it out to know which entries
        # we can't parse.
        if s_entry.bitfield == 0 or s_entry.num_type == 0:
            s_entry.str_start = '//'
            s_entry.str_end = ' //FIXME: 0 bits.'
            return s_entry

        if name.lower() == 'unknown':
            s_entry.str_start = '//'
            s_entry.str_end = ' //FIXME: UNKNOWN in name'

        if 'rsvd' in name.lower():
            s_entry.str_start = '//'
            s_entry.str_end = ' //FIXME: skipping rsvd(X) fields for now'

        s_entry = self.split_entry(s_entry)

        return s_entry