| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 | 
							- #!/usr/bin/env python2.3
 
- import re, sys
 
- import textwrap
 
- files = sys.argv[1:]
 
- funcDeclaredIn = {}
 
- fileDeclares = {}
 
- functionCalls = {}
 
- funcCalledByFile = {}
 
- funcCalledByFunc = {}
 
- cpp_re = re.compile(r'//.*$')
 
- c_re = re.compile(r'/[*]+(?:[^*]+|[*]+[^/*])*[*]+/', re.M|re.S)
 
- for fname in files:
 
-     f = open(fname, 'r')
 
-     curFunc = "???"
 
-     functionCalls.setdefault(curFunc,{})
 
-     lineno = 0
 
-     body = f.read()
 
-     body = cpp_re.sub(" ",body)
 
-     body = c_re.sub(" ",body)
 
-     #if fname == 'dns.c': print body
 
-     for line in body.split("\n"):
 
-         lineno += 1
 
-         m = re.match(r'^[^\s/].*\s(\w+)\([^;]*$', line)
 
-         if m:
 
-             #print line, "->", m.group(1)
 
-             curFunc = m.group(1)
 
-             if curFunc[0] == '_': curFunc = curFunc[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)
 
-             if curFunc[0] == '_': curFunc = curFunc[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 fname, line, curFunc, "->", m.group(1)
 
-             fn = m.group(1)
 
-             if fn[0] == '_':
 
-                 fn = fn[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 != "???" and
 
-                   c in funcnames]
 
-         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))
 
 
  |