+++ /dev/null
-#!/usr/bin/python
-
-
-import select
-import string
-import sys
-import thread
-import threading
-import time
-import os
-import pty
-import Queue
-
-
-class DbgTerminal:
-
- #Reply cache from debugger
- dbgreplyqueue = Queue.Queue()
-
-
- def __init__ (self, binary, gdbReadCallback, childReadCallback):
-
- #Set some members
- self.gdbReadCallback = gdbReadCallback
- self.childReadCallback = childReadCallback
- self.binary = binary
- self.stopped = False
-
- #Connect to sub-process
- self.__connect()
-
- def __connect( self ):
-
- #This function handles readings from the debugger
- def gdbCb(str):
- self.gdbReadCallback(str)
- self.dbgreplyqueue.put(str)
-
- #Open pseudo-terminal where to-be-debugged process reads/writes to
- self.ptymaster, self.ptyslave = pty.openpty()
- self.childout = os.fdopen(self.ptymaster, "r", 0)
- self.childin = os.fdopen(self.ptymaster, "w", 0)
-
- #Call gdb and get in- and out-streams to/from gdb
- cmd = self.getCommand(self.binary)
- self.gdbin, self.gdbout = os.popen4( cmd, bufsize=0)
-
- #Set up a reading thread to gdb output
- self.gdbReadThread = self.ReadThread(self.gdbout, gdbCb)
- self.gdbReadThread.start()
-
- #Set up a reading thread to childs output
- self.childReadThread = self.ReadThread(self.childout, self.childReadCallback)
- self.childReadThread.start()
-
- #Set up tty gdb-childs process
- self.sendSetTTY(os.ttyname(self.ptyslave))
-
-
-
- def getDbgReply(self):
- raise NotImplementedError()
-
-
- def iseof( self ):
- """Check if terminal is closed already"""
- return self.gdbReadThread.eventFin.isSet()
-
- def stop( self ):
-
- if not self.stopped:
-
- self.stopped = True
-
- #Finish the reading-thread
- self.gdbReadThread.fin = True
- self.childReadThread.fin = True
- self.gdbReadThread.eventFin.wait(1)
- self.childReadThread.eventFin.wait(1)
-
-
- def getCommand( self, binary ):
- """Get the command to execute"""
- raise NotImplementedError()
-
- def sendBreak(self, file, lineno):
- raise NotImplementedError()
-
- def sendContinue(self):
- raise NotImplementedError()
-
- def sendRun(self):
- raise NotImplementedError()
-
- def sendInspectVar(self, var):
- raise NotImplementedError()
-
- def sendInspectExpr(self, expr):
- raise NotImplementedError()
-
- def sendSetTTY(self, ttyname):
- raise NotImplementedError()
-
- def sendQuit(self):
- raise NotImplementedError()
-
-
- class ReadThread (threading.Thread):
- """Thread which reads from sub-process output"""
-
- def __init__( self, stream, callback, sleep=0.1):
- self.stream = stream
- self.fin = False
- self.callback = callback
- self.sleep = sleep
- self.eventFin = threading.Event()
- threading.Thread.__init__(self)
-
- def run(self):
-
- try:
- while True:
- #Wait until data is available
- rlist, wlist, xlist = select.select([self.stream], [], [], self.sleep)
-
- #If we should finish, finish
- if self.fin:
- break
-
- #Got new data
- if len(rlist) > 0:
- fd = rlist[0]
- str = fd.read(1)
- #Call callbacks
- self.callback(str)
- except:
- pass
-
- #Set the finished event
- self.eventFin.set()
-
-
-
-
-class GdbTerminal (DbgTerminal):
-
- gdbreply = ""
-
-
- def getCommand( self, binary ):
- return "gdb --fullname %s" % (binary,)
-
- def sendBreak(self, file, lineno):
- self.gdbin.write("break %s:%d\n" % (file, lineno))
-
- def sendContinue(self):
- self.gdbin.write("cont\n")
-
- def sendRun(self):
- self.gdbin.write("run\n")
-
- def sendInspectVar(self, var):
- self.sendInspectExpr(var)
-
- def sendInspectExpr(self, expr):
- self.gdbin.write("print %s\n" % (expr,))
-
- def sendSetTTY(self, ttyname):
- self.gdbin.write("set inferior-tty %s\n" % (ttyname,))
-
- def sendQuit(self):
- self.gdbin.write("quit\n")
- DbgTerminal.stop(self)
-
- def getDbgReply(self, timeout=None):
-
- while True:
- splits = self.gdbreply.split("\n")
-
- #Need more data: If there is a single (gdb) entry, then
- #there are at least two splits
- if len(splits) <= 1:
- try:
- self.gdbreply += self.dbgreplyqueue.get(True, timeout)
- except Queue.Empty:
- return None
- #Yeah there is data!
- else:
- self.gdbreply = string.join(splits[1:], "(gdb)")
- return string.strip(splits[0])
-
- def flushDbgReply(self):
-
- try:
- self.gdbreply = ""
- #Remove all elements from queue
- while True:
- self.dbgreplyqueue.get(False)
- except Queue.Empty:
- pass
-
-if __name__ == "__main__":
-
- def tostdout(str):
- sys.stdout.write(str)
- sys.stdout.flush()
-
- try:
-
- term = GdbTerminal( "./main", tostdout, tostdout)
- term.sendBreak("main.cpp", 13)
- term.sendBreak("main.cpp", 14)
- term.sendRun()
- term.childin.write("1\n");
- term.childin.write("2\n");
-
- time.sleep(0.2)
- term.flushDbgReply()
- term.sendInspectVar("a+b")
-
- term.sendContinue()
- term.sendInspectVar("a+b")
- term.sendContinue()
-
-
- time.sleep(1)
-
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
- print "reply >>>", term.getDbgReply(1)
-
-
- while not term.iseof():
-
- cmd = sys.stdin.readline()
-
- if term.iseof():
- break
-
- if cmd == "quit\n":
- term.sendQuit()
- else:
- term.gdbin.write(cmd)
-
- except Exception, e:
- print e
- except:
- pass
-
-
- print "stopping..."
- term.stop()
-
-
-
--- /dev/null
+#!/usr/bin/python
+#shuber, 2008-06-04
+
+__author__ = "shuber"
+
+
+import gtk
+import pty
+import string
+import time
+import threading
+import vte
+
+import ClientIOWindow
+
+
+class DbgWindow (gtk.Window):
+
+ clientIOWnd = None
+ lastrow = 0
+ history = []
+
+
+
+ def __init__(self, clientCmd):
+
+ #Set up some members
+ self.clientCmd = clientCmd
+
+ #Set up GTK stuff
+ gtk.Window.__init__(self)
+ self.connect("destroy", lambda *w: gtk.main_quit())
+
+ #Set title and add terminal
+ self.set_title("Debugger I/O")
+ self.terminal = vte.Terminal()
+ self.terminal.history = []
+ self.terminal.history_length = 5
+ self.add(self.terminal)
+
+ #Set up terminal window and initialize debugger
+ self.terminal.connect("child-exited", lambda *w: gtk.main_quit())
+ self.terminal.connect("cursor-moved", self.contents_changed)
+ self._initializeDbg()
+
+ #Show the window
+ self.show_all()
+
+
+ def _initializeDbg(self):
+
+ #Start debugger
+ self.terminal.fork_command( self.getDbgCommand(), self.getDbgArgv())
+
+ #Open pseudo-terminal where to-be-debugged process reads/writes to
+ self.client_ptymaster, self.client_ptyslave = pty.openpty()
+ self.setDbgPty(self.client_ptyslave)
+
+
+ def contents_changed(self, term):
+ c,r = term.get_cursor_position()
+
+ if self.lastrow < r:
+ text = self.terminal.get_text_range(self.lastrow,0,r-1,-1,lambda *w:True)
+ self.history += string.split(text, "\n")
+ self.lastrow = r
+
+ def waitForDbgNewline(self):
+ r = self.lastrow
+ while not self.lastrow > r:
+ gtk.main_iteration()
+
+ def waitForDbgRx(self, rx):
+ while True:
+ start = len(self.history)
+ gtk.main_iteration()
+
+ for line in self.history[start:]:
+ if rx.search(line):
+ return line
+
+
+ def getDbgCommand(self):
+ return self.getDbgArgv()[0];
+
+ def getDbgArgv(self):
+ raise NotImplementedError()
+
+ def setDbgPty(self, pty):
+ raise NotImplementedError()
+
+ def setDbgRun(self):
+ raise NotImplementedError()
+
+ def setDbgQuit(self):
+ raise NotImplementedError()
+
+ def setDbgContinue(self):
+ raise NotImplementedError()
+
+ def setDbgBreakpoint(self, file, lineno):
+ raise NotImplementedError()
+
+ def getDbgExpression(self, expr):
+ raise NotImplementedError()
+
+ def getDbgLastLine(self):
+ if len(self.history) == 0:
+ return None
+
+ return self.history[-1]
+
+ def feed_dbg(self, text):
+ self.terminal.feed_child(text)
+
+
+ def showClientIOWindow(self):
+ if not self.clientIOWnd:
+ self.clientIOWnd = ClientIOWindow.ClientIOWindow(self, self.client_ptymaster)
+
+
+
+
+def launchDebugger(wnd):
+
+ wnd.showClientIOWindow()
+
+ wnd.setDbgBreakpoint("main.cpp", 15)
+ wnd.setDbgRun()
+ res = wnd.getDbgExpression("a")
+ print "Result = ", res
+
+ wnd.setDbgQuit()
+
+ gtk.main()
+
+
+
+
+
--- /dev/null
+#!/usr/bin/python
+#shuber, 2008-06-04
+
+__author__ = "shuber"
+
+
+import gtk
+import os
+import re
+import string
+import sys
+import time
+
+import DbgWindow
+
+
+class GdbWindow (DbgWindow.DbgWindow):
+
+
+ def __init__(self, clientCmd):
+ DbgWindow.DbgWindow.__init__(self, clientCmd)
+
+ def getDbgArgv(self):
+ return ["gdb", "--fullname", string.split(self.clientCmd)[0]]
+
+ def setDbgPty(self, pty):
+ ttyname = os.ttyname(pty)
+ self.feed_dbg("set inferior-tty %s\n" % (ttyname,))
+
+ def setDbgRun(self):
+ argv = string.join(string.split(self.clientCmd)[1:])
+ self.feed_dbg("run " + argv + "\n")
+
+ def setDbgQuit(self):
+ self.feed_dbg("quit\n")
+ self.waitForDbgNewline()
+ self.feed_dbg("y\n");
+
+ def setDbgContinue(self):
+ self.feed_dbg("cont\n");
+
+ def setDbgBreakpoint(self, file, lineno):
+ self.feed_dbg("break %s:%d\n" % (file, lineno))
+
+ def getDbgExpression(self, expr):
+
+ self.waitForDbgNewline()
+ self.feed_dbg("print " + expr + "\n")
+
+ rx = re.compile("^\$[1-9][0-9]* = .*$")
+ response = self.waitForDbgRx(rx)
+
+ split = string.split(response, "=")
+ return string.join(split[1:], "=").strip()
+
+
+
+if __name__ == "__main__":
+
+
+ gdbwnd = GdbWindow(string.join(sys.argv[1:]))
+ DbgWindow.launchDebugger(gdbwnd)
+
+
+
+