blob: 08033d04ec67488aeda11f58f552ff331cdc31b5 [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 () :
565 UserSettingsController ("", lldb::UserSettingsControllerSP()),
566 m_term_width (80)
567{
568 m_default_settings.reset (new DebuggerInstanceSettings (*this, InstanceSettings::GetDefaultName().AsCString()));
569}
570
571Debugger::DebuggerSettingsController::~DebuggerSettingsController ()
572{
573}
574
575
576lldb::InstanceSettingsSP
577Debugger::DebuggerSettingsController::CreateNewInstanceSettings ()
578{
579 DebuggerInstanceSettings *new_settings = new DebuggerInstanceSettings (*(Debugger::GetSettingsController().get()));
580 lldb::InstanceSettingsSP new_settings_sp (new_settings);
581 return new_settings_sp;
582}
583
584bool
585Debugger::DebuggerSettingsController::ValidTermWidthValue (const char *value, Error err)
586{
587 bool valid = true;
588
589 // Verify we have a value string.
590 if (value == NULL
591 || strlen (value) == 0)
592 {
593 valid = false;
594 err.SetErrorString ("Missing value. Can't set terminal width without a value.\n");
595 }
596
597 // Verify the string consists entirely of digits.
598 if (valid)
599 {
600 int len = strlen (value);
601 for (int i = 0; i < len; ++i)
602 if (! isdigit (value[i]))
603 {
604 valid = false;
605 err.SetErrorStringWithFormat ("'%s' is not a valid representation of an integer.\n", value);
606 }
607 }
608
609 // Verify the term-width is 'reasonable' (e.g. 10 <= width <= 250).
610 if (valid)
611 {
612 int width = atoi (value);
613 if (width < 10
614 || width > 250)
615 {
616 valid = false;
617 err.SetErrorString ("Invalid term-width value; value must be between 10 and 250.\n");
618 }
619 }
620
621 return valid;
622}
623
624
625//--------------------------------------------------
626// class DebuggerInstanceSettings
627//--------------------------------------------------
628
629DebuggerInstanceSettings::DebuggerInstanceSettings (UserSettingsController &owner, const char *name) :
630 InstanceSettings (owner, (name == NULL ? CreateInstanceName ().AsCString() : name)),
631 m_prompt (),
632 m_script_lang ()
633{
634 if (name == NULL)
635 {
636 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
637 CopyInstanceSettings (pending_settings, false);
638 m_owner.RemovePendingSettings (m_instance_name);
639 }
640}
641
642DebuggerInstanceSettings::DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs) :
643 InstanceSettings (*(Debugger::GetSettingsController().get()), CreateInstanceName ().AsCString()),
644 m_prompt (rhs.m_prompt),
645 m_script_lang (rhs.m_script_lang)
646{
647 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
648 CopyInstanceSettings (pending_settings, false);
649 m_owner.RemovePendingSettings (m_instance_name);
650}
651
652DebuggerInstanceSettings::~DebuggerInstanceSettings ()
653{
654}
655
656DebuggerInstanceSettings&
657DebuggerInstanceSettings::operator= (const DebuggerInstanceSettings &rhs)
658{
659 if (this != &rhs)
660 {
661 m_prompt = rhs.m_prompt;
662 m_script_lang = rhs.m_script_lang;
663 }
664
665 return *this;
666}
667
668void
669DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
670 const char *index_value,
671 const char *value,
672 const ConstString &instance_name,
673 const SettingEntry &entry,
674 lldb::VarSetOperationType op,
675 Error &err,
676 bool pending)
677{
678 if (var_name == PromptVarName())
679 {
680 UserSettingsController::UpdateStringVariable (op, m_prompt, value, err);
681 if (!pending)
682 {
Caroline Tice49e27372010-09-07 18:35:40 +0000683 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
684 // strip off the brackets before passing it to BroadcastPromptChange.
685
686 std::string tmp_instance_name (instance_name.AsCString());
687 if ((tmp_instance_name[0] == '[')
688 && (tmp_instance_name[instance_name.GetLength() - 1] == ']'))
689 tmp_instance_name = tmp_instance_name.substr (1, instance_name.GetLength() - 2);
690 ConstString new_name (tmp_instance_name.c_str());
691
692 BroadcastPromptChange (new_name, m_prompt.c_str());
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000693 }
694 }
695 else if (var_name == ScriptLangVarName())
696 {
697 bool success;
698 m_script_lang = Args::StringToScriptLanguage (value, eScriptLanguageDefault,
699 &success);
700 }
701}
702
703void
704Debugger::DebuggerSettingsController::UpdateGlobalVariable (const ConstString &var_name,
705 const char *index_value,
706 const char *value,
707 const SettingEntry &entry,
708 lldb::VarSetOperationType op,
709 Error &err)
710{
711 static ConstString term_width_name ("term-width");
712
713 if (var_name == term_width_name)
714 {
715 if (ValidTermWidthValue (value, err))
716 {
717 m_term_width = atoi (value);
718 }
719 }
720}
721
722void
723DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
724 const ConstString &var_name,
725 StringList &value)
726{
727 if (var_name == PromptVarName())
728 {
729 value.AppendString (m_prompt.c_str());
730
731 }
732 else if (var_name == ScriptLangVarName())
733 {
734 value.AppendString (ScriptInterpreter::LanguageToString (m_script_lang).c_str());
735 }
736}
737
738void
739DebuggerInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
740 bool pending)
741{
742 if (new_settings.get() == NULL)
743 return;
744
745 DebuggerInstanceSettings *new_debugger_settings = (DebuggerInstanceSettings *) new_settings.get();
746
747 m_prompt = new_debugger_settings->m_prompt;
748 if (!pending)
Caroline Tice49e27372010-09-07 18:35:40 +0000749 {
750 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
751 // strip off the brackets before passing it to BroadcastPromptChange.
752
753 std::string tmp_instance_name (m_instance_name.AsCString());
754 if ((tmp_instance_name[0] == '[')
755 && (tmp_instance_name[m_instance_name.GetLength() - 1] == ']'))
756 tmp_instance_name = tmp_instance_name.substr (1, m_instance_name.GetLength() - 2);
757 ConstString new_name (tmp_instance_name.c_str());
758
759 BroadcastPromptChange (new_name, m_prompt.c_str());
760 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000761
762 m_script_lang = new_debugger_settings->m_script_lang;
763}
764
765void
766Debugger::DebuggerSettingsController::GetGlobalSettingsValue (const ConstString &var_name,
767 StringList &value)
768{
769 static ConstString term_width_name ("term-width");
770
771 if (var_name == term_width_name)
772 {
773 StreamString width_str;
774 width_str.Printf ("%d", m_term_width);
775 value.AppendString (width_str.GetData());
776 }
777}
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
845//--------------------------------------------------
846// DebuggerSettingsController Variable Tables
847//--------------------------------------------------
848
849
850SettingEntry
851Debugger::DebuggerSettingsController::global_settings_table[] =
852{
853 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
854 { "term-width" , eSetVarTypeInt, "80" , NULL, false , false , "The maximum number of columns to use for displaying text." },
855 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
856};
857
858
859
860SettingEntry
861Debugger::DebuggerSettingsController::instance_settings_table[] =
862{
863 //{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
864 { "script-lang" , eSetVarTypeString, "python", NULL, false, false, "The script language to be used for evaluating user-written scripts." },
865 { "prompt" , eSetVarTypeString, "(lldb)", NULL, false, false, "The debugger command line prompt displayed for the user." },
866 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
867};