#!/usr/bin/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) kGCCErrorRE = re.compile('(.*):([0-9]+): error: (.*)') kGCCWarningRE = re.compile('(.*):([0-9]+): warning: (.*)') kClangErrorRE = re.compile('(.*):([0-9]+):([0-9]+): error: (.*)') kClangWarningRE = re.compile('(.*):([0-9]+):([0-9]+): warning: (.*)') kAssertionRE = re.compile('Assertion failed: (.*, function .*, file .*, line [0-9]+\\.)') kStackDumpLineRE = re.compile('^[0-9]+ +([^ ]+) +0x[0-9a-fA-F]+ +([^ ]+)') def readInfo(path, opts): f = open(path) data = f.read() f.close() if opts.truncate != -1: data = data[:opts.truncate] gccwarnings = multidict([(m.group(3),m) for m in kGCCWarningRE.finditer(data)]).items() gccerrors = multidict([(m.group(3),m) for m in kGCCErrorRE.finditer(data)]).items() assertions = multidict([(m.group(1),m) for m in kAssertionRE.finditer(data)]).items() # Manual scan for stack traces aborts = multidict() 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 = [ (gccwarnings, 'Warnings'), (gccerrors, '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()