#!/usr/bin/env python __author__ = "Jan Pokorny " __license__ = "GPLv2" # couple of observations: # - function name placeholder: # - # - single argument placeholder: # - how=how@entry=0 # + totally skewed by Python-aware annotations :-/ from sys import stdin, stderr from re import compile from textwrap import fill, wrap DEF_PATH = '[A-Za-z0-9._/-]+' DEF_IDENT = '[A-Za-z_][A-Za-z0-9_]*' # incl. C++ stuff DEF_IDENT_FUNC = '%(DEF_IDENT)s(?:(?: |::)%(DEF_IDENT)s)*' % locals() # incl. "how=how@entry" in how=how@entry=0 and the like DEF_IDENT_ARG = '(?P[A-Za-z_][A-Za-z0-9_]*)(=(?P=atnotation)@[A-Za-z0-9_]+)?' DEF_UNKNOWN = '[?]{2}' DEF_HEX = '0x[0-9A-Fa-f]+' DEF_NUM = '[+-]?(?:[0-9]+(?:[.][0-9]*)?|[.][0-9]+)(?:[eE][0-9]+)?' DEF_MSG = '(?:%(DEF_HEX)s\s+)?[<][ A-Za-z0-9_.]+[>]' % locals() DEF_STR = '(?:%(DEF_HEX)s\s+)?["][^"]*["]' % locals() DEF_STR2 = "(?:%(DEF_HEX)s\s+)?['][^']*[']" % locals() DEF_STRUCT = '(?:%(DEF_HEX)s\s+=\s+)?[{][^}]*[}]' % locals() DEF_PYTHONFRAME = 'Frame %(DEF_HEX)s, for file %(DEF_PATH)s, line \d+, in %(DEF_IDENT)s [(][^)]*[)]' % locals() RE_BT = compile( '(?P^\#[0-9]+\s+)' '(?:(?P%(DEF_HEX)s) in )?' '(?P%(DEF_IDENT_FUNC)s|(?P%(DEF_UNKNOWN)s|%(DEF_MSG)s))' '(?: (?P[(](?:(?<=[( ])%(DEF_IDENT_ARG)s=(?:%(DEF_IDENT)s|%(DEF_MSG)s|%(DEF_PYTHONFRAME)s|%(DEF_HEX)s|%(DEF_NUM)s|%(DEF_STR)s|%(DEF_STR2)s|%(DEF_STRUCT)s)(?:, )?)*[)])' '(?(unknown)| at (?P%(DEF_PATH)s):(?P[1-9][0-9]*)))?' % locals()) class BtLineError(Exception): def __init__(self, string): self._string = string def __str__(self): return self._string class BtLine(object): def __init__(self, line, space=' ' * 4): self._space = space self._line = line self._found = RE_BT.search(self._line) if self._found: for k, v in self._found.groupdict().iteritems(): #print >>stderr, "\t{0}: {1}".format(k, v) setattr(self, k, v if v is not None else '') else: raise BtLineError(fill(line.strip(), initial_indent=self._space * 2, subsequent_indent=self._space * 3)) def __str__(self): if self._found: args = wrap(self.args, subsequent_indent=self._space) space = '\n' + self._space res = self.init + self.where if args and args[0] != '()': res += space + '\n'.join(args) if self.path: res += space + 'at ' + self.path + ':' + self.line return res def main(**kwargs): line = '__dummy__' firstline = True cnt = 1 while line != '': cnt += 1 line = stdin.readline() if not line.strip(): # unfortunately, textwrap.fill would alias, e.g., '\n' and '' cases print line continue try: btline = BtLine(line, **kwargs) print ('' if firstline else '\n') + str(btline) except BtLineError as ble: line = str(ble) print >>stderr, ">> bad line:%i" % cnt print line finally: firstline = False if __name__ == '__main__': main()