使用 python指令碼獲取函式呼叫關係
阿新 • • 發佈:2018-11-17
函式關係調用圖可使用TestBed或者Source Insight軟體生成。本文工具所提取的函式呼叫關係,是為了方便編寫詳細設計文件,自動將該函式所有呼叫的函式列舉出來。
首先上傳程式碼流程圖:
程式碼的第一部分是變數定義,
- 定義了keyWordList列表,列表中的關鍵字可以根據實際的專案進行調整
- 定義了兩個正則表示式,第一個正則表示式用來提取包含括號的語句中,括號前的欄位,這個欄位有可能是函式名,或者是判斷條件,或者是強制轉換
- 第二個正則表示式用於判斷語句中是否包含控制語句和判斷條件
__author__ = 'Z' #coding:utf-8 import os import re keyWordList = [ 'break','continue', 'else', 'for','include', 'if', 'return', 'while','sizeof','int', 'float','bool','char','switch'] specialCase = ["("] commentCase =["/*","//"] p =re.compile('(?P<name>\w+)\s*\(') pControl =re.compile('\s*(for|if|else|switch|case|default|while|do)\s*\(') methodExtractResult = []
第二部分主函式,執行流程如下:
- 判斷輸入的原始碼檔案是否存在,路徑合法則逐行讀取;
- 判斷該行是否以“/”開頭,是註釋行則跳過該行;
- 如果該行包含關鍵字“(”,且排除控制語句,且不以分號結果,則表明該行為函式定義行,提取函式名;
- 如果該行包含關鍵字“(”,提取所用“(”前的欄位,與預先定義的關鍵字列表取差集,剩餘欄位則為被呼叫函式;
- 去除儲存在列表中重複的被呼叫函式,並寫入日誌中。
def main(): funName = "Out Of the Function" #輸入檔案判斷 filePath = input("請輸入原始檔路徑: \n") while False == os.path.isfile(filePath): print("檔案不存在,請檢查") filePath = input("請輸入原始檔路徑: \n") fd = open(filePath) for line in fd: line = line.strip().strip('\n') if listInString(line[0:2],commentCase): #首先排除註釋行 pass elif listInString(line,specialCase) and (controlCaseInString(line) == False): #不含控制語句的關鍵字和和分號,且包含關鍵字“(”,判斷為函式定義行,提取函式名 mMethod = re.search(p,line) if mMethod: methodName = mMethod.groups("name") funName = methodName[0] else: #line中包含了關鍵字或者分號 mLineList = re.findall(p,line) #list取差集,排除關鍵字 methodList = list(set(mLineList).difference(set(keyWordList))) if methodList: for methodInList in methodList: methodExtractResult.append(funName + ":"+ methodInList) #print (funName + ":"+ methodInList) logfile = open(os.getcwd() + r'\\' + 'methodExtract.txt','w') try: #去除重複行 methodExtractResultWithNoRepeat = [] for elem in methodExtractResult: if elem not in methodExtractResultWithNoRepeat: methodExtractResultWithNoRepeat.append(elem) print (elem) logfile.write(elem + "\n") finally: logfile.close() fd.close()
第三部分為兩個輔助功能函式:
- listInString函式實現了判斷列表中的元素是否存在於string中;
- controlCaseInString函式實現利用正則判斷sting中是否包含的關鍵欄位。
def listInString(strLine, listJar):
result = False
if isinstance(listJar, list):
for item in listJar:
if item in strLine:
result = True
break
else:
result = False
return result
def controlCaseInString(strLine):
if re.search(pControl,strLine) or ";" in strLine:
return True
else:return False
使用限制:
- 由於程式碼實現的是逐行讀取處理,對於一條語句程式碼被分行書寫的情況,可能會出現意外的錯誤;
- 由於註冊函式的使用與變數使用類似,所以註冊函式會被忽略。