Exemple #1
0
def _flatten_container(container, items=None): #, context_name=None):
    """ Given a struct or union, replaces nested structs or unions
    with toplevel struct/unions and a typdef'd member. This will 
    recursively expand everything nested. The `items` and `context_name`
    arguments are used internally. Returns a list of flattened nodes.

    """
    #print '_flatten_container_start', container.__class__.__name__, container.name
    #print [(m.__class__.__name__, m.name) for m in container.members]


    if items is None:
        items = []

    parent_context = container.context
    parent_name = container.name
    if not parent_name:
        parent_name = container.typedef_name

    mod_context = []
    for i, field in enumerate(container.members):
        if isinstance(field, (c_ast.Struct, c_ast.Union)):
            # Create the necessary mangled names
            mangled_name = '__%s_%s' % (parent_name, field.name)
            mangled_typename = mangled_name + '_t'
            
            # Change the name of the nested item to the mangled
            # item the context to the parent context
            field.name = mangled_name
            field.context = parent_context
            
            # Expand any nested definitions for this container.
            _flatten_container(field, items) #, parent_name)
            
            # Create a typedef for the mangled name with the parent_context
            typedef = c_ast.Typedef(mangled_typename, field, parent_context)
                
            # Add the typedef to the list of items
            items.append(typedef)

            # Add the necessary information to the mod_context so 
            # we can modify the list of members at the end.
            mod_context.append((i, field, typedef))

    # Use the mod_context to remove the nest definitions and replace 
    # any fields that reference them with the typedefs.
    for idx, field, typedef in reversed(mod_context):
        r = container.members.pop(idx) #TODO????
        print 'removed member', r.name
        for member in container.members:
            if isinstance(member, c_ast.Field):
                if member.typ is field:
                    member.typ = typedef

    items.append(container) #removed for typedef???

    #print '_flatten_container_end: items', [(item.__class__.__name__, item.name) for item in items]


    return items
Exemple #2
0
    def _build_declarations(self, spec, decls, typedef_namespace=False):
        """ 构建 declarations.

        Args:
            spec: 一个 dict: {qual=[], storage=[], type=[], function=[]}
                来自 declaration_specifiers
            decls: dict 列表:[{decl=, init=}],来自 init_declarator_list
            typedef_namespace:

        Returns:
            构建好的 declarations 列表,元素为 Typedef 或 Decl.
        """
        is_typedef = 'typedef' in spec['storage']
        declarations = []

        for decl in decls:
            assert decl['decl'] is not None
            if is_typedef:
                declaration = c_ast.Typedef(
                    name=None,
                    quals=spec['qual'],
                    storage=spec['storage'],
                    type=decl['decl'],
                    coord=decl['decl'].coord
                )
            else:
                declaration = c_ast.Decl(
                    name=None,
                    quals=spec['qual'],
                    storage=spec['storage'],
                    funcspec=spec['function'],
                    type=decl['decl'],
                    init = decl.get('init'),
                    bitsize=None,   # TODO: Parser全部测试完成后删除此参数
                    coord=decl['decl'].coord
                )

            if isinstance(declaration.type, 
                          (c_ast.Struct, c_ast.IdentifierType)):
                fixed_decl = declaration
            else:
                fixed_decl = self._fix_decl_name_type(declaration, spec['type'])

            # 添加到 scope 中,在语法分析器中使用
            # 
            if typedef_namespace:
                if is_typedef:
                    self._add_typedef_name(fixed_decl.name, fixed_decl.coord)
                else:
                    self._add_identifier(fixed_decl.name, fixed_decl.coord)

            declarations.append(fixed_decl)

        return declarations
Exemple #3
0
    def p_decl_body(self, p):
        """ decl_body : declaration_specifiers init_declarator_list_opt
        """
        spec = p[1]
        is_typedef = 'typedef' in spec['storage']
        decls = []

        # p[2] (init_declarator_list_opt) is either a list or None
        #
        if p[2] is None:
            # Then it's a declaration of a struct / enum tag,
            # without an actual declarator.
            #
            type = spec['type']
            if len(type) > 1:
                coord = '?'
                for t in type:
                    if hasattr(t, 'coord'):
                        coord = t.coord
                        break

                self._parse_error('Multiple type specifiers with a type tag', coord)

            decl = c_ast.Decl(
                name=None,
                quals=spec['qual'],
                storage=spec['storage'],
                type=type[0],
                init=None,
                bitsize=None,
                coord=type[0].coord)
            decls = [decl]
        else:
            for decl, init in p[2] or []:
                if is_typedef:
                    decl = c_ast.Typedef(
                        name=None,
                        quals=spec['qual'],
                        storage=spec['storage'],
                        type=decl,
                        coord=decl.coord)
                else:
                    decl = c_ast.Decl(
                        name=None,
                        quals=spec['qual'],
                        storage=spec['storage'],
                        type=decl,
                        init=init,
                        bitsize=None,
                        coord=decl.coord)

                typename = spec['type']
                fixed_decl = self._fix_decl_name_type(decl, typename)

                # Add the type name defined by typedef to a
                # symbol table (for usage in the lexer)
                #
                if is_typedef:
                    self._add_typedef_type(fixed_decl.name)

                decls.append(fixed_decl)

        p[0] = decls
Exemple #4
0
 def visit_Typedef(self, attrs):
     name = attrs['name']
     typ = attrs['type']
     context = attrs['context']
     return c_ast.Typedef(name, typ, context)