You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
7.4 KiB
289 lines
7.4 KiB
# -*- coding: utf-8 -*-
|
|
import os
|
|
|
|
from . import utils
|
|
|
|
|
|
def extract_forward_declarations(data):
|
|
def filter(item):
|
|
if (item["is_definition"] == False
|
|
and item["kind"] == "CursorKind.STRUCT_DECL"
|
|
):
|
|
return True
|
|
|
|
def xform(item):
|
|
return item
|
|
|
|
return utils.recursive_query(data, filter, xform)
|
|
|
|
|
|
def extract_vars_named(data, var_names):
|
|
def filter(item):
|
|
if (item["kind"] == "CursorKind.VAR_DECL"
|
|
and item["name"] in var_names
|
|
):
|
|
return True
|
|
|
|
def xform(item):
|
|
return item
|
|
|
|
found = utils.recursive_query(data, filter, xform)
|
|
|
|
found_names = []
|
|
for i in found:
|
|
found_names.append(i["name"])
|
|
|
|
notfound_names = []
|
|
for name in var_names:
|
|
if not name in found_names:
|
|
notfound_names.append(name)
|
|
|
|
return (found, notfound_names)
|
|
|
|
|
|
def extract_functions_named(data, function_names):
|
|
def filter(item):
|
|
if (item["kind"] == "CursorKind.FUNCTION_DECL"
|
|
and item["name"] in function_names
|
|
):
|
|
return True
|
|
|
|
def xform(item):
|
|
return item
|
|
|
|
found = utils.recursive_query(data, filter, xform)
|
|
|
|
found_names = []
|
|
for i in found:
|
|
found_names.append(i["name"])
|
|
|
|
notfound_names = []
|
|
for name in function_names:
|
|
if not name in found_names:
|
|
notfound_names.append(name)
|
|
|
|
return (found, notfound_names)
|
|
|
|
|
|
# just the typenames of all typerefs no dups
|
|
def collect_all_typerefs(data):
|
|
def filter(item):
|
|
if (item["kind"] == "CursorKind.TYPE_REF"
|
|
):
|
|
return True
|
|
|
|
def xform(item):
|
|
return item["type"]
|
|
|
|
results = utils.recursive_query(data, filter, xform)
|
|
no_dups = list(set(results))
|
|
return no_dups
|
|
|
|
|
|
def extract_type_names(data):
|
|
def filter(item):
|
|
if (item["kind"] == "CursorKind.TYPEDEF_DECL"
|
|
or item["kind"] == "CursorKind.ENUM_DECL"
|
|
or item["kind"] == "CursorKind.STRUCT_DECL"
|
|
):
|
|
return True
|
|
|
|
def xform(item):
|
|
ret = item["type"]
|
|
return ret
|
|
|
|
return utils.recursive_query(data, filter, xform)
|
|
|
|
|
|
def resolve_typerefs(ast, typeref_names):
|
|
types = []
|
|
typeref_resolved = []
|
|
typeref_notfound = []
|
|
|
|
for typeref_name in typeref_names:
|
|
res = resolve_typeref(ast, typeref_name)
|
|
if not res:
|
|
typeref_notfound.append(typeref_name)
|
|
else:
|
|
types.append(res)
|
|
typeref_resolved.append(typeref_name)
|
|
|
|
return (types, typeref_resolved, typeref_notfound)
|
|
|
|
|
|
def resolve_typeref(ast, typeref_name):
|
|
ret = None
|
|
|
|
ret = extract_enum_decl(ast, typeref_name)
|
|
if not ret:
|
|
ret = extract_struct_decl(ast, typeref_name)
|
|
if not ret:
|
|
ret = extract_typedef_decl(ast, typeref_name)
|
|
|
|
return ret
|
|
|
|
|
|
def extract_enum_decl(ast, name):
|
|
ret = None
|
|
|
|
def filter(data):
|
|
if (data["kind"] == "CursorKind.ENUM_DECL"
|
|
and data["is_definition"] == True # no forward decl
|
|
and data["type"] == name
|
|
):
|
|
return True
|
|
|
|
res = utils.recursive_query(ast, filter)
|
|
if len(res) > 1:
|
|
assert False, "duplicate definition"
|
|
if len(res) == 1:
|
|
ret = res[0]
|
|
|
|
return ret
|
|
|
|
|
|
def extract_struct_decl(ast, name):
|
|
ret = None
|
|
|
|
def filter(data):
|
|
if (data["kind"] == "CursorKind.STRUCT_DECL"
|
|
and data["is_definition"] == True # no forward decl
|
|
and data["type"] == name
|
|
):
|
|
return True
|
|
|
|
res = utils.recursive_query(ast, filter)
|
|
if len(res) > 1:
|
|
assert False, "duplicate definition"
|
|
if len(res) == 1:
|
|
ret = res[0]
|
|
|
|
return ret
|
|
|
|
|
|
def extract_typedef_decl(ast, name):
|
|
ret = None
|
|
|
|
def filter(data):
|
|
if (data["kind"] == "CursorKind.TYPEDEF_DECL"
|
|
and data["type"] == name
|
|
):
|
|
return True
|
|
|
|
res = utils.recursive_query(ast, filter)
|
|
if res:
|
|
ret = res.pop()
|
|
|
|
if ret["utypekind"] == "Typedef":
|
|
ret = extract_typedef_decl(ast, ret["utype"])
|
|
elif ret["utypekind"] == "Elaborated":
|
|
enum_decl = extract_enum_decl(ast, ret["utype"])
|
|
struct_decl = extract_struct_decl(ast, ret["utype"])
|
|
if enum_decl and struct_decl:
|
|
assert False, "duplicate types"
|
|
else:
|
|
ret = enum_decl or struct_decl
|
|
|
|
return ret
|
|
|
|
# TODO: move to tests
|
|
def find_dup_types(data):
|
|
def filter(item):
|
|
if (item["kind"] == "CursorKind.STRUCT_DECL"
|
|
or item["kind"] == "CursorKind.ENUM_DECL"):
|
|
return True
|
|
|
|
def xform(item):
|
|
return item["type"]
|
|
|
|
all_types = utils.recursive_query(data, filter, xform)
|
|
dups = set()
|
|
for type in all_types:
|
|
if all_types.count(type) > 1:
|
|
dups.add(type)
|
|
|
|
return (all_types, list(dups))
|
|
|
|
|
|
# TODO: Check for primitive type
|
|
def remove_typedefs_of_primitive(types):
|
|
types_struct_enum = []
|
|
for type in types:
|
|
if (type["kind"] == "CursorKind.TYPEDEF_DECL"):
|
|
pass
|
|
else:
|
|
types_struct_enum.append(type)
|
|
|
|
return types_struct_enum
|
|
|
|
|
|
def extract_cid_selectively(ast, var_names, function_names):
|
|
# CDL
|
|
cid = {"functions": "",
|
|
"vars": "",
|
|
"types": ""}
|
|
|
|
# stage 1: extract functions and vars
|
|
(cid["functions"], cid["functions_notfound"]) = extract_functions_named(ast, function_names)
|
|
(cid["vars"], cid["vars_notfound"]) = extract_vars_named(ast, var_names)
|
|
|
|
# stage 2: collect type refs
|
|
cid["types"] = []
|
|
typerefs_unresolved = []
|
|
cid["typerefs_resolved"] = []
|
|
cid["typerefs_notfound"] = []
|
|
|
|
while True:
|
|
typerefs_unresolved = collect_all_typerefs(cid) # only list of typenames
|
|
typerefs_unresolved = list(set(typerefs_unresolved) - (set(cid["typerefs_resolved"]).union(set(cid["typerefs_notfound"]))))
|
|
if (len(typerefs_unresolved) <= 0):
|
|
break
|
|
|
|
(types, typerefs_resolved, notfound) = resolve_typerefs(ast, typerefs_unresolved)
|
|
cid["types"] += types
|
|
cid["typerefs_resolved"] += typerefs_resolved
|
|
cid["typerefs_notfound"] += notfound
|
|
|
|
|
|
cid["types"] = remove_typedefs_of_primitive(cid["types"])
|
|
cid["type_names"] = extract_type_names(cid["types"])
|
|
|
|
return cid
|
|
|
|
|
|
def extract_cid_all(ast, function_names, var_names):
|
|
pass
|
|
|
|
|
|
# generates simple-ast for each header specified in spec out dir.
|
|
# def main_old():
|
|
# parser = ASTParser("/opt/local/libexec/llvm-9.0/lib/libclang.dylib")
|
|
#
|
|
# in_dir = r"/Users/heck/local-default/include/pEp/"
|
|
# filenames = ["pEpEngine.h",
|
|
# "keymanagement.h",
|
|
# "message_api.h",
|
|
# "message.h",
|
|
# "sync_api.h",
|
|
# "key_reset.h",
|
|
# "Identity.h",
|
|
# "Rating.h"]
|
|
#
|
|
# out_dir = "data/output"
|
|
#
|
|
# paths = join_dir_and_filenames(in_dir, filenames)
|
|
#
|
|
# headers = []
|
|
# for path in paths:
|
|
# headers.append(create_header(path, out_dir))
|
|
#
|
|
# for header in headers:
|
|
# print("processing path: " + header["path"] + "...")
|
|
# header["ast"] = parser.parse(header["path"], header["sourcecode"])
|
|
# write_json(header["ast"], header["out_dir"] + "/" + header["filename"] + ".ast.json")
|
|
#
|
|
# simpleAst = SimpleAST()
|
|
# header["simple_ast"] = simpleAst.create_simple_ast(header["ast"])
|
|
# write_json(header["simple_ast"], header["out_dir"] + "/" + header["filename"] + ".simple_ast.json")
|
|
#
|
|
#
|
|
|