#!/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()
