def _create_entry(self, field):
        """
            Look at self.parse for full documentation.
        This looks at <subfield> fields of the <field> to create the union entries.
        """
        xml_subfields = field.findall('subfield')
        xml_subfields.append(
            field)  #Weird, but true. <value> can be in <field> too.

        name = get_name(field)
        field_name = trim_name(name)
        field_bits = field.get('num_bits', -1)

        try:
            int(field_bits)
        except Exception:
            logging.error('%s failed to parse bits to int: %s' %
                          (name, field_bits))
            return None

        enum_instance = None
        result = []
        for xml_subfield in xml_subfields:
            xml_values = xml_subfield.findall('value')
            if xml_values is None or len(
                    xml_values) == 0:  # No value - not an enum
                continue

            if xml_subfield != field:
                subfield_name: str = get_name(xml_subfield)
                subfield_name = trim_name(subfield_name)
            else:
                subfield_name = ''

            inst_name = 'genz_%s_%s' % (field_name, subfield_name)
            #empty subfield_name produces trailing '_'. Thus - clean it up.
            inst_name = inst_name.strip('_')
            enum_instance = fields.CEnumEntry(inst_name,
                                              origin=xml_subfield,
                                              parent=field)

            for xml_value in xml_values:
                entry_name = get_name(xml_value)
                entry_name = trim_name(entry_name)
                if entry_name == 'reserved':
                    continue

                entry_name = '%s_%s_%s' % (field_name, subfield_name,
                                           entry_name)
                entry_name = trim_name(entry_name)
                entry_name = entry_name.upper()

                val = xml_value.get('val', -1)
                entry = fields.EStateEntry(entry_name, val)
                entry.origin = field
                enum_instance.append(entry)

            self._instance.append(enum_instance)
            result.append(enum_instance)
        return result
示例#2
0
 def find_struct_enum_by_name(self, target_name):
     struct_ptr_enum = self.structs_enum
     target_name = trim_name('genz_%s' % target_name.lower())
     for enum_entry in struct_ptr_enum.entries:
         if enum_entry.name.lower() == target_name:
             return enum_entry
     return None
示例#3
0
    def _handle_ptr_tables(self, pointer) -> bool:
        """
        "GENZ_CONTROL_POINTER_ARRAY" - "ptr_to" points to a thing that is a Table
        and it has an array that is THE ONLY thing in the table.

        "GENZ_CONTROL_POINTER_TABLE" - points to a table and it just the offsets
        or offsets with arrays that are not "Variable" type. (e.g 'elements' attr
        of the array is not "Variable").

        "GENZ_CONTROL_POINTER_TABLE_WITH_HEADER" - points to a table that has offsets
        with the array of type "Variable".
        """
        logging.debug('%s -> _handle_ptr_tables:\n pointer "%s" arrived.' % \
                (os.path.basename(__file__), pointer.name))
        ptr_flags = self.DataTypes.pointer_types()
        ptr_name = 'genz_%s' % trim_name(pointer.ptr_to)
        struct = self.find_struct_by_name(ptr_name)
        if struct is None:
            return False

        if struct.origin is None:
            return False

        ptr_flag_to_set = None

        if struct.tag == 'struct':
            pointer.p_flag = ptr_flags['struct'].name
            return True

        arrays = struct.origin.findall('array')
        offsets = struct.origin.findall('offset')
        # probably a GENZ_CONTROL_POINTER_ARRAY, as long as the only element is
        # an <array> and nothing else
        if arrays is not None and len(arrays) > 0:
            if len(struct.origin) == 1:
                ptr_flag_to_set = ptr_flags['array']

        if len(offsets) > 0:
            #GENZ_CONTROL_POINTER_TABLE if not a "Variable" array
            if not self._has_variable_array(arrays):
                ptr_flag_to_set = ptr_flags['table']
            else:
                # GENZ_CONTROL_POINTER_TABLE_WITH_HEADER
                if len(arrays) > 0:
                    ptr_flag_to_set = ptr_flags['tbl_w_hdr']

        if ptr_flag_to_set is not None:
            pointer.p_flag = ptr_flag_to_set.name

        return ptr_flag_to_set is not None
示例#4
0
    def _handle_ptr_chain(self, pointer):
        """
        If its pointing to a Struct, then keep following the pointer to find a enum
        value from that big table of Struct names which is Second or whatever value
        in the C array entries. Look up every pointer in the struct it points to.
        If none points to its own struct - then it is a POINTER_STRUCTURE type.

        Looked for a Struct or Table - look up the structure and look inside it
        and its pointers, the First pointer is Start.

        Every next point (technically the last one referencing itself) is Chained.
        """
        logging.debug('%s -> _handle_ptr_chain:\n pointer "%s" arrived.' % \
                        (os.path.basename(__file__), pointer.name))

        ptr_types = self.DataTypes.pointer_types()
        ptr_name = 'genz_%s' % trim_name(pointer.ptr_to)
        struct = self.find_struct_by_name(ptr_name)
        if struct is None:
            return False

        p_flag_to_set = None

        for struct_ptr in struct.child_pointers:
            ptr_to_name = 'genz_%s' % trim_name(struct_ptr.ptr_to)
            if struct.name == ptr_to_name:
                p_flag_to_set = ptr_types['struct' if struct.tag ==
                                          'struct' else 'table'].name
            if struct_ptr == pointer:
                p_flag_to_set = ptr_types['chained'].name
                struct.is_chained = True

        if p_flag_to_set is not None:
            pointer.p_flag = p_flag_to_set

        logging.debug('%s is a %s\n-----\n' % (pointer.name, p_flag_to_set))
        return p_flag_to_set is not None
示例#5
0
    def _create_entry(self, field):
        """
            Look at self.parse for full documentation.
        This looks at <subfield> fields of the <field> to create the union entries.

        @param field: xml field to extract <subfield> from.
        @return: CSubunion instance with all the added entries. Or None if failed.
        """
        xml_subfields = field.findall('subfield')

        name = get_name(field)
        field_name = trim_name(name)
        field_bits = field.get('num_bits', -1)

        try:
            int(field_bits)
        except Exception:
            logging.error('%s failed to parse bits to int: %s' %
                          (name, field_bits))
            return

        union_instance = None
        for xml_subfield in xml_subfields:
            subfield_name: str = get_name(xml_subfield)
            subfield_name = trim_name(subfield_name)
            if xml_subfield.find('value') is not None:
                continue

            if union_instance is None:
                union_instance = fields.CSubunion('genz_%s' % field_name,
                                                  field_bits)

            sub_bits = xml_subfield.get('num_bits', -1)
            union_instance.add(subfield_name, sub_bits, field_bits)

        return union_instance
示例#6
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 test_with_entries(self):
        """
        struct control_structure_pointers core_structure_pointers[]
        """
        name = 'Core Structure PTR 1'
        p_value = '0x48'
        expected = '{ None, GENZ_4_BYTE_POINTER, 0x48, None },'
        var_type = 'struct control_structure_pointers'
        name = name.split('PTR')[0].strip() + '_pointers'
        name = utils.trim_name(name)
        array_entry = fields.CArrayEntry(name, var_type)
        array_entry.l_space = ''

        pModel = fields.CPointerEntry(name, '4', p_value=p_value)
        array_entry.append(pModel)
        expected = 'struct control_structure_pointers core_structure_pointers[] = {\n    %s\n};' % expected
        result = array_entry.pprint()
        self.assertEqual(expected, result)
    def _create_entry(self, field, p_value):
        """
         TODO

        @param field
        @param entry_name <str>: name of the pointer (not the Type name).
        @param type_name <str>: entry type name.

        @return: created/parsed entry on success. None - nothing happened.
        """
        field_name = get_name(field)
        field_name = trim_name(field_name)

        field_num_bits = field.get('num_bits')
        ptr_to = field.get('ptr_to', None)
        if ptr_to is None:
            return None

        try:
            field_min_bits = int(field.get('min_bit'))
        except ValueError:
            # in a perfect world - this should never happened.
            logging.warning('Field %s min_bits is not int?' % field_name)
            field_min_bits = -1

        p_size = '4' if field_num_bits == '32' else '6'
        if field_min_bits > 0:
            try:
                p_value = int((field_min_bits / 8) + int(p_value, 0))
                p_value = hex(p_value)
            except ValueError:
                p_value = '-1'

        pointer_entry = fields.CPointerEntry(field_name,
                                             p_size,
                                             p_value,
                                             ptr_to=ptr_to)
        pointer_entry.origin = field
        pointer_entry.parent = self.root

        return pointer_entry
    def build_struct_instance(self, field):
        """
            TODO
        """
        if not isinstance(field, str):
            name = get_name(field)
        else:
            name = field

        name = trim_name(name)

        struct = fields.CStruct('genz_%s' % name, origin=field)
        struct.vers = field.get('vers', None)
        struct.index = field.get('type', -1)

        # struct.tag = self.root.tag
        length_comment = is_name_too_long(struct.name)
        if length_comment:
            struct.open_bracket = '%s %s' % (struct.open_bracket,
                                             length_comment)
        return struct
    def parse(self, root):
        struct_name = get_name(root)
        struct_name = trim_name(struct_name)
        entry_name = '%s_ptrs' % struct_name

        if self._instance is None:
            self._instance = fields.CArrayEntry(entry_name, self.type_name)
            self._instance.parent = self.root

        offsets = root.findall('offset')
        for offset in offsets:
            p_value = offset.get('value', -1)
            for field in offset.findall('field'):
                if field.get('ptr_to', None) is None:
                    continue

                entry = self._create_entry(field=field, p_value=p_value)
                if entry is not None:
                    self._instance.append(entry)

        if len(self._instance.entries) == 0:
            self._instance = None
    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