call graph using python and cscope

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Roland Puntaier

    #1

    call graph using python and cscope

    """
    Sometimes it is nice to have the data used by cscope accessible in a
    programatic way.
    The following python script extract the "functions called" information
    from cscope (function: callGraph)
    and produced an html file from them.

    from csCallGraph import *
    acg=callGraph(e ntryFun,working Dir)

    entryFun is the function to start with (e.g. main)
    workingDir is the directory where cscope.out is located

    As a script it can be called like:
    csCallGraph main myprogram.html
    """

    import subprocess , os, sys

    def functionsCalled (entryFun,worki ngDir):
    cmd = "cscope -d -l -L -2%s"%entryFun
    process = subprocess.Pope n(cmd, stdout=subproce ss.PIPE, shell=True,
    cwd=workingDir)
    csoutput= process.stdout. read()
    del process
    cslines=[arr.strip().spl it(' ') for arr in csoutput.split( '\n') if
    len(arr.split(' '))>1]
    funsCalled={}
    for fl in cslines:
    if funsCalled.has_ key(fl[0]):
    funsCalled[fl[0]]|=set([fl[1]])
    else:
    funsCalled[fl[0]]=set([fl[1]])
    allFuns=set(map (lambda x:x[1],cslines))
    return (allFuns,funsCa lled)

    def callGraph(entry Fun,workingDir, cg={}):
    if not cg.has_key(entr yFun):
    allFuns,funsCal led=functionsCa lled(entryFun,w orkingDir)
    cg[entryFun]=funsCalled
    for af in allFuns:
    cg=callGraph(af ,workingDir,cg)
    return cg

    def textCallGraph(a cg):
    innerFuns=[(f,d,len(reduce (lambda x,y:x|y,d.value s()))) for f,d in
    acg.items() if len(d)>0 ]
    leafFuns=[(f,d,0) for f,d in acg.items() if not len(d)>0 ]
    innerFuns.sort( lambda x,y: y[2]-x[2])
    innerLen=len(in nerFuns)
    leafLen=len(lea fFuns)
    title=lambda aFun: '\n' + aFun + '\n' + '-'*len(aFun)
    def ff(aFun,funsCal led):
    fileFuns=zip(fu nsCalled.keys() ,[' '+',\n '.join(funsCall edInFile)
    for funsCalledInFil e in funsCalled.valu es()])
    funIn=lambda f: '\n%s in '%f
    return title(aFun) + funIn(aFun) + funIn(aFun).joi n(map(lambda
    x:'%s:\n%s'%(x[0],x[1]),fileFuns))
    strInner='\n'.j oin([ff(f[0],f[1]) for f in innerFuns])
    strLeaves='\n'. join(map(lambda x:title(x[0]),leafFuns))
    return strInner+'\n'+s trLeaves

    def funWeights(acg) :
    funWeights=dict ([(f,reduce(lambd a x,y:x|y,d.value s())) for f,d in
    acg.items() if len(d)>0 ]+
    [(f,[]) for f,d in acg.items() if not len(d)>0 ])
    weights={}
    def calcWeights(af) :
    if not weights.has_key (af):
    subFuns=funWeig hts[af]
    weights[af]=1
    for f in subFuns:
    calcWeights(f)
    weights[af]+=weights[f]
    for af in funWeights.keys (): calcWeights(af)
    return weights

    def htmlCallGraph(a cg):
    funW=funWeights (acg)
    innerFuns=[(f,d,funW[f]) for f,d in acg.items() if len(d)>0 ]
    leafFuns=[(f,d,0) for f,d in acg.items() if not len(d)>0 ]
    #innerFuns.sort (lambda x,y: y[2]-x[2]))
    def cfun(a,b):
    if b a:
    return 1
    elif b < a:
    return -1
    return 0
    innerFuns.sort( lambda x,y: cfun(x[2],y[2]))
    innerLen=len(in nerFuns)
    leafLen=len(lea fFuns)
    funDict=dict(zi p(map(lambda x:x[0],innerFuns)+map (lambda
    x:x[0],leafFuns),rang e(innerLen+leaf Len)))
    title=lambda aFun: '<hr><h4><a name=#f%i'%funD ict[aFun]+'>' + aFun + '
    (%i)'%funW[aFun] + '</a></h4>\n'
    def ff(aFun,funsCal led):
    fun=lambda y:'<a href=#f%i'%funD ict[y]+'
    style="text-decoration:none ">'+y+'</a>'
    fileFuns=zip(fu nsCalled.keys() ,[',\n'.join(map( fun,funsCalledI nFile))
    for funsCalledInFil e in funsCalled.valu es()])
    funIn=lambda f: '<br><em>%s</emin '%f
    return title(aFun) + funIn(aFun) + funIn(aFun).joi n(map(lambda
    x:'%s:\n%s'%(x[0],x[1]),fileFuns))
    strInner='\n'.j oin([ff(f[0],f[1]) for f in innerFuns])
    strLeaves='\n'. join(map(lambda x:title(x[0]),leafFuns))
    return '<html>\n<body> \n'+strInner+'\ n'+strLeaves+"</body>\n</html>\n"

    if __name__ == '__main__':
    if len(sys.argv) < 2:
    print 'Usage: csGragh.py entryFunction'
    sys.exit()
    entryFun=sys.ar gv[1]
    workingDir=os.g etcwd()
    acg=callGraph(e ntryFun,working Dir)
    print htmlCallGraph(a cg)
Working...