mirror of
https://github.com/opentx/opentx.git
synced 2025-07-15 20:35:17 +03:00
182 lines
5.1 KiB
Python
182 lines
5.1 KiB
Python
#!/usr/bin/python
|
|
# vim: set fileencoding=utf-8
|
|
|
|
from clang.cindex import *
|
|
import asciitree # must be version 0.2
|
|
import sys
|
|
|
|
TOP_NODE_TYPES = [
|
|
CursorKind.ENUM_DECL,
|
|
CursorKind.STRUCT_DECL ]
|
|
|
|
CHILD_NODE_TYPES = [
|
|
CursorKind.FIELD_DECL,
|
|
CursorKind.UNION_DECL,
|
|
#CursorKind.STRUCT_DECL,
|
|
CursorKind.ENUM_CONSTANT_DECL ]
|
|
|
|
def filter_node(node):
|
|
if node is None:
|
|
return False
|
|
|
|
# # no node or no location
|
|
# if node is None or node.location is None or node.location.file is None:
|
|
# return False
|
|
|
|
# # not the main source file
|
|
# if node.location.file.name != sys.argv[1]:
|
|
# return False
|
|
|
|
if node.kind in CHILD_NODE_TYPES:
|
|
return True
|
|
|
|
return False
|
|
|
|
def get_struct_decl(node):
|
|
for c in node.get_children():
|
|
if c is not None and c.kind == CursorKind.STRUCT_DECL:
|
|
return c
|
|
return None
|
|
|
|
def node_children(node):
|
|
|
|
if node is None:
|
|
return []
|
|
|
|
if isinstance(node,list):
|
|
return node
|
|
|
|
if node.kind == CursorKind.FIELD_DECL:
|
|
if node.type.kind == TypeKind.ELABORATED:
|
|
return node_children(node.type.get_declaration())
|
|
elif node.type.kind == TypeKind.RECORD:
|
|
return list(c for c in node.type.get_fields())
|
|
elif node.type.kind == TypeKind.CONSTANTARRAY:
|
|
et = node.type.element_type
|
|
if et.kind == TypeKind.RECORD:
|
|
return list(c for c in et.get_fields())
|
|
elif node.type.kind == TypeKind.ENUM:
|
|
return node_children(node.type.get_declaration())
|
|
else:
|
|
print("{} {}".format(str(node.type.kind),node.spelling))
|
|
|
|
return list(c for c in node.get_children() if filter_node(c))
|
|
|
|
def get_array_size(f):
|
|
et = f.type.element_type
|
|
ec = f.type.element_count
|
|
if et.spelling == 'char':
|
|
return 'string({})'.format(ec)
|
|
else:
|
|
return '{} x {} bytes'.format(ec,et.get_size())
|
|
|
|
def get_field_size(f):
|
|
if f.is_bitfield():
|
|
return '{} bits'.format(f.get_bitfield_width())
|
|
elif f.type.kind == TypeKind.CONSTANTARRAY:
|
|
return get_array_size(f)
|
|
return '{} bytes'.format(f.type.get_size())
|
|
|
|
def print_field_decl(kind, text, f):
|
|
ft = ''
|
|
is_anon = f.is_anonymous()
|
|
if f.type.kind == TypeKind.RECORD:
|
|
decl = f.type.get_declaration()
|
|
if decl.kind == CursorKind.UNION_DECL:
|
|
if is_anon:
|
|
ft = 'anonymous union ({})'.format(decl.mangled_name)
|
|
else:
|
|
ft = 'union {}'.format(f.type.spelling)
|
|
elif decl.kind == CursorKind.STRUCT_DECL:
|
|
if is_anon:
|
|
ft = '{} anonymous struct'.format(f.kind)
|
|
else:
|
|
ft = 'struct {}'.format(f.type.spelling)
|
|
elif f.type.kind == TypeKind.TYPEDEF:
|
|
decl = f.type.get_canonical()
|
|
ft = decl.spelling
|
|
elif get_struct_decl(f) is not None:
|
|
ft = 'anon struct'
|
|
elif f.type.kind == TypeKind.CONSTANTARRAY:
|
|
et = f.type.element_type
|
|
ft = et.spelling
|
|
else:
|
|
ft = f.type.spelling
|
|
|
|
return '{} {} ({})'.format(ft, text, get_field_size(f))
|
|
|
|
def print_enum_decl(kind, text, e):
|
|
return '{} {} ({})'.format(kind, text, e.enum_value)
|
|
|
|
def print_union_decl(kind, text, f):
|
|
return '{} {} ({})'.format(kind, text, get_field_size(f))
|
|
|
|
def print_node(node):
|
|
|
|
if isinstance(node,list):
|
|
return 'ROOT'
|
|
|
|
text = node.spelling or node.displayname
|
|
kind = str(node.kind)[str(node.kind).index('.')+1:]
|
|
|
|
if CursorKind.FIELD_DECL == node.kind:
|
|
return print_field_decl(kind, text, node)
|
|
|
|
if CursorKind.ENUM_CONSTANT_DECL == node.kind:
|
|
return print_enum_decl(kind, text, node)
|
|
|
|
if CursorKind.UNION_DECL == node.kind:
|
|
return print_union_decl(kind, text, node)
|
|
|
|
return '{} {}'.format(kind, text)
|
|
|
|
def get_top_node(name, node):
|
|
for c in node.get_children():
|
|
if c.spelling == name:
|
|
# struct found
|
|
return c
|
|
|
|
print("get_top_node: '{}' not found!".format(name))
|
|
return None
|
|
|
|
def get_top_nodes(node):
|
|
l = list()
|
|
for c in node.get_children():
|
|
# no node or no location
|
|
if c is None or c.location is None or c.location.file is None:
|
|
continue
|
|
|
|
# not the main source file
|
|
if c.location.file.name != sys.argv[1]:
|
|
continue
|
|
|
|
if c.kind in TOP_NODE_TYPES:
|
|
# struct found
|
|
l.append(c)
|
|
|
|
return l
|
|
|
|
def print_top_node(name):
|
|
s = get_top_node(name, translation_unit.cursor)
|
|
if s is None:
|
|
return
|
|
print(asciitree.draw_tree(s, node_children, print_node))
|
|
|
|
def print_all():
|
|
s = get_top_nodes(translation_unit.cursor)
|
|
print(asciitree.draw_tree(s, node_children, print_node))
|
|
|
|
|
|
### Main ###
|
|
|
|
if len(sys.argv) < 3:
|
|
print("Usage: dump_ast_yaml.py [header file name] [top node] [additional compile args]")
|
|
sys.exit()
|
|
|
|
Config.set_library_file('/usr/local/Cellar/llvm/6.0.0/lib/libclang.dylib')
|
|
index = Index.create()
|
|
translation_unit = index.parse(sys.argv[1], ['-x', 'c++', '-std=c++11'] + sys.argv[3:])
|
|
|
|
print_top_node(sys.argv[2])
|
|
#print_top_node('CustomFunctionData')
|
|
#print_all()
|