blob: 64d78240dd2fa0f284aa29d17e939b9d9277464a [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
Daniel Dunbar7e075cb2009-04-07 06:43:45 +000027kDiagnosticRE = re.compile(': (error|warning): (.*)')
Daniel Dunbaref64fcf2009-01-09 22:39:43 +000028kAssertionRE = re.compile('Assertion failed: (.*, function .*, file .*, line [0-9]+\\.)')
Daniel Dunbaref64fcf2009-01-09 22:39:43 +000029
30def readInfo(path, opts):
Daniel Dunbar7e075cb2009-04-07 06:43:45 +000031 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
Daniel Dunbaref64fcf2009-01-09 22:39:43 +000038 f = open(path)
39 data = f.read()
40 f.close()
41
42 if opts.truncate != -1:
43 data = data[:opts.truncate]
44
Daniel Dunbar7e075cb2009-04-07 06:43:45 +000045 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()
Daniel Dunbaref64fcf2009-01-09 22:39:43 +000062
63 # Manual scan for stack traces
64 aborts = multidict()
Daniel Dunbar7e075cb2009-04-07 06:43:45 +000065 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
Daniel Dunbaref64fcf2009-01-09 22:39:43 +000080
81 sections = [
Daniel Dunbar7e075cb2009-04-07 06:43:45 +000082 (warnings, 'Warnings'),
83 (errors, 'Errors'),
Daniel Dunbaref64fcf2009-01-09 22:39:43 +000084 (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
98def 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
116if __name__=='__main__':
117 main()