1 #!/usr/bin/env python 2 3 import os, sys, re 4 5 class multidict: 6 def __init__(self, elts=()): 7 self.data = {} 8 for key,value in elts: 9 self[key] = value 10 11 def __getitem__(self, item): 12 return self.data[item] 13 def __setitem__(self, key, value): 14 if key in self.data: 15 self.data[key].append(value) 16 else: 17 self.data[key] = [value] 18 def items(self): 19 return self.data.items() 20 def values(self): 21 return self.data.values() 22 def keys(self): 23 return self.data.keys() 24 def __len__(self): 25 return len(self.data) 26 27 kDiagnosticRE = re.compile(': (error|warning): (.*)') 28 kAssertionRE = re.compile('Assertion failed: (.*, function .*, file .*, line [0-9]+\\.)') 29 30 def readInfo(path, opts): 31 lastProgress = [-100,0] 32 def progress(pos): 33 pct = (100. * pos) / (size * 2) 34 if (pct - lastProgress[0]) >= 10: 35 lastProgress[0] = pct 36 print '%d/%d = %.2f%%' % (pos, size*2, pct) 37 38 f = open(path) 39 data = f.read() 40 f.close() 41 42 if opts.truncate != -1: 43 data = data[:opts.truncate] 44 45 size = len(data) 46 warnings = multidict() 47 errors = multidict() 48 for m in kDiagnosticRE.finditer(data): 49 progress(m.end()) 50 if m.group(1) == 'error': 51 d = errors 52 else: 53 d = warnings 54 d[m.group(2)] = m 55 warnings = warnings.items() 56 errors = errors.items() 57 assertions = multidict() 58 for m in kAssertionRE.finditer(data): 59 print '%d/%d = %.2f%%' % (size + m.end(), size, (float(m.end()) / (size*2)) * 100.) 60 assertions[m.group(1)] = m 61 assertions = assertions.items() 62 63 # Manual scan for stack traces 64 aborts = multidict() 65 if 0: 66 prevLine = None 67 lnIter = iter(data.split('\n')) 68 for ln in lnIter: 69 m = kStackDumpLineRE.match(ln) 70 if m: 71 stack = [m.group(2)] 72 for ln in lnIter: 73 m = kStackDumpLineRE.match(ln) 74 if not m: 75 break 76 stack.append(m.group(2)) 77 if prevLine is None or not kAssertionRE.match(prevLine): 78 aborts[tuple(stack)] = stack 79 prevLine = ln 80 81 sections = [ 82 (warnings, 'Warnings'), 83 (errors, 'Errors'), 84 (assertions, 'Assertions'), 85 (aborts.items(), 'Aborts'), 86 ] 87 88 if opts.ascending: 89 sections.reverse() 90 91 for l,title in sections: 92 l.sort(key = lambda (a,b): -len(b)) 93 if l: 94 print '-- %d %s (%d kinds) --' % (sum([len(b) for a,b in l]), title, len(l)) 95 for name,elts in l: 96 print '%5d:' % len(elts), name 97 98 def main(): 99 global options 100 from optparse import OptionParser 101 parser = OptionParser("usage: %prog [options] {inputs}") 102 parser.add_option("", "--ascending", dest="ascending", 103 help="Print output in ascending order of severity.", 104 action="store_true", default=False) 105 parser.add_option("", "--truncate", dest="truncate", 106 help="Truncate input file (for testing).", 107 type=int, action="store", default=-1) 108 (opts, args) = parser.parse_args() 109 110 if not args: 111 parser.error('No inputs specified') 112 113 for arg in args: 114 readInfo(arg, opts) 115 116 if __name__=='__main__': 117 main() 118