You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.2 KiB
122 lines
3.2 KiB
4 months ago
|
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)
|
||
|
|
||
|
|