Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Tools/c-analyzer/c_analyzer/match.py
12 views
1
import os.path
2
3
from c_parser import (
4
info as _info,
5
match as _match,
6
)
7
8
9
_KIND = _info.KIND
10
11
12
# XXX Use known.tsv for these?
13
SYSTEM_TYPES = {
14
'int8_t',
15
'uint8_t',
16
'int16_t',
17
'uint16_t',
18
'int32_t',
19
'uint32_t',
20
'int64_t',
21
'uint64_t',
22
'size_t',
23
'ssize_t',
24
'intptr_t',
25
'uintptr_t',
26
'wchar_t',
27
'',
28
# OS-specific
29
'pthread_cond_t',
30
'pthread_mutex_t',
31
'pthread_key_t',
32
'atomic_int',
33
'atomic_uintptr_t',
34
'',
35
# lib-specific
36
'WINDOW', # curses
37
'XML_LChar',
38
'XML_Size',
39
'XML_Parser',
40
'enum XML_Error',
41
'enum XML_Status',
42
'',
43
}
44
45
46
def is_system_type(typespec):
47
return typespec in SYSTEM_TYPES
48
49
50
##################################
51
# decl matchers
52
53
def is_public(decl):
54
if not decl.filename.endswith('.h'):
55
return False
56
if 'Include' not in decl.filename.split(os.path.sep):
57
return False
58
return True
59
60
61
def is_process_global(vardecl):
62
kind, storage, _, _, _ = _info.get_parsed_vartype(vardecl)
63
if kind is not _KIND.VARIABLE:
64
raise NotImplementedError(vardecl)
65
if 'static' in (storage or ''):
66
return True
67
68
if hasattr(vardecl, 'parent'):
69
parent = vardecl.parent
70
else:
71
parent = vardecl.get('parent')
72
return not parent
73
74
75
def is_fixed_type(vardecl):
76
if not vardecl:
77
return None
78
_, _, _, typespec, abstract = _info.get_parsed_vartype(vardecl)
79
if 'typeof' in typespec:
80
raise NotImplementedError(vardecl)
81
elif not abstract:
82
return True
83
84
if '*' not in abstract:
85
# XXX What about []?
86
return True
87
elif _match._is_funcptr(abstract):
88
return True
89
else:
90
for after in abstract.split('*')[1:]:
91
if not after.lstrip().startswith('const'):
92
return False
93
else:
94
return True
95
96
97
def is_immutable(vardecl):
98
if not vardecl:
99
return None
100
if not is_fixed_type(vardecl):
101
return False
102
_, _, typequal, _, _ = _info.get_parsed_vartype(vardecl)
103
# If there, it can only be "const" or "volatile".
104
return typequal == 'const'
105
106
107
def is_public_api(decl):
108
if not is_public(decl):
109
return False
110
if decl.kind is _KIND.TYPEDEF:
111
return True
112
elif _match.is_type_decl(decl):
113
return not _match.is_forward_decl(decl)
114
else:
115
return _match.is_external_reference(decl)
116
117
118
def is_public_declaration(decl):
119
if not is_public(decl):
120
return False
121
if decl.kind is _KIND.TYPEDEF:
122
return True
123
elif _match.is_type_decl(decl):
124
return _match.is_forward_decl(decl)
125
else:
126
return _match.is_external_reference(decl)
127
128
129
def is_public_definition(decl):
130
if not is_public(decl):
131
return False
132
if decl.kind is _KIND.TYPEDEF:
133
return True
134
elif _match.is_type_decl(decl):
135
return not _match.is_forward_decl(decl)
136
else:
137
return not _match.is_external_reference(decl)
138
139
140
def is_public_impl(decl):
141
if not _KIND.is_decl(decl.kind):
142
return False
143
# See filter_forward() about "is_public".
144
return getattr(decl, 'is_public', False)
145
146
147
def is_module_global_decl(decl):
148
if is_public_impl(decl):
149
return False
150
if _match.is_forward_decl(decl):
151
return False
152
return not _match.is_local_var(decl)
153
154
155
##################################
156
# filtering with matchers
157
158
def filter_forward(items, *, markpublic=False):
159
if markpublic:
160
public = set()
161
actual = []
162
for item in items:
163
if is_public_api(item):
164
public.add(item.id)
165
elif not _match.is_forward_decl(item):
166
actual.append(item)
167
else:
168
# non-public duplicate!
169
# XXX
170
raise Exception(item)
171
for item in actual:
172
_info.set_flag(item, 'is_public', item.id in public)
173
yield item
174
else:
175
for item in items:
176
if _match.is_forward_decl(item):
177
continue
178
yield item
179
180
181
##################################
182
# grouping with matchers
183
184
def group_by_storage(decls, **kwargs):
185
def is_module_global(decl):
186
if not is_module_global_decl(decl):
187
return False
188
if decl.kind == _KIND.VARIABLE:
189
if _info.get_effective_storage(decl) == 'static':
190
# This is covered by is_static_module_global().
191
return False
192
return True
193
def is_static_module_global(decl):
194
if not _match.is_global_var(decl):
195
return False
196
return _info.get_effective_storage(decl) == 'static'
197
def is_static_local(decl):
198
if not _match.is_local_var(decl):
199
return False
200
return _info.get_effective_storage(decl) == 'static'
201
#def is_local(decl):
202
# if not _match.is_local_var(decl):
203
# return False
204
# return _info.get_effective_storage(decl) != 'static'
205
categories = {
206
#'extern': is_extern,
207
'published': is_public_impl,
208
'module-global': is_module_global,
209
'static-module-global': is_static_module_global,
210
'static-local': is_static_local,
211
}
212
return _match.group_by_category(decls, categories, **kwargs)
213
214