| 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) |
| |
| |