0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C言語のコードを解析 ~ ソースツリーの作り方

Posted at

C言語のソースコードを解析するプログラムを作成します。
私は日々の業務を自動化したいと企む組み込みエンジニアです。:smiling_imp:

完成コード

ここを開くと完成形の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関数を探します。このとき正規表現により検索を行い、関数名から処理内容まですべて抽出します。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?