1 import sys 2 from pycparser import parse_file 3 from pycparser.c_ast import * 4 from pycparser.c_parser import CParser, Coord, ParseError 5 from pycparser.c_lexer import CLexer 6 7 8 def expand_decl(decl): 9 """ Converts the declaration into a nested list. 10 """ 11 typ = type(decl) 12 13 if typ == TypeDecl: 14 return ['TypeDecl', expand_decl(decl.type)] 15 elif typ == IdentifierType: 16 return ['IdentifierType', decl.names] 17 elif typ == ID: 18 return ['ID', decl.name] 19 elif typ in [Struct, Union]: 20 decls = [expand_decl(d) for d in decl.decls or []] 21 return [typ.__name__, decl.name, decls] 22 else: 23 nested = expand_decl(decl.type) 24 25 if typ == Decl: 26 if decl.quals: 27 return ['Decl', decl.quals, decl.name, nested] 28 else: 29 return ['Decl', decl.name, nested] 30 elif typ == Typename: # for function parameters 31 if decl.quals: 32 return ['Typename', decl.quals, nested] 33 else: 34 return ['Typename', nested] 35 elif typ == ArrayDecl: 36 dimval = decl.dim.value if decl.dim else '' 37 return ['ArrayDecl', dimval, nested] 38 elif typ == PtrDecl: 39 return ['PtrDecl', nested] 40 elif typ == Typedef: 41 return ['Typedef', decl.name, nested] 42 elif typ == FuncDecl: 43 if decl.args: 44 params = [expand_decl(param) for param in decl.args.params] 45 else: 46 params = [] 47 return ['FuncDecl', params, nested] 48 49 #----------------------------------------------------------------- 50 class NodeVisitor(object): 51 def __init__(self): 52 self.current_parent = None 53 54 def visit(self, node): 55 """ Visit a node. 56 """ 57 method = 'visit_' + node.__class__.__name__ 58 visitor = getattr(self, method, self.generic_visit) 59 return visitor(node) 60 61 def visit_FuncCall(self, node): 62 print("Visiting FuncCall") 63 print(node.show()) 64 print('---- parent ----') 65 print(self.current_parent.show()) 66 67 def generic_visit(self, node): 68 """ Called if no explicit visitor function exists for a 69 node. Implements preorder visiting of the node. 70 """ 71 oldparent = self.current_parent 72 self.current_parent = node 73 for c in node.children(): 74 self.visit(c) 75 self.current_parent = oldparent 76 77 78 def heapyprofile(): 79 # pip install guppy 80 # [works on python 2.7, AFAIK] 81 from guppy import hpy 82 import gc 83 84 hp = hpy() 85 ast = parse_file('/tmp/197.c') 86 gc.collect() 87 h = hp.heap() 88 print(h) 89 90 91 def memprofile(): 92 import resource 93 import tracemalloc 94 95 tracemalloc.start() 96 97 ast = parse_file('/tmp/197.c') 98 99 print('Memory usage: %s (kb)' % 100 resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) 101 102 snapshot = tracemalloc.take_snapshot() 103 print("[ tracemalloc stats ]") 104 for stat in snapshot.statistics('lineno')[:20]: 105 print(stat) 106 107 108 if __name__ == "__main__": 109 source_code = r'''void foo() { 110 L"hi" L"there"; 111 } 112 ''' 113 114 memprofile() 115 #heapyprofile() 116 117 #parser = CParser() 118 #ast = parser.parse(source_code, filename='zz') 119 #ast.show(showcoord=True, attrnames=True, nodenames=True) 120 121 122