blob: ca3086d9b7fd6ffb59ae61d456f8eedf9bb448df [file] [log] [blame]
Daniel Dunbaref64fcf2009-01-09 22:39:43 +00001#!/usr/bin/python
2
3import os, sys, re
4
5class 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
27kGCCErrorRE = re.compile('(.*):([0-9]+): error: (.*)')
28kGCCWarningRE = re.compile('(.*):([0-9]+): warning: (.*)')
29kClangErrorRE = re.compile('(.*):([0-9]+):([0-9]+): error: (.*)')
30kClangWarningRE = re.compile('(.*):([0-9]+):([0-9]+): warning: (.*)')
31kAssertionRE = re.compile('Assertion failed: (.*, function .*, file .*, line [0-9]+\\.)')
32kStackDumpLineRE = re.compile('^[0-9]+ +([^ ]+) +0x[0-9a-fA-F]+ +([^ ]+)')
33
34def readInfo(path, opts):
35 f = open(path)
36 data = f.read()
37 f.close()
38
39 if opts.truncate != -1:
40 data = data[:opts.truncate]
41
42 gccwarnings = multidict([(m.group(3),m) for m in kGCCWarningRE.finditer(data)]).items()
43 gccerrors = multidict([(m.group(3),m) for m in kGCCErrorRE.finditer(data)]).items()
44 assertions = multidict([(m.group(1),m) for m in kAssertionRE.finditer(data)]).items()
45
46 # Manual scan for stack traces
47 aborts = multidict()
48 prevLine = None
49 lnIter = iter(data.split('\n'))
50 for ln in lnIter:
51 m = kStackDumpLineRE.match(ln)
52 if m:
53 stack = [m.group(2)]
54 for ln in lnIter:
55 m = kStackDumpLineRE.match(ln)
56 if not m:
57 break
58 stack.append(m.group(2))
59 if prevLine is None or not kAssertionRE.match(prevLine):
60 aborts[tuple(stack)] = stack
61 prevLine = ln
62
63 sections = [
64 (gccwarnings, 'Warnings'),
65 (gccerrors, 'Errors'),
66 (assertions, 'Assertions'),
67 (aborts.items(), 'Aborts'),
68 ]
69
70 if opts.ascending:
71 sections.reverse()
72
73 for l,title in sections:
74 l.sort(key = lambda (a,b): -len(b))
75 if l:
76 print '-- %d %s (%d kinds) --' % (sum([len(b) for a,b in l]), title, len(l))
77 for name,elts in l:
78 print '%5d:' % len(elts), name
79
80def main():
81 global options
82 from optparse import OptionParser
83 parser = OptionParser("usage: %prog [options] {inputs}")
84 parser.add_option("", "--ascending", dest="ascending",
85 help="Print output in ascending order of severity.",
86 action="store_true", default=False)
87 parser.add_option("", "--truncate", dest="truncate",
88 help="Truncate input file (for testing).",
89 type=int, action="store", default=-1)
90 (opts, args) = parser.parse_args()
91
92 if not args:
93 parser.error('No inputs specified')
94
95 for arg in args:
96 readInfo(arg, opts)
97
98if __name__=='__main__':
99 main()