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