118 lines
3.4 KiB
Plaintext
118 lines
3.4 KiB
Plaintext
|
#!/usr/bin/env python
|
||
|
|
||
|
import os, sys, re
|
||
|
|
||
|
class multidict:
|
||
|
def __init__(self, elts=()):
|
||
|
self.data = {}
|
||
|
for key,value in elts:
|
||
|
self[key] = value
|
||
|
|
||
|
def __getitem__(self, item):
|
||
|
return self.data[item]
|
||
|
def __setitem__(self, key, value):
|
||
|
if key in self.data:
|
||
|
self.data[key].append(value)
|
||
|
else:
|
||
|
self.data[key] = [value]
|
||
|
def items(self):
|
||
|
return self.data.items()
|
||
|
def values(self):
|
||
|
return self.data.values()
|
||
|
def keys(self):
|
||
|
return self.data.keys()
|
||
|
def __len__(self):
|
||
|
return len(self.data)
|
||
|
|
||
|
kDiagnosticRE = re.compile(': (error|warning): (.*)')
|
||
|
kAssertionRE = re.compile('Assertion failed: (.*, function .*, file .*, line [0-9]+\\.)')
|
||
|
|
||
|
def readInfo(path, opts):
|
||
|
lastProgress = [-100,0]
|
||
|
def progress(pos):
|
||
|
pct = (100. * pos) / (size * 2)
|
||
|
if (pct - lastProgress[0]) >= 10:
|
||
|
lastProgress[0] = pct
|
||
|
print '%d/%d = %.2f%%' % (pos, size*2, pct)
|
||
|
|
||
|
f = open(path)
|
||
|
data = f.read()
|
||
|
f.close()
|
||
|
|
||
|
if opts.truncate != -1:
|
||
|
data = data[:opts.truncate]
|
||
|
|
||
|
size = len(data)
|
||
|
warnings = multidict()
|
||
|
errors = multidict()
|
||
|
for m in kDiagnosticRE.finditer(data):
|
||
|
progress(m.end())
|
||
|
if m.group(1) == 'error':
|
||
|
d = errors
|
||
|
else:
|
||
|
d = warnings
|
||
|
d[m.group(2)] = m
|
||
|
warnings = warnings.items()
|
||
|
errors = errors.items()
|
||
|
assertions = multidict()
|
||
|
for m in kAssertionRE.finditer(data):
|
||
|
print '%d/%d = %.2f%%' % (size + m.end(), size, (float(m.end()) / (size*2)) * 100.)
|
||
|
assertions[m.group(1)] = m
|
||
|
assertions = assertions.items()
|
||
|
|
||
|
# Manual scan for stack traces
|
||
|
aborts = multidict()
|
||
|
if 0:
|
||
|
prevLine = None
|
||
|
lnIter = iter(data.split('\n'))
|
||
|
for ln in lnIter:
|
||
|
m = kStackDumpLineRE.match(ln)
|
||
|
if m:
|
||
|
stack = [m.group(2)]
|
||
|
for ln in lnIter:
|
||
|
m = kStackDumpLineRE.match(ln)
|
||
|
if not m:
|
||
|
break
|
||
|
stack.append(m.group(2))
|
||
|
if prevLine is None or not kAssertionRE.match(prevLine):
|
||
|
aborts[tuple(stack)] = stack
|
||
|
prevLine = ln
|
||
|
|
||
|
sections = [
|
||
|
(warnings, 'Warnings'),
|
||
|
(errors, 'Errors'),
|
||
|
(assertions, 'Assertions'),
|
||
|
(aborts.items(), 'Aborts'),
|
||
|
]
|
||
|
|
||
|
if opts.ascending:
|
||
|
sections.reverse()
|
||
|
|
||
|
for l,title in sections:
|
||
|
l.sort(key = lambda (a,b): -len(b))
|
||
|
if l:
|
||
|
print '-- %d %s (%d kinds) --' % (sum([len(b) for a,b in l]), title, len(l))
|
||
|
for name,elts in l:
|
||
|
print '%5d:' % len(elts), name
|
||
|
|
||
|
def main():
|
||
|
global options
|
||
|
from optparse import OptionParser
|
||
|
parser = OptionParser("usage: %prog [options] {inputs}")
|
||
|
parser.add_option("", "--ascending", dest="ascending",
|
||
|
help="Print output in ascending order of severity.",
|
||
|
action="store_true", default=False)
|
||
|
parser.add_option("", "--truncate", dest="truncate",
|
||
|
help="Truncate input file (for testing).",
|
||
|
type=int, action="store", default=-1)
|
||
|
(opts, args) = parser.parse_args()
|
||
|
|
||
|
if not args:
|
||
|
parser.error('No inputs specified')
|
||
|
|
||
|
for arg in args:
|
||
|
readInfo(arg, opts)
|
||
|
|
||
|
if __name__=='__main__':
|
||
|
main()
|