使用 python脚本获取函数调用关系

来源:互联网 发布:ubuntu 16.04输入法 编辑:程序博客网 时间:2024/06/04 17:43

        函数关系调用图可使用TestBed或者Source Insight软件生成。本文工具所提取的函数调用关系,是为了方便编写详细设计文档,自动将该函数所有调用的函数列举出来。

首先上传代码流程图:


代码的第一部分是变量定义,

  1. 定义了keyWordList列表,列表中的关键字可以根据实际的项目进行调整
  2. 定义了两个正则表达式,第一个正则表达式用来提取包含括号的语句中,括号前的字段,这个字段有可能是函数名,或者是判断条件,或者是强制转换
  3. 第二个正则表达式用于判断语句中是否包含控制语句和判断条件


__author__ = 'Z'#coding:utf-8import osimport 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 = []


第二部分主函数,执行流程如下:

  1. 判断输入的源代码文件是否存在,路径合法则逐行读取;
  2. 判断该行是否以“/”开头,是注释行则跳过该行;
  3. 如果该行包含关键字“(”,且排除控制语句,且不以分号结果,则表明该行为函数定义行,提取函数名;
  4. 如果该行包含关键字“(”,提取所用“(”前的字段,与预先定义的关键字列表取差集,剩余字段则为被调用函数;
  5. 去除存储在列表中重复的被调用函数,并写入日志中。

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()

第三部分为两个辅助功能函数:

  1. listInString函数实现了判断列表中的元素是否存在于string中;
  2. 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  resultdef controlCaseInString(strLine):    if re.search(pControl,strLine) or ";" in strLine:        return True    else:return False

使用限制:

  1. 由于代码实现的是逐行读取处理,对于一条语句代码被分行书写的情况,可能会出现意外的错误;
  2. 由于注册函数的使用与变量使用类似,所以注册函数会被忽略。

0 0