Home | History | Annotate | Download | only in utils
      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