#!/usr/bin/env python import os, re, sys from subprocess import Popen, PIPE, STDOUT import cache _can_debug = os.system('which gdb > /dev/null 2>&1') == 0 def can_debug(): global _can_debug return _can_debug class Debugger(object): frame_begin_re = re.compile('^\032\032frame-begin ([^ ]+) ([^ ]+)$') source_re = re.compile('^\032\032source (.+)$') def __init__(self, cmd='gdb', args=[]): self.pipe = None self.cmd = cmd self.args = [cmd, '--annotate=3'] self.args.extend(args) self.start() #gdb state self.prompt = None self.path = None self.line = None self.char = None self.middle = None self.addr = None self.breaks = [] def start(self): assert self.pipe is None cmd = ' '.join(self.args) self.pipe = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT) def stop(self): self.pipe.stdin.close() self.pipe.stdout.close() self.pipe = None def restart(self): self.stop() self.start() def _readline(self): line = self.pipe.stdout.readline() if line: return line[:-1] else: return None def _assertline(self, s): l = self._readline() assert l == s, repr(l) def run(self): while True: line = self._readline() if line is None: break if line.startswith('\032\032'): if line == '\032\032starting': pass elif line == '\032\032stopped': pass elif line.startswith('\032\032frame-begin'): m = self.frame_begin_re.match(line) assert m elif line.startswith('\032\032source'): m = self.source_re.match(line) assert m fields = m.group(1).split(':') self.path = fields[0] self.line = int(fields[1]) self.char = int(fields[2]) self.middle = fields[3] self.addr = fields[4] print "SOURCE %r, line %d (%s)" % (self.path, self.line, self.addr) elif line == '\032\032pre-prompt': self.prompt = self._readline() print 'PROMPT: %r' % self.prompt self._assertline('\032\032prompt') self.pipe.stdin.write(sys.stdin.readline()) self._assertline('') self._assertline('\032\032post-prompt') else: print 'CMD %r' % line elif line: print line if __name__ == "__main__": args = sys.argv[1:] d = Debugger(args=args) d.run()