1 #!/usr/bin/env python2.3
13 cpp_re
= re
.compile(r
'//.*$')
14 c_re
= re
.compile(r
'/[*]+(?:[^*]+|[*]+[^/*])*[*]+/', re
.M|re
.S
)
19 functionCalls
.setdefault(curFunc
,{})
22 body
= cpp_re
.sub(" ",body
)
23 body
= c_re
.sub(" ",body
)
24 #if fname == 'dns.c': print body
25 for line
in body
.split("\n"):
27 m
= re
.match(r
'^[^\s/].*\s(\w+)\([^;]*$', line
)
29 #print line, "->", m.group(1)
31 if curFunc
[0] == '_': curFunc
= curFunc
[1:]
32 functionCalls
.setdefault(curFunc
,{})
33 funcDeclaredIn
[m
.group(1)] = fname
34 fileDeclares
.setdefault(fname
, {})[m
.group(1)] = 1
36 m
= re
.match(r
'^(\w+)\([^;]', line
)
38 #print line, "->", m.group(1)
40 if curFunc
[0] == '_': curFunc
= curFunc
[1:]
41 functionCalls
.setdefault(curFunc
,{})
42 funcDeclaredIn
[m
.group(1)] = fname
43 fileDeclares
.setdefault(fname
, {})[m
.group(1)] = 1
46 m
= re
.search(r
'(\w+)\(', line
)
48 #print fname, line, curFunc, "->", m.group(1)
52 functionCalls
[curFunc
][m
.group(1)] = 1
54 # print ">>!!!!! at %s:%s"%(fname,lineno)
55 funcCalledByFunc
.setdefault(m
.group(1), {})[curFunc
]=1
56 funcCalledByFile
.setdefault(m
.group(1), {})[fname
]=1
67 for func
in fileDeclares
[fname
]:
68 cb
= funcCalledByFile
.get(func
,{}).keys()
69 for f
in cb
: users
[f
] = 1
70 #print "users[%s] = %s"%(f,users[f])
73 fileUsers
[fname
] = users
75 fileUses
.setdefault(user
,[]).append(fname
)
76 if user
== fname
: continue
77 print " from %s:"%user
78 for func
in fileDeclares
[fname
]:
79 if funcCalledByFile
.get(func
,{}).get(user
,0):
83 return textwrap
.fill(s
,
84 width
=77, initial_indent
=pre
,
85 subsequent_indent
=" "*len(pre
))
89 print "===== %s"%fname
90 print wrap(" ".join(fileUses
[fname
]),
92 print wrap(" ".join(fileUsers
[fname
]),
95 print "=============================="
97 funcnames
= functionCalls
.keys()
101 for func
in funcnames
:
102 print "===== %s"%func
103 callers
= [c
for c
in funcCalledByFunc
.get(func
,{}).keys()
106 called
= [c
for c
in functionCalls
[func
].keys() if c
!= "???" and
109 print wrap(" ".join(callers
),
111 print wrap(" ".join(called
),
114 # simple topological sort.
119 for func
in funcnames
:
120 if functionDepth
.has_key(func
):
122 called
= [c
for c
in functionCalls
[func
] if c
!= func
and
123 functionCalls
.has_key(c
)]
125 functionDepth
[func
] = 0
126 #print "Depth(%s)=%s"%(func,0)
129 calledDepths
= [ functionDepth
.get(c
,BIG
) for c
in called
]
130 if max(calledDepths
) < BIG
:
131 d
= functionDepth
[func
] = max(calledDepths
)+1
132 #print "Depth(%s)=%s"%(func,d)
138 # compute lexical closure.
140 for func
in funcnames
:
141 if not functionDepth
.has_key(func
):
142 calls
= [ c
for c
in functionCalls
[func
] if c
!= func
and
143 functionCalls
.has_key(c
) and not functionDepth
.has_key(c
)]
144 cycCalls
[func
] = d
= {}
148 cycNames
= cycCalls
.keys()
151 for func
in cycNames
:
152 L
= len(cycCalls
[func
])
153 for called
in cycCalls
[func
].keys():
154 cycCalls
[func
].update(cycCalls
[called
])
155 if L
!= len(cycCalls
[func
]):
160 depthList
= [ (v
,k
) for k
,v
in functionDepth
.items() ]
162 cycList
= [ (len(v
),k
) for k
,v
in cycCalls
.items() ]
164 for depth
,name
in depthList
:
165 print "Depth[%s]=%s"%(name
,depth
)
166 for bredth
,name
in cycList
:
167 print "Width[%s]=%s"%(name
,bredth
)
169 print "Sorted %s / %s"%(len(functionDepth
),len(funcnames
))