19 import ClientIOTerminal
23 class DbgTerminal (vte
.Terminal
):
25 def __init__(self
, clientCmd
):
27 vte
.Terminal
.__init
__(self
)
33 self
.lastc
, self
.lastr
= 0,0
34 self
.gotActiveCallback
= []
35 self
.gotInactiveCallback
= []
36 self
.activityChanged
= None
39 self
.clientCmd
= clientCmd
40 #Open pseudo-terminal where to-be-debugged process reads/writes to
41 self
.client_ptymaster
, self
.client_ptyslave
= pty
.openpty()
43 #Set up terminal window and initialize debugger
44 self
.connect("cursor-moved", self
.contents_changed
)
45 self
.connect("child-exited", quitHandler
)
46 gobject
.timeout_add(50, self
.checkActivityChanged
)
49 fontdesc
= pango
.FontDescription("monospace 9")
50 self
.set_font(fontdesc
)
54 self
.childpid
= self
.fork_command( self
.getCommand(), self
.getArgv())
56 self
.setPty(self
.client_ptyslave
)
60 if self
.childpid
!= None:
62 os
.kill(self
.childpid
, 15);
65 def getClientExecuteable(self
):
66 return string
.split(self
.clientCmd
)[0]
69 def toAbsPath(self
, path
):
70 """convert path to an absolute path relative to the client
71 executable we debug."""
74 pwd
= os
.getcwd() + "/"
77 client
= self
.getClientExecuteable()
78 client
= relToAbsPath(pwd
, client
)
80 return relToAbsPath(client
, path
)
83 def checkActivityChanged(self
):
88 if self
.activityChanged
!= None:
90 res
= self
.activityChanged
91 self
.activityChanged
= None
95 print "got active: ", res
96 for cb
in self
.gotActiveCallback
:
99 print "got inactive: ", res
100 for cb
in self
.gotInactiveCallback
:
104 traceback
.print_exc()
111 def contents_changed(self
, term
):
112 assert( self
.getHistoryLen()>0 )
114 c
,r
= term
.get_cursor_position()
115 text
= self
.get_text_range(self
.lastr
,0,r
,c
,lambda *w
:True)
116 self
.lastc
, self
.lastr
= c
,r
118 #Remove annoying \n at the end
119 assert(text
[-1] == "\n")
122 #Get the lines and remove empty lines
123 lines
= string
.split(text
, "\n")
125 #Remove the incomplete line
126 len = max(0,self
.getHistoryLen())
127 self
.history
[-1] = lines
[0]
128 self
.history
+= lines
[1:]
131 #Check if activity status has been changed
132 for i
in range(len, self
.getHistoryLen()):
133 line
= self
.history
[i
]
135 res
= self
.testForInactivity(i
)
137 while self
.activityChanged
!= None:
138 print "wait for pending activity"
141 self
.setActive(False)
142 self
.activityChanged
= res
144 res
= self
.testForActivity(i
)
146 while self
.activityChanged
!= None:
147 print "wait for pending activity"
151 self
.activityChanged
= res
156 def waitForNewline(self
):
157 l
= self
.getHistoryLen()
158 while not self
.getHistoryLen() > l
:
161 def getHistoryLen(self
):
162 return len(self
.history
)
164 def waitForRx(self
, pat
, start
):
169 assert( curr
>=start
)
170 for no
in range(curr
, self
.getHistoryLen()):
171 line
= self
.history
[no
]
175 #Do not forget the last line
176 curr
= max(start
,self
.getHistoryLen()-1)
177 lr
, lc
= self
.lastr
, self
.lastc
179 while (self
.lastr
, self
.lastc
) == (lr
,lc
):
183 def getCommand(self
):
184 return self
.getArgv()[0];
187 raise NotImplementedError()
189 def setPty(self
, pty
):
190 raise NotImplementedError()
193 raise NotImplementedError()
195 def setContinue(self
):
196 raise NotImplementedError()
198 def setStepover(self
):
199 raise NotImplementedError()
202 raise NotImplementedError()
204 def setStepout(self
):
205 raise NotImplementedError()
208 raise NotImplementedError()
210 def setBreakpoint(self
, file, lineno
, condition
=False):
211 raise NotImplementedError()
213 def delBreakpoint(self
, breakpoint
):
214 raise NotImplementedError()
216 def getExpression(self
, expr
):
217 raise NotImplementedError()
219 def listCodeSnippet(self
):
220 raise NotImplementedError()
222 def getBacktrace(self
):
223 raise NotImplementedError()
225 def waitForPrompt(self
, his
):
226 raise NotImplementedError()
228 def testForActivity(self
, his
):
229 raise NotImplementedError()
231 def testForInactivity(self
, his
):
232 raise NotImplementedError()
234 def setActive(self
, isactive
):
235 self
.isactive
= isactive
249 def relToAbsPath(absfile
, relfile
):
250 """When an absfile is given and a relfile is given by
251 relative paths relative to absfile, determine the abs
254 #Get directories except for "." parts
255 relsplit
= filter(lambda x
: x
!=".", string
.split(relfile
, os
.sep
))
256 #Get the directories of absfile withouth the trailing filename
257 abssplit
= string
.split(absfile
, os
.sep
)[:-1]
259 #Determine number of ".." and remove them
261 while relsplit
[0] == "..":
266 return string
.join(abssplit
+ relsplit
, os
.sep
)
269 class DbgWindow (gtk
.Window
):
274 def __init__(self
, terminal
):
277 self
.terminal
= terminal
280 gtk
.Window
.__init
__(self
)
281 self
.connect("destroy", quitHandler
)
283 #Set title and add terminal
284 self
.set_title("Debugger I/O")
285 self
.terminal
.history
= []
286 self
.terminal
.history_length
= 5
287 self
.add(self
.terminal
)
292 def toggleClientIOWindow(self
):
293 if not self
.clientIOWnd
:
294 self
.clientIOWnd
= ClientIOTerminal
.ClientIOWindow(self
, \
295 self
.terminal
.client_ptymaster
)
297 self
.clientIOWnd
.destroy()
298 self
.clientIOWnd
= None
300 def isClientIOWindowExisting(self
):
301 return self
.clientIOWnd
!= None