#!/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()