C言語のソースコードを解析するプログラムを作成します。
私は日々の業務を自動化したいと企む組み込みエンジニアです。
完成コード
ここを開くと完成形のpythonコードが表示されます。
main.py
import glob
import search.func as searchfunc
class FuncNode:
def __init__(self, name):
self.name = name
self.children = []
def add_child(self, child_node):
self.children.append(child_node)
def main():
# 対象のファイルリストを作成.
filelist = glob.glob("**/*.c", recursive=True)
codetree = make_code_tree(filelist, "main")
codetree_text = []
print_code_tree(codetree, codetree_text)
with open("OUTPUT_TREE.txt", "w") as file_obj:
file_obj.writelines(codetree_text)
def make_code_tree(prj_filelist:list, root_funcname:str)->FuncNode:
current_node = None
for target_file in prj_filelist:
with open(target_file, "r", encoding="utf-8", errors="ignore") as file_obj:
codedata = file_obj.read()
functext = searchfunc.gettext(codedata, root_funcname)
if functext:
current_node = FuncNode(root_funcname)
call_funcs = searchfunc.find_call_funcs(functext)
for called_func in call_funcs:
child_node = make_code_tree(prj_filelist, called_func)
if child_node:
current_node.add_child(child_node)
break
return current_node
def print_code_tree(codetree:FuncNode, output_list:list = None, callstack:str = ""):
if callstack != "":
callstack += "->"
callstack += codetree.name
for child in codetree.children:
print_code_tree(child, output_list, callstack)
print(callstack)
if output_list != None:
output_list.append(callstack + "\n")
if __name__ == "__main__":
main()
func.py
import regex
import re
def gettext(text:str, funcname:str)->str:
ret = None
pattern = r"(?:(?:auto|register|static|extern)\s+)?(?:(?:const|volatile|restrict|signed|unsigned|short|long)\s+)*\w+\s+" + funcname + r"\s*\([^()]*\)\s*(\{([^{}]|(?1))*\})"
match = regex.search(pattern, text, regex.DOTALL)
if match:
ret = match.group()
return ret
def find_call_funcs(text:str)->str:
# 関数の処理のみ抽出(関数名など"{"の前は削除してから検索を行う)
index = text.find("{")
if index != -1:
funcproc_text = text[index:]
else:
funcproc_text = text
return re.findall("\w+\s*(?=\([^()]*\))", funcproc_text, re.DOTALL)
解説
プログラムの流れ
ソースツリー作成プログラムの大まかな流れです。
ファイルリストからソースツリーを作成する処理は関数の再帰呼び出しによって実現します。ファイルリストからmain
関数を探します。このとき正規表現により検索を行い、関数名から処理内容まですべて抽出します。