import sys
from unpickle import Unpickler
+from highlight import ColorHighlighter, LessHighlighter
ignoredFunctionNames = set([
self.calls = []
def handleCall(self, call):
- call.no = None
- hash(call)
if call.functionName not in ignoredFunctionNames:
self.calls.append(call)
+ hash(call)
-def readtrace(trace):
+def readtrace(trace, calls):
p = subprocess.Popen(
args = [
options.apitrace,
'pickle',
- '--calls=' + options.calls,
+ '--symbolic',
+ '--calls=' + calls,
trace
],
stdout = subprocess.PIPE,
class SDiffer:
- def __init__(self, a, b):
+ def __init__(self, a, b, highlighter, callNos = False):
self.a = a
self.b = b
+ self.highlighter = highlighter
+ self.delete_color = highlighter.red
+ self.insert_color = highlighter.green
+ self.callNos = callNos
+ self.aSpace = 0
+ self.bSpace = 0
def diff(self):
- matcher = difflib.SequenceMatcher(None, self.a, self.b)
+ matcher = difflib.SequenceMatcher(self.isjunk, self.a, self.b)
for tag, alo, ahi, blo, bhi in matcher.get_opcodes():
if tag == 'replace':
self.replace(alo, ahi, blo, bhi)
elif tag == 'delete':
- self.delete(alo, ahi)
+ self.delete(alo, ahi, blo, bhi)
elif tag == 'insert':
- self.insert(blo, bhi)
+ self.insert(alo, ahi, blo, bhi)
elif tag == 'equal':
- self.equal(alo, ahi)
+ self.equal(alo, ahi, blo, bhi)
else:
raise ValueError, 'unknown tag %s' % (tag,)
+ def isjunk(self, call):
+ return call.functionName == 'glGetError' and call.ret in ('GL_NO_ERROR', 0)
+
def replace(self, alo, ahi, blo, bhi):
assert alo < ahi and blo < bhi
if tag == 'replace':
self.replace_dissimilar(_alo, _ahi, _blo, _bhi)
elif tag == 'delete':
- self.delete(_alo, _ahi)
+ self.delete(_alo, _ahi, _blo, _bhi)
elif tag == 'insert':
- self.insert(_blo, _bhi)
+ self.insert(_alo, _ahi, _blo, _bhi)
elif tag == 'equal':
self.replace_similar(_alo, _ahi, _blo, _bhi)
else:
assert alo < ahi and blo < bhi
assert ahi - alo == bhi - blo
for i in xrange(0, bhi - blo):
+ self.highlighter.write('| ')
a_call = self.a[alo + i]
b_call = self.b[blo + i]
assert a_call.functionName == b_call.functionName
assert len(a_call.args) == len(b_call.args)
- sys.stdout.write(' ' + b_call.functionName + '(')
+ self.dumpCallNos(a_call.no, b_call.no)
+ self.highlighter.bold(True)
+ self.highlighter.write(b_call.functionName)
+ self.highlighter.bold(False)
+ self.highlighter.write('(')
sep = ''
for j in xrange(len(b_call.args)):
- sys.stdout.write(sep)
+ self.highlighter.write(sep)
self.replace_value(a_call.args[j], b_call.args[j])
sep = ', '
- sys.stdout.write(')')
+ self.highlighter.write(')')
if a_call.ret is not None or b_call.ret is not None:
- sys.stdout.write(' = ')
+ self.highlighter.write(' = ')
self.replace_value(a_call.ret, b_call.ret)
- sys.stdout.write('\n')
+ self.highlighter.write('\n')
def replace_dissimilar(self, alo, ahi, blo, bhi):
assert alo < ahi and blo < bhi
def replace_value(self, a, b):
if b == a:
- sys.stdout.write(str(b))
+ self.highlighter.write(str(b))
else:
- sys.stdout.write('%s -> %s' % (a, b))
+ self.highlighter.strike()
+ self.highlighter.color(self.delete_color)
+ self.highlighter.write(str(a))
+ self.highlighter.normal()
+ self.highlighter.write(" ")
+ self.highlighter.color(self.insert_color)
+ self.highlighter.write(str(b))
+ self.highlighter.normal()
escape = "\33["
- def delete(self, alo, ahi):
- self.dump('- ' + self.escape + '9m', self.a, alo, ahi, self.escape + '0m')
-
- def insert(self, blo, bhi):
- self.dump('+ ', self.b, blo, bhi)
+ def delete(self, alo, ahi, blo, bhi):
+ for i in xrange(alo, ahi):
+ call = self.a[i]
+ self.highlighter.write('- ')
+ self.dumpCallNos(call.no, None)
+ self.highlighter.strike()
+ self.highlighter.color(self.delete_color)
+ self.dumpCall(call)
+
+ def insert(self, alo, ahi, blo, bhi):
+ for i in xrange(blo, bhi):
+ call = self.b[i]
+ self.highlighter.write('+ ')
+ self.dumpCallNos(None, call.no)
+ self.highlighter.color(self.insert_color)
+ self.dumpCall(call)
+
+ def equal(self, alo, ahi, blo, bhi):
+ for i in xrange(0, bhi - blo):
+ self.highlighter.write(' ')
+ a_call = self.a[alo + i]
+ b_call = self.b[blo + i]
+ assert a_call.functionName == b_call.functionName
+ assert len(a_call.args) == len(b_call.args)
+ self.dumpCallNos(a_call.no, b_call.no)
+ self.dumpCall(b_call)
- def equal(self, alo, ahi):
- self.dump(' ' + self.escape + '2m', self.a, alo, ahi, self.escape + '0m')
+ def dumpCallNos(self, aNo, bNo):
+ if not self.callNos:
+ return
- def dump(self, prefix, x, lo, hi, suffix=""):
- for i in xrange(lo, hi):
- sys.stdout.write(prefix + str(x[i]) + suffix + '\n')
+ if aNo is None:
+ self.highlighter.write(' '*self.aSpace)
+ else:
+ aStr = str(aNo)
+ self.highlighter.strike()
+ self.highlighter.color(self.delete_color)
+ self.highlighter.write(str(aNo))
+ self.highlighter.normal()
+ self.aSpace = len(aStr)
+ self.highlighter.write(' ')
+ if bNo is None:
+ self.highlighter.write(' '*self.aSpace)
+ else:
+ bStr = str(bNo)
+ self.highlighter.color(self.insert_color)
+ self.highlighter.write(str(bNo))
+ self.highlighter.normal()
+ self.bSpace = len(bStr)
+ self.highlighter.write(' ')
+
+ def dumpCall(self, call):
+ self.highlighter.bold(True)
+ self.highlighter.write(call.functionName)
+ self.highlighter.bold(False)
+ self.highlighter.write('(' + ', '.join(map(repr, call.args)) + ')')
+ if call.ret is not None:
+ self.highlighter.write(' = ' + repr(call.ret))
+ self.highlighter.normal()
+ self.highlighter.write('\n')
def main():
'-c', '--calls', metavar='CALLSET',
type="string", dest="calls", default='1-10000',
help="calls to compare [default: %default]")
-
+ optparser.add_option(
+ '--ref-calls', metavar='CALLSET',
+ type="string", dest="ref_calls", default=None,
+ help="calls to compare from reference trace")
+ optparser.add_option(
+ '--src-calls', metavar='CALLSET',
+ type="string", dest="src_calls", default=None,
+ help="calls to compare from source trace")
+ optparser.add_option(
+ '--call-nos',
+ action="store_true",
+ dest="call_nos", default=False,
+ help="dump call numbers")
global options
(options, args) = optparser.parse_args(sys.argv[1:])
if len(args) != 2:
optparser.error("incorrect number of arguments")
- ref_calls = readtrace(args[0])
- src_calls = readtrace(args[1])
+ if options.ref_calls is None:
+ options.ref_calls = options.calls
+ if options.src_calls is None:
+ options.src_calls = options.calls
+
+ ref_calls = readtrace(args[0], options.ref_calls)
+ src_calls = readtrace(args[1], options.src_calls)
+
+ if sys.stdout.isatty():
+ highlighter = LessHighlighter()
+ else:
+ highlighter = ColorHighlighter()
- differ = SDiffer(ref_calls, src_calls)
+ differ = SDiffer(ref_calls, src_calls, highlighter, options.call_nos)
differ.diff()