Пример #1
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.
        """
        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 parse(self, root):
        """
         In the Root - find <array> element and parse it by the rules of a regular
        <struct> entry.
        """
        arrays = root.findall('array')
        if len(arrays) == 0:
            return

        if self._instance is None:
            self._instance = []

        for array in arrays:
            if self.elements_type is None:
                self.elements_type = array.get('elements')
            elements = array.findall('element')
            if elements is None or len(elements) == 0:
                logging.warning('Empty array in the table "%s"' %
                                root.get('name', 'unknown'))
                continue

            for element in elements:
                name_to_set = get_name(root)
                # if not name_to_set.lower().endswith('array'):
                name_to_set = '%s Array' % name_to_set
                element.set('name', name_to_set)

            cgen = CGenerator.CGenerator(root,
                                         parse_on_init=False,
                                         name='table: %s' % name_to_set)
            cgen.struct_tag_name = 'element'
            cgen.parse_xml(array)
            self._instance.append(cgen)
Пример #3
0
 def _get_longest_name_length(self, root):
     """
         Used for plain silly prettification for the array entries. Helps to
     align the condensed names in a one column for better readability.
     """
     value = -1
     for class_elem in root:
         raw_name = get_name(class_elem)
         if len(raw_name) > value:
             value = len(raw_name)
     return value
Пример #4
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
Пример #5
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
Пример #6
0
    def parse(self, root=None):
        """
            @param root: xml root tree to start parsing from.
        """
        root_name = get_name(root)
        arrays = root.findall('array')
        if len(arrays) > 1:
            logging.warn('More than one <array> in "%s"... not bad, but not good either.' % root_name)

        #use indexed loop to asign index to the name when(if) more than one array
        for index in range(len(arrays)):
            array_xml = arrays[index]
            elements = array_xml.findall('element')
            array_offset = array_xml.get('offset', -1)
            if len(elements) > 1:
                logging.warn('More than one <element> in "%s" with "%s" array offset... only first will get parsed.' %
                            (root_name, array_offset))
            if len(elements) == 0:
                logging.warn('No <element> in array of "%s"! Skipping...' % root_name)
                continue
Пример #7
0
    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
Пример #8
0
    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
Пример #9
0
    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
Пример #10
0
    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