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