-
Notifications
You must be signed in to change notification settings - Fork 3
/
codepaths.py
158 lines (135 loc) · 4.47 KB
/
codepaths.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import subprocess
import time
import sys
import argparse
class CodeTree:
def __init__(self):
self.root = None
self.remaining = 0
self.processed = 0
self.avg = 0.0
self.total = 0.0
self.discovered = []
def contains(self, name):
if name in self.discovered:
return True
self.discovered.append(name)
return False
def _print_path(self, node, path):
path += " " + node.name
ret = ""
if len(node.children) == 0:
return path + "\n"
for i in node.children:
ret += self._print_path(i, path)
return ret
def __str__(self):
if self.root is None:
return ""
return self._print_path(self.root, "")
def _print_leaves(self, node):
ret = ""
if len(node.children) == 0:
return node.name + "\n"
for i in node.children:
ret += self._print_leaves(i)
return ret
def _find_all_paths(self, node, path):
path = path + [node.name]
if len(node.children) == 0:
return [path]
paths = []
for n in node.children:
newpaths = self._find_all_paths(n, path)
for newpath in newpaths:
paths.append(newpath)
return paths
def paths(self):
if self.root is None:
return []
return self._find_all_paths(self.root, [])
def leaves(self):
if self.root is None:
return ""
return self._print_leaves(self.root)
class CodeNode:
def __init__(self, name):
self.children = []
self.name = name
def add_child(self, child):
self.children.append(child)
def find_callers(func, cscopedb):
p = subprocess.Popen(["cscope", "-d", "-f", cscopedb, "-L3", func],
stdout=subprocess.PIPE)
(output, error) = p.communicate()
output = output.rstrip()
ret = []
for l in output.split('\n'):
ret.append(l.split(' ')[:2])
return ret
def get_paths(tree, node, cscopedb, directories, exclude, dupes):
tree.processed += 1
t0 = time.time()
callers = find_callers(node.name, cscopedb)
tree.total += time.time() - t0
tree.processed += 1
tree.remaining -= 1
tree.remaining += len(callers)
avg = tree.total / tree.processed
remain = tree.remaining * (tree.total / tree.processed)
sys.stderr.write("\r{} elapsed, {} possible remaining".format(tree.total, remain))
sys.stderr.flush()
for c in callers:
skip = True
for i in directories:
if i in c[0]:
skip = False
break
if skip:
tree.remaining -= 1
continue
for i in exclude:
if i in c[0]:
skip = True
break
if skip:
tree.remaining -= 1
continue
if not dupes and tree.contains(c[1]):
tree.remaining -= 1
continue
child = CodeNode(c[1])
node.add_child(child)
tree.processed += 1
get_paths(tree, child, cscopedb, directories, exclude, dupes)
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--cscopedb", default="cscope.out", help="Location of cscope.out")
parser.add_argument("-e", "--exclude", action='append',
help="Exclude this component of the path")
parser.add_argument("-d", "--directory", action='append',
help="Only deal with functions in this directory (can just be one part of the path)")
parser.add_argument("-p", "--duplicates", action='store_true',
help="Don't filter out duplicate leaves (ie have a->b->c as well as a->d->c)")
parser.add_argument("-t", "--tree", action='store_true',
help="Print all of the paths of the whole tree")
parser.add_argument("function", help="Function to build the code paths from")
args = parser.parse_args()
exclude = []
directories = []
if args.directory is not None:
directories = args.directory
if args.exclude is not None:
exclude = args.exclude
tree = CodeTree()
node = CodeNode(args.function)
tree.root = node
get_paths(tree, node, args.cscopedb, directories, exclude, args.duplicates)
sys.stderr.write("\nProccessed {} functions in {} seconds\n".format(tree.processed, tree.total))
sys.stderr.flush()
leaves = tree.paths()
lsorted = sorted(leaves, key=lambda x:len(x))
if args.tree:
print(tree)
else:
for i in lsorted:
print(i[-1])