diff --git a/gen/gen_cid/__init__.py b/gen/gen_cid/__init__.py index fe40614..261ea33 100644 --- a/gen/gen_cid/__init__.py +++ b/gen/gen_cid/__init__.py @@ -1,3 +1,56 @@ # -*- coding: utf-8 -*- -from . import generate_cid +from . import c_2_ast +from . import ast_2_cid +from . import cid_2_yml +from . import utils + +import os + + +class CIDTools: + + def __init__(self, libclang_path, header_filename, out_dir=None): + self.header = self._create_header(header_filename, out_dir) + self.c2ast = c_2_ast.C2AST(libclang_path) + + # out-dir is in-dir if not specified + def _create_header(self, path, out_dir=None): + header = {"path": "", + "dir": "", + "filename": "", + "out_dir": "", + "sourcecode": "", + "ast": "", + "cid": "", + "yml": ""} + + header["path"] = path + header["dir"] = os.path.dirname(path) + header["filename"] = os.path.basename(path) + + header["out_dir"] = header["dir"] + if out_dir: + header["out_dir"] = out_dir + + header["sourcecode"] = utils.read_file(path) + return header + + + def extract(self, var_names, func_names, debug_ast=False, debug_cid=False, debug_yml=False): + # ast + self.header["ast"] = self.c2ast.parse(self.header["path"], follow_includes=True) + if debug_ast: + utils.write_json(self.header["ast"], self.header["out_dir"] + "/" + self.header["filename"] + ".ast.json") + + # cid + self.header["cid"] = ast_2_cid.extract_cid_selectively(self.header["ast"], var_names, func_names) + if debug_cid: + utils.write_json(self.header["cid"], self.header["out_dir"] + "/" + self.header["filename"] + ".cid.json") + + # yml + self.header["yml"] = cid_2_yml.generate_yml(self.header["cid"]) + if debug_yml: + utils.write_string(self.header["yml"], self.header["out_dir"] + "/" + self.header["filename"] + ".cid.yml") + + return self.header diff --git a/gen/gen_cid/generate_cid.py b/gen/gen_cid/ast_2_cid.py similarity index 85% rename from gen/gen_cid/generate_cid.py rename to gen/gen_cid/ast_2_cid.py index 2aa1fdc..1f7776d 100755 --- a/gen/gen_cid/generate_cid.py +++ b/gen/gen_cid/ast_2_cid.py @@ -1,30 +1,9 @@ # -*- coding: utf-8 -*- import os -from . import ast_parser from . import utils -# out-dir is in-dir if not specified -def create_header(path, out_dir=None): - header = {"path": "", - "dir": "", - "filename": "", - "out_dir": "", - "sourcecode": ""} - - header["path"] = path - header["dir"] = os.path.dirname(path) - header["filename"] = os.path.basename(path) - - header["out_dir"] = header["dir"] - if out_dir: - header["out_dir"] = out_dir - - header["sourcecode"] = utils.read_file(path) - return header - - def extract_forward_declarations(data): def filter(item): if (item["is_definition"] == False @@ -207,7 +186,7 @@ def extract_typedef_decl(ast, name): return ret - +# TODO: move to tests def find_dup_types(data): def filter(item): if (item["kind"] == "CursorKind.STRUCT_DECL" @@ -238,35 +217,29 @@ def remove_typedefs_of_primitive(types): return types_struct_enum -def parse(libclang_path, header_filename, function_names, var_names, debug_ast=False): - astp = ast_parser.ASTParser(libclang_path) - # header = create_header("/Users/heck/local-default/include/pEp/pEpEngine.h", out_dir="./") - header = create_header(header_filename) - header["ast"] = astp.parse(header["path"], follow_includes=True) - if debug_ast: - utils.write_json(header["ast"], header["out_dir"] + "/" + header["filename"] + ".ast.json") +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(header["ast"], function_names) - (cid["vars"], cid["vars_notfound"]) = extract_vars_named(header["ast"], var_names) + (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(header["ast"], typerefs_unresolved) + (types, typerefs_resolved, notfound) = resolve_typerefs(ast, typerefs_unresolved) cid["types"] += types cid["typerefs_resolved"] += typerefs_resolved cid["typerefs_notfound"] += notfound @@ -274,8 +247,13 @@ def parse(libclang_path, header_filename, function_names, var_names, debug_ast=F cid["types"] = remove_typedefs_of_primitive(cid["types"]) cid["type_names"] = extract_type_names(cid["types"]) - header["cid"] = cid - return header + + 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(): diff --git a/gen/gen_cid/ast_parser.py b/gen/gen_cid/c_2_ast.py similarity index 99% rename from gen/gen_cid/ast_parser.py rename to gen/gen_cid/c_2_ast.py index 1944c74..68557e7 100644 --- a/gen/gen_cid/ast_parser.py +++ b/gen/gen_cid/c_2_ast.py @@ -3,7 +3,7 @@ import clang.cindex from clang.cindex import CursorKind -class ASTParser: +class C2AST: def __init__(self, library_file): if not clang.cindex.Config.loaded: print("Using libclang from: %s", library_file) diff --git a/gen/gen_cid/utils.py b/gen/gen_cid/utils.py index 9870a7a..385fd33 100644 --- a/gen/gen_cid/utils.py +++ b/gen/gen_cid/utils.py @@ -15,7 +15,7 @@ def read_file(path): file_content = f.read() return file_content -def write_file(path, data): +def write_string(data, path): with open(path, "w+") as f: f.write(data)