| import sys | |
| from pycparser import parse_file | |
| from pycparser.c_ast import * | |
| from pycparser.c_parser import CParser, Coord, ParseError | |
| from pycparser.c_lexer import CLexer | |
| def expand_decl(decl): | |
| """ Converts the declaration into a nested list. | |
| """ | |
| typ = type(decl) | |
| if typ == TypeDecl: | |
| return ['TypeDecl', expand_decl(decl.type)] | |
| elif typ == IdentifierType: | |
| return ['IdentifierType', decl.names] | |
| elif typ == ID: | |
| return ['ID', decl.name] | |
| elif typ in [Struct, Union]: | |
| decls = [expand_decl(d) for d in decl.decls or []] | |
| return [typ.__name__, decl.name, decls] | |
| else: | |
| nested = expand_decl(decl.type) | |
| if typ == Decl: | |
| if decl.quals: | |
| return ['Decl', decl.quals, decl.name, nested] | |
| else: | |
| return ['Decl', decl.name, nested] | |
| elif typ == Typename: # for function parameters | |
| if decl.quals: | |
| return ['Typename', decl.quals, nested] | |
| else: | |
| return ['Typename', nested] | |
| elif typ == ArrayDecl: | |
| dimval = decl.dim.value if decl.dim else '' | |
| return ['ArrayDecl', dimval, nested] | |
| elif typ == PtrDecl: | |
| return ['PtrDecl', nested] | |
| elif typ == Typedef: | |
| return ['Typedef', decl.name, nested] | |
| elif typ == FuncDecl: | |
| if decl.args: | |
| params = [expand_decl(param) for param in decl.args.params] | |
| else: | |
| params = [] | |
| return ['FuncDecl', params, nested] | |
| #----------------------------------------------------------------- | |
| class NodeVisitor(object): | |
| def __init__(self): | |
| self.current_parent = None | |
| def visit(self, node): | |
| """ Visit a node. | |
| """ | |
| method = 'visit_' + node.__class__.__name__ | |
| visitor = getattr(self, method, self.generic_visit) | |
| return visitor(node) | |
| def visit_FuncCall(self, node): | |
| print("Visiting FuncCall") | |
| print(node.show()) | |
| print('---- parent ----') | |
| print(self.current_parent.show()) | |
| def generic_visit(self, node): | |
| """ Called if no explicit visitor function exists for a | |
| node. Implements preorder visiting of the node. | |
| """ | |
| oldparent = self.current_parent | |
| self.current_parent = node | |
| for c in node.children(): | |
| self.visit(c) | |
| self.current_parent = oldparent | |
| def heapyprofile(): | |
| # pip install guppy | |
| # [works on python 2.7, AFAIK] | |
| from guppy import hpy | |
| import gc | |
| hp = hpy() | |
| ast = parse_file('/tmp/197.c') | |
| gc.collect() | |
| h = hp.heap() | |
| print(h) | |
| def memprofile(): | |
| import resource | |
| import tracemalloc | |
| tracemalloc.start() | |
| ast = parse_file('/tmp/197.c') | |
| print('Memory usage: %s (kb)' % | |
| resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) | |
| snapshot = tracemalloc.take_snapshot() | |
| print("[ tracemalloc stats ]") | |
| for stat in snapshot.statistics('lineno')[:20]: | |
| print(stat) | |
| if __name__ == "__main__": | |
| source_code = r'''void foo() { | |
| L"hi" L"there"; | |
| } | |
| ''' | |
| memprofile() | |
| #heapyprofile() | |
| #parser = CParser() | |
| #ast = parser.parse(source_code, filename='zz') | |
| #ast.show(showcoord=True, attrnames=True, nodenames=True) | |