#!/usr/bin/env python # ===-- IStatsSum.py ------------------------------------------------------===## # # The KLEE Symbolic Virtual Machine # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. # # ===----------------------------------------------------------------------===## from __future__ import division import sys, os def getSummary(input): inputs = [[None,iter(open(input))]] def getLine(elt): la,i = elt if la is None: try: ln = i.next() except StopIteration: ln = None except: raise ValueError("unexpected IO error") return ln else: elt[0] = None return la def getLines(): return map(getLine,inputs) def putback(ln,elt): assert elt[0] is None elt[0] = ln events = None # read header (up to ob=) while 1: lns = getLines() ln = lns[0] if ln.startswith('ob='): break else: if ln.startswith('positions:'): if ln!='positions: instr line\n': raise ValueError("unexpected 'positions' directive") elif ln.startswith('events:'): events = ln[len('events: '):].strip().split(' ') if events is None: raise ValueError('missing events directive') boolTypes = set(['Icov','Iuncov']) numEvents = len(events) eventTypes = [e in boolTypes for e in events] def readCalls(): results = {} for elt in inputs: while 1: ln = getLine(elt) if ln is not None and (ln.startswith('cfl=') or ln.startswith('cfn=')): if ln.startswith('cfl='): cfl = ln cfn = getLine(elt) if not cfn.startswith('cfn='): raise ValueError("unexpected cfl directive without function") else: cfl = None cfn = ln target = getLine(elt) if not target.startswith('calls='): raise ValueError("unexpected cfn directive with calls") stat = map(int,getLine(elt).strip().split(' ')) key = target existing = results.get(target) if existing is None: results[key] = [cfl,cfn,target,stat] else: if existing[0]!=cfl or existing[1]!=cfn: raise ValueError("multiple call descriptions for a single target") existing[3] = mergeStats([existing[3],stat]) else: putback(ln, elt) break return results summed = [0]*len(events) # read statistics while 1: lns = getLines() ln = lns[0] if ln is None: break elif ln.startswith('fn') or ln.startswith('fl'): pass elif ln.strip(): # an actual statistic data = [map(int,ln.strip().split(' ')) for ln in lns][0] summed = map(lambda a,b: a+b, data[2:], summed) # read any associated calls for cfl,cfn,calls,stat in readCalls().values(): pass return events,summed def main(args): from optparse import OptionParser op = OptionParser("usage: %prog [options] file") opts,args = op.parse_args() total = {} for i in args: events,summed = getSummary(i) for e,s in zip(events,summed): total[e] = total.get(e,[0,0]) total[e][0] += s total[e][1] += 1 print '-- %s --'%(i,) items = zip(events,summed) items.sort() for e,s in items: print '%s: %s'%(e,s) print '-- totals --' items = total.items() table = [] for e,(s,N) in items: table.append((str(e),str(s),str(N),str(s//N))) w = map(lambda l: max(map(len,l)), zip(*table)) for (a,b,c,d) in table: print '%-*s: %*s (in %*s files, avg: %*s)'%(w[0],a,w[1],b,w[2],c,w[3],d) if __name__=='__main__': main(sys.argv)