-
Notifications
You must be signed in to change notification settings - Fork 0
/
tsa_utils.py
151 lines (127 loc) · 5.01 KB
/
tsa_utils.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
#!/usr/bin/python3
import logging
def find_c_functions(root_node):
functions = []
for child in root_node.children:
if is_c_function(child):
functions.append(child)
return functions
def is_c_function(node, log=False):
result = (node.type == "function_definition")
if result and log:
func_decl = node.child_by_field_name("declarator")
name_decl = func_decl.child_by_field_name("declarator")
logging.debug("is_c_function found: %s", name_decl.text)
return result
def c_function_return_type(node):
assert(is_c_function(node))
return_type = node.child_by_field_name('type')
assert(return_type)
return return_type
def is_c_function_return_type(node, return_type):
fn_return = c_function_return_type(node)
if not fn_return:
return False
result = fn_return.text == bytes(return_type, "utf8")
if result:
logging.debug(" is_c_function_return_type found: %s", return_type)
return result
def c_function_parameter_count(node):
assert(is_c_function(node))
func_decl = node.child_by_field_name("declarator")
assert(func_decl)
param_list = func_decl.child_by_field_name("parameters")
assert(param_list)
params = [x for x in param_list.children if x.type == "parameter_declaration"]
return len(params)
def is_c_function_parameter_count(node, count):
param_count = c_function_parameter_count(node)
result = param_count == count
if result:
logging.debug(" is_c_function_parameter_count found: %d", count)
return result
def c_function_parameter_type(node, param_pos):
assert(is_c_function(node))
func_decl = node.child_by_field_name("declarator")
assert(func_decl)
param_list = func_decl.child_by_field_name("parameters")
assert(param_list)
params = [x for x in param_list.children if x.type == "parameter_declaration"]
assert(len(params) > param_pos)
target_param = params[param_pos].child_by_field_name("type")
assert(target_param)
return target_param
def c_function_name(node):
assert(is_c_function(node))
func_decl = node.child_by_field_name("declarator")
name_decl = func_decl.child_by_field_name("declarator")
return name_decl.text
def is_c_function_parameter_type(node, param_pos, param_type):
target_param = c_function_parameter_type(node, param_pos)
result = target_param.text == bytes(param_type, "utf8")
if result:
logging.debug(" is_c_function_parameter_type found: %d -> %s", param_pos, param_type)
return result
def is_lua_c_api_function(node):
return is_c_function(node, log=True) and \
is_c_function_return_type(node, "int") and \
is_c_function_parameter_count(node, 1) and \
is_c_function_parameter_type(node, 0, "lua_State")
def get_lua_c_api_functions(root_node):
return [x for x in find_c_functions(root_node) if is_lua_c_api_function(x)]
# FIXME: This only finds the first item at each level, which is likely not useful in most cases
def find_item_by_type_path(node, type_path):
logging.debug("find_item_by_type_path: %s", type_path)
result = None
to_search = node.children
last_found = None
while len(type_path) > 0:
found = False
target_type = type_path.pop(0)
logging.debug(" Next in path: %s", target_type)
for item in to_search:
logging.debug(" checking %s", item.type)
if item.type == target_type:
to_search = item.children
last_found = item
found = True
break
if not found:
logging.debug("find_item_by_type_path: Unable to find %s", target_type)
return None
return last_found
def find_node_children_of_type(node, target_type):
logging.debug("find_children_of_type: %s", target_type)
return [x for x in node.children if x.type == target_type]
def find_items_by_type_path(node, type_path):
logging.debug("find_items_by_type_path: %s", type_path)
def paths(tree):
if tree is None:
return([], [])
else:
root = tree
rooted_paths = [[root]]
unrooted_paths = []
for subtree in tree.children:
(useable, unuseable) = paths(subtree)
for path in useable:
unrooted_paths.append(path)
rooted_paths.append([root]+path)
for path in unuseable:
unrooted_paths.append(path)
return (rooted_paths, unrooted_paths)
a,b = paths(node)
all_paths = a+b
results = []
for path in all_paths:
if len(path) == len(type_path):
found = True
for i in range(0, len(type_path)):
if path[i].type != type_path[i]:
found = False
if found:
results.append(path)
logging.debug(" found matching path: %s", path)
return results
def is_text_in_item(item, text):
return (item and item.text.find(bytes(text, "utf8")) != -1)