diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/utils/CmpDriver | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/utils/CmpDriver')
-rwxr-xr-x | clang/utils/CmpDriver | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/clang/utils/CmpDriver b/clang/utils/CmpDriver new file mode 100755 index 0000000..2533f54 --- /dev/null +++ b/clang/utils/CmpDriver @@ -0,0 +1,210 @@ +#!/usr/bin/env 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. + """ + + def cost(a, b): + return sum(map(dist, a + [None] * (len(b) - len(a)), b)) + + # Normalize so a is shortest. + if len(b) < len(a): + b, a = insertMinimumPadding(b, a, dist) + return a,b + + # For each None we have to insert... + for i in range(len(b) - len(a)): + # For each position we could insert it... + current = cost(a, b) + best = None + for j in range(len(a) + 1): + a_0 = a[:j] + [None] + a[j:] + candidate = cost(a_0, b) + if best is None or candidate < best[0]: + best = (candidate, a_0, j) + a = best[1] + return a,b + +class ZipperDiff(object): + """ZipperDiff - Simple (slow) diff only accommodating 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('clang 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 'clang' + + infoA = captureDriverInfo(driverA, args) + infoB = captureDriverInfo(driverB, args) + + differ = False + + # Compare stdout. + if infoA.stdout != infoB.stdout: + print '-- STDOUT DIFFERS -' + print 'A OUTPUT: ',infoA.stdout + print 'B OUTPUT: ',infoB.stdout + print + + diff = ZipperDiff(infoA.stdout.split('\n'), + infoB.stdout.split('\n')) + for i,(aElt,bElt) in enumerate(diff.getDiffs()): + 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 stderr. + if infoA.stderr != infoB.stderr: + print '-- STDERR DIFFERS -' + print 'A STDERR: ',infoA.stderr + print 'B STDERR: ',infoB.stderr + print + + diff = ZipperDiff(infoA.stderr.split('\n'), + infoB.stderr.split('\n')) + for i,(aElt,bElt) in enumerate(diff.getDiffs()): + 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 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() |