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