842f76862123027b809e690aebab5fda54ae220b
[pygdb.git] / GdbTerminal.py
1 #!/usr/bin/python
2 #shuber, 2008-06-04
3
4 __author__ = "shuber"
5
6
7 import gtk
8 import os
9 import re
10 import string
11 import sys
12 import time
13
14 import DbgTerminal
15
16
17 class GdbTerminal (DbgTerminal.DbgTerminal):
18
19
20 def __init__(self, clientCmd):
21 DbgTerminal.DbgTerminal.__init__(self, clientCmd)
22
23 def getArgv(self):
24 return ["gdb", "--fullname", string.split(self.clientCmd)[0]]
25
26 def setRun(self):
27 argv = string.join(string.split(self.clientCmd)[1:])
28 self.feed_child("run " + argv + "\n")
29
30 def setContinue(self):
31 self.feed_child("cont\n");
32
33 def setStepover(self):
34 self.feed_child("next\n");
35
36 def setStepin(self):
37 self.feed_child("step\n");
38
39 def setStepout(self):
40 bt = self.getBacktrace()
41
42 if len(bt) < 2:
43 self.setContinue()
44
45 else:
46 #Get the second line
47 sec = bt[1]
48
49 #Check if it is a backtrace line
50 if re.compile("^#1\s+.*\s\S+:\d+$").search(sec):
51 pos = string.split(sec)[-1]
52 self.feed_child("advance %s\n" % pos)
53
54
55 def setQuit(self):
56 self.feed_child("quit\n")
57 self.waitForNewline()
58 self.feed_child("y\n");
59
60 def setPty(self, pty):
61 ttyname = os.ttyname(pty)
62 self.__getAnswerFromCmd("set inferior-tty %s\n" % (ttyname,))
63
64 def setBreakpoint(self, file, lineno, condition=None):
65 his = self.getHistoryLen()
66 if condition==None:
67 self.feed_child("break %s:%s\n" % (file, str(lineno)))
68 else:
69 self.feed_child("break %s:%s if %s\n" % \
70 (file, str(lineno), condition))
71
72 rx = "^Breakpoint |^No |^\(gdb\) "
73 his, response = self.waitForRx(rx, his)
74
75 answer = None
76
77 if response[0:10] == "Breakpoint":
78 answer = string.split(response)[1].strip()
79
80 #Wants an answer: "No"
81 if response[0:14] == "No source file":
82 self.feed_child("n\n");
83
84 #Wait again for (gdb)...
85 self.waitForPrompt(his)
86
87 return answer
88
89
90 def delBreakpoint(self, breakpoint):
91 self.__getAnswerFromCmd("del breakpoint %s\n" % (breakpoint,))
92
93
94 def getBreakpoints(self):
95 bplines = self.__getAnswerFromCmd("info breakpoints\n")
96
97 rxbp = re.compile("^\d+\s+breakpoint")
98 rxpos = re.compile("^.*at\s+\S+:\d+$")
99 rxcond = re.compile("^\s+stop only if")
100
101 bpnts = []
102 i = 1
103
104 #Parse the resulting lines
105 while i<len(bplines):
106 line = bplines[i]
107
108 if not rxbp.search(line):
109 i += 1
110 continue
111
112 #Get number of breakpoint
113 no = string.split(line)[0]
114
115 #This line does not contain the file!
116 #Check for next line...
117 if not rxpos.search(line):
118 i += 1
119 line = bplines[i]
120 if not rxpos.search(line):
121 i += 1
122 continue
123
124 pos = string.split(line)[-1]
125 [file,lineno] = string.split(pos,":")
126 cond = None
127
128 #Look for conditions
129 if i+1<len(bplines) and rxcond.search(bplines[i+1]):
130 i +=1
131 line = bplines[i]
132 cond = string.join(string.split(line," if ")[1:], " if ")
133 cond = cond.strip()
134
135 bpnts += [[no, file, lineno, cond]]
136 i += 1
137
138 return bpnts
139
140
141
142 def getExpression(self, expr):
143 answer = self.__getAnswerFromCmd("print " + expr + "\n")
144 answer = answer[-1]
145
146 if len(string.split(answer, "=")) == 1:
147 return answer.strip()
148
149 split = string.split(answer, "=")
150 return string.join(split[1:], "=").strip()
151
152
153 def listCodeSnippet(self):
154 return self.__getAnswerFromCmd("list\n")
155
156 def getBacktrace(self):
157
158 stack = []
159 answ = self.__getAnswerFromCmd("bt\n")
160
161 rxstartfull = re.compile("^\#\d+\s+0x[0-9a-f]+\s+in\s+\S+\s+\(")
162 rxstartshort = re.compile("^\#\d+\s+\S+\s+\(")
163 rxpos = re.compile("at \S+:\d+$")
164
165 try:
166
167 i=0
168 while i<len(answ):
169 line = answ[i]
170
171 while not rxstartfull.search(line) and not rxstartshort.search(line):
172 print "Warning: '", line, "' does not match bt entry."
173 i+=1
174 line = answ[i]
175
176 parts = line.split()
177
178 if rxstartfull.search(line):
179 func = parts[3]
180 addr = parts[1]
181 else:
182 func = parts[1]
183 addr = None
184
185
186 #Search for file position
187 while not rxpos.search(line):
188 print "Warning: '", line, "' does not match file pos marker."
189 i+=1
190 line = answ[i]
191
192 parts = line.split()
193 pos = parts[-1]
194 [file,lineno] = pos.split(":")
195
196 stack += [[addr,func,file,lineno]]
197
198 i+=1
199
200 except IndexError:
201 pass
202
203 return stack
204
205 def waitForPrompt(self, his):
206 rx = "^\(gdb\)"
207 return self.waitForRx(rx,his)
208
209 def __getAnswerFromCmd(self, cmd):
210 starthis = self.getHistoryLen()
211 self.feed_child(cmd)
212 endhis, response = self.waitForPrompt(starthis)
213
214 return self.history[starthis:endhis]
215
216
217 def testForActivity(self, his):
218 """Test whether debugger got active again"""
219
220 line = self.history[his]
221
222 if string.find(line, "\x1a\x1a") == 0:
223 tuples = string.split(line[2:], ":")
224 tuples[1] = int(tuples[1])
225 return "break", [tuples[0], int(tuples[1])]
226
227 if string.find(line, "Program exited") == 0:
228 code = string.split(line)[-1]
229
230 codeno = 0
231
232 #Parse the octal number
233 if code[0] == "O":
234 code = code[1:-1]
235 for c in code:
236 codeno = codeno*8 + int(c)
237
238 return "exited", codeno
239
240 return None
241
242
243 def testForInactivity(self, his):
244 """Test whether debugger got inactive"""
245 line = self.history[his]
246
247 if string.find(line, "Starting program:") == 0:
248 prog = string.join( string.split(line)[1:])
249 return "started", prog
250
251 if string.find(line, "Continuing.") == 0:
252 return "continued", None
253
254 if string.find(line, "\x1a\x1a") == 0:
255 rxcont = re.compile("^\(gdb\)\s+(cont|step|next|stepi|nexti|advance)")
256
257 if rxcont.search(self.history[his-1]):
258 return "stepped", None
259 if rxcont.search(self.history[his-2]):
260 return "stepped", None
261
262 return None
263
264
265
266
267
268
269
270
271 if __name__ == "__main__":
272
273
274 dbgterm = GdbTerminal(string.join(sys.argv[1:]))
275 dbgwnd = DbgTerminal.DbgWindow(dbgterm)
276
277 gtk.main()
278
279
280
281