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
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
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
def visit_Typedef(self, attrs): name = attrs['name'] typ = attrs['type'] context = attrs['context'] return c_ast.Typedef(name, typ, context)