1*30fdc8d8SChris Lattner //===-- Debugger.cpp --------------------------------------------*- C++ -*-===//
2*30fdc8d8SChris Lattner //
3*30fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
4*30fdc8d8SChris Lattner //
5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
7*30fdc8d8SChris Lattner //
8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
9*30fdc8d8SChris Lattner 
10*30fdc8d8SChris Lattner #include "lldb/lldb-private.h"
11*30fdc8d8SChris Lattner #include "lldb/Core/ConnectionFileDescriptor.h"
12*30fdc8d8SChris Lattner #include "lldb/Core/Debugger.h"
13*30fdc8d8SChris Lattner #include "lldb/Core/InputReader.h"
14*30fdc8d8SChris Lattner #include "lldb/Core/State.h"
15*30fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
16*30fdc8d8SChris Lattner 
17*30fdc8d8SChris Lattner #include "lldb/Target/TargetList.h"
18*30fdc8d8SChris Lattner #include "lldb/Target/Process.h"
19*30fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
20*30fdc8d8SChris Lattner 
21*30fdc8d8SChris Lattner 
22*30fdc8d8SChris Lattner using namespace lldb;
23*30fdc8d8SChris Lattner using namespace lldb_private;
24*30fdc8d8SChris Lattner 
25*30fdc8d8SChris Lattner int Debugger::g_shared_debugger_refcount = 0;
26*30fdc8d8SChris Lattner bool Debugger::g_in_terminate = false;
27*30fdc8d8SChris Lattner 
28*30fdc8d8SChris Lattner Debugger::DebuggerSP &
29*30fdc8d8SChris Lattner Debugger::GetDebuggerSP ()
30*30fdc8d8SChris Lattner {
31*30fdc8d8SChris Lattner     static DebuggerSP g_shared_debugger_sp;
32*30fdc8d8SChris Lattner     return g_shared_debugger_sp;
33*30fdc8d8SChris Lattner }
34*30fdc8d8SChris Lattner 
35*30fdc8d8SChris Lattner void
36*30fdc8d8SChris Lattner Debugger::Initialize ()
37*30fdc8d8SChris Lattner {
38*30fdc8d8SChris Lattner     g_shared_debugger_refcount++;
39*30fdc8d8SChris Lattner     if (GetDebuggerSP().get() == NULL)
40*30fdc8d8SChris Lattner     {
41*30fdc8d8SChris Lattner         GetDebuggerSP().reset (new Debugger());
42*30fdc8d8SChris Lattner         lldb_private::Initialize();
43*30fdc8d8SChris Lattner         GetDebuggerSP()->GetCommandInterpreter().Initialize();
44*30fdc8d8SChris Lattner     }
45*30fdc8d8SChris Lattner }
46*30fdc8d8SChris Lattner 
47*30fdc8d8SChris Lattner void
48*30fdc8d8SChris Lattner Debugger::Terminate ()
49*30fdc8d8SChris Lattner {
50*30fdc8d8SChris Lattner     g_shared_debugger_refcount--;
51*30fdc8d8SChris Lattner     if (g_shared_debugger_refcount == 0)
52*30fdc8d8SChris Lattner     {
53*30fdc8d8SChris Lattner         // Because Terminate is called also in the destructor, we need to make sure
54*30fdc8d8SChris Lattner         // that none of the calls to GetSharedInstance leads to a call to Initialize,
55*30fdc8d8SChris Lattner         // thus bumping the refcount back to 1 & causing Debugger::~Debugger to try to
56*30fdc8d8SChris Lattner         // re-terminate.  So we use g_in_terminate to indicate this condition.
57*30fdc8d8SChris Lattner         // When we can require at least Initialize to be called, we won't have to do
58*30fdc8d8SChris Lattner         // this since then the GetSharedInstance won't have to auto-call Initialize...
59*30fdc8d8SChris Lattner 
60*30fdc8d8SChris Lattner         g_in_terminate = true;
61*30fdc8d8SChris Lattner         int num_targets = GetDebuggerSP()->GetTargetList().GetNumTargets();
62*30fdc8d8SChris Lattner         for (int i = 0; i < num_targets; i++)
63*30fdc8d8SChris Lattner         {
64*30fdc8d8SChris Lattner             ProcessSP process_sp(GetDebuggerSP()->GetTargetList().GetTargetAtIndex (i)->GetProcessSP());
65*30fdc8d8SChris Lattner             if (process_sp)
66*30fdc8d8SChris Lattner                 process_sp->Destroy();
67*30fdc8d8SChris Lattner         }
68*30fdc8d8SChris Lattner         GetDebuggerSP()->DisconnectInput();
69*30fdc8d8SChris Lattner         lldb_private::WillTerminate();
70*30fdc8d8SChris Lattner         GetDebuggerSP().reset();
71*30fdc8d8SChris Lattner     }
72*30fdc8d8SChris Lattner }
73*30fdc8d8SChris Lattner 
74*30fdc8d8SChris Lattner Debugger &
75*30fdc8d8SChris Lattner Debugger::GetSharedInstance()
76*30fdc8d8SChris Lattner {
77*30fdc8d8SChris Lattner     // Don't worry about thread race conditions with the code below as
78*30fdc8d8SChris Lattner     // lldb_private::Initialize(); does this in a thread safe way. I just
79*30fdc8d8SChris Lattner     // want to avoid having to lock and unlock a mutex in
80*30fdc8d8SChris Lattner     // lldb_private::Initialize(); every time we want to access the
81*30fdc8d8SChris Lattner     // Debugger shared instance.
82*30fdc8d8SChris Lattner 
83*30fdc8d8SChris Lattner     // FIXME: We intend to require clients to call Initialize by hand (since they
84*30fdc8d8SChris Lattner     // will also have to call Terminate by hand.)  But for now it is not clear where
85*30fdc8d8SChris Lattner     // we can reliably call these in JH.  So the present version initializes on first use
86*30fdc8d8SChris Lattner     // here, and terminates in the destructor.
87*30fdc8d8SChris Lattner     if (g_shared_debugger_refcount == 0 && !g_in_terminate)
88*30fdc8d8SChris Lattner         Initialize();
89*30fdc8d8SChris Lattner 
90*30fdc8d8SChris Lattner     assert(GetDebuggerSP().get()!= NULL);
91*30fdc8d8SChris Lattner     return *(GetDebuggerSP().get());
92*30fdc8d8SChris Lattner }
93*30fdc8d8SChris Lattner 
94*30fdc8d8SChris Lattner Debugger::Debugger () :
95*30fdc8d8SChris Lattner     m_input_comm("debugger.input"),
96*30fdc8d8SChris Lattner     m_input_file (),
97*30fdc8d8SChris Lattner     m_output_file (),
98*30fdc8d8SChris Lattner     m_error_file (),
99*30fdc8d8SChris Lattner     m_async_execution (true),
100*30fdc8d8SChris Lattner     m_target_list (),
101*30fdc8d8SChris Lattner     m_listener ("lldb.Debugger"),
102*30fdc8d8SChris Lattner     m_source_manager (),
103*30fdc8d8SChris Lattner     m_command_interpreter (eScriptLanguageDefault, false, &m_listener, m_source_manager),
104*30fdc8d8SChris Lattner     m_input_readers (),
105*30fdc8d8SChris Lattner     m_input_reader_data ()
106*30fdc8d8SChris Lattner {
107*30fdc8d8SChris Lattner }
108*30fdc8d8SChris Lattner 
109*30fdc8d8SChris Lattner Debugger::~Debugger ()
110*30fdc8d8SChris Lattner {
111*30fdc8d8SChris Lattner     // FIXME:
112*30fdc8d8SChris Lattner     // Remove this once this version of lldb has made its way through a build.
113*30fdc8d8SChris Lattner     Terminate();
114*30fdc8d8SChris Lattner }
115*30fdc8d8SChris Lattner 
116*30fdc8d8SChris Lattner 
117*30fdc8d8SChris Lattner bool
118*30fdc8d8SChris Lattner Debugger::GetAsyncExecution ()
119*30fdc8d8SChris Lattner {
120*30fdc8d8SChris Lattner     return m_async_execution;
121*30fdc8d8SChris Lattner }
122*30fdc8d8SChris Lattner 
123*30fdc8d8SChris Lattner void
124*30fdc8d8SChris Lattner Debugger::SetAsyncExecution (bool async_execution)
125*30fdc8d8SChris Lattner {
126*30fdc8d8SChris Lattner     static bool value_has_been_set = false;
127*30fdc8d8SChris Lattner 
128*30fdc8d8SChris Lattner     if (!value_has_been_set)
129*30fdc8d8SChris Lattner     {
130*30fdc8d8SChris Lattner         value_has_been_set = true;
131*30fdc8d8SChris Lattner         m_async_execution = async_execution;
132*30fdc8d8SChris Lattner         m_command_interpreter.SetSynchronous (!async_execution);
133*30fdc8d8SChris Lattner     }
134*30fdc8d8SChris Lattner }
135*30fdc8d8SChris Lattner 
136*30fdc8d8SChris Lattner void
137*30fdc8d8SChris Lattner Debugger::DisconnectInput()
138*30fdc8d8SChris Lattner {
139*30fdc8d8SChris Lattner     m_input_comm.Clear ();
140*30fdc8d8SChris Lattner }
141*30fdc8d8SChris Lattner 
142*30fdc8d8SChris Lattner void
143*30fdc8d8SChris Lattner Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
144*30fdc8d8SChris Lattner {
145*30fdc8d8SChris Lattner     m_input_file.SetFileHandle (fh, tranfer_ownership);
146*30fdc8d8SChris Lattner     if (m_input_file.GetFileHandle() == NULL)
147*30fdc8d8SChris Lattner         m_input_file.SetFileHandle (stdin, false);
148*30fdc8d8SChris Lattner 
149*30fdc8d8SChris Lattner     // Disconnect from any old connection if we had one
150*30fdc8d8SChris Lattner     m_input_comm.Disconnect ();
151*30fdc8d8SChris Lattner     m_input_comm.SetConnection (new ConnectionFileDescriptor (::fileno (GetInputFileHandle()), true));
152*30fdc8d8SChris Lattner     m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
153*30fdc8d8SChris Lattner 
154*30fdc8d8SChris Lattner     Error error;
155*30fdc8d8SChris Lattner     if (m_input_comm.StartReadThread (&error) == false)
156*30fdc8d8SChris Lattner     {
157*30fdc8d8SChris Lattner         FILE *err_fh = GetErrorFileHandle();
158*30fdc8d8SChris Lattner         if (err_fh)
159*30fdc8d8SChris Lattner         {
160*30fdc8d8SChris Lattner             ::fprintf (err_fh, "error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
161*30fdc8d8SChris Lattner             exit(1);
162*30fdc8d8SChris Lattner         }
163*30fdc8d8SChris Lattner     }
164*30fdc8d8SChris Lattner 
165*30fdc8d8SChris Lattner }
166*30fdc8d8SChris Lattner 
167*30fdc8d8SChris Lattner FILE *
168*30fdc8d8SChris Lattner Debugger::GetInputFileHandle ()
169*30fdc8d8SChris Lattner {
170*30fdc8d8SChris Lattner     return m_input_file.GetFileHandle();
171*30fdc8d8SChris Lattner }
172*30fdc8d8SChris Lattner 
173*30fdc8d8SChris Lattner 
174*30fdc8d8SChris Lattner void
175*30fdc8d8SChris Lattner Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
176*30fdc8d8SChris Lattner {
177*30fdc8d8SChris Lattner     m_output_file.SetFileHandle (fh, tranfer_ownership);
178*30fdc8d8SChris Lattner     if (m_output_file.GetFileHandle() == NULL)
179*30fdc8d8SChris Lattner         m_output_file.SetFileHandle (stdin, false);
180*30fdc8d8SChris Lattner }
181*30fdc8d8SChris Lattner 
182*30fdc8d8SChris Lattner FILE *
183*30fdc8d8SChris Lattner Debugger::GetOutputFileHandle ()
184*30fdc8d8SChris Lattner {
185*30fdc8d8SChris Lattner     return m_output_file.GetFileHandle();
186*30fdc8d8SChris Lattner }
187*30fdc8d8SChris Lattner 
188*30fdc8d8SChris Lattner void
189*30fdc8d8SChris Lattner Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
190*30fdc8d8SChris Lattner {
191*30fdc8d8SChris Lattner     m_error_file.SetFileHandle (fh, tranfer_ownership);
192*30fdc8d8SChris Lattner     if (m_error_file.GetFileHandle() == NULL)
193*30fdc8d8SChris Lattner         m_error_file.SetFileHandle (stdin, false);
194*30fdc8d8SChris Lattner }
195*30fdc8d8SChris Lattner 
196*30fdc8d8SChris Lattner 
197*30fdc8d8SChris Lattner FILE *
198*30fdc8d8SChris Lattner Debugger::GetErrorFileHandle ()
199*30fdc8d8SChris Lattner {
200*30fdc8d8SChris Lattner     return m_error_file.GetFileHandle();
201*30fdc8d8SChris Lattner }
202*30fdc8d8SChris Lattner 
203*30fdc8d8SChris Lattner CommandInterpreter &
204*30fdc8d8SChris Lattner Debugger::GetCommandInterpreter ()
205*30fdc8d8SChris Lattner {
206*30fdc8d8SChris Lattner     return m_command_interpreter;
207*30fdc8d8SChris Lattner }
208*30fdc8d8SChris Lattner 
209*30fdc8d8SChris Lattner Listener &
210*30fdc8d8SChris Lattner Debugger::GetListener ()
211*30fdc8d8SChris Lattner {
212*30fdc8d8SChris Lattner     return m_listener;
213*30fdc8d8SChris Lattner }
214*30fdc8d8SChris Lattner 
215*30fdc8d8SChris Lattner 
216*30fdc8d8SChris Lattner TargetSP
217*30fdc8d8SChris Lattner Debugger::GetCurrentTarget ()
218*30fdc8d8SChris Lattner {
219*30fdc8d8SChris Lattner     return m_target_list.GetCurrentTarget ();
220*30fdc8d8SChris Lattner }
221*30fdc8d8SChris Lattner 
222*30fdc8d8SChris Lattner ExecutionContext
223*30fdc8d8SChris Lattner Debugger::GetCurrentExecutionContext ()
224*30fdc8d8SChris Lattner {
225*30fdc8d8SChris Lattner     ExecutionContext exe_ctx;
226*30fdc8d8SChris Lattner     exe_ctx.Clear();
227*30fdc8d8SChris Lattner 
228*30fdc8d8SChris Lattner     lldb::TargetSP target_sp = GetCurrentTarget();
229*30fdc8d8SChris Lattner     exe_ctx.target = target_sp.get();
230*30fdc8d8SChris Lattner 
231*30fdc8d8SChris Lattner     if (target_sp)
232*30fdc8d8SChris Lattner     {
233*30fdc8d8SChris Lattner         exe_ctx.process = target_sp->GetProcessSP().get();
234*30fdc8d8SChris Lattner         if (exe_ctx.process && exe_ctx.process->IsRunning() == false)
235*30fdc8d8SChris Lattner         {
236*30fdc8d8SChris Lattner             exe_ctx.thread = exe_ctx.process->GetThreadList().GetCurrentThread().get();
237*30fdc8d8SChris Lattner             if (exe_ctx.thread == NULL)
238*30fdc8d8SChris Lattner                 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
239*30fdc8d8SChris Lattner             if (exe_ctx.thread)
240*30fdc8d8SChris Lattner             {
241*30fdc8d8SChris Lattner                 exe_ctx.frame = exe_ctx.thread->GetCurrentFrame().get();
242*30fdc8d8SChris Lattner                 if (exe_ctx.frame == NULL)
243*30fdc8d8SChris Lattner                     exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex (0).get();
244*30fdc8d8SChris Lattner             }
245*30fdc8d8SChris Lattner         }
246*30fdc8d8SChris Lattner     }
247*30fdc8d8SChris Lattner     return exe_ctx;
248*30fdc8d8SChris Lattner 
249*30fdc8d8SChris Lattner }
250*30fdc8d8SChris Lattner 
251*30fdc8d8SChris Lattner SourceManager &
252*30fdc8d8SChris Lattner Debugger::GetSourceManager ()
253*30fdc8d8SChris Lattner {
254*30fdc8d8SChris Lattner     return m_source_manager;
255*30fdc8d8SChris Lattner }
256*30fdc8d8SChris Lattner 
257*30fdc8d8SChris Lattner 
258*30fdc8d8SChris Lattner TargetList&
259*30fdc8d8SChris Lattner Debugger::GetTargetList ()
260*30fdc8d8SChris Lattner {
261*30fdc8d8SChris Lattner     return m_target_list;
262*30fdc8d8SChris Lattner }
263*30fdc8d8SChris Lattner 
264*30fdc8d8SChris Lattner void
265*30fdc8d8SChris Lattner Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
266*30fdc8d8SChris Lattner {
267*30fdc8d8SChris Lattner     ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
268*30fdc8d8SChris Lattner }
269*30fdc8d8SChris Lattner 
270*30fdc8d8SChris Lattner 
271*30fdc8d8SChris Lattner void
272*30fdc8d8SChris Lattner Debugger::DispatchInput (const char *bytes, size_t bytes_len)
273*30fdc8d8SChris Lattner {
274*30fdc8d8SChris Lattner     if (bytes == NULL || bytes_len == 0)
275*30fdc8d8SChris Lattner         return;
276*30fdc8d8SChris Lattner 
277*30fdc8d8SChris Lattner     // TODO: implement the STDIO to the process as an input reader...
278*30fdc8d8SChris Lattner     TargetSP target = GetCurrentTarget();
279*30fdc8d8SChris Lattner     if (target.get() != NULL)
280*30fdc8d8SChris Lattner     {
281*30fdc8d8SChris Lattner         ProcessSP process_sp = target->GetProcessSP();
282*30fdc8d8SChris Lattner         if (process_sp.get() != NULL
283*30fdc8d8SChris Lattner             && StateIsRunningState (process_sp->GetState()))
284*30fdc8d8SChris Lattner         {
285*30fdc8d8SChris Lattner             Error error;
286*30fdc8d8SChris Lattner             if (process_sp->PutSTDIN (bytes, bytes_len, error) == bytes_len)
287*30fdc8d8SChris Lattner                 return;
288*30fdc8d8SChris Lattner         }
289*30fdc8d8SChris Lattner     }
290*30fdc8d8SChris Lattner 
291*30fdc8d8SChris Lattner     WriteToDefaultReader (bytes, bytes_len);
292*30fdc8d8SChris Lattner }
293*30fdc8d8SChris Lattner 
294*30fdc8d8SChris Lattner void
295*30fdc8d8SChris Lattner Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
296*30fdc8d8SChris Lattner {
297*30fdc8d8SChris Lattner     if (bytes && bytes_len)
298*30fdc8d8SChris Lattner         m_input_reader_data.append (bytes, bytes_len);
299*30fdc8d8SChris Lattner 
300*30fdc8d8SChris Lattner     if (m_input_reader_data.empty())
301*30fdc8d8SChris Lattner         return;
302*30fdc8d8SChris Lattner 
303*30fdc8d8SChris Lattner     while (!m_input_readers.empty() && !m_input_reader_data.empty())
304*30fdc8d8SChris Lattner     {
305*30fdc8d8SChris Lattner         while (CheckIfTopInputReaderIsDone ())
306*30fdc8d8SChris Lattner             /* Do nothing. */;
307*30fdc8d8SChris Lattner 
308*30fdc8d8SChris Lattner         // Get the input reader from the top of the stack
309*30fdc8d8SChris Lattner         InputReaderSP reader_sp(m_input_readers.top());
310*30fdc8d8SChris Lattner 
311*30fdc8d8SChris Lattner         if (!reader_sp)
312*30fdc8d8SChris Lattner             break;
313*30fdc8d8SChris Lattner 
314*30fdc8d8SChris Lattner         size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.data(),
315*30fdc8d8SChris Lattner                                                           m_input_reader_data.size());
316*30fdc8d8SChris Lattner         if (bytes_handled)
317*30fdc8d8SChris Lattner         {
318*30fdc8d8SChris Lattner             m_input_reader_data.erase (0, bytes_handled);
319*30fdc8d8SChris Lattner         }
320*30fdc8d8SChris Lattner         else
321*30fdc8d8SChris Lattner         {
322*30fdc8d8SChris Lattner             // No bytes were handled, we might not have reached our
323*30fdc8d8SChris Lattner             // granularity, just return and wait for more data
324*30fdc8d8SChris Lattner             break;
325*30fdc8d8SChris Lattner         }
326*30fdc8d8SChris Lattner     }
327*30fdc8d8SChris Lattner 
328*30fdc8d8SChris Lattner     // Flush out any input readers that are donesvn
329*30fdc8d8SChris Lattner     while (CheckIfTopInputReaderIsDone ())
330*30fdc8d8SChris Lattner         /* Do nothing. */;
331*30fdc8d8SChris Lattner 
332*30fdc8d8SChris Lattner }
333*30fdc8d8SChris Lattner 
334*30fdc8d8SChris Lattner void
335*30fdc8d8SChris Lattner Debugger::PushInputReader (const InputReaderSP& reader_sp)
336*30fdc8d8SChris Lattner {
337*30fdc8d8SChris Lattner     if (!reader_sp)
338*30fdc8d8SChris Lattner         return;
339*30fdc8d8SChris Lattner     if (!m_input_readers.empty())
340*30fdc8d8SChris Lattner     {
341*30fdc8d8SChris Lattner         // Deactivate the old top reader
342*30fdc8d8SChris Lattner         InputReaderSP top_reader_sp (m_input_readers.top());
343*30fdc8d8SChris Lattner         if (top_reader_sp)
344*30fdc8d8SChris Lattner             top_reader_sp->Notify (eInputReaderDeactivate);
345*30fdc8d8SChris Lattner     }
346*30fdc8d8SChris Lattner     m_input_readers.push (reader_sp);
347*30fdc8d8SChris Lattner     reader_sp->Notify (eInputReaderActivate);
348*30fdc8d8SChris Lattner     ActivateInputReader (reader_sp);
349*30fdc8d8SChris Lattner }
350*30fdc8d8SChris Lattner 
351*30fdc8d8SChris Lattner bool
352*30fdc8d8SChris Lattner Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp)
353*30fdc8d8SChris Lattner {
354*30fdc8d8SChris Lattner     bool result = false;
355*30fdc8d8SChris Lattner 
356*30fdc8d8SChris Lattner     // The reader on the stop of the stack is done, so let the next
357*30fdc8d8SChris Lattner     // read on the stack referesh its prompt and if there is one...
358*30fdc8d8SChris Lattner     if (!m_input_readers.empty())
359*30fdc8d8SChris Lattner     {
360*30fdc8d8SChris Lattner         InputReaderSP reader_sp(m_input_readers.top());
361*30fdc8d8SChris Lattner 
362*30fdc8d8SChris Lattner         if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
363*30fdc8d8SChris Lattner         {
364*30fdc8d8SChris Lattner             m_input_readers.pop ();
365*30fdc8d8SChris Lattner             reader_sp->Notify (eInputReaderDeactivate);
366*30fdc8d8SChris Lattner             reader_sp->Notify (eInputReaderDone);
367*30fdc8d8SChris Lattner             result = true;
368*30fdc8d8SChris Lattner 
369*30fdc8d8SChris Lattner             if (!m_input_readers.empty())
370*30fdc8d8SChris Lattner             {
371*30fdc8d8SChris Lattner                 reader_sp = m_input_readers.top();
372*30fdc8d8SChris Lattner                 if (reader_sp)
373*30fdc8d8SChris Lattner                 {
374*30fdc8d8SChris Lattner                     ActivateInputReader (reader_sp);
375*30fdc8d8SChris Lattner                     reader_sp->Notify (eInputReaderReactivate);
376*30fdc8d8SChris Lattner                 }
377*30fdc8d8SChris Lattner             }
378*30fdc8d8SChris Lattner         }
379*30fdc8d8SChris Lattner     }
380*30fdc8d8SChris Lattner     return result;
381*30fdc8d8SChris Lattner }
382*30fdc8d8SChris Lattner 
383*30fdc8d8SChris Lattner bool
384*30fdc8d8SChris Lattner Debugger::CheckIfTopInputReaderIsDone ()
385*30fdc8d8SChris Lattner {
386*30fdc8d8SChris Lattner     bool result = false;
387*30fdc8d8SChris Lattner     if (!m_input_readers.empty())
388*30fdc8d8SChris Lattner     {
389*30fdc8d8SChris Lattner         InputReaderSP reader_sp(m_input_readers.top());
390*30fdc8d8SChris Lattner 
391*30fdc8d8SChris Lattner         if (reader_sp && reader_sp->IsDone())
392*30fdc8d8SChris Lattner         {
393*30fdc8d8SChris Lattner             result = true;
394*30fdc8d8SChris Lattner             PopInputReader (reader_sp);
395*30fdc8d8SChris Lattner         }
396*30fdc8d8SChris Lattner     }
397*30fdc8d8SChris Lattner     return result;
398*30fdc8d8SChris Lattner }
399*30fdc8d8SChris Lattner 
400*30fdc8d8SChris Lattner void
401*30fdc8d8SChris Lattner Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
402*30fdc8d8SChris Lattner {
403*30fdc8d8SChris Lattner     FILE *in_fh = GetInputFileHandle();
404*30fdc8d8SChris Lattner 
405*30fdc8d8SChris Lattner     if (in_fh)
406*30fdc8d8SChris Lattner     {
407*30fdc8d8SChris Lattner         struct termios in_fh_termios;
408*30fdc8d8SChris Lattner         int in_fd = fileno (in_fh);
409*30fdc8d8SChris Lattner         if (::tcgetattr(in_fd, &in_fh_termios) == 0)
410*30fdc8d8SChris Lattner         {
411*30fdc8d8SChris Lattner             if (reader_sp->GetEcho())
412*30fdc8d8SChris Lattner                 in_fh_termios.c_lflag |= ECHO;  // Turn on echoing
413*30fdc8d8SChris Lattner             else
414*30fdc8d8SChris Lattner                 in_fh_termios.c_lflag &= ~ECHO; // Turn off echoing
415*30fdc8d8SChris Lattner 
416*30fdc8d8SChris Lattner             switch (reader_sp->GetGranularity())
417*30fdc8d8SChris Lattner             {
418*30fdc8d8SChris Lattner             case eInputReaderGranularityByte:
419*30fdc8d8SChris Lattner             case eInputReaderGranularityWord:
420*30fdc8d8SChris Lattner                 in_fh_termios.c_lflag &= ~ICANON;   // Get one char at a time
421*30fdc8d8SChris Lattner                 break;
422*30fdc8d8SChris Lattner 
423*30fdc8d8SChris Lattner             case eInputReaderGranularityLine:
424*30fdc8d8SChris Lattner             case eInputReaderGranularityAll:
425*30fdc8d8SChris Lattner                 in_fh_termios.c_lflag |= ICANON;   // Get lines at a time
426*30fdc8d8SChris Lattner                 break;
427*30fdc8d8SChris Lattner 
428*30fdc8d8SChris Lattner             default:
429*30fdc8d8SChris Lattner                 break;
430*30fdc8d8SChris Lattner             }
431*30fdc8d8SChris Lattner             ::tcsetattr (in_fd, TCSANOW, &in_fh_termios);
432*30fdc8d8SChris Lattner         }
433*30fdc8d8SChris Lattner     }
434*30fdc8d8SChris Lattner }
435