#!/usr/bin/env python from pydot import * class Record(Node): def __init__(self,name,**attrs): Node.__init__(self,name,**attrs) self.set("shape","record"); class CodeSegment(Record): def __init__(self,name): Record.__init__(self,name) self.no_parent = True; self.sub_name=name; self.plist=() self.locals=() class SubProgram(CodeSegment): def __init__(self,name,plist,locals_list,parent): CodeSegment.__init__(self,name) self.no_parent = False self.parent=parent self.plist = plist self.locals = locals_list class ActivationRecord(Record): def __init__(self,prog,funcname,count,dynparent="null"): self.ari_name=(funcname + str(count)) Record.__init__(self,self.ari_name) self.funcname=funcname self.dynparent=dynparent self.program = prog self.param_count = len(prog.subs[funcname].plist) class ARIcontents: def __init__(self): self.referables=[] def add(self,port,label): self.referables.append((port,label)) def dotLabel(self): lstr="" joiner = "" for (port,label) in self.referables: lstr = lstr + joiner + " <" + port + "> " + label joiner = " | " return lstr def getPort(self,index): (port,label) = self.referables[index] return port self.ARI_fields = ARIcontents() self.ARI_fields.add("radr","return_addr") self.ARI_fields.add("slink","static_link") self.ARI_fields.add("dlink","dynamic_link") #self.ARI_fields.add("parameters","parameters") for p in prog.subs[funcname].plist: self.ARI_fields.add("p_"+p,"parameter: "+p) #self.ARI_fields.add("locals","locals") for l in prog.subs[funcname].locals: self.ARI_fields.add("l_"+l,"local: "+l) self.ARI_fields.add("func_val","functional_value") self.set("label",self.ARI_fields.dotLabel()) class Program: def __init__(self,label_ari=False): self.label_ari = label_ari self.subs={} self.top_ar={} self.ar_count={} self.g = Dot(ranksep="0.25",compound="true",rankdir="LR",nodesep="0"); self.code = Cluster(graph_name="Code",label="Code Segment",color="white") self.stack = Cluster(graph_name="Stack",label="Stack Segment",color="white") self.g.add_subgraph(self.code) self.g.add_subgraph(self.stack) self.Main = CodeSegment("main") self.add_sub_obj(self.Main) self.call("null","main") def add_sub_obj(self,sub): self.subs[sub.sub_name]=sub self.ar_count[sub.sub_name]=0 self.code.add_node(sub) def add_sub(self,sub_name,param_list,locals_list,static_parent): sub = SubProgram(sub_name,param_list,locals_list,self.subs[static_parent]) self.add_sub_obj(sub) def write(self,foo): self.g.write(foo) def call(self,caller_name,callee_name): act_rec = ActivationRecord(self,callee_name,self.ar_count[callee_name],caller_name) self.ar_count[callee_name]=self.ar_count[callee_name]+1; if(self.label_ari): identified_frame = Cluster(graph_name=act_rec.ari_name, label=callee_name, labelloc="lt", labeljust="l") identified_frame.add_node(act_rec) self.stack.add_subgraph(identified_frame) else: self.stack.add_node(act_rec) if(caller_name != "null"): ret_addr = Edge(act_rec.ari_name+":radr",caller_name) self.g.add_edge(ret_addr) dyn_link = Edge(act_rec.ari_name+":dlink",self.top_ar[caller_name].ari_name+":radr",constraint="false") self.g.add_edge(dyn_link) callee_code = self.subs[callee_name] callee_parent = callee_code.parent stat_parent_name = callee_parent.sub_name stat_link = Edge(act_rec.ari_name+":slink",self.top_ar[stat_parent_name].ari_name+":radr",constraint="false",tailport="n") self.g.add_edge(stat_link) self.top_ar[act_rec.funcname]=act_rec def localRef(self,subprogram,offset): act_rec = self.top_ar[subprogram] rec_name = act_rec.ari_name port = act_rec.ARI_fields.getPort(offset) return (rec_name + ":" + port) def staticRef(self,subprogram,chain_offset,local_offset): act_rec = self.top_ar[subprogram] for count in range(chain_offset): pass # What was I trying to do here? def show(self): self.g.write_ps("tmp") import commands commands.getoutput("gv tmp") P = Program(True) P.add_sub("foo",("a", "b", "c"),("char bob",),"main") P.add_sub("bar",(),("int this", "int that"),"foo") P.add_sub("baz",(),(),"bar") P.call("main","foo") P.call("foo","foo") P.call("foo","bar") P.call("bar","baz") P.call("foo","foo") P.write("./sgen.dot") #print P.ref("foo",4) P.show()