mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-09-20 13:06:20 +02:00
159 lines
4.5 KiB
Python
159 lines
4.5 KiB
Python
|
#!/home/nickm/bin/python2.3
|
||
|
|
||
|
import re, sys
|
||
|
import textwrap
|
||
|
|
||
|
files = sys.argv[1:]
|
||
|
funcDeclaredIn = {}
|
||
|
fileDeclares = {}
|
||
|
functionCalls = {}
|
||
|
funcCalledByFile = {}
|
||
|
funcCalledByFunc = {}
|
||
|
|
||
|
for fname in files:
|
||
|
f = open(fname, 'r')
|
||
|
curFunc = "???"
|
||
|
functionCalls.setdefault(curFunc,{})
|
||
|
lineno = 0
|
||
|
for line in f.xreadlines():
|
||
|
lineno += 1
|
||
|
m = re.match(r'^[^\s/].*\s(\w+)\([^;]*$', line)
|
||
|
if m:
|
||
|
#print line, "->", m.group(1)
|
||
|
curFunc = m.group(1)
|
||
|
functionCalls.setdefault(curFunc,{})
|
||
|
funcDeclaredIn[m.group(1)] = fname
|
||
|
fileDeclares.setdefault(fname, {})[m.group(1)] = 1
|
||
|
continue
|
||
|
m = re.match(r'^(\w+)\([^;]', line)
|
||
|
if m:
|
||
|
#print line, "->", m.group(1)
|
||
|
curFunc = m.group(1)
|
||
|
functionCalls.setdefault(curFunc,{})
|
||
|
funcDeclaredIn[m.group(1)] = fname
|
||
|
fileDeclares.setdefault(fname, {})[m.group(1)] = 1
|
||
|
continue
|
||
|
while line:
|
||
|
m = re.search(r'(\w+)\(', line)
|
||
|
if not m: break
|
||
|
#print line, "->", m.group(1)
|
||
|
functionCalls[curFunc][m.group(1)] = 1
|
||
|
#if curFunc == "???":
|
||
|
# print ">>!!!!! at %s:%s"%(fname,lineno)
|
||
|
funcCalledByFunc.setdefault(m.group(1), {})[curFunc]=1
|
||
|
funcCalledByFile.setdefault(m.group(1), {})[fname]=1
|
||
|
line = line[m.end():]
|
||
|
|
||
|
f.close()
|
||
|
|
||
|
fileUsers = {}
|
||
|
fileUses = {}
|
||
|
|
||
|
for fname in files:
|
||
|
print "%s:"%fname
|
||
|
users = {}
|
||
|
for func in fileDeclares[fname]:
|
||
|
cb = funcCalledByFile.get(func,{}).keys()
|
||
|
for f in cb: users[f] = 1
|
||
|
#print "users[%s] = %s"%(f,users[f])
|
||
|
users = users.keys()
|
||
|
users.sort()
|
||
|
fileUsers[fname] = users
|
||
|
for user in users:
|
||
|
fileUses.setdefault(user,[]).append(fname)
|
||
|
if user == fname: continue
|
||
|
print " from %s:"%user
|
||
|
for func in fileDeclares[fname]:
|
||
|
if funcCalledByFile.get(func,{}).get(user,0):
|
||
|
print " %s()"%func
|
||
|
|
||
|
def wrap(s, pre):
|
||
|
return textwrap.fill(s,
|
||
|
width=77, initial_indent=pre,
|
||
|
subsequent_indent=" "*len(pre))
|
||
|
|
||
|
for fname in files:
|
||
|
print
|
||
|
print "===== %s"%fname
|
||
|
print wrap(" ".join(fileUses[fname]),
|
||
|
" Calls: ")
|
||
|
print wrap(" ".join(fileUsers[fname]),
|
||
|
" Called by: ")
|
||
|
|
||
|
print "=============================="
|
||
|
|
||
|
|
||
|
funcnames = functionCalls.keys()
|
||
|
funcnames.sort()
|
||
|
|
||
|
if 1:
|
||
|
for func in funcnames:
|
||
|
print "===== %s"%func
|
||
|
callers = [c for c in funcCalledByFunc.get(func,{}).keys()
|
||
|
if c != "???"]
|
||
|
callers.sort()
|
||
|
called = [c for c in functionCalls[func].keys() if c != "???"]
|
||
|
called.sort()
|
||
|
print wrap(" ".join(callers),
|
||
|
" Called by:")
|
||
|
print wrap(" ".join(called),
|
||
|
" Calls:")
|
||
|
|
||
|
# simple topological sort.
|
||
|
functionDepth = {}
|
||
|
while 1:
|
||
|
BIG = 1000000
|
||
|
any = 0
|
||
|
for func in funcnames:
|
||
|
if functionDepth.has_key(func):
|
||
|
continue
|
||
|
called = [c for c in functionCalls[func] if c != func and
|
||
|
functionCalls.has_key(c)]
|
||
|
if len(called) == 0:
|
||
|
functionDepth[func] = 0
|
||
|
#print "Depth(%s)=%s"%(func,0)
|
||
|
any = 1
|
||
|
continue
|
||
|
calledDepths = [ functionDepth.get(c,BIG) for c in called ]
|
||
|
if max(calledDepths) < BIG:
|
||
|
d = functionDepth[func] = max(calledDepths)+1
|
||
|
#print "Depth(%s)=%s"%(func,d)
|
||
|
any = 1
|
||
|
continue
|
||
|
if not any:
|
||
|
break
|
||
|
|
||
|
# compute lexical closure.
|
||
|
cycCalls = {}
|
||
|
for func in funcnames:
|
||
|
if not functionDepth.has_key(func):
|
||
|
calls = [ c for c in functionCalls[func] if c != func and
|
||
|
functionCalls.has_key(c) and not functionDepth.has_key(c)]
|
||
|
cycCalls[func] = d = {}
|
||
|
for c in calls:
|
||
|
d[c]=1
|
||
|
|
||
|
|
||
|
cycNames = cycCalls.keys()
|
||
|
while 1:
|
||
|
any = 0
|
||
|
for func in cycNames:
|
||
|
L = len(cycCalls[func])
|
||
|
for called in cycCalls[func].keys():
|
||
|
cycCalls[func].update(cycCalls[called])
|
||
|
if L != len(cycCalls[func]):
|
||
|
any = 1
|
||
|
if not any:
|
||
|
break
|
||
|
|
||
|
depthList = [ (v,k) for k,v in functionDepth.items() ]
|
||
|
depthList.sort()
|
||
|
cycList = [ (len(v),k) for k,v in cycCalls.items() ]
|
||
|
cycList.sort()
|
||
|
for depth,name in depthList:
|
||
|
print "Depth[%s]=%s"%(name,depth)
|
||
|
for bredth,name in cycList:
|
||
|
print "Width[%s]=%s"%(name,bredth)
|
||
|
|
||
|
print "Sorted %s / %s"%(len(functionDepth),len(funcnames))
|