summaryrefslogtreecommitdiffstats
path: root/utils/CmpDriver
diff options
context:
space:
mode:
Diffstat (limited to 'utils/CmpDriver')
-rwxr-xr-xutils/CmpDriver194
1 files changed, 194 insertions, 0 deletions
diff --git a/utils/CmpDriver b/utils/CmpDriver
new file mode 100755
index 0000000..97c91a8
--- /dev/null
+++ b/utils/CmpDriver
@@ -0,0 +1,194 @@
+#!/usr/bin/python
+
+import subprocess
+
+def splitArgs(s):
+ it = iter(s)
+ current = ''
+ inQuote = False
+ for c in it:
+ if c == '"':
+ if inQuote:
+ inQuote = False
+ yield current + '"'
+ else:
+ inQuote = True
+ current = '"'
+ elif inQuote:
+ if c == '\\':
+ current += c
+ current += it.next()
+ else:
+ current += c
+ elif not c.isspace():
+ yield c
+
+def insertMinimumPadding(a, b, dist):
+ """insertMinimumPadding(a,b) -> (a',b')
+
+ Return two lists of equal length, where some number of Nones have
+ been inserted into the shorter list such that sum(map(dist, a',
+ b')) is minimized.
+
+ Assumes dist(X, Y) -> int and non-negative.
+ """
+
+ # Yay for simplicity over complexity.
+
+ def extend(aElt, bElt, solution):
+ d0,(a0,b0) = solution
+ return d0 + dist(aElt,bElt), (([aElt]+a0),([bElt]+b0))
+
+ def f(a, b):
+ if len(a) == len(b):
+ return (sum(map(dist, a, b)), (a, b))
+
+ if not a or not b:
+ if not a:
+ a += [None] * len(b)
+ else:
+ b += [None] * len(a)
+ return (sum(map(dist, a, b)), (a, b))
+
+ if int(dist(a[0], b[0])) == 0:
+ # Non-negative condition implies maximum is satisfied
+ # taking this.
+ return extend(a[0], b[0], f(a[1:], b[1:]))
+
+ if len(a) < len(b):
+ return min(f([None] + a, b),
+ extend(a[0], b[0], f(a[1:], b[1:])))
+ else:
+ return min(f(a, [None] + b),
+ extend(a[0], b[0], f(a[1:], b[1:])))
+
+ return f(a, b)[1]
+
+class ZipperDiff(object):
+ """ZipperDiff - Simple (slow) diff only accomodating inserts."""
+
+ def __init__(self, a, b):
+ self.a = a
+ self.b = b
+
+ def dist(self, a, b):
+ return a != b
+
+ def getDiffs(self):
+ a,b = insertMinimumPadding(self.a, self.b, self.dist)
+ for aElt,bElt in zip(a,b):
+ if self.dist(aElt, bElt):
+ yield aElt,bElt
+
+class DriverZipperDiff(ZipperDiff):
+ def isTempFile(self, filename):
+ if filename[0] != '"' or filename[-1] != '"':
+ return False
+ return (filename.startswith('/tmp/', 1) or
+ filename.startswith('/var/', 1))
+
+ def dist(self, a, b):
+ if a and b and self.isTempFile(a) and self.isTempFile(b):
+ return 0
+ return super(DriverZipperDiff, self).dist(a,b)
+
+class CompileInfo:
+ def __init__(self, out, err, res):
+ self.commands = []
+
+ # Standard out isn't used for much.
+ self.stdout = out
+ self.stderr = ''
+
+ # FIXME: Compare error messages as well.
+ for ln in err.split('\n'):
+ if (ln == 'Using built-in specs.' or
+ ln.startswith('Target: ') or
+ ln.startswith('Configured with: ') or
+ ln.startswith('Thread model: ') or
+ ln.startswith('gcc version') or
+ ln.startswith('ccc version')):
+ pass
+ elif ln.strip().startswith('"'):
+ self.commands.append(list(splitArgs(ln)))
+ else:
+ self.stderr += ln + '\n'
+
+ self.stderr = self.stderr.strip()
+ self.exitCode = res
+
+def captureDriverInfo(cmd, args):
+ p = subprocess.Popen([cmd,'-###'] + args,
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out,err = p.communicate()
+ res = p.wait()
+ return CompileInfo(out,err,res)
+
+def main():
+ import os, sys
+
+ args = sys.argv[1:]
+ driverA = os.getenv('DRIVER_A') or 'gcc'
+ driverB = os.getenv('DRIVER_B') or 'xcc'
+
+ infoA = captureDriverInfo(driverA, args)
+ infoB = captureDriverInfo(driverB, args)
+
+ differ = False
+
+ # Compare stdout.
+ if infoA.stdout != infoB.stdout:
+ print '-- STDOUT DIFFERS -'
+ print 'A: ',infoA.stdout
+ print 'B: ',infoB.stdout
+ differ = True
+
+ # Compare stderr.
+ if infoA.stderr != infoB.stderr:
+ print '-- STDERR DIFFERS -'
+ print 'A: ',infoA.stderr
+ print 'B: ',infoB.stderr
+ differ = True
+
+ # Compare commands.
+ for i,(a,b) in enumerate(map(None, infoA.commands, infoB.commands)):
+ if a is None:
+ print 'A MISSING:',' '.join(b)
+ differ = True
+ continue
+ elif b is None:
+ print 'B MISSING:',' '.join(a)
+ differ = True
+ continue
+
+ diff = DriverZipperDiff(a,b)
+ diffs = list(diff.getDiffs())
+ if diffs:
+ print '-- COMMAND %d DIFFERS -' % i
+ print 'A COMMAND:',' '.join(a)
+ print 'B COMMAND:',' '.join(b)
+ print
+ for i,(aElt,bElt) in enumerate(diffs):
+ if aElt is None:
+ print 'A missing: %s' % bElt
+ elif bElt is None:
+ print 'B missing: %s' % aElt
+ else:
+ print 'mismatch: A: %s' % aElt
+ print ' B: %s' % bElt
+ differ = True
+
+ # Compare result codes.
+ if infoA.exitCode != infoB.exitCode:
+ print '-- EXIT CODES DIFFER -'
+ print 'A: ',infoA.exitCode
+ print 'B: ',infoB.exitCode
+ differ = True
+
+ if differ:
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
OpenPOWER on IntegriCloud