26 def insertMinimumPadding(a
, b
, dist
):
27 """insertMinimumPadding(a,b) -> (a',b')
29 Return two lists of equal length, where some number of Nones have
30 been inserted into the shorter list such that sum(map(dist, a',
33 Assumes dist(X, Y) -> int and non-negative.
37 return sum(map(dist
, a
+ [None] * (len(b
) - len(a
)), b
))
39 # Normalize so a is shortest.
41 b
, a
= insertMinimumPadding(b
, a
, dist
)
44 # For each None we have to insert...
45 for i
in range(len(b
) - len(a
)):
46 # For each position we could insert it...
49 for j
in range(len(a
) + 1):
50 a_0
= a
[:j
] + [None] + a
[j
:]
51 candidate
= cost(a_0
, b
)
52 if best
is None or candidate
< best
[0]:
53 best
= (candidate
, a_0
, j
)
57 class ZipperDiff(object):
58 """ZipperDiff - Simple (slow) diff only accomodating inserts."""
60 def __init__(self
, a
, b
):
68 a
,b
= insertMinimumPadding(self
.a
, self
.b
, self
.dist
)
69 for aElt
,bElt
in zip(a
,b
):
70 if self
.dist(aElt
, bElt
):
73 class DriverZipperDiff(ZipperDiff
):
74 def isTempFile(self
, filename
):
75 if filename
[0] != '"' or filename
[-1] != '"':
77 return (filename
.startswith('/tmp/', 1) or
78 filename
.startswith('/var/', 1))
81 if a
and b
and self
.isTempFile(a
) and self
.isTempFile(b
):
83 return super(DriverZipperDiff
, self
).dist(a
,b
)
86 def __init__(self
, out
, err
, res
):
89 # Standard out isn't used for much.
93 # FIXME: Compare error messages as well.
94 for ln
in err
.split('\n'):
95 if (ln
== 'Using built-in specs.' or
96 ln
.startswith('Target: ') or
97 ln
.startswith('Configured with: ') or
98 ln
.startswith('Thread model: ') or
99 ln
.startswith('gcc version') or
100 ln
.startswith('clang version')):
102 elif ln
.strip().startswith('"'):
103 self
.commands
.append(list(splitArgs(ln
)))
105 self
.stderr
+= ln
+ '\n'
107 self
.stderr
= self
.stderr
.strip()
110 def captureDriverInfo(cmd
, args
):
111 p
= subprocess
.Popen([cmd
,'-###'] + args
,
113 stdout
=subprocess
.PIPE
,
114 stderr
=subprocess
.PIPE
)
115 out
,err
= p
.communicate()
117 return CompileInfo(out
,err
,res
)
123 driverA
= os
.getenv('DRIVER_A') or 'gcc'
124 driverB
= os
.getenv('DRIVER_B') or 'clang'
126 infoA
= captureDriverInfo(driverA
, args
)
127 infoB
= captureDriverInfo(driverB
, args
)
132 if infoA
.stdout
!= infoB
.stdout
:
133 print '-- STDOUT DIFFERS -'
134 print 'A OUTPUT: ',infoA
.stdout
135 print 'B OUTPUT: ',infoB
.stdout
138 diff
= ZipperDiff(infoA
.stdout
.split('\n'),
139 infoB
.stdout
.split('\n'))
140 for i
,(aElt
,bElt
) in enumerate(diff
.getDiffs()):
142 print 'A missing: %s' % bElt
144 print 'B missing: %s' % aElt
146 print 'mismatch: A: %s' % aElt
147 print ' B: %s' % bElt
152 if infoA
.stderr
!= infoB
.stderr
:
153 print '-- STDERR DIFFERS -'
154 print 'A STDERR: ',infoA
.stderr
155 print 'B STDERR: ',infoB
.stderr
158 diff
= ZipperDiff(infoA
.stderr
.split('\n'),
159 infoB
.stderr
.split('\n'))
160 for i
,(aElt
,bElt
) in enumerate(diff
.getDiffs()):
162 print 'A missing: %s' % bElt
164 print 'B missing: %s' % aElt
166 print 'mismatch: A: %s' % aElt
167 print ' B: %s' % bElt
172 for i
,(a
,b
) in enumerate(map(None, infoA
.commands
, infoB
.commands
)):
174 print 'A MISSING:',' '.join(b
)
178 print 'B MISSING:',' '.join(a
)
182 diff
= DriverZipperDiff(a
,b
)
183 diffs
= list(diff
.getDiffs())
185 print '-- COMMAND %d DIFFERS -' % i
186 print 'A COMMAND:',' '.join(a
)
187 print 'B COMMAND:',' '.join(b
)
189 for i
,(aElt
,bElt
) in enumerate(diffs
):
191 print 'A missing: %s' % bElt
193 print 'B missing: %s' % aElt
195 print 'mismatch: A: %s' % aElt
196 print ' B: %s' % bElt
199 # Compare result codes.
200 if infoA
.exitCode
!= infoB
.exitCode
:
201 print '-- EXIT CODES DIFFER -'
202 print 'A: ',infoA
.exitCode
203 print 'B: ',infoB
.exitCode
209 if __name__
== '__main__':