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 "=============================="
98 funcnames
= functionCalls
.keys()
102 for func
in funcnames
:
103 print "===== %s"%func
104 callers
= [c
for c
in funcCalledByFunc
.get(func
,{}).keys()
107 called
= [c
for c
in functionCalls
[func
].keys() if c
!= "???" and
110 print wrap(" ".join(callers
),
112 print wrap(" ".join(called
),
115 # simple topological sort.
120 for func
in funcnames
:
121 if functionDepth
.has_key(func
):
123 called
= [c
for c
in functionCalls
[func
] if c
!= func
and
124 functionCalls
.has_key(c
)]
126 functionDepth
[func
] = 0
127 #print "Depth(%s)=%s"%(func,0)
130 calledDepths
= [ functionDepth
.get(c
,BIG
) for c
in called
]
131 if max(calledDepths
) < BIG
:
132 d
= functionDepth
[func
] = max(calledDepths
)+1
133 #print "Depth(%s)=%s"%(func,d)
139 # compute lexical closure.
141 for func
in funcnames
:
142 if not functionDepth
.has_key(func
):
143 calls
= [ c
for c
in functionCalls
[func
] if c
!= func
and
144 functionCalls
.has_key(c
) and not functionDepth
.has_key(c
)]
145 cycCalls
[func
] = d
= {}
150 cycNames
= cycCalls
.keys()
153 for func
in cycNames
:
154 L
= len(cycCalls
[func
])
155 for called
in cycCalls
[func
].keys():
156 cycCalls
[func
].update(cycCalls
[called
])
157 if L
!= len(cycCalls
[func
]):
162 depthList
= [ (v
,k
) for k
,v
in functionDepth
.items() ]
164 cycList
= [ (len(v
),k
) for k
,v
in cycCalls
.items() ]
166 for depth
,name
in depthList
:
167 print "Depth[%s]=%s"%(name
,depth
)
168 for bredth
,name
in cycList
:
169 print "Width[%s]=%s"%(name
,bredth
)
171 print "Sorted %s / %s"%(len(functionDepth
),len(funcnames
))