1 //===-- 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/Core/Debugger.h"
11 
12 #include <map>
13 
14 #include "clang/AST/DeclCXX.h"
15 #include "clang/AST/Type.h"
16 
17 #include "lldb/lldb-private.h"
18 #include "lldb/Core/ConnectionFileDescriptor.h"
19 #include "lldb/Core/FormatManager.h"
20 #include "lldb/Core/InputReader.h"
21 #include "lldb/Core/RegisterValue.h"
22 #include "lldb/Core/State.h"
23 #include "lldb/Core/StreamAsynchronousIO.h"
24 #include "lldb/Core/StreamCallback.h"
25 #include "lldb/Core/StreamString.h"
26 #include "lldb/Core/Timer.h"
27 #include "lldb/Core/ValueObject.h"
28 #include "lldb/Core/ValueObjectVariable.h"
29 #include "lldb/Host/Terminal.h"
30 #include "lldb/Interpreter/CommandInterpreter.h"
31 #include "lldb/Symbol/VariableList.h"
32 #include "lldb/Target/TargetList.h"
33 #include "lldb/Target/Process.h"
34 #include "lldb/Target/RegisterContext.h"
35 #include "lldb/Target/StopInfo.h"
36 #include "lldb/Target/Thread.h"
37 #include "lldb/Utility/AnsiTerminal.h"
38 
39 using namespace lldb;
40 using namespace lldb_private;
41 
42 
43 static uint32_t g_shared_debugger_refcount = 0;
44 static lldb::user_id_t g_unique_id = 1;
45 
46 #pragma mark Static Functions
47 
48 static Mutex &
49 GetDebuggerListMutex ()
50 {
51     static Mutex g_mutex(Mutex::eMutexTypeRecursive);
52     return g_mutex;
53 }
54 
55 typedef std::vector<DebuggerSP> DebuggerList;
56 
57 static DebuggerList &
58 GetDebuggerList()
59 {
60     // hide the static debugger list inside a singleton accessor to avoid
61     // global init contructors
62     static DebuggerList g_list;
63     return g_list;
64 }
65 
66 
67 static const ConstString &
68 PromptVarName ()
69 {
70     static ConstString g_const_string ("prompt");
71     return g_const_string;
72 }
73 
74 static const ConstString &
75 GetFrameFormatName ()
76 {
77     static ConstString g_const_string ("frame-format");
78     return g_const_string;
79 }
80 
81 static const ConstString &
82 GetThreadFormatName ()
83 {
84     static ConstString g_const_string ("thread-format");
85     return g_const_string;
86 }
87 
88 static const ConstString &
89 ScriptLangVarName ()
90 {
91     static ConstString g_const_string ("script-lang");
92     return g_const_string;
93 }
94 
95 static const ConstString &
96 TermWidthVarName ()
97 {
98     static ConstString g_const_string ("term-width");
99     return g_const_string;
100 }
101 
102 static const ConstString &
103 UseExternalEditorVarName ()
104 {
105     static ConstString g_const_string ("use-external-editor");
106     return g_const_string;
107 }
108 
109 static const ConstString &
110 AutoConfirmName ()
111 {
112     static ConstString g_const_string ("auto-confirm");
113     return g_const_string;
114 }
115 
116 static const ConstString &
117 StopSourceContextBeforeName ()
118 {
119     static ConstString g_const_string ("stop-line-count-before");
120     return g_const_string;
121 }
122 
123 static const ConstString &
124 StopSourceContextAfterName ()
125 {
126     static ConstString g_const_string ("stop-line-count-after");
127     return g_const_string;
128 }
129 
130 static const ConstString &
131 StopDisassemblyCountName ()
132 {
133     static ConstString g_const_string ("stop-disassembly-count");
134     return g_const_string;
135 }
136 
137 static const ConstString &
138 StopDisassemblyDisplayName ()
139 {
140     static ConstString g_const_string ("stop-disassembly-display");
141     return g_const_string;
142 }
143 
144 OptionEnumValueElement
145 DebuggerInstanceSettings::g_show_disassembly_enum_values[] =
146 {
147     { eStopDisassemblyTypeNever,    "never",     "Never show disassembly when displaying a stop context."},
148     { eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."},
149     { eStopDisassemblyTypeAlways,   "always",    "Always show disassembly when displaying a stop context."},
150     { 0, NULL, NULL }
151 };
152 
153 
154 
155 #pragma mark Debugger
156 
157 UserSettingsControllerSP &
158 Debugger::GetSettingsController ()
159 {
160     static UserSettingsControllerSP g_settings_controller_sp;
161     if (!g_settings_controller_sp)
162     {
163         g_settings_controller_sp.reset (new Debugger::SettingsController);
164 
165         // The first shared pointer to Debugger::SettingsController in
166         // g_settings_controller_sp must be fully created above so that
167         // the DebuggerInstanceSettings can use a weak_ptr to refer back
168         // to the master setttings controller
169         InstanceSettingsSP default_instance_settings_sp (new DebuggerInstanceSettings (g_settings_controller_sp,
170                                                                                        false,
171                                                                                        InstanceSettings::GetDefaultName().AsCString()));
172         g_settings_controller_sp->SetDefaultInstanceSettings (default_instance_settings_sp);
173     }
174     return g_settings_controller_sp;
175 }
176 
177 int
178 Debugger::TestDebuggerRefCount ()
179 {
180     return g_shared_debugger_refcount;
181 }
182 
183 void
184 Debugger::Initialize ()
185 {
186     if (g_shared_debugger_refcount++ == 0)
187         lldb_private::Initialize();
188 }
189 
190 void
191 Debugger::Terminate ()
192 {
193     if (g_shared_debugger_refcount > 0)
194     {
195         g_shared_debugger_refcount--;
196         if (g_shared_debugger_refcount == 0)
197         {
198             lldb_private::WillTerminate();
199             lldb_private::Terminate();
200 
201             // Clear our master list of debugger objects
202             Mutex::Locker locker (GetDebuggerListMutex ());
203             GetDebuggerList().clear();
204         }
205     }
206 }
207 
208 void
209 Debugger::SettingsInitialize ()
210 {
211     static bool g_initialized = false;
212 
213     if (!g_initialized)
214     {
215         g_initialized = true;
216         UserSettingsController::InitializeSettingsController (GetSettingsController(),
217                                                               SettingsController::global_settings_table,
218                                                               SettingsController::instance_settings_table);
219         // Now call SettingsInitialize for each settings 'child' of Debugger
220         Target::SettingsInitialize ();
221     }
222 }
223 
224 void
225 Debugger::SettingsTerminate ()
226 {
227 
228     // Must call SettingsTerminate() for each settings 'child' of Debugger, before terminating the Debugger's
229     // Settings.
230 
231     Target::SettingsTerminate ();
232 
233     // Now terminate the Debugger Settings.
234 
235     UserSettingsControllerSP &usc = GetSettingsController();
236     UserSettingsController::FinalizeSettingsController (usc);
237     usc.reset();
238 }
239 
240 DebuggerSP
241 Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton)
242 {
243     DebuggerSP debugger_sp (new Debugger(log_callback, baton));
244     if (g_shared_debugger_refcount > 0)
245     {
246         Mutex::Locker locker (GetDebuggerListMutex ());
247         GetDebuggerList().push_back(debugger_sp);
248     }
249     return debugger_sp;
250 }
251 
252 void
253 Debugger::Destroy (DebuggerSP &debugger_sp)
254 {
255     if (debugger_sp.get() == NULL)
256         return;
257 
258     debugger_sp->Clear();
259 
260     if (g_shared_debugger_refcount > 0)
261     {
262         Mutex::Locker locker (GetDebuggerListMutex ());
263         DebuggerList &debugger_list = GetDebuggerList ();
264         DebuggerList::iterator pos, end = debugger_list.end();
265         for (pos = debugger_list.begin (); pos != end; ++pos)
266         {
267             if ((*pos).get() == debugger_sp.get())
268             {
269                 debugger_list.erase (pos);
270                 return;
271             }
272         }
273     }
274 }
275 
276 DebuggerSP
277 Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name)
278 {
279     DebuggerSP debugger_sp;
280 
281     if (g_shared_debugger_refcount > 0)
282     {
283         Mutex::Locker locker (GetDebuggerListMutex ());
284         DebuggerList &debugger_list = GetDebuggerList();
285         DebuggerList::iterator pos, end = debugger_list.end();
286 
287         for (pos = debugger_list.begin(); pos != end; ++pos)
288         {
289             if ((*pos).get()->m_instance_name == instance_name)
290             {
291                 debugger_sp = *pos;
292                 break;
293             }
294         }
295     }
296     return debugger_sp;
297 }
298 
299 TargetSP
300 Debugger::FindTargetWithProcessID (lldb::pid_t pid)
301 {
302     TargetSP target_sp;
303     if (g_shared_debugger_refcount > 0)
304     {
305         Mutex::Locker locker (GetDebuggerListMutex ());
306         DebuggerList &debugger_list = GetDebuggerList();
307         DebuggerList::iterator pos, end = debugger_list.end();
308         for (pos = debugger_list.begin(); pos != end; ++pos)
309         {
310             target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid);
311             if (target_sp)
312                 break;
313         }
314     }
315     return target_sp;
316 }
317 
318 TargetSP
319 Debugger::FindTargetWithProcess (Process *process)
320 {
321     TargetSP target_sp;
322     if (g_shared_debugger_refcount > 0)
323     {
324         Mutex::Locker locker (GetDebuggerListMutex ());
325         DebuggerList &debugger_list = GetDebuggerList();
326         DebuggerList::iterator pos, end = debugger_list.end();
327         for (pos = debugger_list.begin(); pos != end; ++pos)
328         {
329             target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process);
330             if (target_sp)
331                 break;
332         }
333     }
334     return target_sp;
335 }
336 
337 
338 Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) :
339     UserID (g_unique_id++),
340     DebuggerInstanceSettings (GetSettingsController()),
341     m_input_comm("debugger.input"),
342     m_input_file (),
343     m_output_file (),
344     m_error_file (),
345     m_target_list (*this),
346     m_platform_list (),
347     m_listener ("lldb.Debugger"),
348     m_source_manager(*this),
349     m_source_file_cache(),
350     m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
351     m_input_reader_stack (),
352     m_input_reader_data ()
353 {
354     if (log_callback)
355         m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton));
356     m_command_interpreter_ap->Initialize ();
357     // Always add our default platform to the platform list
358     PlatformSP default_platform_sp (Platform::GetDefaultPlatform());
359     assert (default_platform_sp.get());
360     m_platform_list.Append (default_platform_sp, true);
361 }
362 
363 Debugger::~Debugger ()
364 {
365     Clear();
366 }
367 
368 void
369 Debugger::Clear()
370 {
371     CleanUpInputReaders();
372     m_listener.Clear();
373     int num_targets = m_target_list.GetNumTargets();
374     for (int i = 0; i < num_targets; i++)
375     {
376         TargetSP target_sp (m_target_list.GetTargetAtIndex (i));
377         if (target_sp)
378         {
379             ProcessSP process_sp (target_sp->GetProcessSP());
380             if (process_sp)
381             {
382                 if (process_sp->GetShouldDetach())
383                     process_sp->Detach();
384             }
385             target_sp->Destroy();
386         }
387     }
388     BroadcasterManager::Clear ();
389     DisconnectInput();
390 
391 }
392 
393 bool
394 Debugger::GetCloseInputOnEOF () const
395 {
396     return m_input_comm.GetCloseOnEOF();
397 }
398 
399 void
400 Debugger::SetCloseInputOnEOF (bool b)
401 {
402     m_input_comm.SetCloseOnEOF(b);
403 }
404 
405 bool
406 Debugger::GetAsyncExecution ()
407 {
408     return !m_command_interpreter_ap->GetSynchronous();
409 }
410 
411 void
412 Debugger::SetAsyncExecution (bool async_execution)
413 {
414     m_command_interpreter_ap->SetSynchronous (!async_execution);
415 }
416 
417 
418 void
419 Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
420 {
421     File &in_file = GetInputFile();
422     in_file.SetStream (fh, tranfer_ownership);
423     if (in_file.IsValid() == false)
424         in_file.SetStream (stdin, true);
425 
426     // Disconnect from any old connection if we had one
427     m_input_comm.Disconnect ();
428     // Pass false as the second argument to ConnectionFileDescriptor below because
429     // our "in_file" above will already take ownership if requested and we don't
430     // want to objects trying to own and close a file descriptor.
431     m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false));
432     m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
433 
434     Error error;
435     if (m_input_comm.StartReadThread (&error) == false)
436     {
437         File &err_file = GetErrorFile();
438 
439         err_file.Printf ("error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
440         exit(1);
441     }
442 }
443 
444 void
445 Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
446 {
447     File &out_file = GetOutputFile();
448     out_file.SetStream (fh, tranfer_ownership);
449     if (out_file.IsValid() == false)
450         out_file.SetStream (stdout, false);
451 
452     GetCommandInterpreter().GetScriptInterpreter()->ResetOutputFileHandle (fh);
453 }
454 
455 void
456 Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
457 {
458     File &err_file = GetErrorFile();
459     err_file.SetStream (fh, tranfer_ownership);
460     if (err_file.IsValid() == false)
461         err_file.SetStream (stderr, false);
462 }
463 
464 ExecutionContext
465 Debugger::GetSelectedExecutionContext ()
466 {
467     ExecutionContext exe_ctx;
468     TargetSP target_sp(GetSelectedTarget());
469     exe_ctx.SetTargetSP (target_sp);
470 
471     if (target_sp)
472     {
473         ProcessSP process_sp (target_sp->GetProcessSP());
474         exe_ctx.SetProcessSP (process_sp);
475         if (process_sp && process_sp->IsRunning() == false)
476         {
477             ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread());
478             if (thread_sp)
479             {
480                 exe_ctx.SetThreadSP (thread_sp);
481                 exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame());
482                 if (exe_ctx.GetFramePtr() == NULL)
483                     exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0));
484             }
485         }
486     }
487     return exe_ctx;
488 
489 }
490 
491 InputReaderSP
492 Debugger::GetCurrentInputReader ()
493 {
494     InputReaderSP reader_sp;
495 
496     if (!m_input_reader_stack.IsEmpty())
497     {
498         // Clear any finished readers from the stack
499         while (CheckIfTopInputReaderIsDone()) ;
500 
501         if (!m_input_reader_stack.IsEmpty())
502             reader_sp = m_input_reader_stack.Top();
503     }
504 
505     return reader_sp;
506 }
507 
508 void
509 Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
510 {
511     if (bytes_len > 0)
512         ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
513     else
514         ((Debugger *)baton)->DispatchInputEndOfFile ();
515 }
516 
517 
518 void
519 Debugger::DispatchInput (const char *bytes, size_t bytes_len)
520 {
521     if (bytes == NULL || bytes_len == 0)
522         return;
523 
524     WriteToDefaultReader (bytes, bytes_len);
525 }
526 
527 void
528 Debugger::DispatchInputInterrupt ()
529 {
530     m_input_reader_data.clear();
531 
532     InputReaderSP reader_sp (GetCurrentInputReader ());
533     if (reader_sp)
534     {
535         reader_sp->Notify (eInputReaderInterrupt);
536 
537         // If notifying the reader of the interrupt finished the reader, we should pop it off the stack.
538         while (CheckIfTopInputReaderIsDone ()) ;
539     }
540 }
541 
542 void
543 Debugger::DispatchInputEndOfFile ()
544 {
545     m_input_reader_data.clear();
546 
547     InputReaderSP reader_sp (GetCurrentInputReader ());
548     if (reader_sp)
549     {
550         reader_sp->Notify (eInputReaderEndOfFile);
551 
552         // If notifying the reader of the end-of-file finished the reader, we should pop it off the stack.
553         while (CheckIfTopInputReaderIsDone ()) ;
554     }
555 }
556 
557 void
558 Debugger::CleanUpInputReaders ()
559 {
560     m_input_reader_data.clear();
561 
562     // The bottom input reader should be the main debugger input reader.  We do not want to close that one here.
563     while (m_input_reader_stack.GetSize() > 1)
564     {
565         InputReaderSP reader_sp (GetCurrentInputReader ());
566         if (reader_sp)
567         {
568             reader_sp->Notify (eInputReaderEndOfFile);
569             reader_sp->SetIsDone (true);
570         }
571     }
572 }
573 
574 void
575 Debugger::NotifyTopInputReader (InputReaderAction notification)
576 {
577     InputReaderSP reader_sp (GetCurrentInputReader());
578     if (reader_sp)
579 	{
580         reader_sp->Notify (notification);
581 
582         // Flush out any input readers that are done.
583         while (CheckIfTopInputReaderIsDone ())
584             /* Do nothing. */;
585     }
586 }
587 
588 bool
589 Debugger::InputReaderIsTopReader (const InputReaderSP& reader_sp)
590 {
591     InputReaderSP top_reader_sp (GetCurrentInputReader());
592 
593     return (reader_sp.get() == top_reader_sp.get());
594 }
595 
596 
597 void
598 Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
599 {
600     if (bytes && bytes_len)
601         m_input_reader_data.append (bytes, bytes_len);
602 
603     if (m_input_reader_data.empty())
604         return;
605 
606     while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty())
607     {
608         // Get the input reader from the top of the stack
609         InputReaderSP reader_sp (GetCurrentInputReader ());
610         if (!reader_sp)
611             break;
612 
613         size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(),
614                                                           m_input_reader_data.size());
615         if (bytes_handled)
616         {
617             m_input_reader_data.erase (0, bytes_handled);
618         }
619         else
620         {
621             // No bytes were handled, we might not have reached our
622             // granularity, just return and wait for more data
623             break;
624         }
625     }
626 
627     // Flush out any input readers that are done.
628     while (CheckIfTopInputReaderIsDone ())
629         /* Do nothing. */;
630 
631 }
632 
633 void
634 Debugger::PushInputReader (const InputReaderSP& reader_sp)
635 {
636     if (!reader_sp)
637         return;
638 
639     // Deactivate the old top reader
640     InputReaderSP top_reader_sp (GetCurrentInputReader ());
641 
642     if (top_reader_sp)
643         top_reader_sp->Notify (eInputReaderDeactivate);
644 
645     m_input_reader_stack.Push (reader_sp);
646     reader_sp->Notify (eInputReaderActivate);
647     ActivateInputReader (reader_sp);
648 }
649 
650 bool
651 Debugger::PopInputReader (const InputReaderSP& pop_reader_sp)
652 {
653     bool result = false;
654 
655     // The reader on the stop of the stack is done, so let the next
656     // read on the stack referesh its prompt and if there is one...
657     if (!m_input_reader_stack.IsEmpty())
658     {
659         // Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
660         InputReaderSP reader_sp(m_input_reader_stack.Top());
661 
662         if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
663         {
664             m_input_reader_stack.Pop ();
665             reader_sp->Notify (eInputReaderDeactivate);
666             reader_sp->Notify (eInputReaderDone);
667             result = true;
668 
669             if (!m_input_reader_stack.IsEmpty())
670             {
671                 reader_sp = m_input_reader_stack.Top();
672                 if (reader_sp)
673                 {
674                     ActivateInputReader (reader_sp);
675                     reader_sp->Notify (eInputReaderReactivate);
676                 }
677             }
678         }
679     }
680     return result;
681 }
682 
683 bool
684 Debugger::CheckIfTopInputReaderIsDone ()
685 {
686     bool result = false;
687     if (!m_input_reader_stack.IsEmpty())
688     {
689         // Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
690         InputReaderSP reader_sp(m_input_reader_stack.Top());
691 
692         if (reader_sp && reader_sp->IsDone())
693         {
694             result = true;
695             PopInputReader (reader_sp);
696         }
697     }
698     return result;
699 }
700 
701 void
702 Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
703 {
704     int input_fd = m_input_file.GetFile().GetDescriptor();
705 
706     if (input_fd >= 0)
707     {
708         Terminal tty(input_fd);
709 
710         tty.SetEcho(reader_sp->GetEcho());
711 
712         switch (reader_sp->GetGranularity())
713         {
714         case eInputReaderGranularityByte:
715         case eInputReaderGranularityWord:
716             tty.SetCanonical (false);
717             break;
718 
719         case eInputReaderGranularityLine:
720         case eInputReaderGranularityAll:
721             tty.SetCanonical (true);
722             break;
723 
724         default:
725             break;
726         }
727     }
728 }
729 
730 StreamSP
731 Debugger::GetAsyncOutputStream ()
732 {
733     return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(),
734                                                CommandInterpreter::eBroadcastBitAsynchronousOutputData));
735 }
736 
737 StreamSP
738 Debugger::GetAsyncErrorStream ()
739 {
740     return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(),
741                                                CommandInterpreter::eBroadcastBitAsynchronousErrorData));
742 }
743 
744 uint32_t
745 Debugger::GetNumDebuggers()
746 {
747     if (g_shared_debugger_refcount > 0)
748     {
749         Mutex::Locker locker (GetDebuggerListMutex ());
750         return GetDebuggerList().size();
751     }
752     return 0;
753 }
754 
755 lldb::DebuggerSP
756 Debugger::GetDebuggerAtIndex (uint32_t index)
757 {
758     DebuggerSP debugger_sp;
759 
760     if (g_shared_debugger_refcount > 0)
761     {
762         Mutex::Locker locker (GetDebuggerListMutex ());
763         DebuggerList &debugger_list = GetDebuggerList();
764 
765         if (index < debugger_list.size())
766             debugger_sp = debugger_list[index];
767     }
768 
769     return debugger_sp;
770 }
771 
772 DebuggerSP
773 Debugger::FindDebuggerWithID (lldb::user_id_t id)
774 {
775     DebuggerSP debugger_sp;
776 
777     if (g_shared_debugger_refcount > 0)
778     {
779         Mutex::Locker locker (GetDebuggerListMutex ());
780         DebuggerList &debugger_list = GetDebuggerList();
781         DebuggerList::iterator pos, end = debugger_list.end();
782         for (pos = debugger_list.begin(); pos != end; ++pos)
783         {
784             if ((*pos).get()->GetID() == id)
785             {
786                 debugger_sp = *pos;
787                 break;
788             }
789         }
790     }
791     return debugger_sp;
792 }
793 
794 static void
795 TestPromptFormats (StackFrame *frame)
796 {
797     if (frame == NULL)
798         return;
799 
800     StreamString s;
801     const char *prompt_format =
802     "{addr = '${addr}'\n}"
803     "{process.id = '${process.id}'\n}"
804     "{process.name = '${process.name}'\n}"
805     "{process.file.basename = '${process.file.basename}'\n}"
806     "{process.file.fullpath = '${process.file.fullpath}'\n}"
807     "{thread.id = '${thread.id}'\n}"
808     "{thread.index = '${thread.index}'\n}"
809     "{thread.name = '${thread.name}'\n}"
810     "{thread.queue = '${thread.queue}'\n}"
811     "{thread.stop-reason = '${thread.stop-reason}'\n}"
812     "{target.arch = '${target.arch}'\n}"
813     "{module.file.basename = '${module.file.basename}'\n}"
814     "{module.file.fullpath = '${module.file.fullpath}'\n}"
815     "{file.basename = '${file.basename}'\n}"
816     "{file.fullpath = '${file.fullpath}'\n}"
817     "{frame.index = '${frame.index}'\n}"
818     "{frame.pc = '${frame.pc}'\n}"
819     "{frame.sp = '${frame.sp}'\n}"
820     "{frame.fp = '${frame.fp}'\n}"
821     "{frame.flags = '${frame.flags}'\n}"
822     "{frame.reg.rdi = '${frame.reg.rdi}'\n}"
823     "{frame.reg.rip = '${frame.reg.rip}'\n}"
824     "{frame.reg.rsp = '${frame.reg.rsp}'\n}"
825     "{frame.reg.rbp = '${frame.reg.rbp}'\n}"
826     "{frame.reg.rflags = '${frame.reg.rflags}'\n}"
827     "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}"
828     "{frame.reg.carp = '${frame.reg.carp}'\n}"
829     "{function.id = '${function.id}'\n}"
830     "{function.name = '${function.name}'\n}"
831     "{function.name-with-args = '${function.name-with-args}'\n}"
832     "{function.addr-offset = '${function.addr-offset}'\n}"
833     "{function.line-offset = '${function.line-offset}'\n}"
834     "{function.pc-offset = '${function.pc-offset}'\n}"
835     "{line.file.basename = '${line.file.basename}'\n}"
836     "{line.file.fullpath = '${line.file.fullpath}'\n}"
837     "{line.number = '${line.number}'\n}"
838     "{line.start-addr = '${line.start-addr}'\n}"
839     "{line.end-addr = '${line.end-addr}'\n}"
840 ;
841 
842     SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
843     ExecutionContext exe_ctx;
844     frame->CalculateExecutionContext(exe_ctx);
845     const char *end = NULL;
846     if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end))
847     {
848         printf("%s\n", s.GetData());
849     }
850     else
851     {
852         printf ("error: at '%s'\n", end);
853         printf ("what we got: %s\n", s.GetData());
854     }
855 }
856 
857 static bool
858 ScanFormatDescriptor (const char* var_name_begin,
859                       const char* var_name_end,
860                       const char** var_name_final,
861                       const char** percent_position,
862                       Format* custom_format,
863                       ValueObject::ValueObjectRepresentationStyle* val_obj_display)
864 {
865     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
866     *percent_position = ::strchr(var_name_begin,'%');
867     if (!*percent_position || *percent_position > var_name_end)
868     {
869         if (log)
870             log->Printf("no format descriptor in string, skipping");
871         *var_name_final = var_name_end;
872     }
873     else
874     {
875         *var_name_final = *percent_position;
876         char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0';
877         memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1);
878         if (log)
879             log->Printf("parsing %s as a format descriptor", format_name);
880         if ( !FormatManager::GetFormatFromCString(format_name,
881                                                   true,
882                                                   *custom_format) )
883         {
884             if (log)
885                 log->Printf("%s is an unknown format", format_name);
886             // if this is an @ sign, print ObjC description
887             if (*format_name == '@')
888                 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific;
889             // if this is a V, print the value using the default format
890             else if (*format_name == 'V')
891                 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
892             // if this is an L, print the location of the value
893             else if (*format_name == 'L')
894                 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation;
895             // if this is an S, print the summary after all
896             else if (*format_name == 'S')
897                 *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
898             else if (*format_name == '#')
899                 *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount;
900             else if (*format_name == 'T')
901                 *val_obj_display = ValueObject::eValueObjectRepresentationStyleType;
902             else if (log)
903                 log->Printf("%s is an error, leaving the previous value alone", format_name);
904         }
905         // a good custom format tells us to print the value using it
906         else
907         {
908             if (log)
909                 log->Printf("will display value for this VO");
910             *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
911         }
912         delete format_name;
913     }
914     if (log)
915         log->Printf("final format description outcome: custom_format = %d, val_obj_display = %d",
916                     *custom_format,
917                     *val_obj_display);
918     return true;
919 }
920 
921 static bool
922 ScanBracketedRange (const char* var_name_begin,
923                     const char* var_name_end,
924                     const char* var_name_final,
925                     const char** open_bracket_position,
926                     const char** separator_position,
927                     const char** close_bracket_position,
928                     const char** var_name_final_if_array_range,
929                     int64_t* index_lower,
930                     int64_t* index_higher)
931 {
932     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
933     *open_bracket_position = ::strchr(var_name_begin,'[');
934     if (*open_bracket_position && *open_bracket_position < var_name_final)
935     {
936         *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
937         *close_bracket_position = ::strchr(*open_bracket_position,']');
938         // as usual, we assume that [] will come before %
939         //printf("trying to expand a []\n");
940         *var_name_final_if_array_range = *open_bracket_position;
941         if (*close_bracket_position - *open_bracket_position == 1)
942         {
943             if (log)
944                 log->Printf("[] detected.. going from 0 to end of data");
945             *index_lower = 0;
946         }
947         else if (*separator_position == NULL || *separator_position > var_name_end)
948         {
949             char *end = NULL;
950             *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
951             *index_higher = *index_lower;
952             if (log)
953                 log->Printf("[%lld] detected, high index is same", *index_lower);
954         }
955         else if (*close_bracket_position && *close_bracket_position < var_name_end)
956         {
957             char *end = NULL;
958             *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
959             *index_higher = ::strtoul (*separator_position+1, &end, 0);
960             if (log)
961                 log->Printf("[%lld-%lld] detected", *index_lower, *index_higher);
962         }
963         else
964         {
965             if (log)
966                 log->Printf("expression is erroneous, cannot extract indices out of it");
967             return false;
968         }
969         if (*index_lower > *index_higher && *index_higher > 0)
970         {
971             if (log)
972                 log->Printf("swapping indices");
973             int temp = *index_lower;
974             *index_lower = *index_higher;
975             *index_higher = temp;
976         }
977     }
978     else if (log)
979             log->Printf("no bracketed range, skipping entirely");
980     return true;
981 }
982 
983 
984 static ValueObjectSP
985 ExpandExpressionPath (ValueObject* valobj,
986                       StackFrame* frame,
987                       bool* do_deref_pointer,
988                       const char* var_name_begin,
989                       const char* var_name_final,
990                       Error& error)
991 {
992     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
993     StreamString sstring;
994     VariableSP var_sp;
995 
996     if (*do_deref_pointer)
997     {
998         if (log)
999             log->Printf("been told to deref_pointer by caller");
1000         sstring.PutChar('*');
1001     }
1002     else if (valobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(valobj->GetParent()->GetClangType()) && !valobj->IsArrayItemForPointer())
1003     {
1004         if (log)
1005             log->Printf("decided to deref_pointer myself");
1006         sstring.PutChar('*');
1007         *do_deref_pointer = true;
1008     }
1009 
1010     valobj->GetExpressionPath(sstring, true, ValueObject::eGetExpressionPathFormatHonorPointers);
1011     if (log)
1012         log->Printf("expression path to expand in phase 0: %s",sstring.GetData());
1013     sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3);
1014     if (log)
1015         log->Printf("expression path to expand in phase 1: %s",sstring.GetData());
1016     std::string name = std::string(sstring.GetData());
1017     ValueObjectSP target = frame->GetValueForVariableExpressionPath (name.c_str(),
1018                                                                      eNoDynamicValues,
1019                                                                      0,
1020                                                                      var_sp,
1021                                                                      error);
1022     return target;
1023 }
1024 
1025 static ValueObjectSP
1026 ExpandIndexedExpression (ValueObject* valobj,
1027                          uint32_t index,
1028                          StackFrame* frame,
1029                          bool deref_pointer)
1030 {
1031     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
1032     const char* ptr_deref_format = "[%d]";
1033     std::auto_ptr<char> ptr_deref_buffer(new char[10]);
1034     ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index);
1035     if (log)
1036         log->Printf("name to deref: %s",ptr_deref_buffer.get());
1037     const char* first_unparsed;
1038     ValueObject::GetValueForExpressionPathOptions options;
1039     ValueObject::ExpressionPathEndResultType final_value_type;
1040     ValueObject::ExpressionPathScanEndReason reason_to_stop;
1041     ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
1042     ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.get(),
1043                                                           &first_unparsed,
1044                                                           &reason_to_stop,
1045                                                           &final_value_type,
1046                                                           options,
1047                                                           &what_next);
1048     if (!item)
1049     {
1050         if (log)
1051             log->Printf("ERROR: unparsed portion = %s, why stopping = %d,"
1052                " final_value_type %d",
1053                first_unparsed, reason_to_stop, final_value_type);
1054     }
1055     else
1056     {
1057         if (log)
1058             log->Printf("ALL RIGHT: unparsed portion = %s, why stopping = %d,"
1059                " final_value_type %d",
1060                first_unparsed, reason_to_stop, final_value_type);
1061     }
1062     return item;
1063 }
1064 
1065 bool
1066 Debugger::FormatPrompt
1067 (
1068     const char *format,
1069     const SymbolContext *sc,
1070     const ExecutionContext *exe_ctx,
1071     const Address *addr,
1072     Stream &s,
1073     const char **end,
1074     ValueObject* valobj
1075 )
1076 {
1077     ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers
1078     bool success = true;
1079     const char *p;
1080     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
1081     for (p = format; *p != '\0'; ++p)
1082     {
1083         if (realvalobj)
1084         {
1085             valobj = realvalobj;
1086             realvalobj = NULL;
1087         }
1088         size_t non_special_chars = ::strcspn (p, "${}\\");
1089         if (non_special_chars > 0)
1090         {
1091             if (success)
1092                 s.Write (p, non_special_chars);
1093             p += non_special_chars;
1094         }
1095 
1096         if (*p == '\0')
1097         {
1098             break;
1099         }
1100         else if (*p == '{')
1101         {
1102             // Start a new scope that must have everything it needs if it is to
1103             // to make it into the final output stream "s". If you want to make
1104             // a format that only prints out the function or symbol name if there
1105             // is one in the symbol context you can use:
1106             //      "{function =${function.name}}"
1107             // The first '{' starts a new scope that end with the matching '}' at
1108             // the end of the string. The contents "function =${function.name}"
1109             // will then be evaluated and only be output if there is a function
1110             // or symbol with a valid name.
1111             StreamString sub_strm;
1112 
1113             ++p;  // Skip the '{'
1114 
1115             if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p, valobj))
1116             {
1117                 // The stream had all it needed
1118                 s.Write(sub_strm.GetData(), sub_strm.GetSize());
1119             }
1120             if (*p != '}')
1121             {
1122                 success = false;
1123                 break;
1124             }
1125         }
1126         else if (*p == '}')
1127         {
1128             // End of a enclosing scope
1129             break;
1130         }
1131         else if (*p == '$')
1132         {
1133             // We have a prompt variable to print
1134             ++p;
1135             if (*p == '{')
1136             {
1137                 ++p;
1138                 const char *var_name_begin = p;
1139                 const char *var_name_end = ::strchr (p, '}');
1140 
1141                 if (var_name_end && var_name_begin < var_name_end)
1142                 {
1143                     // if we have already failed to parse, skip this variable
1144                     if (success)
1145                     {
1146                         const char *cstr = NULL;
1147                         Address format_addr;
1148                         bool calculate_format_addr_function_offset = false;
1149                         // Set reg_kind and reg_num to invalid values
1150                         RegisterKind reg_kind = kNumRegisterKinds;
1151                         uint32_t reg_num = LLDB_INVALID_REGNUM;
1152                         FileSpec format_file_spec;
1153                         const RegisterInfo *reg_info = NULL;
1154                         RegisterContext *reg_ctx = NULL;
1155                         bool do_deref_pointer = false;
1156                         ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
1157                         ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain;
1158 
1159                         // Each variable must set success to true below...
1160                         bool var_success = false;
1161                         switch (var_name_begin[0])
1162                         {
1163                         case '*':
1164                         case 'v':
1165                         case 's':
1166                             {
1167                                 if (!valobj)
1168                                     break;
1169 
1170                                 if (log)
1171                                     log->Printf("initial string: %s",var_name_begin);
1172 
1173                                 // check for *var and *svar
1174                                 if (*var_name_begin == '*')
1175                                 {
1176                                     do_deref_pointer = true;
1177                                     var_name_begin++;
1178                                 }
1179 
1180                                 if (log)
1181                                     log->Printf("initial string: %s",var_name_begin);
1182 
1183                                 if (*var_name_begin == 's')
1184                                 {
1185                                     if (!valobj->IsSynthetic())
1186                                         valobj = valobj->GetSyntheticValue().get();
1187                                     if (!valobj)
1188                                         break;
1189                                     var_name_begin++;
1190                                 }
1191 
1192                                 if (log)
1193                                     log->Printf("initial string: %s",var_name_begin);
1194 
1195                                 // should be a 'v' by now
1196                                 if (*var_name_begin != 'v')
1197                                     break;
1198 
1199                                 if (log)
1200                                     log->Printf("initial string: %s",var_name_begin);
1201 
1202                                 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
1203                                                                                   ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
1204                                 ValueObject::GetValueForExpressionPathOptions options;
1205                                 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren();
1206                                 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
1207                                 ValueObject* target = NULL;
1208                                 Format custom_format = eFormatInvalid;
1209                                 const char* var_name_final = NULL;
1210                                 const char* var_name_final_if_array_range = NULL;
1211                                 const char* close_bracket_position = NULL;
1212                                 int64_t index_lower = -1;
1213                                 int64_t index_higher = -1;
1214                                 bool is_array_range = false;
1215                                 const char* first_unparsed;
1216                                 bool was_plain_var = false;
1217                                 bool was_var_format = false;
1218 
1219                                 if (!valobj) break;
1220                                 // simplest case ${var}, just print valobj's value
1221                                 if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0)
1222                                 {
1223                                     was_plain_var = true;
1224                                     target = valobj;
1225                                     val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1226                                 }
1227                                 else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0)
1228                                 {
1229                                     was_var_format = true;
1230                                     // this is a variable with some custom format applied to it
1231                                     const char* percent_position;
1232                                     target = valobj;
1233                                     val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1234                                     ScanFormatDescriptor (var_name_begin,
1235                                                           var_name_end,
1236                                                           &var_name_final,
1237                                                           &percent_position,
1238                                                           &custom_format,
1239                                                           &val_obj_display);
1240                                 }
1241                                     // this is ${var.something} or multiple .something nested
1242                                 else if (::strncmp (var_name_begin, "var", strlen("var")) == 0)
1243                                 {
1244 
1245                                     const char* percent_position;
1246                                     ScanFormatDescriptor (var_name_begin,
1247                                                           var_name_end,
1248                                                           &var_name_final,
1249                                                           &percent_position,
1250                                                           &custom_format,
1251                                                           &val_obj_display);
1252 
1253                                     const char* open_bracket_position;
1254                                     const char* separator_position;
1255                                     ScanBracketedRange (var_name_begin,
1256                                                         var_name_end,
1257                                                         var_name_final,
1258                                                         &open_bracket_position,
1259                                                         &separator_position,
1260                                                         &close_bracket_position,
1261                                                         &var_name_final_if_array_range,
1262                                                         &index_lower,
1263                                                         &index_higher);
1264 
1265                                     Error error;
1266 
1267                                     std::auto_ptr<char> expr_path(new char[var_name_final-var_name_begin-1]);
1268                                     ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1);
1269                                     memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3);
1270 
1271                                     if (log)
1272                                         log->Printf("symbol to expand: %s",expr_path.get());
1273 
1274                                     target = valobj->GetValueForExpressionPath(expr_path.get(),
1275                                                                              &first_unparsed,
1276                                                                              &reason_to_stop,
1277                                                                              &final_value_type,
1278                                                                              options,
1279                                                                              &what_next).get();
1280 
1281                                     if (!target)
1282                                     {
1283                                         if (log)
1284                                             log->Printf("ERROR: unparsed portion = %s, why stopping = %d,"
1285                                                " final_value_type %d",
1286                                                first_unparsed, reason_to_stop, final_value_type);
1287                                         break;
1288                                     }
1289                                     else
1290                                     {
1291                                         if (log)
1292                                             log->Printf("ALL RIGHT: unparsed portion = %s, why stopping = %d,"
1293                                                " final_value_type %d",
1294                                                first_unparsed, reason_to_stop, final_value_type);
1295                                     }
1296                                 }
1297                                 else
1298                                     break;
1299 
1300                                 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange ||
1301                                                   final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange);
1302 
1303                                 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference);
1304 
1305                                 if (do_deref_pointer && !is_array_range)
1306                                 {
1307                                     // I have not deref-ed yet, let's do it
1308                                     // this happens when we are not going through GetValueForVariableExpressionPath
1309                                     // to get to the target ValueObject
1310                                     Error error;
1311                                     target = target->Dereference(error).get();
1312                                     if (error.Fail())
1313                                     {
1314                                         if (log)
1315                                             log->Printf("ERROR: %s\n", error.AsCString("unknown")); \
1316                                         break;
1317                                     }
1318                                     do_deref_pointer = false;
1319                                 }
1320 
1321                                 // TODO use flags for these
1322                                 bool is_array = ClangASTContext::IsArrayType(target->GetClangType());
1323                                 bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType());
1324                                 bool is_aggregate = ClangASTContext::IsAggregateType(target->GetClangType());
1325 
1326                                 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
1327                                 {
1328                                     StreamString str_temp;
1329                                     if (log)
1330                                         log->Printf("I am into array || pointer && !range");
1331 
1332                                     if (target->HasSpecialPrintableRepresentation(val_obj_display,
1333                                                                                   custom_format))
1334                                     {
1335                                         // try to use the special cases
1336                                         var_success = target->DumpPrintableRepresentation(str_temp,
1337                                                                                           val_obj_display,
1338                                                                                           custom_format);
1339                                         if (log)
1340                                             log->Printf("special cases did%s match", var_success ? "" : "n't");
1341 
1342                                         // should not happen
1343                                         if (!var_success)
1344                                             s << "<invalid usage of pointer value as object>";
1345                                         else
1346                                             s << str_temp.GetData();
1347                                         var_success = true;
1348                                         break;
1349                                     }
1350                                     else
1351                                     {
1352                                         if (was_plain_var) // if ${var}
1353                                         {
1354                                             s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
1355                                         }
1356                                         else if (is_pointer) // if pointer, value is the address stored
1357                                         {
1358                                             var_success = target->DumpPrintableRepresentation(s,
1359                                                                                              val_obj_display,
1360                                                                                              custom_format,
1361                                                                                              ValueObject::ePrintableRepresentationSpecialCasesDisable);
1362                                         }
1363                                         else
1364                                         {
1365                                             s << "<invalid usage of pointer value as object>";
1366                                         }
1367                                         var_success = true;
1368                                         break;
1369                                     }
1370                                 }
1371 
1372                                 // if directly trying to print ${var}, and this is an aggregate, display a nice
1373                                 // type @ location message
1374                                 if (is_aggregate && was_plain_var)
1375                                 {
1376                                     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
1377                                     var_success = true;
1378                                     break;
1379                                 }
1380 
1381                                 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
1382                                 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)))
1383                                 {
1384                                     s << "<invalid use of aggregate type>";
1385                                     var_success = true;
1386                                     break;
1387                                 }
1388 
1389                                 if (!is_array_range)
1390                                 {
1391                                     if (log)
1392                                         log->Printf("dumping ordinary printable output");
1393                                     var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
1394                                 }
1395                                 else
1396                                 {
1397                                     if (log)
1398                                         log->Printf("checking if I can handle as array");
1399                                     if (!is_array && !is_pointer)
1400                                         break;
1401                                     if (log)
1402                                         log->Printf("handle as array");
1403                                     const char* special_directions = NULL;
1404                                     StreamString special_directions_writer;
1405                                     if (close_bracket_position && (var_name_end-close_bracket_position > 1))
1406                                     {
1407                                         ConstString additional_data;
1408                                         additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1);
1409                                         special_directions_writer.Printf("${%svar%s}",
1410                                                                          do_deref_pointer ? "*" : "",
1411                                                                          additional_data.GetCString());
1412                                         special_directions = special_directions_writer.GetData();
1413                                     }
1414 
1415                                     // let us display items index_lower thru index_higher of this array
1416                                     s.PutChar('[');
1417                                     var_success = true;
1418 
1419                                     if (index_higher < 0)
1420                                         index_higher = valobj->GetNumChildren() - 1;
1421 
1422                                     uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
1423 
1424                                     for (;index_lower<=index_higher;index_lower++)
1425                                     {
1426                                         ValueObject* item = ExpandIndexedExpression (target,
1427                                                                                      index_lower,
1428                                                                                      exe_ctx->GetFramePtr(),
1429                                                                                      false).get();
1430 
1431                                         if (!item)
1432                                         {
1433                                             if (log)
1434                                                 log->Printf("ERROR in getting child item at index %lld", index_lower);
1435                                         }
1436                                         else
1437                                         {
1438                                             if (log)
1439                                                 log->Printf("special_directions for child item: %s",special_directions);
1440                                         }
1441 
1442                                         if (!special_directions)
1443                                             var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
1444                                         else
1445                                             var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item);
1446 
1447                                         if (--max_num_children == 0)
1448                                         {
1449                                             s.PutCString(", ...");
1450                                             break;
1451                                         }
1452 
1453                                         if (index_lower < index_higher)
1454                                             s.PutChar(',');
1455                                     }
1456                                     s.PutChar(']');
1457                                 }
1458                             }
1459                             break;
1460                         case 'a':
1461                             if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0)
1462                             {
1463                                 if (addr && addr->IsValid())
1464                                 {
1465                                     var_success = true;
1466                                     format_addr = *addr;
1467                                 }
1468                             }
1469                             else if (::strncmp (var_name_begin, "ansi.", strlen("ansi.")) == 0)
1470                             {
1471                                 var_success = true;
1472                                 var_name_begin += strlen("ansi."); // Skip the "ansi."
1473                                 if (::strncmp (var_name_begin, "fg.", strlen("fg.")) == 0)
1474                                 {
1475                                     var_name_begin += strlen("fg."); // Skip the "fg."
1476                                     if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0)
1477                                     {
1478                                         s.Printf ("%s%s%s",
1479                                                   lldb_utility::ansi::k_escape_start,
1480                                                   lldb_utility::ansi::k_fg_black,
1481                                                   lldb_utility::ansi::k_escape_end);
1482                                     }
1483                                     else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0)
1484                                     {
1485                                         s.Printf ("%s%s%s",
1486                                                   lldb_utility::ansi::k_escape_start,
1487                                                   lldb_utility::ansi::k_fg_red,
1488                                                   lldb_utility::ansi::k_escape_end);
1489                                     }
1490                                     else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0)
1491                                     {
1492                                         s.Printf ("%s%s%s",
1493                                                   lldb_utility::ansi::k_escape_start,
1494                                                   lldb_utility::ansi::k_fg_green,
1495                                                   lldb_utility::ansi::k_escape_end);
1496                                     }
1497                                     else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0)
1498                                     {
1499                                         s.Printf ("%s%s%s",
1500                                                   lldb_utility::ansi::k_escape_start,
1501                                                   lldb_utility::ansi::k_fg_yellow,
1502                                                   lldb_utility::ansi::k_escape_end);
1503                                     }
1504                                     else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0)
1505                                     {
1506                                         s.Printf ("%s%s%s",
1507                                                   lldb_utility::ansi::k_escape_start,
1508                                                   lldb_utility::ansi::k_fg_blue,
1509                                                   lldb_utility::ansi::k_escape_end);
1510                                     }
1511                                     else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0)
1512                                     {
1513                                         s.Printf ("%s%s%s",
1514                                                   lldb_utility::ansi::k_escape_start,
1515                                                   lldb_utility::ansi::k_fg_purple,
1516                                                   lldb_utility::ansi::k_escape_end);
1517                                     }
1518                                     else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0)
1519                                     {
1520                                         s.Printf ("%s%s%s",
1521                                                   lldb_utility::ansi::k_escape_start,
1522                                                   lldb_utility::ansi::k_fg_cyan,
1523                                                   lldb_utility::ansi::k_escape_end);
1524                                     }
1525                                     else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0)
1526                                     {
1527                                         s.Printf ("%s%s%s",
1528                                                   lldb_utility::ansi::k_escape_start,
1529                                                   lldb_utility::ansi::k_fg_white,
1530                                                   lldb_utility::ansi::k_escape_end);
1531                                     }
1532                                     else
1533                                     {
1534                                         var_success = false;
1535                                     }
1536                                 }
1537                                 else if (::strncmp (var_name_begin, "bg.", strlen("bg.")) == 0)
1538                                 {
1539                                     var_name_begin += strlen("bg."); // Skip the "bg."
1540                                     if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0)
1541                                     {
1542                                         s.Printf ("%s%s%s",
1543                                                   lldb_utility::ansi::k_escape_start,
1544                                                   lldb_utility::ansi::k_bg_black,
1545                                                   lldb_utility::ansi::k_escape_end);
1546                                     }
1547                                     else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0)
1548                                     {
1549                                         s.Printf ("%s%s%s",
1550                                                   lldb_utility::ansi::k_escape_start,
1551                                                   lldb_utility::ansi::k_bg_red,
1552                                                   lldb_utility::ansi::k_escape_end);
1553                                     }
1554                                     else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0)
1555                                     {
1556                                         s.Printf ("%s%s%s",
1557                                                   lldb_utility::ansi::k_escape_start,
1558                                                   lldb_utility::ansi::k_bg_green,
1559                                                   lldb_utility::ansi::k_escape_end);
1560                                     }
1561                                     else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0)
1562                                     {
1563                                         s.Printf ("%s%s%s",
1564                                                   lldb_utility::ansi::k_escape_start,
1565                                                   lldb_utility::ansi::k_bg_yellow,
1566                                                   lldb_utility::ansi::k_escape_end);
1567                                     }
1568                                     else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0)
1569                                     {
1570                                         s.Printf ("%s%s%s",
1571                                                   lldb_utility::ansi::k_escape_start,
1572                                                   lldb_utility::ansi::k_bg_blue,
1573                                                   lldb_utility::ansi::k_escape_end);
1574                                     }
1575                                     else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0)
1576                                     {
1577                                         s.Printf ("%s%s%s",
1578                                                   lldb_utility::ansi::k_escape_start,
1579                                                   lldb_utility::ansi::k_bg_purple,
1580                                                   lldb_utility::ansi::k_escape_end);
1581                                     }
1582                                     else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0)
1583                                     {
1584                                         s.Printf ("%s%s%s",
1585                                                   lldb_utility::ansi::k_escape_start,
1586                                                   lldb_utility::ansi::k_bg_cyan,
1587                                                   lldb_utility::ansi::k_escape_end);
1588                                     }
1589                                     else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0)
1590                                     {
1591                                         s.Printf ("%s%s%s",
1592                                                   lldb_utility::ansi::k_escape_start,
1593                                                   lldb_utility::ansi::k_bg_white,
1594                                                   lldb_utility::ansi::k_escape_end);
1595                                     }
1596                                     else
1597                                     {
1598                                         var_success = false;
1599                                     }
1600                                 }
1601                                 else if (::strncmp (var_name_begin, "normal}", strlen ("normal}")) == 0)
1602                                 {
1603                                     s.Printf ("%s%s%s",
1604                                               lldb_utility::ansi::k_escape_start,
1605                                               lldb_utility::ansi::k_ctrl_normal,
1606                                               lldb_utility::ansi::k_escape_end);
1607                                 }
1608                                 else if (::strncmp (var_name_begin, "bold}", strlen("bold}")) == 0)
1609                                 {
1610                                     s.Printf ("%s%s%s",
1611                                               lldb_utility::ansi::k_escape_start,
1612                                               lldb_utility::ansi::k_ctrl_bold,
1613                                               lldb_utility::ansi::k_escape_end);
1614                                 }
1615                                 else if (::strncmp (var_name_begin, "faint}", strlen("faint}")) == 0)
1616                                 {
1617                                     s.Printf ("%s%s%s",
1618                                               lldb_utility::ansi::k_escape_start,
1619                                               lldb_utility::ansi::k_ctrl_faint,
1620                                               lldb_utility::ansi::k_escape_end);
1621                                 }
1622                                 else if (::strncmp (var_name_begin, "italic}", strlen("italic}")) == 0)
1623                                 {
1624                                     s.Printf ("%s%s%s",
1625                                               lldb_utility::ansi::k_escape_start,
1626                                               lldb_utility::ansi::k_ctrl_italic,
1627                                               lldb_utility::ansi::k_escape_end);
1628                                 }
1629                                 else if (::strncmp (var_name_begin, "underline}", strlen("underline}")) == 0)
1630                                 {
1631                                     s.Printf ("%s%s%s",
1632                                               lldb_utility::ansi::k_escape_start,
1633                                               lldb_utility::ansi::k_ctrl_underline,
1634                                               lldb_utility::ansi::k_escape_end);
1635                                 }
1636                                 else if (::strncmp (var_name_begin, "slow-blink}", strlen("slow-blink}")) == 0)
1637                                 {
1638                                     s.Printf ("%s%s%s",
1639                                               lldb_utility::ansi::k_escape_start,
1640                                               lldb_utility::ansi::k_ctrl_slow_blink,
1641                                               lldb_utility::ansi::k_escape_end);
1642                                 }
1643                                 else if (::strncmp (var_name_begin, "fast-blink}", strlen("fast-blink}")) == 0)
1644                                 {
1645                                     s.Printf ("%s%s%s",
1646                                               lldb_utility::ansi::k_escape_start,
1647                                               lldb_utility::ansi::k_ctrl_fast_blink,
1648                                               lldb_utility::ansi::k_escape_end);
1649                                 }
1650                                 else if (::strncmp (var_name_begin, "negative}", strlen("negative}")) == 0)
1651                                 {
1652                                     s.Printf ("%s%s%s",
1653                                               lldb_utility::ansi::k_escape_start,
1654                                               lldb_utility::ansi::k_ctrl_negative,
1655                                               lldb_utility::ansi::k_escape_end);
1656                                 }
1657                                 else if (::strncmp (var_name_begin, "conceal}", strlen("conceal}")) == 0)
1658                                 {
1659                                     s.Printf ("%s%s%s",
1660                                               lldb_utility::ansi::k_escape_start,
1661                                               lldb_utility::ansi::k_ctrl_conceal,
1662                                               lldb_utility::ansi::k_escape_end);
1663 
1664                                 }
1665                                 else if (::strncmp (var_name_begin, "crossed-out}", strlen("crossed-out}")) == 0)
1666                                 {
1667                                     s.Printf ("%s%s%s",
1668                                               lldb_utility::ansi::k_escape_start,
1669                                               lldb_utility::ansi::k_ctrl_crossed_out,
1670                                               lldb_utility::ansi::k_escape_end);
1671                                 }
1672                                 else
1673                                 {
1674                                     var_success = false;
1675                                 }
1676                             }
1677                             break;
1678 
1679                         case 'p':
1680                             if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0)
1681                             {
1682                                 if (exe_ctx)
1683                                 {
1684                                     Process *process = exe_ctx->GetProcessPtr();
1685                                     if (process)
1686                                     {
1687                                         var_name_begin += ::strlen ("process.");
1688                                         if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0)
1689                                         {
1690                                             s.Printf("%llu", process->GetID());
1691                                             var_success = true;
1692                                         }
1693                                         else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) ||
1694                                                  (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) ||
1695                                                  (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0))
1696                                         {
1697                                             Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1698                                             if (exe_module)
1699                                             {
1700                                                 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f')
1701                                                 {
1702                                                     format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename();
1703                                                     var_success = format_file_spec;
1704                                                 }
1705                                                 else
1706                                                 {
1707                                                     format_file_spec = exe_module->GetFileSpec();
1708                                                     var_success = format_file_spec;
1709                                                 }
1710                                             }
1711                                         }
1712                                     }
1713                                 }
1714                             }
1715                             break;
1716 
1717                         case 't':
1718                             if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0)
1719                             {
1720                                 if (exe_ctx)
1721                                 {
1722                                     Thread *thread = exe_ctx->GetThreadPtr();
1723                                     if (thread)
1724                                     {
1725                                         var_name_begin += ::strlen ("thread.");
1726                                         if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0)
1727                                         {
1728                                             s.Printf("0x%4.4llx", thread->GetID());
1729                                             var_success = true;
1730                                         }
1731                                         else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0)
1732                                         {
1733                                             s.Printf("%u", thread->GetIndexID());
1734                                             var_success = true;
1735                                         }
1736                                         else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0)
1737                                         {
1738                                             cstr = thread->GetName();
1739                                             var_success = cstr && cstr[0];
1740                                             if (var_success)
1741                                                 s.PutCString(cstr);
1742                                         }
1743                                         else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0)
1744                                         {
1745                                             cstr = thread->GetQueueName();
1746                                             var_success = cstr && cstr[0];
1747                                             if (var_success)
1748                                                 s.PutCString(cstr);
1749                                         }
1750                                         else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0)
1751                                         {
1752                                             StopInfoSP stop_info_sp = thread->GetStopInfo ();
1753                                             if (stop_info_sp)
1754                                             {
1755                                                 cstr = stop_info_sp->GetDescription();
1756                                                 if (cstr && cstr[0])
1757                                                 {
1758                                                     s.PutCString(cstr);
1759                                                     var_success = true;
1760                                                 }
1761                                             }
1762                                         }
1763                                         else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0)
1764                                         {
1765                                             StopInfoSP stop_info_sp = thread->GetStopInfo ();
1766                                             if (stop_info_sp)
1767                                             {
1768                                                 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
1769                                                 if (return_valobj_sp)
1770                                                 {
1771                                                     ValueObject::DumpValueObjectOptions dump_options;
1772                                                     ValueObject::DumpValueObject (s, return_valobj_sp.get(), dump_options);
1773                                                     var_success = true;
1774                                                 }
1775                                             }
1776                                         }
1777                                     }
1778                                 }
1779                             }
1780                             else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0)
1781                             {
1782                                 Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
1783                                 if (target)
1784                                 {
1785                                     var_name_begin += ::strlen ("target.");
1786                                     if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0)
1787                                     {
1788                                         ArchSpec arch (target->GetArchitecture ());
1789                                         if (arch.IsValid())
1790                                         {
1791                                             s.PutCString (arch.GetArchitectureName());
1792                                             var_success = true;
1793                                         }
1794                                     }
1795                                 }
1796                             }
1797                             break;
1798 
1799 
1800                         case 'm':
1801                             if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0)
1802                             {
1803                                 if (sc && sc->module_sp.get())
1804                                 {
1805                                     Module *module = sc->module_sp.get();
1806                                     var_name_begin += ::strlen ("module.");
1807 
1808                                     if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0)
1809                                     {
1810                                         if (module->GetFileSpec())
1811                                         {
1812                                             var_name_begin += ::strlen ("file.");
1813 
1814                                             if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0)
1815                                             {
1816                                                 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename();
1817                                                 var_success = format_file_spec;
1818                                             }
1819                                             else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0)
1820                                             {
1821                                                 format_file_spec = module->GetFileSpec();
1822                                                 var_success = format_file_spec;
1823                                             }
1824                                         }
1825                                     }
1826                                 }
1827                             }
1828                             break;
1829 
1830 
1831                         case 'f':
1832                             if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0)
1833                             {
1834                                 if (sc && sc->comp_unit != NULL)
1835                                 {
1836                                     var_name_begin += ::strlen ("file.");
1837 
1838                                     if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0)
1839                                     {
1840                                         format_file_spec.GetFilename() = sc->comp_unit->GetFilename();
1841                                         var_success = format_file_spec;
1842                                     }
1843                                     else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0)
1844                                     {
1845                                         format_file_spec = *sc->comp_unit;
1846                                         var_success = format_file_spec;
1847                                     }
1848                                 }
1849                             }
1850                             else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0)
1851                             {
1852                                 if (exe_ctx)
1853                                 {
1854                                     StackFrame *frame = exe_ctx->GetFramePtr();
1855                                     if (frame)
1856                                     {
1857                                         var_name_begin += ::strlen ("frame.");
1858                                         if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0)
1859                                         {
1860                                             s.Printf("%u", frame->GetFrameIndex());
1861                                             var_success = true;
1862                                         }
1863                                         else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0)
1864                                         {
1865                                             reg_kind = eRegisterKindGeneric;
1866                                             reg_num = LLDB_REGNUM_GENERIC_PC;
1867                                             var_success = true;
1868                                         }
1869                                         else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0)
1870                                         {
1871                                             reg_kind = eRegisterKindGeneric;
1872                                             reg_num = LLDB_REGNUM_GENERIC_SP;
1873                                             var_success = true;
1874                                         }
1875                                         else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0)
1876                                         {
1877                                             reg_kind = eRegisterKindGeneric;
1878                                             reg_num = LLDB_REGNUM_GENERIC_FP;
1879                                             var_success = true;
1880                                         }
1881                                         else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0)
1882                                         {
1883                                             reg_kind = eRegisterKindGeneric;
1884                                             reg_num = LLDB_REGNUM_GENERIC_FLAGS;
1885                                             var_success = true;
1886                                         }
1887                                         else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0)
1888                                         {
1889                                             reg_ctx = frame->GetRegisterContext().get();
1890                                             if (reg_ctx)
1891                                             {
1892                                                 var_name_begin += ::strlen ("reg.");
1893                                                 if (var_name_begin < var_name_end)
1894                                                 {
1895                                                     std::string reg_name (var_name_begin, var_name_end);
1896                                                     reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str());
1897                                                     if (reg_info)
1898                                                         var_success = true;
1899                                                 }
1900                                             }
1901                                         }
1902                                     }
1903                                 }
1904                             }
1905                             else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0)
1906                             {
1907                                 if (sc && (sc->function != NULL || sc->symbol != NULL))
1908                                 {
1909                                     var_name_begin += ::strlen ("function.");
1910                                     if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0)
1911                                     {
1912                                         if (sc->function)
1913                                             s.Printf("function{0x%8.8llx}", sc->function->GetID());
1914                                         else
1915                                             s.Printf("symbol[%u]", sc->symbol->GetID());
1916 
1917                                         var_success = true;
1918                                     }
1919                                     else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0)
1920                                     {
1921                                         if (sc->function)
1922                                             cstr = sc->function->GetName().AsCString (NULL);
1923                                         else if (sc->symbol)
1924                                             cstr = sc->symbol->GetName().AsCString (NULL);
1925                                         if (cstr)
1926                                         {
1927                                             s.PutCString(cstr);
1928 
1929                                             if (sc->block)
1930                                             {
1931                                                 Block *inline_block = sc->block->GetContainingInlinedBlock ();
1932                                                 if (inline_block)
1933                                                 {
1934                                                     const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
1935                                                     if (inline_info)
1936                                                     {
1937                                                         s.PutCString(" [inlined] ");
1938                                                         inline_info->GetName().Dump(&s);
1939                                                     }
1940                                                 }
1941                                             }
1942                                             var_success = true;
1943                                         }
1944                                     }
1945                                     else if (::strncmp (var_name_begin, "name-with-args}", strlen("name-with-args}")) == 0)
1946                                     {
1947                                         // Print the function name with arguments in it
1948 
1949                                         if (sc->function)
1950                                         {
1951                                             var_success = true;
1952                                             ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
1953                                             cstr = sc->function->GetName().AsCString (NULL);
1954                                             if (cstr)
1955                                             {
1956                                                 const InlineFunctionInfo *inline_info = NULL;
1957                                                 VariableListSP variable_list_sp;
1958                                                 bool get_function_vars = true;
1959                                                 if (sc->block)
1960                                                 {
1961                                                     Block *inline_block = sc->block->GetContainingInlinedBlock ();
1962 
1963                                                     if (inline_block)
1964                                                     {
1965                                                         get_function_vars = false;
1966                                                         inline_info = sc->block->GetInlinedFunctionInfo();
1967                                                         if (inline_info)
1968                                                             variable_list_sp = inline_block->GetBlockVariableList (true);
1969                                                     }
1970                                                 }
1971 
1972                                                 if (get_function_vars)
1973                                                 {
1974                                                     variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
1975                                                 }
1976 
1977                                                 if (inline_info)
1978                                                 {
1979                                                     s.PutCString (cstr);
1980                                                     s.PutCString (" [inlined] ");
1981                                                     cstr = inline_info->GetName().GetCString();
1982                                                 }
1983 
1984                                                 VariableList args;
1985                                                 if (variable_list_sp)
1986                                                 {
1987                                                     const size_t num_variables = variable_list_sp->GetSize();
1988                                                     for (size_t var_idx = 0; var_idx < num_variables; ++var_idx)
1989                                                     {
1990                                                         VariableSP var_sp (variable_list_sp->GetVariableAtIndex(var_idx));
1991                                                         if (var_sp->GetScope() == eValueTypeVariableArgument)
1992                                                             args.AddVariable (var_sp);
1993                                                     }
1994 
1995                                                 }
1996                                                 if (args.GetSize() > 0)
1997                                                 {
1998                                                     const char *open_paren = strchr (cstr, '(');
1999                                                     const char *close_paren = NULL;
2000                                                     if (open_paren)
2001                                                         close_paren = strchr (open_paren, ')');
2002 
2003                                                     if (open_paren)
2004                                                         s.Write(cstr, open_paren - cstr + 1);
2005                                                     else
2006                                                     {
2007                                                         s.PutCString (cstr);
2008                                                         s.PutChar ('(');
2009                                                     }
2010                                                     const size_t num_args = args.GetSize();
2011                                                     for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
2012                                                     {
2013                                                         VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
2014                                                         ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
2015                                                         const char *var_name = var_value_sp->GetName().GetCString();
2016                                                         const char *var_value = var_value_sp->GetValueAsCString();
2017                                                         if (var_value_sp->GetError().Success())
2018                                                         {
2019                                                             if (arg_idx > 0)
2020                                                                 s.PutCString (", ");
2021                                                             s.Printf ("%s=%s", var_name, var_value);
2022                                                         }
2023                                                     }
2024 
2025                                                     if (close_paren)
2026                                                         s.PutCString (close_paren);
2027                                                     else
2028                                                         s.PutChar(')');
2029 
2030                                                 }
2031                                                 else
2032                                                 {
2033                                                     s.PutCString(cstr);
2034                                                 }
2035                                             }
2036                                         }
2037                                         else if (sc->symbol)
2038                                         {
2039                                             cstr = sc->symbol->GetName().AsCString (NULL);
2040                                             if (cstr)
2041                                             {
2042                                                 s.PutCString(cstr);
2043                                                 var_success = true;
2044                                             }
2045                                         }
2046                                     }
2047                                     else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0)
2048                                     {
2049                                         var_success = addr != NULL;
2050                                         if (var_success)
2051                                         {
2052                                             format_addr = *addr;
2053                                             calculate_format_addr_function_offset = true;
2054                                         }
2055                                     }
2056                                     else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0)
2057                                     {
2058                                         var_success = sc->line_entry.range.GetBaseAddress().IsValid();
2059                                         if (var_success)
2060                                         {
2061                                             format_addr = sc->line_entry.range.GetBaseAddress();
2062                                             calculate_format_addr_function_offset = true;
2063                                         }
2064                                     }
2065                                     else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0)
2066                                     {
2067                                         StackFrame *frame = exe_ctx->GetFramePtr();
2068                                         var_success = frame != NULL;
2069                                         if (var_success)
2070                                         {
2071                                             format_addr = frame->GetFrameCodeAddress();
2072                                             calculate_format_addr_function_offset = true;
2073                                         }
2074                                     }
2075                                 }
2076                             }
2077                             break;
2078 
2079                         case 'l':
2080                             if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0)
2081                             {
2082                                 if (sc && sc->line_entry.IsValid())
2083                                 {
2084                                     var_name_begin += ::strlen ("line.");
2085                                     if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0)
2086                                     {
2087                                         var_name_begin += ::strlen ("file.");
2088 
2089                                         if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0)
2090                                         {
2091                                             format_file_spec.GetFilename() = sc->line_entry.file.GetFilename();
2092                                             var_success = format_file_spec;
2093                                         }
2094                                         else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0)
2095                                         {
2096                                             format_file_spec = sc->line_entry.file;
2097                                             var_success = format_file_spec;
2098                                         }
2099                                     }
2100                                     else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0)
2101                                     {
2102                                         var_success = true;
2103                                         s.Printf("%u", sc->line_entry.line);
2104                                     }
2105                                     else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) ||
2106                                              (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0))
2107                                     {
2108                                         var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid();
2109                                         if (var_success)
2110                                         {
2111                                             format_addr = sc->line_entry.range.GetBaseAddress();
2112                                             if (var_name_begin[0] == 'e')
2113                                                 format_addr.Slide (sc->line_entry.range.GetByteSize());
2114                                         }
2115                                     }
2116                                 }
2117                             }
2118                             break;
2119                         }
2120 
2121                         if (var_success)
2122                         {
2123                             // If format addr is valid, then we need to print an address
2124                             if (reg_num != LLDB_INVALID_REGNUM)
2125                             {
2126                                 StackFrame *frame = exe_ctx->GetFramePtr();
2127                                 // We have a register value to display...
2128                                 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric)
2129                                 {
2130                                     format_addr = frame->GetFrameCodeAddress();
2131                                 }
2132                                 else
2133                                 {
2134                                     if (reg_ctx == NULL)
2135                                         reg_ctx = frame->GetRegisterContext().get();
2136 
2137                                     if (reg_ctx)
2138                                     {
2139                                         if (reg_kind != kNumRegisterKinds)
2140                                             reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
2141                                         reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
2142                                         var_success = reg_info != NULL;
2143                                     }
2144                                 }
2145                             }
2146 
2147                             if (reg_info != NULL)
2148                             {
2149                                 RegisterValue reg_value;
2150                                 var_success = reg_ctx->ReadRegister (reg_info, reg_value);
2151                                 if (var_success)
2152                                 {
2153                                     reg_value.Dump(&s, reg_info, false, false, eFormatDefault);
2154                                 }
2155                             }
2156 
2157                             if (format_file_spec)
2158                             {
2159                                 s << format_file_spec;
2160                             }
2161 
2162                             // If format addr is valid, then we need to print an address
2163                             if (format_addr.IsValid())
2164                             {
2165                                 var_success = false;
2166 
2167                                 if (calculate_format_addr_function_offset)
2168                                 {
2169                                     Address func_addr;
2170 
2171                                     if (sc)
2172                                     {
2173                                         if (sc->function)
2174                                         {
2175                                             func_addr = sc->function->GetAddressRange().GetBaseAddress();
2176                                             if (sc->block)
2177                                             {
2178                                                 // Check to make sure we aren't in an inline
2179                                                 // function. If we are, use the inline block
2180                                                 // range that contains "format_addr" since
2181                                                 // blocks can be discontiguous.
2182                                                 Block *inline_block = sc->block->GetContainingInlinedBlock ();
2183                                                 AddressRange inline_range;
2184                                                 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range))
2185                                                     func_addr = inline_range.GetBaseAddress();
2186                                             }
2187                                         }
2188                                         else if (sc->symbol && sc->symbol->ValueIsAddress())
2189                                             func_addr = sc->symbol->GetAddress();
2190                                     }
2191 
2192                                     if (func_addr.IsValid())
2193                                     {
2194                                         if (func_addr.GetSection() == format_addr.GetSection())
2195                                         {
2196                                             addr_t func_file_addr = func_addr.GetFileAddress();
2197                                             addr_t addr_file_addr = format_addr.GetFileAddress();
2198                                             if (addr_file_addr > func_file_addr)
2199                                                 s.Printf(" + %llu", addr_file_addr - func_file_addr);
2200                                             else if (addr_file_addr < func_file_addr)
2201                                                 s.Printf(" - %llu", func_file_addr - addr_file_addr);
2202                                             var_success = true;
2203                                         }
2204                                         else
2205                                         {
2206                                             Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
2207                                             if (target)
2208                                             {
2209                                                 addr_t func_load_addr = func_addr.GetLoadAddress (target);
2210                                                 addr_t addr_load_addr = format_addr.GetLoadAddress (target);
2211                                                 if (addr_load_addr > func_load_addr)
2212                                                     s.Printf(" + %llu", addr_load_addr - func_load_addr);
2213                                                 else if (addr_load_addr < func_load_addr)
2214                                                     s.Printf(" - %llu", func_load_addr - addr_load_addr);
2215                                                 var_success = true;
2216                                             }
2217                                         }
2218                                     }
2219                                 }
2220                                 else
2221                                 {
2222                                     Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
2223                                     addr_t vaddr = LLDB_INVALID_ADDRESS;
2224                                     if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
2225                                         vaddr = format_addr.GetLoadAddress (target);
2226                                     if (vaddr == LLDB_INVALID_ADDRESS)
2227                                         vaddr = format_addr.GetFileAddress ();
2228 
2229                                     if (vaddr != LLDB_INVALID_ADDRESS)
2230                                     {
2231                                         int addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
2232                                         if (addr_width == 0)
2233                                             addr_width = 16;
2234                                         s.Printf("0x%*.*llx", addr_width, addr_width, vaddr);
2235                                         var_success = true;
2236                                     }
2237                                 }
2238                             }
2239                         }
2240 
2241                         if (var_success == false)
2242                             success = false;
2243                     }
2244                     p = var_name_end;
2245                 }
2246                 else
2247                     break;
2248             }
2249             else
2250             {
2251                 // We got a dollar sign with no '{' after it, it must just be a dollar sign
2252                 s.PutChar(*p);
2253             }
2254         }
2255         else if (*p == '\\')
2256         {
2257             ++p; // skip the slash
2258             switch (*p)
2259             {
2260             case 'a': s.PutChar ('\a'); break;
2261             case 'b': s.PutChar ('\b'); break;
2262             case 'f': s.PutChar ('\f'); break;
2263             case 'n': s.PutChar ('\n'); break;
2264             case 'r': s.PutChar ('\r'); break;
2265             case 't': s.PutChar ('\t'); break;
2266             case 'v': s.PutChar ('\v'); break;
2267             case '\'': s.PutChar ('\''); break;
2268             case '\\': s.PutChar ('\\'); break;
2269             case '0':
2270                 // 1 to 3 octal chars
2271                 {
2272                     // Make a string that can hold onto the initial zero char,
2273                     // up to 3 octal digits, and a terminating NULL.
2274                     char oct_str[5] = { 0, 0, 0, 0, 0 };
2275 
2276                     int i;
2277                     for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
2278                         oct_str[i] = p[i];
2279 
2280                     // We don't want to consume the last octal character since
2281                     // the main for loop will do this for us, so we advance p by
2282                     // one less than i (even if i is zero)
2283                     p += i - 1;
2284                     unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
2285                     if (octal_value <= UINT8_MAX)
2286                     {
2287                         char octal_char = octal_value;
2288                         s.Write (&octal_char, 1);
2289                     }
2290                 }
2291                 break;
2292 
2293             case 'x':
2294                 // hex number in the format
2295                 if (isxdigit(p[1]))
2296                 {
2297                     ++p;    // Skip the 'x'
2298 
2299                     // Make a string that can hold onto two hex chars plus a
2300                     // NULL terminator
2301                     char hex_str[3] = { 0,0,0 };
2302                     hex_str[0] = *p;
2303                     if (isxdigit(p[1]))
2304                     {
2305                         ++p; // Skip the first of the two hex chars
2306                         hex_str[1] = *p;
2307                     }
2308 
2309                     unsigned long hex_value = strtoul (hex_str, NULL, 16);
2310                     if (hex_value <= UINT8_MAX)
2311                         s.PutChar (hex_value);
2312                 }
2313                 else
2314                 {
2315                     s.PutChar('x');
2316                 }
2317                 break;
2318 
2319             default:
2320                 // Just desensitize any other character by just printing what
2321                 // came after the '\'
2322                 s << *p;
2323                 break;
2324 
2325             }
2326 
2327         }
2328     }
2329     if (end)
2330         *end = p;
2331     return success;
2332 }
2333 
2334 void
2335 Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton)
2336 {
2337     // For simplicity's sake, I am not going to deal with how to close down any
2338     // open logging streams, I just redirect everything from here on out to the
2339     // callback.
2340     m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton));
2341 }
2342 
2343 bool
2344 Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream)
2345 {
2346     Log::Callbacks log_callbacks;
2347 
2348     StreamSP log_stream_sp;
2349     if (m_log_callback_stream_sp != NULL)
2350     {
2351         log_stream_sp = m_log_callback_stream_sp;
2352         // For now when using the callback mode you always get thread & timestamp.
2353         log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
2354     }
2355     else if (log_file == NULL || *log_file == '\0')
2356     {
2357         log_stream_sp.reset(new StreamFile(GetOutputFile().GetDescriptor(), false));
2358     }
2359     else
2360     {
2361         LogStreamMap::iterator pos = m_log_streams.find(log_file);
2362         if (pos == m_log_streams.end())
2363         {
2364             log_stream_sp.reset (new StreamFile (log_file));
2365             m_log_streams[log_file] = log_stream_sp;
2366         }
2367         else
2368             log_stream_sp = pos->second;
2369     }
2370     assert (log_stream_sp.get());
2371 
2372     if (log_options == 0)
2373         log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
2374 
2375     if (Log::GetLogChannelCallbacks (channel, log_callbacks))
2376     {
2377         log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream);
2378         return true;
2379     }
2380     else
2381     {
2382         LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel));
2383         if (log_channel_sp)
2384         {
2385             if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories))
2386             {
2387                 return true;
2388             }
2389             else
2390             {
2391                 error_stream.Printf ("Invalid log channel '%s'.\n", channel);
2392                 return false;
2393             }
2394         }
2395         else
2396         {
2397             error_stream.Printf ("Invalid log channel '%s'.\n", channel);
2398             return false;
2399         }
2400     }
2401     return false;
2402 }
2403 
2404 #pragma mark Debugger::SettingsController
2405 
2406 //--------------------------------------------------
2407 // class Debugger::SettingsController
2408 //--------------------------------------------------
2409 
2410 Debugger::SettingsController::SettingsController () :
2411     UserSettingsController ("", UserSettingsControllerSP())
2412 {
2413 }
2414 
2415 Debugger::SettingsController::~SettingsController ()
2416 {
2417 }
2418 
2419 
2420 InstanceSettingsSP
2421 Debugger::SettingsController::CreateInstanceSettings (const char *instance_name)
2422 {
2423     InstanceSettingsSP new_settings_sp (new DebuggerInstanceSettings (GetSettingsController(),
2424                                                                       false,
2425                                                                       instance_name));
2426     return new_settings_sp;
2427 }
2428 
2429 #pragma mark DebuggerInstanceSettings
2430 //--------------------------------------------------
2431 //  class DebuggerInstanceSettings
2432 //--------------------------------------------------
2433 
2434 DebuggerInstanceSettings::DebuggerInstanceSettings
2435 (
2436     const UserSettingsControllerSP &m_owner_sp,
2437     bool live_instance,
2438     const char *name
2439 ) :
2440     InstanceSettings (m_owner_sp, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
2441     m_term_width (80),
2442     m_stop_source_before_count (3),
2443     m_stop_source_after_count (3),
2444     m_stop_disassembly_count (4),
2445     m_stop_disassembly_display (eStopDisassemblyTypeNoSource),
2446     m_prompt (),
2447     m_frame_format (),
2448     m_thread_format (),
2449     m_script_lang (),
2450     m_use_external_editor (false),
2451     m_auto_confirm_on (false)
2452 {
2453     // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
2454     // until the vtables for DebuggerInstanceSettings are properly set up, i.e. AFTER all the initializers.
2455     // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
2456     // The same is true of CreateInstanceName().
2457 
2458     if (GetInstanceName() == InstanceSettings::InvalidName())
2459     {
2460         ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
2461         m_owner_sp->RegisterInstanceSettings (this);
2462     }
2463 
2464     if (live_instance)
2465     {
2466         const InstanceSettingsSP &pending_settings = m_owner_sp->FindPendingSettings (m_instance_name);
2467         CopyInstanceSettings (pending_settings, false);
2468     }
2469 }
2470 
2471 DebuggerInstanceSettings::DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs) :
2472     InstanceSettings (Debugger::GetSettingsController(), CreateInstanceName ().AsCString()),
2473     m_prompt (rhs.m_prompt),
2474     m_frame_format (rhs.m_frame_format),
2475     m_thread_format (rhs.m_thread_format),
2476     m_script_lang (rhs.m_script_lang),
2477     m_use_external_editor (rhs.m_use_external_editor),
2478     m_auto_confirm_on(rhs.m_auto_confirm_on)
2479 {
2480     UserSettingsControllerSP owner_sp (m_owner_wp.lock());
2481     if (owner_sp)
2482     {
2483         CopyInstanceSettings (owner_sp->FindPendingSettings (m_instance_name), false);
2484         owner_sp->RemovePendingSettings (m_instance_name);
2485     }
2486 }
2487 
2488 DebuggerInstanceSettings::~DebuggerInstanceSettings ()
2489 {
2490 }
2491 
2492 DebuggerInstanceSettings&
2493 DebuggerInstanceSettings::operator= (const DebuggerInstanceSettings &rhs)
2494 {
2495     if (this != &rhs)
2496     {
2497         m_term_width = rhs.m_term_width;
2498         m_prompt = rhs.m_prompt;
2499         m_frame_format = rhs.m_frame_format;
2500         m_thread_format = rhs.m_thread_format;
2501         m_script_lang = rhs.m_script_lang;
2502         m_use_external_editor = rhs.m_use_external_editor;
2503         m_auto_confirm_on = rhs.m_auto_confirm_on;
2504     }
2505 
2506     return *this;
2507 }
2508 
2509 bool
2510 DebuggerInstanceSettings::ValidTermWidthValue (const char *value, Error err)
2511 {
2512     bool valid = false;
2513 
2514     // Verify we have a value string.
2515     if (value == NULL || value[0] == '\0')
2516     {
2517         err.SetErrorString ("missing value, can't set terminal width without a value");
2518     }
2519     else
2520     {
2521         char *end = NULL;
2522         const uint32_t width = ::strtoul (value, &end, 0);
2523 
2524         if (end && end[0] == '\0')
2525         {
2526             if (width >= 10 && width <= 1024)
2527                 valid = true;
2528             else
2529                 err.SetErrorString ("invalid term-width value; value must be between 10 and 1024");
2530         }
2531         else
2532             err.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string", value);
2533     }
2534 
2535     return valid;
2536 }
2537 
2538 
2539 void
2540 DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
2541                                                           const char *index_value,
2542                                                           const char *value,
2543                                                           const ConstString &instance_name,
2544                                                           const SettingEntry &entry,
2545                                                           VarSetOperationType op,
2546                                                           Error &err,
2547                                                           bool pending)
2548 {
2549 
2550     if (var_name == TermWidthVarName())
2551     {
2552         if (ValidTermWidthValue (value, err))
2553         {
2554             m_term_width = ::strtoul (value, NULL, 0);
2555         }
2556     }
2557     else if (var_name == PromptVarName())
2558     {
2559         UserSettingsController::UpdateStringVariable (op, m_prompt, value, err);
2560         if (!pending)
2561         {
2562             // 'instance_name' is actually (probably) in the form '[<instance_name>]';  if so, we need to
2563             // strip off the brackets before passing it to BroadcastPromptChange.
2564 
2565             std::string tmp_instance_name (instance_name.AsCString());
2566             if ((tmp_instance_name[0] == '[')
2567                 && (tmp_instance_name[instance_name.GetLength() - 1] == ']'))
2568                 tmp_instance_name = tmp_instance_name.substr (1, instance_name.GetLength() - 2);
2569             ConstString new_name (tmp_instance_name.c_str());
2570 
2571             BroadcastPromptChange (new_name, m_prompt.c_str());
2572         }
2573     }
2574     else if (var_name == GetFrameFormatName())
2575     {
2576         UserSettingsController::UpdateStringVariable (op, m_frame_format, value, err);
2577     }
2578     else if (var_name == GetThreadFormatName())
2579     {
2580         UserSettingsController::UpdateStringVariable (op, m_thread_format, value, err);
2581     }
2582     else if (var_name == ScriptLangVarName())
2583     {
2584         bool success;
2585         m_script_lang = Args::StringToScriptLanguage (value, eScriptLanguageDefault,
2586                                                       &success);
2587     }
2588     else if (var_name == UseExternalEditorVarName ())
2589     {
2590         UserSettingsController::UpdateBooleanVariable (op, m_use_external_editor, value, false, err);
2591     }
2592     else if (var_name == AutoConfirmName ())
2593     {
2594         UserSettingsController::UpdateBooleanVariable (op, m_auto_confirm_on, value, false, err);
2595     }
2596     else if (var_name == StopSourceContextBeforeName ())
2597     {
2598         uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL);
2599         if (new_value != UINT32_MAX)
2600             m_stop_source_before_count = new_value;
2601         else
2602             err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextAfterName ().GetCString());
2603     }
2604     else if (var_name == StopSourceContextAfterName ())
2605     {
2606         uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL);
2607         if (new_value != UINT32_MAX)
2608             m_stop_source_after_count = new_value;
2609         else
2610             err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextBeforeName ().GetCString());
2611     }
2612     else if (var_name == StopDisassemblyCountName ())
2613     {
2614         uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL);
2615         if (new_value != UINT32_MAX)
2616             m_stop_disassembly_count = new_value;
2617         else
2618             err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopDisassemblyCountName ().GetCString());
2619     }
2620     else if (var_name == StopDisassemblyDisplayName ())
2621     {
2622         int new_value;
2623         UserSettingsController::UpdateEnumVariable (g_show_disassembly_enum_values, &new_value, value, err);
2624         if (err.Success())
2625             m_stop_disassembly_display = (StopDisassemblyType)new_value;
2626     }
2627 }
2628 
2629 bool
2630 DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
2631                                                     const ConstString &var_name,
2632                                                     StringList &value,
2633                                                     Error *err)
2634 {
2635     if (var_name == PromptVarName())
2636     {
2637         value.AppendString (m_prompt.c_str(), m_prompt.size());
2638 
2639     }
2640     else if (var_name == ScriptLangVarName())
2641     {
2642         value.AppendString (ScriptInterpreter::LanguageToString (m_script_lang).c_str());
2643     }
2644     else if (var_name == TermWidthVarName())
2645     {
2646         StreamString width_str;
2647         width_str.Printf ("%u", m_term_width);
2648         value.AppendString (width_str.GetData());
2649     }
2650     else if (var_name == GetFrameFormatName ())
2651     {
2652         value.AppendString(m_frame_format.c_str(), m_frame_format.size());
2653     }
2654     else if (var_name == GetThreadFormatName ())
2655     {
2656         value.AppendString(m_thread_format.c_str(), m_thread_format.size());
2657     }
2658     else if (var_name == UseExternalEditorVarName())
2659     {
2660         if (m_use_external_editor)
2661             value.AppendString ("true");
2662         else
2663             value.AppendString ("false");
2664     }
2665     else if (var_name == AutoConfirmName())
2666     {
2667         if (m_auto_confirm_on)
2668             value.AppendString ("true");
2669         else
2670             value.AppendString ("false");
2671     }
2672     else if (var_name == StopSourceContextAfterName ())
2673     {
2674         StreamString strm;
2675         strm.Printf ("%u", m_stop_source_before_count);
2676         value.AppendString (strm.GetData());
2677     }
2678     else if (var_name == StopSourceContextBeforeName ())
2679     {
2680         StreamString strm;
2681         strm.Printf ("%u", m_stop_source_after_count);
2682         value.AppendString (strm.GetData());
2683     }
2684     else if (var_name == StopDisassemblyCountName ())
2685     {
2686         StreamString strm;
2687         strm.Printf ("%u", m_stop_disassembly_count);
2688         value.AppendString (strm.GetData());
2689     }
2690     else if (var_name == StopDisassemblyDisplayName ())
2691     {
2692         if (m_stop_disassembly_display >= eStopDisassemblyTypeNever && m_stop_disassembly_display <= eStopDisassemblyTypeAlways)
2693             value.AppendString (g_show_disassembly_enum_values[m_stop_disassembly_display].string_value);
2694         else
2695             value.AppendString ("<invalid>");
2696     }
2697     else
2698     {
2699         if (err)
2700             err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
2701         return false;
2702     }
2703     return true;
2704 }
2705 
2706 void
2707 DebuggerInstanceSettings::CopyInstanceSettings (const InstanceSettingsSP &new_settings,
2708                                                 bool pending)
2709 {
2710     if (new_settings.get() == NULL)
2711         return;
2712 
2713     DebuggerInstanceSettings *new_debugger_settings = (DebuggerInstanceSettings *) new_settings.get();
2714 
2715     m_prompt = new_debugger_settings->m_prompt;
2716     if (!pending)
2717     {
2718         // 'instance_name' is actually (probably) in the form '[<instance_name>]';  if so, we need to
2719         // strip off the brackets before passing it to BroadcastPromptChange.
2720 
2721         std::string tmp_instance_name (m_instance_name.AsCString());
2722         if ((tmp_instance_name[0] == '[')
2723             && (tmp_instance_name[m_instance_name.GetLength() - 1] == ']'))
2724             tmp_instance_name = tmp_instance_name.substr (1, m_instance_name.GetLength() - 2);
2725         ConstString new_name (tmp_instance_name.c_str());
2726 
2727         BroadcastPromptChange (new_name, m_prompt.c_str());
2728     }
2729     m_frame_format = new_debugger_settings->m_frame_format;
2730     m_thread_format = new_debugger_settings->m_thread_format;
2731     m_term_width = new_debugger_settings->m_term_width;
2732     m_script_lang = new_debugger_settings->m_script_lang;
2733     m_use_external_editor = new_debugger_settings->m_use_external_editor;
2734     m_auto_confirm_on = new_debugger_settings->m_auto_confirm_on;
2735 }
2736 
2737 
2738 bool
2739 DebuggerInstanceSettings::BroadcastPromptChange (const ConstString &instance_name, const char *new_prompt)
2740 {
2741     std::string tmp_prompt;
2742 
2743     if (new_prompt != NULL)
2744     {
2745         tmp_prompt = new_prompt ;
2746         int len = tmp_prompt.size();
2747         if (len > 1
2748             && (tmp_prompt[0] == '\'' || tmp_prompt[0] == '"')
2749             && (tmp_prompt[len-1] == tmp_prompt[0]))
2750         {
2751             tmp_prompt = tmp_prompt.substr(1,len-2);
2752         }
2753         len = tmp_prompt.size();
2754         if (tmp_prompt[len-1] != ' ')
2755             tmp_prompt.append(" ");
2756     }
2757     EventSP new_event_sp;
2758     new_event_sp.reset (new Event(CommandInterpreter::eBroadcastBitResetPrompt,
2759                                   new EventDataBytes (tmp_prompt.c_str())));
2760 
2761     if (instance_name.GetLength() != 0)
2762     {
2763         // Set prompt for a particular instance.
2764         Debugger *dbg = Debugger::FindDebuggerWithInstanceName (instance_name).get();
2765         if (dbg != NULL)
2766         {
2767             dbg->GetCommandInterpreter().BroadcastEvent (new_event_sp);
2768         }
2769     }
2770 
2771     return true;
2772 }
2773 
2774 const ConstString
2775 DebuggerInstanceSettings::CreateInstanceName ()
2776 {
2777     static int instance_count = 1;
2778     StreamString sstr;
2779 
2780     sstr.Printf ("debugger_%d", instance_count);
2781     ++instance_count;
2782 
2783     const ConstString ret_val (sstr.GetData());
2784 
2785     return ret_val;
2786 }
2787 
2788 
2789 //--------------------------------------------------
2790 // SettingsController Variable Tables
2791 //--------------------------------------------------
2792 
2793 
2794 SettingEntry
2795 Debugger::SettingsController::global_settings_table[] =
2796 {
2797   //{ "var-name",    var-type,      "default", enum-table, init'd, hidden, "help-text"},
2798   // The Debugger level global table should always be empty; all Debugger settable variables should be instance
2799   // variables.
2800     {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
2801 };
2802 
2803 #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name}${function.pc-offset}}}"
2804 #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
2805 
2806 #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\
2807     "{, ${frame.pc}}"\
2808     MODULE_WITH_FUNC\
2809     FILE_AND_LINE\
2810     "{, stop reason = ${thread.stop-reason}}"\
2811     "{\\nReturn value: ${thread.return-value}}"\
2812     "\\n"
2813 
2814 //#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\
2815 //    "{, ${frame.pc}}"\
2816 //    MODULE_WITH_FUNC\
2817 //    FILE_AND_LINE\
2818 //    "{, stop reason = ${thread.stop-reason}}"\
2819 //    "{, name = ${thread.name}}"\
2820 //    "{, queue = ${thread.queue}}"\
2821 //    "\\n"
2822 
2823 #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\
2824     MODULE_WITH_FUNC\
2825     FILE_AND_LINE\
2826     "\\n"
2827 
2828 SettingEntry
2829 Debugger::SettingsController::instance_settings_table[] =
2830 {
2831 //  NAME                    Setting variable type   Default                 Enum  Init'd Hidden Help
2832 //  ======================= ======================= ======================  ====  ====== ====== ======================
2833 {   "frame-format",         eSetVarTypeString,      DEFAULT_FRAME_FORMAT,   NULL, false, false, "The default frame format string to use when displaying thread information." },
2834 {   "prompt",               eSetVarTypeString,      "(lldb) ",              NULL, false, false, "The debugger command line prompt displayed for the user." },
2835 {   "script-lang",          eSetVarTypeString,      "python",               NULL, false, false, "The script language to be used for evaluating user-written scripts." },
2836 {   "term-width",           eSetVarTypeInt,         "80"    ,               NULL, false, false, "The maximum number of columns to use for displaying text." },
2837 {   "thread-format",        eSetVarTypeString,      DEFAULT_THREAD_FORMAT,  NULL, false, false, "The default thread format string to use when displaying thread information." },
2838 {   "use-external-editor",  eSetVarTypeBoolean,     "false",                NULL, false, false, "Whether to use an external editor or not." },
2839 {   "auto-confirm",         eSetVarTypeBoolean,     "false",                NULL, false, false, "If true all confirmation prompts will receive their default reply." },
2840 {   "stop-line-count-before",eSetVarTypeInt,        "3",                    NULL, false, false, "The number of sources lines to display that come before the current source line when displaying a stopped context." },
2841 {   "stop-line-count-after", eSetVarTypeInt,        "3",                    NULL, false, false, "The number of sources lines to display that come after the current source line when displaying a stopped context." },
2842 {   "stop-disassembly-count",  eSetVarTypeInt,      "0",                    NULL, false, false, "The number of disassembly lines to show when displaying a stopped context." },
2843 {   "stop-disassembly-display", eSetVarTypeEnum,    "no-source",           g_show_disassembly_enum_values, false, false, "Control when to display disassembly when displaying a stopped context." },
2844 {   NULL,                   eSetVarTypeNone,        NULL,                   NULL, false, false, NULL }
2845 };
2846