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