import clang.cindex as cindex from pathlib import Path
# folder of libclang.so, found in step 0.5 cindex.Config.library_path = "/usr/lib"
file = Path("test.c") parser = cindex.Index.create() tu = parser.parse(file.absolute())
for node in tu.cursor.get_children(): node: cindex.Cursor = node # for type hint ifnotstr(node.location.file).endswith(".c"): # if no need to dive into header files continue print(node.kind, node.spelling, node.extent.start)
1.1 从 CALL_EXPR 取调用的方法名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
deffind_function_name_in_CALL_EXPR(node: cindex.Cursor) -> str: assert node.kind == cindex.CursorKind.CALL_EXPR tmp = next(node.get_children()) if tmp.kind == cindex.CursorKind.DECL_REF_EXPR: DEBUG(f"Fall back to DECL_REF_EXPR {tmp.spelling}{tmp.kind}{tmp.extent.start}") name = tmp.spelling else: childs = [c for c in tmp.get_children()] # panic_if_not(len(childs) == 1, childs) iflen(childs) != 1: returnNone if childs[0].kind != cindex.CursorKind.DECL_REF_EXPR: DEBUG(f"(Skip indirect calling)UB in parse {childs[0].spelling}{childs[0].kind}{childs[0].extent.start}") returnNone name = childs[0].spelling return name
1.2 取方法中调用的方法名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defparse_function(node: cindex.Cursor) -> set[str]: assert node.kind == cindex.CursorKind.FUNCTION_DECL dep_funcs = set() func_body = [n for n in node.get_children() if n.kind == cindex.CursorKind.COMPOUND_STMT] iflen(func_body) == 0: # Can be forward-decline DEBUG(f"not found body, can be forward-decline {node.spelling}") return dep_funcs assertlen(func_body) == 1 func_body: cindex.Cursor = func_body[0] for child in func_body.walk_preorder(): child: cindex.Cursor = child # for type hint if child.kind == cindex.CursorKind.CALL_EXPR: name = find_function_name_in_CALL_EXPR(child) dep_funcs.add(name) return dep_funcs