blob: d4b9bf6c37c9679c7330f3a47ccd05b70a487ff8 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Debugger.cpp --------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-private.h"
11#include "lldb/Core/ConnectionFileDescriptor.h"
12#include "lldb/Core/Debugger.h"
13#include "lldb/Core/InputReader.h"
14#include "lldb/Core/State.h"
15#include "lldb/Core/Timer.h"
Greg Clayton66111032010-06-23 01:19:29 +000016#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Target/TargetList.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/Thread.h"
20
21
22using namespace lldb;
23using namespace lldb_private;
24
Greg Clayton66111032010-06-23 01:19:29 +000025static uint32_t g_shared_debugger_refcount = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026
Caroline Ticeebc1bb22010-06-30 16:22:25 +000027static lldb::user_id_t g_unique_id = 1;
28
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029void
30Debugger::Initialize ()
31{
Greg Clayton66111032010-06-23 01:19:29 +000032 if (g_shared_debugger_refcount == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033 lldb_private::Initialize();
Greg Clayton66111032010-06-23 01:19:29 +000034 g_shared_debugger_refcount++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035}
36
37void
38Debugger::Terminate ()
39{
Greg Clayton66111032010-06-23 01:19:29 +000040 if (g_shared_debugger_refcount > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041 {
Greg Clayton66111032010-06-23 01:19:29 +000042 g_shared_debugger_refcount--;
43 if (g_shared_debugger_refcount == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044 {
Greg Clayton66111032010-06-23 01:19:29 +000045 lldb_private::WillTerminate();
46 lldb_private::Terminate();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048 }
49}
50
Greg Clayton66111032010-06-23 01:19:29 +000051typedef std::vector<DebuggerSP> DebuggerList;
52
53static Mutex &
54GetDebuggerListMutex ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055{
Greg Clayton66111032010-06-23 01:19:29 +000056 static Mutex g_mutex(Mutex::eMutexTypeRecursive);
57 return g_mutex;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058}
59
Greg Clayton66111032010-06-23 01:19:29 +000060static DebuggerList &
61GetDebuggerList()
62{
63 // hide the static debugger list inside a singleton accessor to avoid
64 // global init contructors
65 static DebuggerList g_list;
66 return g_list;
67}
68
69
70DebuggerSP
71Debugger::CreateInstance ()
72{
73 DebuggerSP debugger_sp (new Debugger);
74 // Scope for locker
75 {
76 Mutex::Locker locker (GetDebuggerListMutex ());
77 GetDebuggerList().push_back(debugger_sp);
78 }
79 return debugger_sp;
80}
81
82lldb::DebuggerSP
83Debugger::GetSP ()
84{
85 lldb::DebuggerSP debugger_sp;
86
87 Mutex::Locker locker (GetDebuggerListMutex ());
88 DebuggerList &debugger_list = GetDebuggerList();
89 DebuggerList::iterator pos, end = debugger_list.end();
90 for (pos = debugger_list.begin(); pos != end; ++pos)
91 {
92 if ((*pos).get() == this)
93 {
94 debugger_sp = *pos;
95 break;
96 }
97 }
98 return debugger_sp;
99}
100
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000101lldb::DebuggerSP
102Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name)
103{
104 lldb::DebuggerSP debugger_sp;
105
106 Mutex::Locker locker (GetDebuggerListMutex ());
107 DebuggerList &debugger_list = GetDebuggerList();
108 DebuggerList::iterator pos, end = debugger_list.end();
109
110 for (pos = debugger_list.begin(); pos != end; ++pos)
111 {
112 if ((*pos).get()->m_instance_name == instance_name)
113 {
114 debugger_sp = *pos;
115 break;
116 }
117 }
118 return debugger_sp;
119}
Greg Clayton66111032010-06-23 01:19:29 +0000120
121TargetSP
122Debugger::FindTargetWithProcessID (lldb::pid_t pid)
123{
124 lldb::TargetSP target_sp;
125 Mutex::Locker locker (GetDebuggerListMutex ());
126 DebuggerList &debugger_list = GetDebuggerList();
127 DebuggerList::iterator pos, end = debugger_list.end();
128 for (pos = debugger_list.begin(); pos != end; ++pos)
129 {
130 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid);
131 if (target_sp)
132 break;
133 }
134 return target_sp;
135}
136
137
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138Debugger::Debugger () :
Caroline Ticeebc1bb22010-06-30 16:22:25 +0000139 UserID (g_unique_id++),
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000140 DebuggerInstanceSettings (*(Debugger::GetSettingsController().get())),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141 m_input_comm("debugger.input"),
142 m_input_file (),
143 m_output_file (),
144 m_error_file (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145 m_target_list (),
146 m_listener ("lldb.Debugger"),
147 m_source_manager (),
Greg Clayton66111032010-06-23 01:19:29 +0000148 m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
149 m_exe_ctx (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150 m_input_readers (),
Jim Inghame40e4212010-08-30 19:44:40 +0000151 m_input_reader_data (),
152 m_use_external_editor(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153{
Greg Clayton66111032010-06-23 01:19:29 +0000154 m_command_interpreter_ap->Initialize ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000155}
156
157Debugger::~Debugger ()
158{
Greg Clayton66111032010-06-23 01:19:29 +0000159 int num_targets = m_target_list.GetNumTargets();
160 for (int i = 0; i < num_targets; i++)
161 {
162 ProcessSP process_sp (m_target_list.GetTargetAtIndex (i)->GetProcessSP());
163 if (process_sp)
164 process_sp->Destroy();
165 }
166 DisconnectInput();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167}
168
169
170bool
171Debugger::GetAsyncExecution ()
172{
Greg Clayton66111032010-06-23 01:19:29 +0000173 return !m_command_interpreter_ap->GetSynchronous();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174}
175
176void
177Debugger::SetAsyncExecution (bool async_execution)
178{
Greg Clayton66111032010-06-23 01:19:29 +0000179 m_command_interpreter_ap->SetSynchronous (!async_execution);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180}
181
182void
183Debugger::DisconnectInput()
184{
185 m_input_comm.Clear ();
186}
187
188void
189Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
190{
191 m_input_file.SetFileHandle (fh, tranfer_ownership);
192 if (m_input_file.GetFileHandle() == NULL)
193 m_input_file.SetFileHandle (stdin, false);
194
195 // Disconnect from any old connection if we had one
196 m_input_comm.Disconnect ();
197 m_input_comm.SetConnection (new ConnectionFileDescriptor (::fileno (GetInputFileHandle()), true));
198 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
199
200 Error error;
201 if (m_input_comm.StartReadThread (&error) == false)
202 {
203 FILE *err_fh = GetErrorFileHandle();
204 if (err_fh)
205 {
206 ::fprintf (err_fh, "error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
207 exit(1);
208 }
209 }
210
211}
212
213FILE *
214Debugger::GetInputFileHandle ()
215{
216 return m_input_file.GetFileHandle();
217}
218
219
220void
221Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
222{
223 m_output_file.SetFileHandle (fh, tranfer_ownership);
224 if (m_output_file.GetFileHandle() == NULL)
225 m_output_file.SetFileHandle (stdin, false);
226}
227
228FILE *
229Debugger::GetOutputFileHandle ()
230{
231 return m_output_file.GetFileHandle();
232}
233
234void
235Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
236{
237 m_error_file.SetFileHandle (fh, tranfer_ownership);
238 if (m_error_file.GetFileHandle() == NULL)
239 m_error_file.SetFileHandle (stdin, false);
240}
241
242
243FILE *
244Debugger::GetErrorFileHandle ()
245{
246 return m_error_file.GetFileHandle();
247}
248
249CommandInterpreter &
250Debugger::GetCommandInterpreter ()
251{
Greg Clayton66111032010-06-23 01:19:29 +0000252 assert (m_command_interpreter_ap.get());
253 return *m_command_interpreter_ap;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000254}
255
256Listener &
257Debugger::GetListener ()
258{
259 return m_listener;
260}
261
262
263TargetSP
Jim Ingham2976d002010-08-26 21:32:51 +0000264Debugger::GetSelectedTarget ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000265{
Jim Ingham2976d002010-08-26 21:32:51 +0000266 return m_target_list.GetSelectedTarget ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000267}
268
269ExecutionContext
Jim Ingham2976d002010-08-26 21:32:51 +0000270Debugger::GetSelectedExecutionContext ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271{
272 ExecutionContext exe_ctx;
273 exe_ctx.Clear();
274
Jim Ingham2976d002010-08-26 21:32:51 +0000275 lldb::TargetSP target_sp = GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276 exe_ctx.target = target_sp.get();
277
278 if (target_sp)
279 {
280 exe_ctx.process = target_sp->GetProcessSP().get();
281 if (exe_ctx.process && exe_ctx.process->IsRunning() == false)
282 {
Jim Ingham2976d002010-08-26 21:32:51 +0000283 exe_ctx.thread = exe_ctx.process->GetThreadList().GetSelectedThread().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000284 if (exe_ctx.thread == NULL)
285 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
286 if (exe_ctx.thread)
287 {
Jim Ingham2976d002010-08-26 21:32:51 +0000288 exe_ctx.frame = exe_ctx.thread->GetSelectedFrame().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289 if (exe_ctx.frame == NULL)
290 exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex (0).get();
291 }
292 }
293 }
294 return exe_ctx;
295
296}
297
298SourceManager &
299Debugger::GetSourceManager ()
300{
301 return m_source_manager;
302}
303
304
305TargetList&
306Debugger::GetTargetList ()
307{
308 return m_target_list;
309}
310
311void
312Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
313{
314 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
315}
316
317
318void
319Debugger::DispatchInput (const char *bytes, size_t bytes_len)
320{
321 if (bytes == NULL || bytes_len == 0)
322 return;
323
324 // TODO: implement the STDIO to the process as an input reader...
Jim Ingham2976d002010-08-26 21:32:51 +0000325 TargetSP target = GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326 if (target.get() != NULL)
327 {
328 ProcessSP process_sp = target->GetProcessSP();
329 if (process_sp.get() != NULL
330 && StateIsRunningState (process_sp->GetState()))
331 {
332 Error error;
333 if (process_sp->PutSTDIN (bytes, bytes_len, error) == bytes_len)
334 return;
335 }
336 }
337
338 WriteToDefaultReader (bytes, bytes_len);
339}
340
341void
342Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
343{
344 if (bytes && bytes_len)
345 m_input_reader_data.append (bytes, bytes_len);
346
347 if (m_input_reader_data.empty())
348 return;
349
350 while (!m_input_readers.empty() && !m_input_reader_data.empty())
351 {
352 while (CheckIfTopInputReaderIsDone ())
353 /* Do nothing. */;
354
355 // Get the input reader from the top of the stack
356 InputReaderSP reader_sp(m_input_readers.top());
357
358 if (!reader_sp)
359 break;
360
Greg Clayton471b31c2010-07-20 22:52:08 +0000361 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000362 m_input_reader_data.size());
363 if (bytes_handled)
364 {
365 m_input_reader_data.erase (0, bytes_handled);
366 }
367 else
368 {
369 // No bytes were handled, we might not have reached our
370 // granularity, just return and wait for more data
371 break;
372 }
373 }
374
375 // Flush out any input readers that are donesvn
376 while (CheckIfTopInputReaderIsDone ())
377 /* Do nothing. */;
378
379}
380
381void
382Debugger::PushInputReader (const InputReaderSP& reader_sp)
383{
384 if (!reader_sp)
385 return;
386 if (!m_input_readers.empty())
387 {
388 // Deactivate the old top reader
389 InputReaderSP top_reader_sp (m_input_readers.top());
390 if (top_reader_sp)
391 top_reader_sp->Notify (eInputReaderDeactivate);
392 }
393 m_input_readers.push (reader_sp);
394 reader_sp->Notify (eInputReaderActivate);
395 ActivateInputReader (reader_sp);
396}
397
398bool
399Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp)
400{
401 bool result = false;
402
403 // The reader on the stop of the stack is done, so let the next
404 // read on the stack referesh its prompt and if there is one...
405 if (!m_input_readers.empty())
406 {
407 InputReaderSP reader_sp(m_input_readers.top());
408
409 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
410 {
411 m_input_readers.pop ();
412 reader_sp->Notify (eInputReaderDeactivate);
413 reader_sp->Notify (eInputReaderDone);
414 result = true;
415
416 if (!m_input_readers.empty())
417 {
418 reader_sp = m_input_readers.top();
419 if (reader_sp)
420 {
421 ActivateInputReader (reader_sp);
422 reader_sp->Notify (eInputReaderReactivate);
423 }
424 }
425 }
426 }
427 return result;
428}
429
430bool
431Debugger::CheckIfTopInputReaderIsDone ()
432{
433 bool result = false;
434 if (!m_input_readers.empty())
435 {
436 InputReaderSP reader_sp(m_input_readers.top());
437
438 if (reader_sp && reader_sp->IsDone())
439 {
440 result = true;
441 PopInputReader (reader_sp);
442 }
443 }
444 return result;
445}
446
447void
448Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
449{
450 FILE *in_fh = GetInputFileHandle();
451
452 if (in_fh)
453 {
454 struct termios in_fh_termios;
455 int in_fd = fileno (in_fh);
456 if (::tcgetattr(in_fd, &in_fh_termios) == 0)
457 {
458 if (reader_sp->GetEcho())
459 in_fh_termios.c_lflag |= ECHO; // Turn on echoing
460 else
461 in_fh_termios.c_lflag &= ~ECHO; // Turn off echoing
462
463 switch (reader_sp->GetGranularity())
464 {
465 case eInputReaderGranularityByte:
466 case eInputReaderGranularityWord:
467 in_fh_termios.c_lflag &= ~ICANON; // Get one char at a time
468 break;
469
470 case eInputReaderGranularityLine:
471 case eInputReaderGranularityAll:
472 in_fh_termios.c_lflag |= ICANON; // Get lines at a time
473 break;
474
475 default:
476 break;
477 }
478 ::tcsetattr (in_fd, TCSANOW, &in_fh_termios);
479 }
480 }
481}
Greg Clayton66111032010-06-23 01:19:29 +0000482
483void
484Debugger::UpdateExecutionContext (ExecutionContext *override_context)
485{
486 m_exe_ctx.Clear();
487
488 if (override_context != NULL)
489 {
490 m_exe_ctx.target = override_context->target;
491 m_exe_ctx.process = override_context->process;
492 m_exe_ctx.thread = override_context->thread;
493 m_exe_ctx.frame = override_context->frame;
494 }
495 else
496 {
Jim Ingham2976d002010-08-26 21:32:51 +0000497 TargetSP target_sp (GetSelectedTarget());
Greg Clayton66111032010-06-23 01:19:29 +0000498 if (target_sp)
499 {
500 m_exe_ctx.target = target_sp.get();
501 m_exe_ctx.process = target_sp->GetProcessSP().get();
Johnny Chen725945d2010-09-03 22:35:47 +0000502 if (m_exe_ctx.process && m_exe_ctx.process->IsAlive() && !m_exe_ctx.process->IsRunning())
Greg Clayton66111032010-06-23 01:19:29 +0000503 {
Jim Ingham2976d002010-08-26 21:32:51 +0000504 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetSelectedThread().get();
Greg Clayton66111032010-06-23 01:19:29 +0000505 if (m_exe_ctx.thread == NULL)
506 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
507 if (m_exe_ctx.thread)
508 {
Jim Ingham2976d002010-08-26 21:32:51 +0000509 m_exe_ctx.frame = m_exe_ctx.thread->GetSelectedFrame().get();
Greg Clayton66111032010-06-23 01:19:29 +0000510 if (m_exe_ctx.frame == NULL)
511 m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
512 }
513 }
514 }
515 }
516}
517
Caroline Ticeebc1bb22010-06-30 16:22:25 +0000518DebuggerSP
519Debugger::FindDebuggerWithID (lldb::user_id_t id)
520{
521 lldb::DebuggerSP debugger_sp;
522
523 Mutex::Locker locker (GetDebuggerListMutex ());
524 DebuggerList &debugger_list = GetDebuggerList();
525 DebuggerList::iterator pos, end = debugger_list.end();
526 for (pos = debugger_list.begin(); pos != end; ++pos)
527 {
528 if ((*pos).get()->GetID() == id)
529 {
530 debugger_sp = *pos;
531 break;
532 }
533 }
534 return debugger_sp;
535}
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000536
537lldb::UserSettingsControllerSP &
538Debugger::GetSettingsController (bool finish)
539{
540 static lldb::UserSettingsControllerSP g_settings_controller (new DebuggerSettingsController);
541 static bool initialized = false;
542
543 if (!initialized)
544 {
Jim Ingham95852752010-09-07 20:27:09 +0000545 initialized = UserSettingsController::InitializeSettingsController (g_settings_controller,
546 Debugger::DebuggerSettingsController::global_settings_table,
547 Debugger::DebuggerSettingsController::instance_settings_table);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000548 }
549
550 if (finish)
551 {
552 UserSettingsControllerSP parent = g_settings_controller->GetParent();
553 if (parent)
554 parent->RemoveChild (g_settings_controller);
555 g_settings_controller.reset();
556 }
557 return g_settings_controller;
558}
559
560//--------------------------------------------------
561// class Debugger::DebuggerSettingsController
562//--------------------------------------------------
563
564Debugger::DebuggerSettingsController::DebuggerSettingsController () :
Caroline Tice101c7c22010-09-09 06:25:08 +0000565 UserSettingsController ("", lldb::UserSettingsControllerSP())
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000566{
Caroline Tice91123da2010-09-08 17:48:55 +0000567 m_default_settings.reset (new DebuggerInstanceSettings (*this, false,
568 InstanceSettings::GetDefaultName().AsCString()));
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000569}
570
571Debugger::DebuggerSettingsController::~DebuggerSettingsController ()
572{
573}
574
575
576lldb::InstanceSettingsSP
Caroline Tice91123da2010-09-08 17:48:55 +0000577Debugger::DebuggerSettingsController::CreateNewInstanceSettings (const char *instance_name)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000578{
Caroline Tice91123da2010-09-08 17:48:55 +0000579 DebuggerInstanceSettings *new_settings = new DebuggerInstanceSettings (*(Debugger::GetSettingsController().get()),
580 false, instance_name);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000581 lldb::InstanceSettingsSP new_settings_sp (new_settings);
582 return new_settings_sp;
583}
584
585bool
Caroline Tice101c7c22010-09-09 06:25:08 +0000586Debugger::DebuggerInstanceSettings::ValidTermWidthValue (const char *value, Error err)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000587{
588 bool valid = true;
589
590 // Verify we have a value string.
591 if (value == NULL
592 || strlen (value) == 0)
593 {
594 valid = false;
595 err.SetErrorString ("Missing value. Can't set terminal width without a value.\n");
596 }
597
598 // Verify the string consists entirely of digits.
599 if (valid)
600 {
601 int len = strlen (value);
602 for (int i = 0; i < len; ++i)
603 if (! isdigit (value[i]))
604 {
605 valid = false;
Caroline Tice101c7c22010-09-09 06:25:08 +0000606 err.SetErrorStringWithFormat ("'%s' is not a valid representation of an unsigned integer.\n", value);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000607 }
608 }
609
610 // Verify the term-width is 'reasonable' (e.g. 10 <= width <= 250).
611 if (valid)
612 {
613 int width = atoi (value);
614 if (width < 10
615 || width > 250)
616 {
617 valid = false;
618 err.SetErrorString ("Invalid term-width value; value must be between 10 and 250.\n");
619 }
620 }
621
622 return valid;
623}
624
625
626//--------------------------------------------------
627// class DebuggerInstanceSettings
628//--------------------------------------------------
629
Caroline Tice91123da2010-09-08 17:48:55 +0000630DebuggerInstanceSettings::DebuggerInstanceSettings (UserSettingsController &owner, bool live_instance,
631 const char *name) :
632 InstanceSettings (owner, (name == NULL ? CreateInstanceName ().AsCString() : name), live_instance),
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000633 m_prompt (),
634 m_script_lang ()
635{
Caroline Tice91123da2010-09-08 17:48:55 +0000636 if (name == NULL && live_instance)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000637 {
638 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
639 CopyInstanceSettings (pending_settings, false);
640 m_owner.RemovePendingSettings (m_instance_name);
641 }
642}
643
644DebuggerInstanceSettings::DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs) :
645 InstanceSettings (*(Debugger::GetSettingsController().get()), CreateInstanceName ().AsCString()),
646 m_prompt (rhs.m_prompt),
647 m_script_lang (rhs.m_script_lang)
648{
649 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
650 CopyInstanceSettings (pending_settings, false);
651 m_owner.RemovePendingSettings (m_instance_name);
652}
653
654DebuggerInstanceSettings::~DebuggerInstanceSettings ()
655{
656}
657
658DebuggerInstanceSettings&
659DebuggerInstanceSettings::operator= (const DebuggerInstanceSettings &rhs)
660{
661 if (this != &rhs)
662 {
663 m_prompt = rhs.m_prompt;
664 m_script_lang = rhs.m_script_lang;
665 }
666
667 return *this;
668}
669
670void
671DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
672 const char *index_value,
673 const char *value,
674 const ConstString &instance_name,
675 const SettingEntry &entry,
676 lldb::VarSetOperationType op,
677 Error &err,
678 bool pending)
679{
680 if (var_name == PromptVarName())
681 {
Caroline Tice101c7c22010-09-09 06:25:08 +0000682 UserSettingsController::UpdateStringVariable (op, m_prompt, value, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000683 if (!pending)
684 {
Caroline Tice49e27372010-09-07 18:35:40 +0000685 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
686 // strip off the brackets before passing it to BroadcastPromptChange.
687
688 std::string tmp_instance_name (instance_name.AsCString());
689 if ((tmp_instance_name[0] == '[')
690 && (tmp_instance_name[instance_name.GetLength() - 1] == ']'))
691 tmp_instance_name = tmp_instance_name.substr (1, instance_name.GetLength() - 2);
692 ConstString new_name (tmp_instance_name.c_str());
693
694 BroadcastPromptChange (new_name, m_prompt.c_str());
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000695 }
696 }
697 else if (var_name == ScriptLangVarName())
698 {
699 bool success;
700 m_script_lang = Args::StringToScriptLanguage (value, eScriptLanguageDefault,
701 &success);
702 }
Caroline Tice101c7c22010-09-09 06:25:08 +0000703 else if (var_name == TermWidthVarName())
704 {
705 if (ValidTermWidthValue (value, err))
706 {
707 m_term_width = atoi (value);
708 }
709 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000710}
711
712void
713Debugger::DebuggerSettingsController::UpdateGlobalVariable (const ConstString &var_name,
714 const char *index_value,
715 const char *value,
716 const SettingEntry &entry,
717 lldb::VarSetOperationType op,
718 Error &err)
719{
Caroline Tice101c7c22010-09-09 06:25:08 +0000720 // There should not be any global variables at the Debugger level.
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000721}
722
723void
724DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
725 const ConstString &var_name,
726 StringList &value)
727{
728 if (var_name == PromptVarName())
729 {
730 value.AppendString (m_prompt.c_str());
731
732 }
733 else if (var_name == ScriptLangVarName())
734 {
735 value.AppendString (ScriptInterpreter::LanguageToString (m_script_lang).c_str());
736 }
Caroline Tice101c7c22010-09-09 06:25:08 +0000737 else if (var_name == TermWidthVarName())
738 {
739 StreamString width_str;
740 width_str.Printf ("%d", m_term_width);
741 value.AppendString (width_str.GetData());
742 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000743}
744
745void
746DebuggerInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
747 bool pending)
748{
749 if (new_settings.get() == NULL)
750 return;
751
752 DebuggerInstanceSettings *new_debugger_settings = (DebuggerInstanceSettings *) new_settings.get();
753
754 m_prompt = new_debugger_settings->m_prompt;
755 if (!pending)
Caroline Tice49e27372010-09-07 18:35:40 +0000756 {
757 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
758 // strip off the brackets before passing it to BroadcastPromptChange.
759
760 std::string tmp_instance_name (m_instance_name.AsCString());
761 if ((tmp_instance_name[0] == '[')
762 && (tmp_instance_name[m_instance_name.GetLength() - 1] == ']'))
763 tmp_instance_name = tmp_instance_name.substr (1, m_instance_name.GetLength() - 2);
764 ConstString new_name (tmp_instance_name.c_str());
765
766 BroadcastPromptChange (new_name, m_prompt.c_str());
767 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000768
769 m_script_lang = new_debugger_settings->m_script_lang;
770}
771
772void
773Debugger::DebuggerSettingsController::GetGlobalSettingsValue (const ConstString &var_name,
774 StringList &value)
775{
Caroline Tice101c7c22010-09-09 06:25:08 +0000776 // There should not be any global variables at the Debugger level.
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000777}
778
779bool
780DebuggerInstanceSettings::BroadcastPromptChange (const ConstString &instance_name, const char *new_prompt)
781{
782 std::string tmp_prompt;
783
784 if (new_prompt != NULL)
785 {
786 tmp_prompt = new_prompt ;
787 int len = tmp_prompt.size();
788 if (len > 1
789 && (tmp_prompt[0] == '\'' || tmp_prompt[0] == '"')
790 && (tmp_prompt[len-1] == tmp_prompt[0]))
791 {
792 tmp_prompt = tmp_prompt.substr(1,len-2);
793 }
794 len = tmp_prompt.size();
795 if (tmp_prompt[len-1] != ' ')
796 tmp_prompt.append(" ");
797 }
798 EventSP new_event_sp;
799 new_event_sp.reset (new Event(CommandInterpreter::eBroadcastBitResetPrompt,
800 new EventDataBytes (tmp_prompt.c_str())));
801
802 if (instance_name.GetLength() != 0)
803 {
804 // Set prompt for a particular instance.
805 Debugger *dbg = Debugger::FindDebuggerWithInstanceName (instance_name).get();
806 if (dbg != NULL)
807 {
808 dbg->GetCommandInterpreter().BroadcastEvent (new_event_sp);
809 }
810 }
811
812 return true;
813}
814
815const ConstString
816DebuggerInstanceSettings::CreateInstanceName ()
817{
818 static int instance_count = 1;
819 StreamString sstr;
820
821 sstr.Printf ("debugger_%d", instance_count);
822 ++instance_count;
823
824 const ConstString ret_val (sstr.GetData());
825
826 return ret_val;
827}
828
829const ConstString &
830DebuggerInstanceSettings::PromptVarName ()
831{
832 static ConstString prompt_var_name ("prompt");
833
834 return prompt_var_name;
835}
836
837const ConstString &
838DebuggerInstanceSettings::ScriptLangVarName ()
839{
840 static ConstString script_lang_var_name ("script-lang");
841
842 return script_lang_var_name;
843}
844
Caroline Tice101c7c22010-09-09 06:25:08 +0000845const ConstString &
846DebuggerInstanceSettings::TermWidthVarName ()
847{
848 static ConstString term_width_var_name ("term-width");
849
850 return term_width_var_name;
851}
852
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000853//--------------------------------------------------
854// DebuggerSettingsController Variable Tables
855//--------------------------------------------------
856
857
858SettingEntry
859Debugger::DebuggerSettingsController::global_settings_table[] =
860{
861 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
Caroline Tice101c7c22010-09-09 06:25:08 +0000862 // The Debugger level global table should always be empty; all Debugger settable variables should be instance
863 // variables.
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000864 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
865};
866
867
868
869SettingEntry
870Debugger::DebuggerSettingsController::instance_settings_table[] =
871{
872 //{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
Caroline Tice101c7c22010-09-09 06:25:08 +0000873 { "term-width" , eSetVarTypeInt, "80" , NULL, false , false , "The maximum number of columns to use for displaying text." },
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000874 { "script-lang" , eSetVarTypeString, "python", NULL, false, false, "The script language to be used for evaluating user-written scripts." },
875 { "prompt" , eSetVarTypeString, "(lldb)", NULL, false, false, "The debugger command line prompt displayed for the user." },
876 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
877};