130fdc8d8SChris Lattner //===-- Debugger.cpp --------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1093a64300SDaniel Malea #include "lldb/lldb-python.h"
1193a64300SDaniel Malea 
124a33d318SGreg Clayton #include "lldb/Core/Debugger.h"
134a33d318SGreg Clayton 
144a33d318SGreg Clayton #include <map>
154a33d318SGreg Clayton 
164becb37eSEnrico Granata #include "clang/AST/DeclCXX.h"
174becb37eSEnrico Granata #include "clang/AST/Type.h"
184becb37eSEnrico Granata 
1930fdc8d8SChris Lattner #include "lldb/lldb-private.h"
2030fdc8d8SChris Lattner #include "lldb/Core/ConnectionFileDescriptor.h"
211f746071SGreg Clayton #include "lldb/Core/Module.h"
22e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h"
237349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h"
2430fdc8d8SChris Lattner #include "lldb/Core/State.h"
255b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h"
26228063cdSJim Ingham #include "lldb/Core/StreamCallback.h"
2744d93782SGreg Clayton #include "lldb/Core/StreamFile.h"
281b654882SGreg Clayton #include "lldb/Core/StreamString.h"
2930fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
304becb37eSEnrico Granata #include "lldb/Core/ValueObject.h"
316d3dbf51SGreg Clayton #include "lldb/Core/ValueObjectVariable.h"
325548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
335548cb50SEnrico Granata #include "lldb/DataFormatters/FormatManager.h"
3421dfcd9dSEnrico Granata #include "lldb/Host/DynamicLibrary.h"
35a3406614SGreg Clayton #include "lldb/Host/Terminal.h"
366611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
3767cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h"
3867cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h"
391f746071SGreg Clayton #include "lldb/Symbol/ClangASTContext.h"
401f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
411f746071SGreg Clayton #include "lldb/Symbol/Function.h"
421f746071SGreg Clayton #include "lldb/Symbol/Symbol.h"
436d3dbf51SGreg Clayton #include "lldb/Symbol/VariableList.h"
4430fdc8d8SChris Lattner #include "lldb/Target/TargetList.h"
4530fdc8d8SChris Lattner #include "lldb/Target/Process.h"
461b654882SGreg Clayton #include "lldb/Target/RegisterContext.h"
475fb8f797SGreg Clayton #include "lldb/Target/SectionLoadList.h"
481b654882SGreg Clayton #include "lldb/Target/StopInfo.h"
4984a53dfbSEnrico Granata #include "lldb/Target/Target.h"
5030fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
515a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
5230fdc8d8SChris Lattner 
5330fdc8d8SChris Lattner using namespace lldb;
5430fdc8d8SChris Lattner using namespace lldb_private;
5530fdc8d8SChris Lattner 
5630fdc8d8SChris Lattner 
571b654882SGreg Clayton static uint32_t g_shared_debugger_refcount = 0;
58ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1;
59ebc1bb27SCaroline Tice 
601b654882SGreg Clayton #pragma mark Static Functions
611b654882SGreg Clayton 
621b654882SGreg Clayton static Mutex &
631b654882SGreg Clayton GetDebuggerListMutex ()
641b654882SGreg Clayton {
651b654882SGreg Clayton     static Mutex g_mutex(Mutex::eMutexTypeRecursive);
661b654882SGreg Clayton     return g_mutex;
671b654882SGreg Clayton }
681b654882SGreg Clayton 
691b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList;
701b654882SGreg Clayton 
711b654882SGreg Clayton static DebuggerList &
721b654882SGreg Clayton GetDebuggerList()
731b654882SGreg Clayton {
741b654882SGreg Clayton     // hide the static debugger list inside a singleton accessor to avoid
751b654882SGreg Clayton     // global init contructors
761b654882SGreg Clayton     static DebuggerList g_list;
771b654882SGreg Clayton     return g_list;
781b654882SGreg Clayton }
79e372b98dSGreg Clayton 
80e372b98dSGreg Clayton OptionEnumValueElement
8167cc0636SGreg Clayton g_show_disassembly_enum_values[] =
82e372b98dSGreg Clayton {
8367cc0636SGreg Clayton     { Debugger::eStopDisassemblyTypeNever,    "never",     "Never show disassembly when displaying a stop context."},
8467cc0636SGreg Clayton     { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."},
8567cc0636SGreg Clayton     { Debugger::eStopDisassemblyTypeAlways,   "always",    "Always show disassembly when displaying a stop context."},
86e372b98dSGreg Clayton     { 0, NULL, NULL }
87e372b98dSGreg Clayton };
88e372b98dSGreg Clayton 
8967cc0636SGreg Clayton OptionEnumValueElement
9067cc0636SGreg Clayton g_language_enumerators[] =
9167cc0636SGreg Clayton {
9267cc0636SGreg Clayton     { eScriptLanguageNone,      "none",     "Disable scripting languages."},
9367cc0636SGreg Clayton     { eScriptLanguagePython,    "python",   "Select python as the default scripting language."},
9467cc0636SGreg Clayton     { eScriptLanguageDefault,   "default",  "Select the lldb default as the default scripting language."},
95a12993c9SGreg Clayton     { 0, NULL, NULL }
9667cc0636SGreg Clayton };
97e372b98dSGreg Clayton 
9867cc0636SGreg Clayton #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
9967cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
10067cc0636SGreg Clayton 
1010769b2b1SMichael Sartain #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\
10267cc0636SGreg Clayton     "{, ${frame.pc}}"\
10367cc0636SGreg Clayton     MODULE_WITH_FUNC\
10467cc0636SGreg Clayton     FILE_AND_LINE\
1050769b2b1SMichael Sartain     "{, name = '${thread.name}'}"\
1060769b2b1SMichael Sartain     "{, queue = '${thread.queue}'}"\
10767cc0636SGreg Clayton     "{, stop reason = ${thread.stop-reason}}"\
10867cc0636SGreg Clayton     "{\\nReturn value: ${thread.return-value}}"\
10967cc0636SGreg Clayton     "\\n"
11067cc0636SGreg Clayton 
11167cc0636SGreg Clayton #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\
11267cc0636SGreg Clayton     MODULE_WITH_FUNC\
11367cc0636SGreg Clayton     FILE_AND_LINE\
11467cc0636SGreg Clayton     "\\n"
11567cc0636SGreg Clayton 
11667cc0636SGreg Clayton 
11767cc0636SGreg Clayton 
118754a9369SGreg Clayton static PropertyDefinition
119754a9369SGreg Clayton g_properties[] =
12067cc0636SGreg Clayton {
12167cc0636SGreg Clayton {   "auto-confirm",             OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." },
12267cc0636SGreg Clayton {   "frame-format",             OptionValue::eTypeString , true, 0    , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." },
12367cc0636SGreg Clayton {   "notify-void",              OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." },
1244c05410fSGreg Clayton {   "prompt",                   OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." },
12567cc0636SGreg Clayton {   "script-lang",              OptionValue::eTypeEnum   , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." },
12667cc0636SGreg Clayton {   "stop-disassembly-count",   OptionValue::eTypeSInt64 , true, 4    , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." },
12767cc0636SGreg Clayton {   "stop-disassembly-display", OptionValue::eTypeEnum   , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." },
12867cc0636SGreg Clayton {   "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." },
12967cc0636SGreg Clayton {   "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." },
13067cc0636SGreg Clayton {   "term-width",               OptionValue::eTypeSInt64 , true, 80   , NULL, NULL, "The maximum number of columns to use for displaying text." },
13167cc0636SGreg Clayton {   "thread-format",            OptionValue::eTypeString , true, 0    , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." },
13267cc0636SGreg Clayton {   "use-external-editor",      OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." },
133c3ce7f27SMichael Sartain {   "use-color",                OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." },
13490a8db30SEnrico Granata {   "auto-one-line-summaries",     OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },
135e8cd0c98SGreg Clayton 
13667cc0636SGreg Clayton     {   NULL,                       OptionValue::eTypeInvalid, true, 0    , NULL, NULL, NULL }
13767cc0636SGreg Clayton };
13867cc0636SGreg Clayton 
13967cc0636SGreg Clayton enum
14067cc0636SGreg Clayton {
14167cc0636SGreg Clayton     ePropertyAutoConfirm = 0,
14267cc0636SGreg Clayton     ePropertyFrameFormat,
14367cc0636SGreg Clayton     ePropertyNotiftVoid,
14467cc0636SGreg Clayton     ePropertyPrompt,
14567cc0636SGreg Clayton     ePropertyScriptLanguage,
14667cc0636SGreg Clayton     ePropertyStopDisassemblyCount,
14767cc0636SGreg Clayton     ePropertyStopDisassemblyDisplay,
14867cc0636SGreg Clayton     ePropertyStopLineCountAfter,
14967cc0636SGreg Clayton     ePropertyStopLineCountBefore,
15067cc0636SGreg Clayton     ePropertyTerminalWidth,
15167cc0636SGreg Clayton     ePropertyThreadFormat,
152c3ce7f27SMichael Sartain     ePropertyUseExternalEditor,
153c3ce7f27SMichael Sartain     ePropertyUseColor,
15490a8db30SEnrico Granata     ePropertyAutoOneLineSummaries
15567cc0636SGreg Clayton };
15667cc0636SGreg Clayton 
1575fb8f797SGreg Clayton Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL;
1584c05410fSGreg Clayton 
1594c05410fSGreg Clayton Error
1604c05410fSGreg Clayton Debugger::SetPropertyValue (const ExecutionContext *exe_ctx,
1614c05410fSGreg Clayton                             VarSetOperationType op,
1624c05410fSGreg Clayton                             const char *property_path,
1634c05410fSGreg Clayton                             const char *value)
1644c05410fSGreg Clayton {
16584a53dfbSEnrico Granata     bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0;
16684a53dfbSEnrico Granata     TargetSP target_sp;
167397ddd5fSEnrico Granata     LoadScriptFromSymFile load_script_old_value;
16884a53dfbSEnrico Granata     if (is_load_script && exe_ctx->GetTargetSP())
16984a53dfbSEnrico Granata     {
17084a53dfbSEnrico Granata         target_sp = exe_ctx->GetTargetSP();
17184a53dfbSEnrico Granata         load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
17284a53dfbSEnrico Granata     }
1734c05410fSGreg Clayton     Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value));
1744c05410fSGreg Clayton     if (error.Success())
1754c05410fSGreg Clayton     {
17684a53dfbSEnrico Granata         // FIXME it would be nice to have "on-change" callbacks for properties
1774c05410fSGreg Clayton         if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0)
1784c05410fSGreg Clayton         {
1794c05410fSGreg Clayton             const char *new_prompt = GetPrompt();
180c3ce7f27SMichael Sartain             std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
181c3ce7f27SMichael Sartain             if (str.length())
182c3ce7f27SMichael Sartain                 new_prompt = str.c_str();
18344d93782SGreg Clayton             GetCommandInterpreter().UpdatePrompt(new_prompt);
1844c05410fSGreg Clayton             EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));
1854c05410fSGreg Clayton             GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp);
1864c05410fSGreg Clayton         }
187c3ce7f27SMichael Sartain         else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0)
188c3ce7f27SMichael Sartain         {
189c3ce7f27SMichael Sartain 			// use-color changed. Ping the prompt so it can reset the ansi terminal codes.
190c3ce7f27SMichael Sartain             SetPrompt (GetPrompt());
191c3ce7f27SMichael Sartain         }
192397ddd5fSEnrico Granata         else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn)
19384a53dfbSEnrico Granata         {
194397ddd5fSEnrico Granata             if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue)
19584a53dfbSEnrico Granata             {
19684a53dfbSEnrico Granata                 std::list<Error> errors;
1979730339bSEnrico Granata                 StreamString feedback_stream;
1989730339bSEnrico Granata                 if (!target_sp->LoadScriptingResources(errors,&feedback_stream))
19984a53dfbSEnrico Granata                 {
20044d93782SGreg Clayton                     StreamFileSP stream_sp (GetErrorFile());
20144d93782SGreg Clayton                     if (stream_sp)
20244d93782SGreg Clayton                     {
20384a53dfbSEnrico Granata                         for (auto error : errors)
20484a53dfbSEnrico Granata                         {
20544d93782SGreg Clayton                             stream_sp->Printf("%s\n",error.AsCString());
20684a53dfbSEnrico Granata                         }
2079730339bSEnrico Granata                         if (feedback_stream.GetSize())
20844d93782SGreg Clayton                             stream_sp->Printf("%s",feedback_stream.GetData());
20944d93782SGreg Clayton                     }
21084a53dfbSEnrico Granata                 }
21184a53dfbSEnrico Granata             }
21284a53dfbSEnrico Granata         }
2134c05410fSGreg Clayton     }
2144c05410fSGreg Clayton     return error;
2154c05410fSGreg Clayton }
2164c05410fSGreg Clayton 
21767cc0636SGreg Clayton bool
21867cc0636SGreg Clayton Debugger::GetAutoConfirm () const
21967cc0636SGreg Clayton {
22067cc0636SGreg Clayton     const uint32_t idx = ePropertyAutoConfirm;
221754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
22267cc0636SGreg Clayton }
22367cc0636SGreg Clayton 
22467cc0636SGreg Clayton const char *
22567cc0636SGreg Clayton Debugger::GetFrameFormat() const
22667cc0636SGreg Clayton {
22767cc0636SGreg Clayton     const uint32_t idx = ePropertyFrameFormat;
228754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value);
22967cc0636SGreg Clayton }
23067cc0636SGreg Clayton 
23167cc0636SGreg Clayton bool
23267cc0636SGreg Clayton Debugger::GetNotifyVoid () const
23367cc0636SGreg Clayton {
23467cc0636SGreg Clayton     const uint32_t idx = ePropertyNotiftVoid;
235754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
23667cc0636SGreg Clayton }
23767cc0636SGreg Clayton 
23867cc0636SGreg Clayton const char *
23967cc0636SGreg Clayton Debugger::GetPrompt() const
24067cc0636SGreg Clayton {
24167cc0636SGreg Clayton     const uint32_t idx = ePropertyPrompt;
242754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value);
24367cc0636SGreg Clayton }
24467cc0636SGreg Clayton 
24567cc0636SGreg Clayton void
24667cc0636SGreg Clayton Debugger::SetPrompt(const char *p)
24767cc0636SGreg Clayton {
24867cc0636SGreg Clayton     const uint32_t idx = ePropertyPrompt;
24967cc0636SGreg Clayton     m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p);
25067cc0636SGreg Clayton     const char *new_prompt = GetPrompt();
251c3ce7f27SMichael Sartain     std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
252c3ce7f27SMichael Sartain     if (str.length())
253c3ce7f27SMichael Sartain         new_prompt = str.c_str();
25444d93782SGreg Clayton     GetCommandInterpreter().UpdatePrompt(new_prompt);
25567cc0636SGreg Clayton }
25667cc0636SGreg Clayton 
25767cc0636SGreg Clayton const char *
25867cc0636SGreg Clayton Debugger::GetThreadFormat() const
25967cc0636SGreg Clayton {
26067cc0636SGreg Clayton     const uint32_t idx = ePropertyThreadFormat;
261754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value);
26267cc0636SGreg Clayton }
26367cc0636SGreg Clayton 
26467cc0636SGreg Clayton lldb::ScriptLanguage
26567cc0636SGreg Clayton Debugger::GetScriptLanguage() const
26667cc0636SGreg Clayton {
26767cc0636SGreg Clayton     const uint32_t idx = ePropertyScriptLanguage;
268754a9369SGreg Clayton     return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value);
26967cc0636SGreg Clayton }
27067cc0636SGreg Clayton 
27167cc0636SGreg Clayton bool
27267cc0636SGreg Clayton Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang)
27367cc0636SGreg Clayton {
27467cc0636SGreg Clayton     const uint32_t idx = ePropertyScriptLanguage;
27567cc0636SGreg Clayton     return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL, idx, script_lang);
27667cc0636SGreg Clayton }
27767cc0636SGreg Clayton 
27867cc0636SGreg Clayton uint32_t
27967cc0636SGreg Clayton Debugger::GetTerminalWidth () const
28067cc0636SGreg Clayton {
28167cc0636SGreg Clayton     const uint32_t idx = ePropertyTerminalWidth;
282754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
28367cc0636SGreg Clayton }
28467cc0636SGreg Clayton 
28567cc0636SGreg Clayton bool
28667cc0636SGreg Clayton Debugger::SetTerminalWidth (uint32_t term_width)
28767cc0636SGreg Clayton {
28867cc0636SGreg Clayton     const uint32_t idx = ePropertyTerminalWidth;
28967cc0636SGreg Clayton     return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL, idx, term_width);
29067cc0636SGreg Clayton }
29167cc0636SGreg Clayton 
29267cc0636SGreg Clayton bool
29367cc0636SGreg Clayton Debugger::GetUseExternalEditor () const
29467cc0636SGreg Clayton {
29567cc0636SGreg Clayton     const uint32_t idx = ePropertyUseExternalEditor;
296754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
29767cc0636SGreg Clayton }
29867cc0636SGreg Clayton 
29967cc0636SGreg Clayton bool
30067cc0636SGreg Clayton Debugger::SetUseExternalEditor (bool b)
30167cc0636SGreg Clayton {
30267cc0636SGreg Clayton     const uint32_t idx = ePropertyUseExternalEditor;
30367cc0636SGreg Clayton     return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
30467cc0636SGreg Clayton }
30567cc0636SGreg Clayton 
306c3ce7f27SMichael Sartain bool
307c3ce7f27SMichael Sartain Debugger::GetUseColor () const
308c3ce7f27SMichael Sartain {
309c3ce7f27SMichael Sartain     const uint32_t idx = ePropertyUseColor;
310c3ce7f27SMichael Sartain     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
311c3ce7f27SMichael Sartain }
312c3ce7f27SMichael Sartain 
313c3ce7f27SMichael Sartain bool
314c3ce7f27SMichael Sartain Debugger::SetUseColor (bool b)
315c3ce7f27SMichael Sartain {
316c3ce7f27SMichael Sartain     const uint32_t idx = ePropertyUseColor;
317c3ce7f27SMichael Sartain     bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
318c3ce7f27SMichael Sartain     SetPrompt (GetPrompt());
319c3ce7f27SMichael Sartain     return ret;
320c3ce7f27SMichael Sartain }
321c3ce7f27SMichael Sartain 
32267cc0636SGreg Clayton uint32_t
32367cc0636SGreg Clayton Debugger::GetStopSourceLineCount (bool before) const
32467cc0636SGreg Clayton {
32567cc0636SGreg Clayton     const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
326754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
32767cc0636SGreg Clayton }
32867cc0636SGreg Clayton 
32967cc0636SGreg Clayton Debugger::StopDisassemblyType
33067cc0636SGreg Clayton Debugger::GetStopDisassemblyDisplay () const
33167cc0636SGreg Clayton {
33267cc0636SGreg Clayton     const uint32_t idx = ePropertyStopDisassemblyDisplay;
333754a9369SGreg Clayton     return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value);
33467cc0636SGreg Clayton }
33567cc0636SGreg Clayton 
33667cc0636SGreg Clayton uint32_t
33767cc0636SGreg Clayton Debugger::GetDisassemblyLineCount () const
33867cc0636SGreg Clayton {
33967cc0636SGreg Clayton     const uint32_t idx = ePropertyStopDisassemblyCount;
340754a9369SGreg Clayton     return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
34167cc0636SGreg Clayton }
342e372b98dSGreg Clayton 
343553fad5cSEnrico Granata bool
34490a8db30SEnrico Granata Debugger::GetAutoOneLineSummaries () const
345553fad5cSEnrico Granata {
34690a8db30SEnrico Granata     const uint32_t idx = ePropertyAutoOneLineSummaries;
347553fad5cSEnrico Granata     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
348553fad5cSEnrico Granata 
349553fad5cSEnrico Granata }
350553fad5cSEnrico Granata 
3511b654882SGreg Clayton #pragma mark Debugger
3521b654882SGreg Clayton 
35367cc0636SGreg Clayton //const DebuggerPropertiesSP &
35467cc0636SGreg Clayton //Debugger::GetSettings() const
35567cc0636SGreg Clayton //{
35667cc0636SGreg Clayton //    return m_properties_sp;
35767cc0636SGreg Clayton //}
35867cc0636SGreg Clayton //
35999d0faf2SGreg Clayton 
3602f88aadfSCaroline Tice int
3612f88aadfSCaroline Tice Debugger::TestDebuggerRefCount ()
3622f88aadfSCaroline Tice {
3632f88aadfSCaroline Tice     return g_shared_debugger_refcount;
3642f88aadfSCaroline Tice }
3652f88aadfSCaroline Tice 
36630fdc8d8SChris Lattner void
3675fb8f797SGreg Clayton Debugger::Initialize (LoadPluginCallbackType load_plugin_callback)
36830fdc8d8SChris Lattner {
3695fb8f797SGreg Clayton     g_load_plugin_callback = load_plugin_callback;
370c15f55e2SGreg Clayton     if (g_shared_debugger_refcount++ == 0)
371dbe54508SGreg Clayton         lldb_private::Initialize();
37299d0faf2SGreg Clayton }
37330fdc8d8SChris Lattner 
37430fdc8d8SChris Lattner void
37530fdc8d8SChris Lattner Debugger::Terminate ()
37630fdc8d8SChris Lattner {
3776611103cSGreg Clayton     if (g_shared_debugger_refcount > 0)
3786611103cSGreg Clayton     {
37930fdc8d8SChris Lattner         g_shared_debugger_refcount--;
38030fdc8d8SChris Lattner         if (g_shared_debugger_refcount == 0)
38130fdc8d8SChris Lattner         {
382dbe54508SGreg Clayton             lldb_private::WillTerminate();
383dbe54508SGreg Clayton             lldb_private::Terminate();
3846760a517SCaroline Tice 
38599d0faf2SGreg Clayton             // Clear our master list of debugger objects
38699d0faf2SGreg Clayton             Mutex::Locker locker (GetDebuggerListMutex ());
38799d0faf2SGreg Clayton             GetDebuggerList().clear();
38830fdc8d8SChris Lattner         }
3896760a517SCaroline Tice     }
3906760a517SCaroline Tice }
39130fdc8d8SChris Lattner 
39220bd37f7SCaroline Tice void
39320bd37f7SCaroline Tice Debugger::SettingsInitialize ()
39420bd37f7SCaroline Tice {
3956920b52bSGreg Clayton     Target::SettingsInitialize ();
39620bd37f7SCaroline Tice }
39720bd37f7SCaroline Tice 
39820bd37f7SCaroline Tice void
39920bd37f7SCaroline Tice Debugger::SettingsTerminate ()
40020bd37f7SCaroline Tice {
4016920b52bSGreg Clayton     Target::SettingsTerminate ();
40220bd37f7SCaroline Tice }
40320bd37f7SCaroline Tice 
40421dfcd9dSEnrico Granata bool
405e743c782SEnrico Granata Debugger::LoadPlugin (const FileSpec& spec, Error& error)
40621dfcd9dSEnrico Granata {
4075fb8f797SGreg Clayton     if (g_load_plugin_callback)
408e743c782SEnrico Granata     {
4095fb8f797SGreg Clayton         lldb::DynamicLibrarySP dynlib_sp = g_load_plugin_callback (shared_from_this(), spec, error);
4105fb8f797SGreg Clayton         if (dynlib_sp)
41121dfcd9dSEnrico Granata         {
41221dfcd9dSEnrico Granata             m_loaded_plugins.push_back(dynlib_sp);
41321dfcd9dSEnrico Granata             return true;
41421dfcd9dSEnrico Granata         }
4155fb8f797SGreg Clayton     }
4165fb8f797SGreg Clayton     else
4175fb8f797SGreg Clayton     {
4185fb8f797SGreg Clayton         // The g_load_plugin_callback is registered in SBDebugger::Initialize()
4195fb8f797SGreg Clayton         // and if the public API layer isn't available (code is linking against
4205fb8f797SGreg Clayton         // all of the internal LLDB static libraries), then we can't load plugins
4215fb8f797SGreg Clayton         error.SetErrorString("Public API layer is not available");
4225fb8f797SGreg Clayton     }
42321dfcd9dSEnrico Granata     return false;
42421dfcd9dSEnrico Granata }
42521dfcd9dSEnrico Granata 
42621dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult
42721dfcd9dSEnrico Granata LoadPluginCallback
42821dfcd9dSEnrico Granata (
42921dfcd9dSEnrico Granata  void *baton,
43021dfcd9dSEnrico Granata  FileSpec::FileType file_type,
43121dfcd9dSEnrico Granata  const FileSpec &file_spec
43221dfcd9dSEnrico Granata  )
43321dfcd9dSEnrico Granata {
43421dfcd9dSEnrico Granata     Error error;
43521dfcd9dSEnrico Granata 
43621dfcd9dSEnrico Granata     static ConstString g_dylibext("dylib");
4373cf443ddSMichael Sartain     static ConstString g_solibext("so");
43821dfcd9dSEnrico Granata 
43921dfcd9dSEnrico Granata     if (!baton)
44021dfcd9dSEnrico Granata         return FileSpec::eEnumerateDirectoryResultQuit;
44121dfcd9dSEnrico Granata 
44221dfcd9dSEnrico Granata     Debugger *debugger = (Debugger*)baton;
44321dfcd9dSEnrico Granata 
44421dfcd9dSEnrico Granata     // If we have a regular file, a symbolic link or unknown file type, try
44521dfcd9dSEnrico Granata     // and process the file. We must handle unknown as sometimes the directory
44621dfcd9dSEnrico Granata     // enumeration might be enumerating a file system that doesn't have correct
44721dfcd9dSEnrico Granata     // file type information.
44821dfcd9dSEnrico Granata     if (file_type == FileSpec::eFileTypeRegular         ||
44921dfcd9dSEnrico Granata         file_type == FileSpec::eFileTypeSymbolicLink    ||
45021dfcd9dSEnrico Granata         file_type == FileSpec::eFileTypeUnknown          )
45121dfcd9dSEnrico Granata     {
45221dfcd9dSEnrico Granata         FileSpec plugin_file_spec (file_spec);
45321dfcd9dSEnrico Granata         plugin_file_spec.ResolvePath ();
45421dfcd9dSEnrico Granata 
4553cf443ddSMichael Sartain         if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
4563cf443ddSMichael Sartain             plugin_file_spec.GetFileNameExtension() != g_solibext)
4573cf443ddSMichael Sartain         {
45821dfcd9dSEnrico Granata             return FileSpec::eEnumerateDirectoryResultNext;
4593cf443ddSMichael Sartain         }
46021dfcd9dSEnrico Granata 
461e743c782SEnrico Granata         Error plugin_load_error;
462e743c782SEnrico Granata         debugger->LoadPlugin (plugin_file_spec, plugin_load_error);
46321dfcd9dSEnrico Granata 
46421dfcd9dSEnrico Granata         return FileSpec::eEnumerateDirectoryResultNext;
46521dfcd9dSEnrico Granata     }
46621dfcd9dSEnrico Granata 
46721dfcd9dSEnrico Granata     else if (file_type == FileSpec::eFileTypeUnknown     ||
46821dfcd9dSEnrico Granata         file_type == FileSpec::eFileTypeDirectory   ||
46921dfcd9dSEnrico Granata         file_type == FileSpec::eFileTypeSymbolicLink )
47021dfcd9dSEnrico Granata     {
47121dfcd9dSEnrico Granata         // Try and recurse into anything that a directory or symbolic link.
47221dfcd9dSEnrico Granata         // We must also do this for unknown as sometimes the directory enumeration
47321dfcd9dSEnrico Granata         // might be enurating a file system that doesn't have correct file type
47421dfcd9dSEnrico Granata         // information.
47521dfcd9dSEnrico Granata         return FileSpec::eEnumerateDirectoryResultEnter;
47621dfcd9dSEnrico Granata     }
47721dfcd9dSEnrico Granata 
47821dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultNext;
47921dfcd9dSEnrico Granata }
48021dfcd9dSEnrico Granata 
48121dfcd9dSEnrico Granata void
48221dfcd9dSEnrico Granata Debugger::InstanceInitialize ()
48321dfcd9dSEnrico Granata {
48421dfcd9dSEnrico Granata     FileSpec dir_spec;
48521dfcd9dSEnrico Granata     const bool find_directories = true;
48621dfcd9dSEnrico Granata     const bool find_files = true;
48721dfcd9dSEnrico Granata     const bool find_other = true;
48821dfcd9dSEnrico Granata     char dir_path[PATH_MAX];
48921dfcd9dSEnrico Granata     if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec))
49021dfcd9dSEnrico Granata     {
49121dfcd9dSEnrico Granata         if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
49221dfcd9dSEnrico Granata         {
49321dfcd9dSEnrico Granata             FileSpec::EnumerateDirectory (dir_path,
49421dfcd9dSEnrico Granata                                           find_directories,
49521dfcd9dSEnrico Granata                                           find_files,
49621dfcd9dSEnrico Granata                                           find_other,
49721dfcd9dSEnrico Granata                                           LoadPluginCallback,
49821dfcd9dSEnrico Granata                                           this);
49921dfcd9dSEnrico Granata         }
50021dfcd9dSEnrico Granata     }
50121dfcd9dSEnrico Granata 
50221dfcd9dSEnrico Granata     if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec))
50321dfcd9dSEnrico Granata     {
50421dfcd9dSEnrico Granata         if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
50521dfcd9dSEnrico Granata         {
50621dfcd9dSEnrico Granata             FileSpec::EnumerateDirectory (dir_path,
50721dfcd9dSEnrico Granata                                           find_directories,
50821dfcd9dSEnrico Granata                                           find_files,
50921dfcd9dSEnrico Granata                                           find_other,
51021dfcd9dSEnrico Granata                                           LoadPluginCallback,
51121dfcd9dSEnrico Granata                                           this);
51221dfcd9dSEnrico Granata         }
51321dfcd9dSEnrico Granata     }
514e8cd0c98SGreg Clayton 
515e8cd0c98SGreg Clayton     PluginManager::DebuggerInitialize (*this);
51621dfcd9dSEnrico Granata }
51721dfcd9dSEnrico Granata 
5186611103cSGreg Clayton DebuggerSP
519228063cdSJim Ingham Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton)
5206611103cSGreg Clayton {
521228063cdSJim Ingham     DebuggerSP debugger_sp (new Debugger(log_callback, baton));
522c15f55e2SGreg Clayton     if (g_shared_debugger_refcount > 0)
5236611103cSGreg Clayton     {
5246611103cSGreg Clayton         Mutex::Locker locker (GetDebuggerListMutex ());
5256611103cSGreg Clayton         GetDebuggerList().push_back(debugger_sp);
5266611103cSGreg Clayton     }
52721dfcd9dSEnrico Granata     debugger_sp->InstanceInitialize ();
5286611103cSGreg Clayton     return debugger_sp;
5296611103cSGreg Clayton }
5306611103cSGreg Clayton 
531e02657b1SCaroline Tice void
5324d122c40SGreg Clayton Debugger::Destroy (DebuggerSP &debugger_sp)
533e02657b1SCaroline Tice {
534e02657b1SCaroline Tice     if (debugger_sp.get() == NULL)
535e02657b1SCaroline Tice         return;
536e02657b1SCaroline Tice 
5378314c525SJim Ingham     debugger_sp->Clear();
5388314c525SJim Ingham 
539c15f55e2SGreg Clayton     if (g_shared_debugger_refcount > 0)
540c15f55e2SGreg Clayton     {
541e02657b1SCaroline Tice         Mutex::Locker locker (GetDebuggerListMutex ());
542e02657b1SCaroline Tice         DebuggerList &debugger_list = GetDebuggerList ();
543e02657b1SCaroline Tice         DebuggerList::iterator pos, end = debugger_list.end();
544e02657b1SCaroline Tice         for (pos = debugger_list.begin (); pos != end; ++pos)
545e02657b1SCaroline Tice         {
546e02657b1SCaroline Tice             if ((*pos).get() == debugger_sp.get())
547e02657b1SCaroline Tice             {
548e02657b1SCaroline Tice                 debugger_list.erase (pos);
549e02657b1SCaroline Tice                 return;
550e02657b1SCaroline Tice             }
551e02657b1SCaroline Tice         }
552e02657b1SCaroline Tice     }
553c15f55e2SGreg Clayton }
554e02657b1SCaroline Tice 
5554d122c40SGreg Clayton DebuggerSP
5563df9a8dfSCaroline Tice Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name)
5573df9a8dfSCaroline Tice {
5584d122c40SGreg Clayton     DebuggerSP debugger_sp;
5596920b52bSGreg Clayton     if (g_shared_debugger_refcount > 0)
5606920b52bSGreg Clayton     {
5616920b52bSGreg Clayton         Mutex::Locker locker (GetDebuggerListMutex ());
5626920b52bSGreg Clayton         DebuggerList &debugger_list = GetDebuggerList();
5636920b52bSGreg Clayton         DebuggerList::iterator pos, end = debugger_list.end();
5646920b52bSGreg Clayton 
5656920b52bSGreg Clayton         for (pos = debugger_list.begin(); pos != end; ++pos)
5666920b52bSGreg Clayton         {
5676920b52bSGreg Clayton             if ((*pos).get()->m_instance_name == instance_name)
5686920b52bSGreg Clayton             {
5696920b52bSGreg Clayton                 debugger_sp = *pos;
5706920b52bSGreg Clayton                 break;
5716920b52bSGreg Clayton             }
5726920b52bSGreg Clayton         }
5736920b52bSGreg Clayton     }
5743df9a8dfSCaroline Tice     return debugger_sp;
5753df9a8dfSCaroline Tice }
5766611103cSGreg Clayton 
5776611103cSGreg Clayton TargetSP
5786611103cSGreg Clayton Debugger::FindTargetWithProcessID (lldb::pid_t pid)
5796611103cSGreg Clayton {
5804d122c40SGreg Clayton     TargetSP target_sp;
581c15f55e2SGreg Clayton     if (g_shared_debugger_refcount > 0)
582c15f55e2SGreg Clayton     {
5836611103cSGreg Clayton         Mutex::Locker locker (GetDebuggerListMutex ());
5846611103cSGreg Clayton         DebuggerList &debugger_list = GetDebuggerList();
5856611103cSGreg Clayton         DebuggerList::iterator pos, end = debugger_list.end();
5866611103cSGreg Clayton         for (pos = debugger_list.begin(); pos != end; ++pos)
5876611103cSGreg Clayton         {
5886611103cSGreg Clayton             target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid);
5896611103cSGreg Clayton             if (target_sp)
5906611103cSGreg Clayton                 break;
5916611103cSGreg Clayton         }
592c15f55e2SGreg Clayton     }
5936611103cSGreg Clayton     return target_sp;
5946611103cSGreg Clayton }
5956611103cSGreg Clayton 
596e4e45924SGreg Clayton TargetSP
597e4e45924SGreg Clayton Debugger::FindTargetWithProcess (Process *process)
598e4e45924SGreg Clayton {
599e4e45924SGreg Clayton     TargetSP target_sp;
600c15f55e2SGreg Clayton     if (g_shared_debugger_refcount > 0)
601c15f55e2SGreg Clayton     {
602e4e45924SGreg Clayton         Mutex::Locker locker (GetDebuggerListMutex ());
603e4e45924SGreg Clayton         DebuggerList &debugger_list = GetDebuggerList();
604e4e45924SGreg Clayton         DebuggerList::iterator pos, end = debugger_list.end();
605e4e45924SGreg Clayton         for (pos = debugger_list.begin(); pos != end; ++pos)
606e4e45924SGreg Clayton         {
607e4e45924SGreg Clayton             target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process);
608e4e45924SGreg Clayton             if (target_sp)
609e4e45924SGreg Clayton                 break;
610e4e45924SGreg Clayton         }
611c15f55e2SGreg Clayton     }
612e4e45924SGreg Clayton     return target_sp;
613e4e45924SGreg Clayton }
614e4e45924SGreg Clayton 
615228063cdSJim Ingham Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) :
616ebc1bb27SCaroline Tice     UserID (g_unique_id++),
61767cc0636SGreg Clayton     Properties(OptionValuePropertiesSP(new OptionValueProperties())),
61844d93782SGreg Clayton     m_input_file_sp (new StreamFile (stdin, false)),
61944d93782SGreg Clayton     m_output_file_sp (new StreamFile (stdout, false)),
62044d93782SGreg Clayton     m_error_file_sp (new StreamFile (stderr, false)),
621c5917d9aSJim Ingham     m_terminal_state (),
6224bddaeb5SJim Ingham     m_target_list (*this),
623ded470d3SGreg Clayton     m_platform_list (),
62430fdc8d8SChris Lattner     m_listener ("lldb.Debugger"),
6259585fbfcSGreg Clayton     m_source_manager_ap(),
626e37d605eSJim Ingham     m_source_file_cache(),
6276611103cSGreg Clayton     m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
628d5a0a01bSCaroline Tice     m_input_reader_stack (),
62944d93782SGreg Clayton     m_instance_name (),
63044d93782SGreg Clayton     m_loaded_plugins (),
63144d93782SGreg Clayton     m_event_handler_thread (LLDB_INVALID_HOST_THREAD),
63244d93782SGreg Clayton     m_io_handler_thread (LLDB_INVALID_HOST_THREAD),
63344d93782SGreg Clayton     m_event_handler_thread_alive(false)
63430fdc8d8SChris Lattner {
63567cc0636SGreg Clayton     char instance_cstr[256];
63667cc0636SGreg Clayton     snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
63767cc0636SGreg Clayton     m_instance_name.SetCString(instance_cstr);
638228063cdSJim Ingham     if (log_callback)
639228063cdSJim Ingham         m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton));
6406611103cSGreg Clayton     m_command_interpreter_ap->Initialize ();
641ded470d3SGreg Clayton     // Always add our default platform to the platform list
642ded470d3SGreg Clayton     PlatformSP default_platform_sp (Platform::GetDefaultPlatform());
643ded470d3SGreg Clayton     assert (default_platform_sp.get());
644ded470d3SGreg Clayton     m_platform_list.Append (default_platform_sp, true);
64567cc0636SGreg Clayton 
646754a9369SGreg Clayton     m_collection_sp->Initialize (g_properties);
64767cc0636SGreg Clayton     m_collection_sp->AppendProperty (ConstString("target"),
64867cc0636SGreg Clayton                                      ConstString("Settings specify to debugging targets."),
64967cc0636SGreg Clayton                                      true,
65067cc0636SGreg Clayton                                      Target::GetGlobalProperties()->GetValueProperties());
651754a9369SGreg Clayton     if (m_command_interpreter_ap.get())
652754a9369SGreg Clayton     {
653754a9369SGreg Clayton         m_collection_sp->AppendProperty (ConstString("interpreter"),
654754a9369SGreg Clayton                                          ConstString("Settings specify to the debugger's command interpreter."),
655754a9369SGreg Clayton                                          true,
656754a9369SGreg Clayton                                          m_command_interpreter_ap->GetValueProperties());
657754a9369SGreg Clayton     }
65867cc0636SGreg Clayton     OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth);
65967cc0636SGreg Clayton     term_width->SetMinimumValue(10);
66067cc0636SGreg Clayton     term_width->SetMaximumValue(1024);
661c3ce7f27SMichael Sartain 
662c3ce7f27SMichael Sartain     // Turn off use-color if this is a dumb terminal.
663c3ce7f27SMichael Sartain     const char *term = getenv ("TERM");
664c3ce7f27SMichael Sartain     if (term && !strcmp (term, "dumb"))
665c3ce7f27SMichael Sartain         SetUseColor (false);
66630fdc8d8SChris Lattner }
66730fdc8d8SChris Lattner 
66830fdc8d8SChris Lattner Debugger::~Debugger ()
66930fdc8d8SChris Lattner {
6708314c525SJim Ingham     Clear();
6718314c525SJim Ingham }
6728314c525SJim Ingham 
6738314c525SJim Ingham void
6748314c525SJim Ingham Debugger::Clear()
6758314c525SJim Ingham {
67644d93782SGreg Clayton     ClearIOHandlers();
67744d93782SGreg Clayton     StopIOHandlerThread();
67844d93782SGreg Clayton     StopEventHandlerThread();
6791ed54f50SGreg Clayton     m_listener.Clear();
6806611103cSGreg Clayton     int num_targets = m_target_list.GetNumTargets();
6816611103cSGreg Clayton     for (int i = 0; i < num_targets; i++)
6826611103cSGreg Clayton     {
683ccbc08e6SGreg Clayton         TargetSP target_sp (m_target_list.GetTargetAtIndex (i));
684ccbc08e6SGreg Clayton         if (target_sp)
685ccbc08e6SGreg Clayton         {
686ccbc08e6SGreg Clayton             ProcessSP process_sp (target_sp->GetProcessSP());
6876611103cSGreg Clayton             if (process_sp)
6881fd07059SJim Ingham                 process_sp->Finalize();
689ccbc08e6SGreg Clayton             target_sp->Destroy();
6906611103cSGreg Clayton         }
69130fdc8d8SChris Lattner     }
6924bddaeb5SJim Ingham     BroadcasterManager::Clear ();
69330fdc8d8SChris Lattner 
6940d69a3a4SGreg Clayton     // Close the input file _before_ we close the input read communications class
6950d69a3a4SGreg Clayton     // as it does NOT own the input file, our m_input_file does.
696c5917d9aSJim Ingham     m_terminal_state.Clear();
69744d93782SGreg Clayton     if (m_input_file_sp)
69844d93782SGreg Clayton         m_input_file_sp->GetFile().Close ();
6998314c525SJim Ingham }
70030fdc8d8SChris Lattner 
70130fdc8d8SChris Lattner bool
702fc3f027dSGreg Clayton Debugger::GetCloseInputOnEOF () const
703fc3f027dSGreg Clayton {
70444d93782SGreg Clayton //    return m_input_comm.GetCloseOnEOF();
70544d93782SGreg Clayton     return false;
706fc3f027dSGreg Clayton }
707fc3f027dSGreg Clayton 
708fc3f027dSGreg Clayton void
709fc3f027dSGreg Clayton Debugger::SetCloseInputOnEOF (bool b)
710fc3f027dSGreg Clayton {
71144d93782SGreg Clayton //    m_input_comm.SetCloseOnEOF(b);
712fc3f027dSGreg Clayton }
713fc3f027dSGreg Clayton 
714fc3f027dSGreg Clayton bool
71530fdc8d8SChris Lattner Debugger::GetAsyncExecution ()
71630fdc8d8SChris Lattner {
7176611103cSGreg Clayton     return !m_command_interpreter_ap->GetSynchronous();
71830fdc8d8SChris Lattner }
71930fdc8d8SChris Lattner 
72030fdc8d8SChris Lattner void
72130fdc8d8SChris Lattner Debugger::SetAsyncExecution (bool async_execution)
72230fdc8d8SChris Lattner {
7236611103cSGreg Clayton     m_command_interpreter_ap->SetSynchronous (!async_execution);
72430fdc8d8SChris Lattner }
72530fdc8d8SChris Lattner 
72630fdc8d8SChris Lattner 
72730fdc8d8SChris Lattner void
72830fdc8d8SChris Lattner Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
72930fdc8d8SChris Lattner {
73044d93782SGreg Clayton     if (m_input_file_sp)
73144d93782SGreg Clayton         m_input_file_sp->GetFile().SetStream (fh, tranfer_ownership);
73244d93782SGreg Clayton     else
73344d93782SGreg Clayton         m_input_file_sp.reset (new StreamFile (fh, tranfer_ownership));
73444d93782SGreg Clayton 
73544d93782SGreg Clayton     File &in_file = m_input_file_sp->GetFile();
73651b1e2d2SGreg Clayton     if (in_file.IsValid() == false)
73751b1e2d2SGreg Clayton         in_file.SetStream (stdin, true);
73830fdc8d8SChris Lattner 
739c5917d9aSJim Ingham     // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState.
740c5917d9aSJim Ingham     SaveInputTerminalState ();
74130fdc8d8SChris Lattner }
74230fdc8d8SChris Lattner 
74330fdc8d8SChris Lattner void
74430fdc8d8SChris Lattner Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
74530fdc8d8SChris Lattner {
74644d93782SGreg Clayton     if (m_output_file_sp)
74744d93782SGreg Clayton         m_output_file_sp->GetFile().SetStream (fh, tranfer_ownership);
74844d93782SGreg Clayton     else
74944d93782SGreg Clayton         m_output_file_sp.reset (new StreamFile (fh, tranfer_ownership));
75044d93782SGreg Clayton 
75144d93782SGreg Clayton     File &out_file = m_output_file_sp->GetFile();
75251b1e2d2SGreg Clayton     if (out_file.IsValid() == false)
75351b1e2d2SGreg Clayton         out_file.SetStream (stdout, false);
7542f88aadfSCaroline Tice 
755b588726eSEnrico Granata     // do not create the ScriptInterpreter just for setting the output file handle
756b588726eSEnrico Granata     // as the constructor will know how to do the right thing on its own
757b588726eSEnrico Granata     const bool can_create = false;
758b588726eSEnrico Granata     ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create);
759b588726eSEnrico Granata     if (script_interpreter)
760b588726eSEnrico Granata         script_interpreter->ResetOutputFileHandle (fh);
76130fdc8d8SChris Lattner }
76230fdc8d8SChris Lattner 
76330fdc8d8SChris Lattner void
76430fdc8d8SChris Lattner Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
76530fdc8d8SChris Lattner {
76644d93782SGreg Clayton     if (m_error_file_sp)
76744d93782SGreg Clayton         m_error_file_sp->GetFile().SetStream (fh, tranfer_ownership);
76844d93782SGreg Clayton     else
76944d93782SGreg Clayton         m_error_file_sp.reset (new StreamFile (fh, tranfer_ownership));
77044d93782SGreg Clayton 
77144d93782SGreg Clayton     File &err_file = m_error_file_sp->GetFile();
77251b1e2d2SGreg Clayton     if (err_file.IsValid() == false)
77351b1e2d2SGreg Clayton         err_file.SetStream (stderr, false);
77430fdc8d8SChris Lattner }
77530fdc8d8SChris Lattner 
776c5917d9aSJim Ingham void
777c5917d9aSJim Ingham Debugger::SaveInputTerminalState ()
778c5917d9aSJim Ingham {
77944d93782SGreg Clayton     if (m_input_file_sp)
78044d93782SGreg Clayton     {
78144d93782SGreg Clayton         File &in_file = m_input_file_sp->GetFile();
782c5917d9aSJim Ingham         if (in_file.GetDescriptor() != File::kInvalidDescriptor)
783c5917d9aSJim Ingham             m_terminal_state.Save(in_file.GetDescriptor(), true);
784c5917d9aSJim Ingham     }
78544d93782SGreg Clayton }
786c5917d9aSJim Ingham 
787c5917d9aSJim Ingham void
788c5917d9aSJim Ingham Debugger::RestoreInputTerminalState ()
789c5917d9aSJim Ingham {
790c5917d9aSJim Ingham     m_terminal_state.Restore();
791c5917d9aSJim Ingham }
792c5917d9aSJim Ingham 
79330fdc8d8SChris Lattner ExecutionContext
7942976d00aSJim Ingham Debugger::GetSelectedExecutionContext ()
79530fdc8d8SChris Lattner {
79630fdc8d8SChris Lattner     ExecutionContext exe_ctx;
797c14ee32dSGreg Clayton     TargetSP target_sp(GetSelectedTarget());
798c14ee32dSGreg Clayton     exe_ctx.SetTargetSP (target_sp);
79930fdc8d8SChris Lattner 
80030fdc8d8SChris Lattner     if (target_sp)
80130fdc8d8SChris Lattner     {
802c14ee32dSGreg Clayton         ProcessSP process_sp (target_sp->GetProcessSP());
803c14ee32dSGreg Clayton         exe_ctx.SetProcessSP (process_sp);
804c14ee32dSGreg Clayton         if (process_sp && process_sp->IsRunning() == false)
80530fdc8d8SChris Lattner         {
806c14ee32dSGreg Clayton             ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread());
807c14ee32dSGreg Clayton             if (thread_sp)
80830fdc8d8SChris Lattner             {
809c14ee32dSGreg Clayton                 exe_ctx.SetThreadSP (thread_sp);
810c14ee32dSGreg Clayton                 exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame());
811c14ee32dSGreg Clayton                 if (exe_ctx.GetFramePtr() == NULL)
812c14ee32dSGreg Clayton                     exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0));
81330fdc8d8SChris Lattner             }
81430fdc8d8SChris Lattner         }
81530fdc8d8SChris Lattner     }
81630fdc8d8SChris Lattner     return exe_ctx;
81730fdc8d8SChris Lattner }
81830fdc8d8SChris Lattner 
81930fdc8d8SChris Lattner void
820efed6131SCaroline Tice Debugger::DispatchInputInterrupt ()
821efed6131SCaroline Tice {
82244d93782SGreg Clayton     Mutex::Locker locker (m_input_reader_stack.GetMutex());
82344d93782SGreg Clayton     IOHandlerSP reader_sp (m_input_reader_stack.Top());
824efed6131SCaroline Tice     if (reader_sp)
82544d93782SGreg Clayton         reader_sp->Interrupt();
826efed6131SCaroline Tice }
827efed6131SCaroline Tice 
828efed6131SCaroline Tice void
829efed6131SCaroline Tice Debugger::DispatchInputEndOfFile ()
830efed6131SCaroline Tice {
83144d93782SGreg Clayton     Mutex::Locker locker (m_input_reader_stack.GetMutex());
83244d93782SGreg Clayton     IOHandlerSP reader_sp (m_input_reader_stack.Top());
833efed6131SCaroline Tice     if (reader_sp)
83444d93782SGreg Clayton         reader_sp->GotEOF();
835efed6131SCaroline Tice }
836efed6131SCaroline Tice 
837efed6131SCaroline Tice void
83844d93782SGreg Clayton Debugger::ClearIOHandlers ()
8393d6086f6SCaroline Tice {
840b44880caSCaroline Tice     // The bottom input reader should be the main debugger input reader.  We do not want to close that one here.
84144d93782SGreg Clayton     Mutex::Locker locker (m_input_reader_stack.GetMutex());
842d5a0a01bSCaroline Tice     while (m_input_reader_stack.GetSize() > 1)
8433d6086f6SCaroline Tice     {
84444d93782SGreg Clayton         IOHandlerSP reader_sp (m_input_reader_stack.Top());
8453d6086f6SCaroline Tice         if (reader_sp)
8463d6086f6SCaroline Tice         {
84744d93782SGreg Clayton             m_input_reader_stack.Pop();
8483d6086f6SCaroline Tice             reader_sp->SetIsDone(true);
84944d93782SGreg Clayton             reader_sp->Interrupt();
8503d6086f6SCaroline Tice         }
8513d6086f6SCaroline Tice     }
8523d6086f6SCaroline Tice }
8533d6086f6SCaroline Tice 
8543d6086f6SCaroline Tice void
85544d93782SGreg Clayton Debugger::ExecuteIOHanders()
856969ed3d1SCaroline Tice {
85744d93782SGreg Clayton 
85844d93782SGreg Clayton     while (1)
859969ed3d1SCaroline Tice     {
86044d93782SGreg Clayton         IOHandlerSP reader_sp(m_input_reader_stack.Top());
86130fdc8d8SChris Lattner         if (!reader_sp)
86230fdc8d8SChris Lattner             break;
86330fdc8d8SChris Lattner 
86444d93782SGreg Clayton         reader_sp->Activate();
86544d93782SGreg Clayton         reader_sp->Run();
86644d93782SGreg Clayton         reader_sp->Deactivate();
86744d93782SGreg Clayton 
86844d93782SGreg Clayton         // Remove all input readers that are done from the top of the stack
86944d93782SGreg Clayton         while (1)
87030fdc8d8SChris Lattner         {
87144d93782SGreg Clayton             IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
87244d93782SGreg Clayton             if (top_reader_sp && top_reader_sp->GetIsDone())
87344d93782SGreg Clayton                 m_input_reader_stack.Pop();
87430fdc8d8SChris Lattner             else
87530fdc8d8SChris Lattner                 break;
87630fdc8d8SChris Lattner         }
87730fdc8d8SChris Lattner     }
87844d93782SGreg Clayton     ClearIOHandlers();
87944d93782SGreg Clayton }
88030fdc8d8SChris Lattner 
88144d93782SGreg Clayton bool
88244d93782SGreg Clayton Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp)
88344d93782SGreg Clayton {
88444d93782SGreg Clayton     return m_input_reader_stack.IsTop (reader_sp);
88544d93782SGreg Clayton }
88630fdc8d8SChris Lattner 
88744d93782SGreg Clayton 
88844d93782SGreg Clayton ConstString
88944d93782SGreg Clayton Debugger::GetTopIOHandlerControlSequence(char ch)
89044d93782SGreg Clayton {
89144d93782SGreg Clayton     return m_input_reader_stack.GetTopIOHandlerControlSequence (ch);
89230fdc8d8SChris Lattner }
89330fdc8d8SChris Lattner 
89430fdc8d8SChris Lattner void
89544d93782SGreg Clayton Debugger::RunIOHandler (const IOHandlerSP& reader_sp)
89644d93782SGreg Clayton {
89744d93782SGreg Clayton     Mutex::Locker locker (m_input_reader_stack.GetMutex());
89844d93782SGreg Clayton     PushIOHandler (reader_sp);
89944d93782SGreg Clayton     reader_sp->Activate();
90044d93782SGreg Clayton     reader_sp->Run();
90144d93782SGreg Clayton     PopIOHandler (reader_sp);
90244d93782SGreg Clayton }
90344d93782SGreg Clayton 
90444d93782SGreg Clayton void
90544d93782SGreg Clayton Debugger::AdoptTopIOHandlerFilesIfInvalid (StreamFileSP &in, StreamFileSP &out, StreamFileSP &err)
90644d93782SGreg Clayton {
90744d93782SGreg Clayton     // Before an IOHandler runs, it must have in/out/err streams.
90844d93782SGreg Clayton     // This function is called when one ore more of the streams
90944d93782SGreg Clayton     // are NULL. We use the top input reader's in/out/err streams,
91044d93782SGreg Clayton     // or fall back to the debugger file handles, or we fall back
91144d93782SGreg Clayton     // onto stdin/stdout/stderr as a last resort.
91244d93782SGreg Clayton 
91344d93782SGreg Clayton     Mutex::Locker locker (m_input_reader_stack.GetMutex());
91444d93782SGreg Clayton     IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
91544d93782SGreg Clayton     // If no STDIN has been set, then set it appropriately
91644d93782SGreg Clayton     if (!in)
91744d93782SGreg Clayton     {
91844d93782SGreg Clayton         if (top_reader_sp)
91944d93782SGreg Clayton             in = top_reader_sp->GetInputStreamFile();
92044d93782SGreg Clayton         else
92144d93782SGreg Clayton             in = GetInputFile();
92244d93782SGreg Clayton 
92344d93782SGreg Clayton         // If there is nothing, use stdin
92444d93782SGreg Clayton         if (!in)
92544d93782SGreg Clayton             in = StreamFileSP(new StreamFile(stdin, false));
92644d93782SGreg Clayton     }
92744d93782SGreg Clayton     // If no STDOUT has been set, then set it appropriately
92844d93782SGreg Clayton     if (!out)
92944d93782SGreg Clayton     {
93044d93782SGreg Clayton         if (top_reader_sp)
93144d93782SGreg Clayton             out = top_reader_sp->GetOutputStreamFile();
93244d93782SGreg Clayton         else
93344d93782SGreg Clayton             out = GetOutputFile();
93444d93782SGreg Clayton 
93544d93782SGreg Clayton         // If there is nothing, use stdout
93644d93782SGreg Clayton         if (!out)
93744d93782SGreg Clayton             out = StreamFileSP(new StreamFile(stdout, false));
93844d93782SGreg Clayton     }
93944d93782SGreg Clayton     // If no STDERR has been set, then set it appropriately
94044d93782SGreg Clayton     if (!err)
94144d93782SGreg Clayton     {
94244d93782SGreg Clayton         if (top_reader_sp)
94344d93782SGreg Clayton             err = top_reader_sp->GetErrorStreamFile();
94444d93782SGreg Clayton         else
94544d93782SGreg Clayton             err = GetErrorFile();
94644d93782SGreg Clayton 
94744d93782SGreg Clayton         // If there is nothing, use stderr
94844d93782SGreg Clayton         if (!err)
94944d93782SGreg Clayton             err = StreamFileSP(new StreamFile(stdout, false));
95044d93782SGreg Clayton 
95144d93782SGreg Clayton     }
95244d93782SGreg Clayton }
95344d93782SGreg Clayton 
95444d93782SGreg Clayton void
95544d93782SGreg Clayton Debugger::PushIOHandler (const IOHandlerSP& reader_sp)
95630fdc8d8SChris Lattner {
95730fdc8d8SChris Lattner     if (!reader_sp)
95830fdc8d8SChris Lattner         return;
959b44880caSCaroline Tice 
96044d93782SGreg Clayton     // Got the current top input reader...
96144d93782SGreg Clayton     IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
962b44880caSCaroline Tice 
96344d93782SGreg Clayton     // Push our new input reader
964d5a0a01bSCaroline Tice     m_input_reader_stack.Push (reader_sp);
96544d93782SGreg Clayton 
96644d93782SGreg Clayton     // Interrupt the top input reader to it will exit its Run() function
96744d93782SGreg Clayton     // and let this new input reader take over
96844d93782SGreg Clayton     if (top_reader_sp)
96944d93782SGreg Clayton         top_reader_sp->Deactivate();
97030fdc8d8SChris Lattner }
97130fdc8d8SChris Lattner 
97230fdc8d8SChris Lattner bool
97344d93782SGreg Clayton Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp)
97430fdc8d8SChris Lattner {
97530fdc8d8SChris Lattner     bool result = false;
97630fdc8d8SChris Lattner 
97744d93782SGreg Clayton     Mutex::Locker locker (m_input_reader_stack.GetMutex());
97844d93782SGreg Clayton 
97930fdc8d8SChris Lattner     // The reader on the stop of the stack is done, so let the next
98030fdc8d8SChris Lattner     // read on the stack referesh its prompt and if there is one...
981d5a0a01bSCaroline Tice     if (!m_input_reader_stack.IsEmpty())
98230fdc8d8SChris Lattner     {
98344d93782SGreg Clayton         IOHandlerSP reader_sp(m_input_reader_stack.Top());
98430fdc8d8SChris Lattner 
98530fdc8d8SChris Lattner         if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
98630fdc8d8SChris Lattner         {
98744d93782SGreg Clayton             reader_sp->Deactivate();
988d5a0a01bSCaroline Tice             m_input_reader_stack.Pop ();
98930fdc8d8SChris Lattner 
990d5a0a01bSCaroline Tice             reader_sp = m_input_reader_stack.Top();
99130fdc8d8SChris Lattner             if (reader_sp)
99244d93782SGreg Clayton                 reader_sp->Activate();
99344d93782SGreg Clayton 
99444d93782SGreg Clayton             result = true;
99530fdc8d8SChris Lattner         }
99630fdc8d8SChris Lattner     }
99730fdc8d8SChris Lattner     return result;
99830fdc8d8SChris Lattner }
99930fdc8d8SChris Lattner 
100030fdc8d8SChris Lattner bool
100144d93782SGreg Clayton Debugger::HideTopIOHandler()
100230fdc8d8SChris Lattner {
100344d93782SGreg Clayton     Mutex::Locker locker;
100430fdc8d8SChris Lattner 
100544d93782SGreg Clayton     if (locker.TryLock(m_input_reader_stack.GetMutex()))
100630fdc8d8SChris Lattner     {
100744d93782SGreg Clayton         IOHandlerSP reader_sp(m_input_reader_stack.Top());
100844d93782SGreg Clayton         if (reader_sp)
100944d93782SGreg Clayton             reader_sp->Hide();
101044d93782SGreg Clayton         return true;
101130fdc8d8SChris Lattner     }
101244d93782SGreg Clayton     return false;
101330fdc8d8SChris Lattner }
101430fdc8d8SChris Lattner 
101530fdc8d8SChris Lattner void
101644d93782SGreg Clayton Debugger::RefreshTopIOHandler()
101730fdc8d8SChris Lattner {
101844d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
101944d93782SGreg Clayton     if (reader_sp)
102044d93782SGreg Clayton         reader_sp->Refresh();
102130fdc8d8SChris Lattner }
102244d93782SGreg Clayton 
10236611103cSGreg Clayton 
10245b52f0c7SJim Ingham StreamSP
10255b52f0c7SJim Ingham Debugger::GetAsyncOutputStream ()
10265b52f0c7SJim Ingham {
10275b52f0c7SJim Ingham     return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(),
10285b52f0c7SJim Ingham                                                CommandInterpreter::eBroadcastBitAsynchronousOutputData));
10295b52f0c7SJim Ingham }
10305b52f0c7SJim Ingham 
10315b52f0c7SJim Ingham StreamSP
10325b52f0c7SJim Ingham Debugger::GetAsyncErrorStream ()
10335b52f0c7SJim Ingham {
10345b52f0c7SJim Ingham     return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(),
10355b52f0c7SJim Ingham                                                CommandInterpreter::eBroadcastBitAsynchronousErrorData));
10365b52f0c7SJim Ingham }
10375b52f0c7SJim Ingham 
1038c7bece56SGreg Clayton size_t
1039061858ceSEnrico Granata Debugger::GetNumDebuggers()
1040061858ceSEnrico Granata {
1041c15f55e2SGreg Clayton     if (g_shared_debugger_refcount > 0)
1042c15f55e2SGreg Clayton     {
1043061858ceSEnrico Granata         Mutex::Locker locker (GetDebuggerListMutex ());
1044061858ceSEnrico Granata         return GetDebuggerList().size();
1045061858ceSEnrico Granata     }
1046c15f55e2SGreg Clayton     return 0;
1047c15f55e2SGreg Clayton }
1048061858ceSEnrico Granata 
1049061858ceSEnrico Granata lldb::DebuggerSP
1050c7bece56SGreg Clayton Debugger::GetDebuggerAtIndex (size_t index)
1051061858ceSEnrico Granata {
1052061858ceSEnrico Granata     DebuggerSP debugger_sp;
1053061858ceSEnrico Granata 
1054c15f55e2SGreg Clayton     if (g_shared_debugger_refcount > 0)
1055c15f55e2SGreg Clayton     {
1056061858ceSEnrico Granata         Mutex::Locker locker (GetDebuggerListMutex ());
1057061858ceSEnrico Granata         DebuggerList &debugger_list = GetDebuggerList();
1058061858ceSEnrico Granata 
1059061858ceSEnrico Granata         if (index < debugger_list.size())
1060061858ceSEnrico Granata             debugger_sp = debugger_list[index];
1061c15f55e2SGreg Clayton     }
1062061858ceSEnrico Granata 
1063061858ceSEnrico Granata     return debugger_sp;
1064061858ceSEnrico Granata }
1065061858ceSEnrico Granata 
1066ebc1bb27SCaroline Tice DebuggerSP
1067ebc1bb27SCaroline Tice Debugger::FindDebuggerWithID (lldb::user_id_t id)
1068ebc1bb27SCaroline Tice {
10694d122c40SGreg Clayton     DebuggerSP debugger_sp;
1070ebc1bb27SCaroline Tice 
1071c15f55e2SGreg Clayton     if (g_shared_debugger_refcount > 0)
1072c15f55e2SGreg Clayton     {
1073ebc1bb27SCaroline Tice         Mutex::Locker locker (GetDebuggerListMutex ());
1074ebc1bb27SCaroline Tice         DebuggerList &debugger_list = GetDebuggerList();
1075ebc1bb27SCaroline Tice         DebuggerList::iterator pos, end = debugger_list.end();
1076ebc1bb27SCaroline Tice         for (pos = debugger_list.begin(); pos != end; ++pos)
1077ebc1bb27SCaroline Tice         {
1078ebc1bb27SCaroline Tice             if ((*pos).get()->GetID() == id)
1079ebc1bb27SCaroline Tice             {
1080ebc1bb27SCaroline Tice                 debugger_sp = *pos;
1081ebc1bb27SCaroline Tice                 break;
1082ebc1bb27SCaroline Tice             }
1083ebc1bb27SCaroline Tice         }
1084c15f55e2SGreg Clayton     }
1085ebc1bb27SCaroline Tice     return debugger_sp;
1086ebc1bb27SCaroline Tice }
10873df9a8dfSCaroline Tice 
10881b654882SGreg Clayton static void
1089b57e4a1bSJason Molenda TestPromptFormats (StackFrame *frame)
10901b654882SGreg Clayton {
10911b654882SGreg Clayton     if (frame == NULL)
10921b654882SGreg Clayton         return;
10931b654882SGreg Clayton 
10941b654882SGreg Clayton     StreamString s;
10951b654882SGreg Clayton     const char *prompt_format =
10961b654882SGreg Clayton     "{addr = '${addr}'\n}"
10971b654882SGreg Clayton     "{process.id = '${process.id}'\n}"
10981b654882SGreg Clayton     "{process.name = '${process.name}'\n}"
10991b654882SGreg Clayton     "{process.file.basename = '${process.file.basename}'\n}"
11001b654882SGreg Clayton     "{process.file.fullpath = '${process.file.fullpath}'\n}"
11011b654882SGreg Clayton     "{thread.id = '${thread.id}'\n}"
11021b654882SGreg Clayton     "{thread.index = '${thread.index}'\n}"
11031b654882SGreg Clayton     "{thread.name = '${thread.name}'\n}"
11041b654882SGreg Clayton     "{thread.queue = '${thread.queue}'\n}"
11051b654882SGreg Clayton     "{thread.stop-reason = '${thread.stop-reason}'\n}"
11061b654882SGreg Clayton     "{target.arch = '${target.arch}'\n}"
11071b654882SGreg Clayton     "{module.file.basename = '${module.file.basename}'\n}"
11081b654882SGreg Clayton     "{module.file.fullpath = '${module.file.fullpath}'\n}"
11091b654882SGreg Clayton     "{file.basename = '${file.basename}'\n}"
11101b654882SGreg Clayton     "{file.fullpath = '${file.fullpath}'\n}"
11111b654882SGreg Clayton     "{frame.index = '${frame.index}'\n}"
11121b654882SGreg Clayton     "{frame.pc = '${frame.pc}'\n}"
11131b654882SGreg Clayton     "{frame.sp = '${frame.sp}'\n}"
11141b654882SGreg Clayton     "{frame.fp = '${frame.fp}'\n}"
11151b654882SGreg Clayton     "{frame.flags = '${frame.flags}'\n}"
11161b654882SGreg Clayton     "{frame.reg.rdi = '${frame.reg.rdi}'\n}"
11171b654882SGreg Clayton     "{frame.reg.rip = '${frame.reg.rip}'\n}"
11181b654882SGreg Clayton     "{frame.reg.rsp = '${frame.reg.rsp}'\n}"
11191b654882SGreg Clayton     "{frame.reg.rbp = '${frame.reg.rbp}'\n}"
11201b654882SGreg Clayton     "{frame.reg.rflags = '${frame.reg.rflags}'\n}"
11211b654882SGreg Clayton     "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}"
11221b654882SGreg Clayton     "{frame.reg.carp = '${frame.reg.carp}'\n}"
11231b654882SGreg Clayton     "{function.id = '${function.id}'\n}"
11241b654882SGreg Clayton     "{function.name = '${function.name}'\n}"
1125ccbc08e6SGreg Clayton     "{function.name-with-args = '${function.name-with-args}'\n}"
11261b654882SGreg Clayton     "{function.addr-offset = '${function.addr-offset}'\n}"
11271b654882SGreg Clayton     "{function.line-offset = '${function.line-offset}'\n}"
11281b654882SGreg Clayton     "{function.pc-offset = '${function.pc-offset}'\n}"
11291b654882SGreg Clayton     "{line.file.basename = '${line.file.basename}'\n}"
11301b654882SGreg Clayton     "{line.file.fullpath = '${line.file.fullpath}'\n}"
11311b654882SGreg Clayton     "{line.number = '${line.number}'\n}"
11321b654882SGreg Clayton     "{line.start-addr = '${line.start-addr}'\n}"
11331b654882SGreg Clayton     "{line.end-addr = '${line.end-addr}'\n}"
11341b654882SGreg Clayton ;
11351b654882SGreg Clayton 
11361b654882SGreg Clayton     SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
11371b654882SGreg Clayton     ExecutionContext exe_ctx;
11380603aa9dSGreg Clayton     frame->CalculateExecutionContext(exe_ctx);
1139c3ce7f27SMichael Sartain     if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s))
11401b654882SGreg Clayton     {
11411b654882SGreg Clayton         printf("%s\n", s.GetData());
11421b654882SGreg Clayton     }
11431b654882SGreg Clayton     else
11441b654882SGreg Clayton     {
11451b654882SGreg Clayton         printf ("what we got: %s\n", s.GetData());
11461b654882SGreg Clayton     }
11471b654882SGreg Clayton }
11481b654882SGreg Clayton 
11499fc1944eSEnrico Granata static bool
11509fc1944eSEnrico Granata ScanFormatDescriptor (const char* var_name_begin,
11519fc1944eSEnrico Granata                       const char* var_name_end,
11529fc1944eSEnrico Granata                       const char** var_name_final,
11539fc1944eSEnrico Granata                       const char** percent_position,
11544d122c40SGreg Clayton                       Format* custom_format,
11559fc1944eSEnrico Granata                       ValueObject::ValueObjectRepresentationStyle* val_obj_display)
11569fc1944eSEnrico Granata {
11575160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
11589fc1944eSEnrico Granata     *percent_position = ::strchr(var_name_begin,'%');
11599fc1944eSEnrico Granata     if (!*percent_position || *percent_position > var_name_end)
1160e992a089SEnrico Granata     {
1161e992a089SEnrico Granata         if (log)
1162d228483dSEnrico Granata             log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping");
11639fc1944eSEnrico Granata         *var_name_final = var_name_end;
1164e992a089SEnrico Granata     }
11659fc1944eSEnrico Granata     else
11669fc1944eSEnrico Granata     {
11679fc1944eSEnrico Granata         *var_name_final = *percent_position;
116836aa5ae6SEnrico Granata         std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1);
1169e992a089SEnrico Granata         if (log)
117068ae4117SEnrico Granata             log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str());
117136aa5ae6SEnrico Granata         if ( !FormatManager::GetFormatFromCString(format_name.c_str(),
11729fc1944eSEnrico Granata                                                   true,
11739fc1944eSEnrico Granata                                                   *custom_format) )
11749fc1944eSEnrico Granata         {
1175e992a089SEnrico Granata             if (log)
117668ae4117SEnrico Granata                 log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str());
117736aa5ae6SEnrico Granata 
117836aa5ae6SEnrico Granata             switch (format_name.front())
117936aa5ae6SEnrico Granata             {
118036aa5ae6SEnrico Granata                 case '@':             // if this is an @ sign, print ObjC description
118186cc9829SEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific;
118236aa5ae6SEnrico Granata                     break;
118336aa5ae6SEnrico Granata                 case 'V': // if this is a V, print the value using the default format
118486cc9829SEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
118536aa5ae6SEnrico Granata                     break;
118636aa5ae6SEnrico Granata                 case 'L': // if this is an L, print the location of the value
118786cc9829SEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation;
118836aa5ae6SEnrico Granata                     break;
118936aa5ae6SEnrico Granata                 case 'S': // if this is an S, print the summary after all
119086cc9829SEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
119136aa5ae6SEnrico Granata                     break;
119236aa5ae6SEnrico Granata                 case '#': // if this is a '#', print the number of children
119386cc9829SEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount;
119436aa5ae6SEnrico Granata                     break;
119536aa5ae6SEnrico Granata                 case 'T': // if this is a 'T', print the type
119686cc9829SEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleType;
119736aa5ae6SEnrico Granata                     break;
11982c75f11eSEnrico Granata                 case 'N': // if this is a 'N', print the name
11992c75f11eSEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleName;
12002c75f11eSEnrico Granata                     break;
12012c75f11eSEnrico Granata                 case '>': // if this is a '>', print the name
12022c75f11eSEnrico Granata                     *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath;
12032c75f11eSEnrico Granata                     break;
120436aa5ae6SEnrico Granata                 default:
12055c42d8a8SJim Ingham                     if (log)
120636aa5ae6SEnrico Granata                         log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str());
120736aa5ae6SEnrico Granata                     break;
120836aa5ae6SEnrico Granata             }
12099fc1944eSEnrico Granata         }
12109fc1944eSEnrico Granata         // a good custom format tells us to print the value using it
12119fc1944eSEnrico Granata         else
1212e992a089SEnrico Granata         {
1213e992a089SEnrico Granata             if (log)
121468ae4117SEnrico Granata                 log->Printf("[ScanFormatDescriptor] will display value for this VO");
121586cc9829SEnrico Granata             *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1216e992a089SEnrico Granata         }
12179fc1944eSEnrico Granata     }
1218e992a089SEnrico Granata     if (log)
121968ae4117SEnrico Granata         log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d",
1220e992a089SEnrico Granata                     *custom_format,
1221e992a089SEnrico Granata                     *val_obj_display);
12229fc1944eSEnrico Granata     return true;
12239fc1944eSEnrico Granata }
12249fc1944eSEnrico Granata 
12259fc1944eSEnrico Granata static bool
12269fc1944eSEnrico Granata ScanBracketedRange (const char* var_name_begin,
12279fc1944eSEnrico Granata                     const char* var_name_end,
12289fc1944eSEnrico Granata                     const char* var_name_final,
12299fc1944eSEnrico Granata                     const char** open_bracket_position,
12309fc1944eSEnrico Granata                     const char** separator_position,
12319fc1944eSEnrico Granata                     const char** close_bracket_position,
12329fc1944eSEnrico Granata                     const char** var_name_final_if_array_range,
12339fc1944eSEnrico Granata                     int64_t* index_lower,
12349fc1944eSEnrico Granata                     int64_t* index_higher)
12359fc1944eSEnrico Granata {
12365160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
12379fc1944eSEnrico Granata     *open_bracket_position = ::strchr(var_name_begin,'[');
12389fc1944eSEnrico Granata     if (*open_bracket_position && *open_bracket_position < var_name_final)
12399fc1944eSEnrico Granata     {
12409fc1944eSEnrico Granata         *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
12419fc1944eSEnrico Granata         *close_bracket_position = ::strchr(*open_bracket_position,']');
12429fc1944eSEnrico Granata         // as usual, we assume that [] will come before %
12439fc1944eSEnrico Granata         //printf("trying to expand a []\n");
12449fc1944eSEnrico Granata         *var_name_final_if_array_range = *open_bracket_position;
12459fc1944eSEnrico Granata         if (*close_bracket_position - *open_bracket_position == 1)
12469fc1944eSEnrico Granata         {
1247e992a089SEnrico Granata             if (log)
1248d228483dSEnrico Granata                 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
12499fc1944eSEnrico Granata             *index_lower = 0;
12509fc1944eSEnrico Granata         }
12519fc1944eSEnrico Granata         else if (*separator_position == NULL || *separator_position > var_name_end)
12529fc1944eSEnrico Granata         {
12539fc1944eSEnrico Granata             char *end = NULL;
12549fc1944eSEnrico Granata             *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
12559fc1944eSEnrico Granata             *index_higher = *index_lower;
1256e992a089SEnrico Granata             if (log)
1257d01b2953SDaniel Malea                 log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower);
12589fc1944eSEnrico Granata         }
12599fc1944eSEnrico Granata         else if (*close_bracket_position && *close_bracket_position < var_name_end)
12609fc1944eSEnrico Granata         {
12619fc1944eSEnrico Granata             char *end = NULL;
12629fc1944eSEnrico Granata             *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
12639fc1944eSEnrico Granata             *index_higher = ::strtoul (*separator_position+1, &end, 0);
1264e992a089SEnrico Granata             if (log)
1265d01b2953SDaniel Malea                 log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher);
12669fc1944eSEnrico Granata         }
12679fc1944eSEnrico Granata         else
1268e992a089SEnrico Granata         {
1269e992a089SEnrico Granata             if (log)
1270d228483dSEnrico Granata                 log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it");
12719fc1944eSEnrico Granata             return false;
1272e992a089SEnrico Granata         }
12739fc1944eSEnrico Granata         if (*index_lower > *index_higher && *index_higher > 0)
12749fc1944eSEnrico Granata         {
1275e992a089SEnrico Granata             if (log)
1276d228483dSEnrico Granata                 log->Printf("[ScanBracketedRange] swapping indices");
1277c7bece56SGreg Clayton             int64_t temp = *index_lower;
12789fc1944eSEnrico Granata             *index_lower = *index_higher;
12799fc1944eSEnrico Granata             *index_higher = temp;
12809fc1944eSEnrico Granata         }
12819fc1944eSEnrico Granata     }
1282e992a089SEnrico Granata     else if (log)
1283d228483dSEnrico Granata             log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
12849fc1944eSEnrico Granata     return true;
12859fc1944eSEnrico Granata }
12869fc1944eSEnrico Granata 
12870769b2b1SMichael Sartain template <typename T>
12880769b2b1SMichael Sartain static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name)
12890769b2b1SMichael Sartain {
12900769b2b1SMichael Sartain     if (script_interpreter)
12910769b2b1SMichael Sartain     {
12920769b2b1SMichael Sartain         Error script_error;
12930769b2b1SMichael Sartain         std::string script_output;
12940769b2b1SMichael Sartain 
12950769b2b1SMichael Sartain         if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success())
12960769b2b1SMichael Sartain         {
12970769b2b1SMichael Sartain             s.Printf("%s", script_output.c_str());
12980769b2b1SMichael Sartain             return true;
12990769b2b1SMichael Sartain         }
13000769b2b1SMichael Sartain         else
13010769b2b1SMichael Sartain         {
13020769b2b1SMichael Sartain             s.Printf("<error: %s>",script_error.AsCString());
13030769b2b1SMichael Sartain         }
13040769b2b1SMichael Sartain     }
13050769b2b1SMichael Sartain     return false;
13060769b2b1SMichael Sartain }
13070769b2b1SMichael Sartain 
13089fc1944eSEnrico Granata static ValueObjectSP
1309c482a192SEnrico Granata ExpandIndexedExpression (ValueObject* valobj,
1310c7bece56SGreg Clayton                          size_t index,
1311b57e4a1bSJason Molenda                          StackFrame* frame,
1312fc7a7f3bSEnrico Granata                          bool deref_pointer)
13139fc1944eSEnrico Granata {
13145160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
1315fc7a7f3bSEnrico Granata     const char* ptr_deref_format = "[%d]";
1316599171adSEnrico Granata     std::string ptr_deref_buffer(10,0);
1317599171adSEnrico Granata     ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
1318e992a089SEnrico Granata     if (log)
1319599171adSEnrico Granata         log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str());
1320fc7a7f3bSEnrico Granata     const char* first_unparsed;
1321fc7a7f3bSEnrico Granata     ValueObject::GetValueForExpressionPathOptions options;
1322fc7a7f3bSEnrico Granata     ValueObject::ExpressionPathEndResultType final_value_type;
1323fc7a7f3bSEnrico Granata     ValueObject::ExpressionPathScanEndReason reason_to_stop;
132486cc9829SEnrico Granata     ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
1325599171adSEnrico Granata     ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(),
1326fc7a7f3bSEnrico Granata                                                           &first_unparsed,
1327fc7a7f3bSEnrico Granata                                                           &reason_to_stop,
1328fc7a7f3bSEnrico Granata                                                           &final_value_type,
1329fc7a7f3bSEnrico Granata                                                           options,
1330fc7a7f3bSEnrico Granata                                                           &what_next);
1331fc7a7f3bSEnrico Granata     if (!item)
1332fc7a7f3bSEnrico Granata     {
1333e992a089SEnrico Granata         if (log)
1334d228483dSEnrico Granata             log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d,"
1335e992a089SEnrico Granata                " final_value_type %d",
1336fc7a7f3bSEnrico Granata                first_unparsed, reason_to_stop, final_value_type);
1337fc7a7f3bSEnrico Granata     }
13389fc1944eSEnrico Granata     else
13399fc1944eSEnrico Granata     {
1340e992a089SEnrico Granata         if (log)
1341d228483dSEnrico Granata             log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
1342e992a089SEnrico Granata                " final_value_type %d",
1343fc7a7f3bSEnrico Granata                first_unparsed, reason_to_stop, final_value_type);
13449fc1944eSEnrico Granata     }
13459fc1944eSEnrico Granata     return item;
13469fc1944eSEnrico Granata }
13479fc1944eSEnrico Granata 
13480769b2b1SMichael Sartain static inline bool
13490769b2b1SMichael Sartain IsToken(const char *var_name_begin, const char *var)
13500769b2b1SMichael Sartain {
13510769b2b1SMichael Sartain     return (::strncmp (var_name_begin, var, strlen(var)) == 0);
13520769b2b1SMichael Sartain }
13530769b2b1SMichael Sartain 
13540769b2b1SMichael Sartain static bool
13550769b2b1SMichael Sartain IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format,
13560769b2b1SMichael Sartain     const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr)
13570769b2b1SMichael Sartain {
13580769b2b1SMichael Sartain     int var_len = strlen(var);
13590769b2b1SMichael Sartain     if (::strncmp (var_name_begin, var, var_len) == 0)
13600769b2b1SMichael Sartain     {
13610769b2b1SMichael Sartain         var_name_begin += var_len;
13620769b2b1SMichael Sartain         if (*var_name_begin == '}')
13630769b2b1SMichael Sartain         {
13640769b2b1SMichael Sartain             format = default_format;
13650769b2b1SMichael Sartain             return true;
13660769b2b1SMichael Sartain         }
13670769b2b1SMichael Sartain         else if (*var_name_begin == '%')
13680769b2b1SMichael Sartain         {
13690769b2b1SMichael Sartain             // Allow format specifiers: x|X|u with optional width specifiers.
13700769b2b1SMichael Sartain             //   ${thread.id%x}    ; hex
13710769b2b1SMichael Sartain             //   ${thread.id%X}    ; uppercase hex
13720769b2b1SMichael Sartain             //   ${thread.id%u}    ; unsigned decimal
13730769b2b1SMichael Sartain             //   ${thread.id%8.8X} ; width.precision + specifier
13740769b2b1SMichael Sartain             //   ${thread.id%tid}  ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id)
13750769b2b1SMichael Sartain             int dot_count = 0;
13760769b2b1SMichael Sartain             const char *specifier = NULL;
13770769b2b1SMichael Sartain             int width_precision_length = 0;
13780769b2b1SMichael Sartain             const char *width_precision = ++var_name_begin;
13790769b2b1SMichael Sartain             while (isdigit(*var_name_begin) || *var_name_begin == '.')
13800769b2b1SMichael Sartain             {
13810769b2b1SMichael Sartain                 dot_count += (*var_name_begin == '.');
13820769b2b1SMichael Sartain                 if (dot_count > 1)
13830769b2b1SMichael Sartain                     break;
13840769b2b1SMichael Sartain                 var_name_begin++;
13850769b2b1SMichael Sartain                 width_precision_length++;
13860769b2b1SMichael Sartain             }
13870769b2b1SMichael Sartain 
13880769b2b1SMichael Sartain             if (IsToken (var_name_begin, "tid}"))
13890769b2b1SMichael Sartain             {
13900769b2b1SMichael Sartain                 Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr);
13910769b2b1SMichael Sartain                 if (target)
13920769b2b1SMichael Sartain                 {
13930769b2b1SMichael Sartain                     ArchSpec arch (target->GetArchitecture ());
13940769b2b1SMichael Sartain                     llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS;
13950769b2b1SMichael Sartain                     if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux))
13960769b2b1SMichael Sartain                         specifier = PRIu64;
13970769b2b1SMichael Sartain                 }
13980769b2b1SMichael Sartain                 if (!specifier)
13990769b2b1SMichael Sartain                 {
14000769b2b1SMichael Sartain                     format = default_format;
14010769b2b1SMichael Sartain                     return true;
14020769b2b1SMichael Sartain                 }
14030769b2b1SMichael Sartain             }
14040769b2b1SMichael Sartain             else if (IsToken (var_name_begin, "x}"))
14050769b2b1SMichael Sartain                 specifier = PRIx64;
14060769b2b1SMichael Sartain             else if (IsToken (var_name_begin, "X}"))
14070769b2b1SMichael Sartain                 specifier = PRIX64;
14080769b2b1SMichael Sartain             else if (IsToken (var_name_begin, "u}"))
14090769b2b1SMichael Sartain                 specifier = PRIu64;
14100769b2b1SMichael Sartain 
14110769b2b1SMichael Sartain             if (specifier)
14120769b2b1SMichael Sartain             {
14130769b2b1SMichael Sartain                 format = "%";
14140769b2b1SMichael Sartain                 if (width_precision_length)
14150769b2b1SMichael Sartain                     format += std::string(width_precision, width_precision_length);
14160769b2b1SMichael Sartain                 format += specifier;
14170769b2b1SMichael Sartain                 return true;
14180769b2b1SMichael Sartain             }
14190769b2b1SMichael Sartain         }
14200769b2b1SMichael Sartain     }
14210769b2b1SMichael Sartain     return false;
14220769b2b1SMichael Sartain }
14230769b2b1SMichael Sartain 
1424c3ce7f27SMichael Sartain static bool
1425c3ce7f27SMichael Sartain FormatPromptRecurse
14261b654882SGreg Clayton (
14271b654882SGreg Clayton     const char *format,
14281b654882SGreg Clayton     const SymbolContext *sc,
14291b654882SGreg Clayton     const ExecutionContext *exe_ctx,
14301b654882SGreg Clayton     const Address *addr,
14311b654882SGreg Clayton     Stream &s,
14324becb37eSEnrico Granata     const char **end,
1433c482a192SEnrico Granata     ValueObject* valobj
14341b654882SGreg Clayton )
14351b654882SGreg Clayton {
1436c482a192SEnrico Granata     ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers
14371b654882SGreg Clayton     bool success = true;
14381b654882SGreg Clayton     const char *p;
14395160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
1440c3ce7f27SMichael Sartain 
14411b654882SGreg Clayton     for (p = format; *p != '\0'; ++p)
14421b654882SGreg Clayton     {
1443c482a192SEnrico Granata         if (realvalobj)
14444becb37eSEnrico Granata         {
1445c482a192SEnrico Granata             valobj = realvalobj;
1446c482a192SEnrico Granata             realvalobj = NULL;
14474becb37eSEnrico Granata         }
14481b654882SGreg Clayton         size_t non_special_chars = ::strcspn (p, "${}\\");
14491b654882SGreg Clayton         if (non_special_chars > 0)
14501b654882SGreg Clayton         {
14511b654882SGreg Clayton             if (success)
14521b654882SGreg Clayton                 s.Write (p, non_special_chars);
14531b654882SGreg Clayton             p += non_special_chars;
14541b654882SGreg Clayton         }
14551b654882SGreg Clayton 
14561b654882SGreg Clayton         if (*p == '\0')
14571b654882SGreg Clayton         {
14581b654882SGreg Clayton             break;
14591b654882SGreg Clayton         }
14601b654882SGreg Clayton         else if (*p == '{')
14611b654882SGreg Clayton         {
14621b654882SGreg Clayton             // Start a new scope that must have everything it needs if it is to
14631b654882SGreg Clayton             // to make it into the final output stream "s". If you want to make
14641b654882SGreg Clayton             // a format that only prints out the function or symbol name if there
14651b654882SGreg Clayton             // is one in the symbol context you can use:
14661b654882SGreg Clayton             //      "{function =${function.name}}"
14671b654882SGreg Clayton             // The first '{' starts a new scope that end with the matching '}' at
14681b654882SGreg Clayton             // the end of the string. The contents "function =${function.name}"
14691b654882SGreg Clayton             // will then be evaluated and only be output if there is a function
14701b654882SGreg Clayton             // or symbol with a valid name.
14711b654882SGreg Clayton             StreamString sub_strm;
14721b654882SGreg Clayton 
14731b654882SGreg Clayton             ++p;  // Skip the '{'
14741b654882SGreg Clayton 
1475c3ce7f27SMichael Sartain             if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj))
14761b654882SGreg Clayton             {
14771b654882SGreg Clayton                 // The stream had all it needed
14781b654882SGreg Clayton                 s.Write(sub_strm.GetData(), sub_strm.GetSize());
14791b654882SGreg Clayton             }
14801b654882SGreg Clayton             if (*p != '}')
14811b654882SGreg Clayton             {
14821b654882SGreg Clayton                 success = false;
14831b654882SGreg Clayton                 break;
14841b654882SGreg Clayton             }
14851b654882SGreg Clayton         }
14861b654882SGreg Clayton         else if (*p == '}')
14871b654882SGreg Clayton         {
14881b654882SGreg Clayton             // End of a enclosing scope
14891b654882SGreg Clayton             break;
14901b654882SGreg Clayton         }
14911b654882SGreg Clayton         else if (*p == '$')
14921b654882SGreg Clayton         {
14931b654882SGreg Clayton             // We have a prompt variable to print
14941b654882SGreg Clayton             ++p;
14951b654882SGreg Clayton             if (*p == '{')
14961b654882SGreg Clayton             {
14971b654882SGreg Clayton                 ++p;
14981b654882SGreg Clayton                 const char *var_name_begin = p;
14991b654882SGreg Clayton                 const char *var_name_end = ::strchr (p, '}');
15001b654882SGreg Clayton 
15011b654882SGreg Clayton                 if (var_name_end && var_name_begin < var_name_end)
15021b654882SGreg Clayton                 {
15031b654882SGreg Clayton                     // if we have already failed to parse, skip this variable
15041b654882SGreg Clayton                     if (success)
15051b654882SGreg Clayton                     {
15061b654882SGreg Clayton                         const char *cstr = NULL;
15070769b2b1SMichael Sartain                         std::string token_format;
15081b654882SGreg Clayton                         Address format_addr;
15091b654882SGreg Clayton                         bool calculate_format_addr_function_offset = false;
15101b654882SGreg Clayton                         // Set reg_kind and reg_num to invalid values
15111b654882SGreg Clayton                         RegisterKind reg_kind = kNumRegisterKinds;
15121b654882SGreg Clayton                         uint32_t reg_num = LLDB_INVALID_REGNUM;
15131b654882SGreg Clayton                         FileSpec format_file_spec;
1514e0d378b3SGreg Clayton                         const RegisterInfo *reg_info = NULL;
15151b654882SGreg Clayton                         RegisterContext *reg_ctx = NULL;
15169fc1944eSEnrico Granata                         bool do_deref_pointer = false;
151786cc9829SEnrico Granata                         ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
151886cc9829SEnrico Granata                         ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain;
15191b654882SGreg Clayton 
15201b654882SGreg Clayton                         // Each variable must set success to true below...
15211b654882SGreg Clayton                         bool var_success = false;
15221b654882SGreg Clayton                         switch (var_name_begin[0])
15231b654882SGreg Clayton                         {
15244becb37eSEnrico Granata                         case '*':
15256f3533fbSEnrico Granata                         case 'v':
15266f3533fbSEnrico Granata                         case 's':
15274becb37eSEnrico Granata                             {
1528c482a192SEnrico Granata                                 if (!valobj)
152934132754SGreg Clayton                                     break;
15306f3533fbSEnrico Granata 
1531c3e320a7SEnrico Granata                                 if (log)
1532d228483dSEnrico Granata                                     log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin);
1533c3e320a7SEnrico Granata 
15346f3533fbSEnrico Granata                                 // check for *var and *svar
15356f3533fbSEnrico Granata                                 if (*var_name_begin == '*')
15366f3533fbSEnrico Granata                                 {
15379fc1944eSEnrico Granata                                     do_deref_pointer = true;
15389fc1944eSEnrico Granata                                     var_name_begin++;
1539c3e320a7SEnrico Granata                                     if (log)
154068ae4117SEnrico Granata                                         log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin);
154168ae4117SEnrico Granata                                 }
1542c3e320a7SEnrico Granata 
15436f3533fbSEnrico Granata                                 if (*var_name_begin == 's')
15444becb37eSEnrico Granata                                 {
1545c5bc412cSEnrico Granata                                     if (!valobj->IsSynthetic())
154686cc9829SEnrico Granata                                         valobj = valobj->GetSyntheticValue().get();
154786cc9829SEnrico Granata                                     if (!valobj)
154886cc9829SEnrico Granata                                         break;
15496f3533fbSEnrico Granata                                     var_name_begin++;
1550c3e320a7SEnrico Granata                                     if (log)
155168ae4117SEnrico Granata                                         log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin);
155268ae4117SEnrico Granata                                 }
1553c3e320a7SEnrico Granata 
15546f3533fbSEnrico Granata                                 // should be a 'v' by now
15556f3533fbSEnrico Granata                                 if (*var_name_begin != 'v')
15566f3533fbSEnrico Granata                                     break;
15576f3533fbSEnrico Granata 
1558c3e320a7SEnrico Granata                                 if (log)
155968ae4117SEnrico Granata                                     log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin);
1560c3e320a7SEnrico Granata 
1561fc7a7f3bSEnrico Granata                                 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
156286cc9829SEnrico Granata                                                                                   ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
1563fc7a7f3bSEnrico Granata                                 ValueObject::GetValueForExpressionPathOptions options;
15648c9d3560SEnrico Granata                                 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren();
156586cc9829SEnrico Granata                                 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
156634132754SGreg Clayton                                 ValueObject* target = NULL;
15674d122c40SGreg Clayton                                 Format custom_format = eFormatInvalid;
156834132754SGreg Clayton                                 const char* var_name_final = NULL;
15699fc1944eSEnrico Granata                                 const char* var_name_final_if_array_range = NULL;
157034132754SGreg Clayton                                 const char* close_bracket_position = NULL;
157134132754SGreg Clayton                                 int64_t index_lower = -1;
157234132754SGreg Clayton                                 int64_t index_higher = -1;
15739fc1944eSEnrico Granata                                 bool is_array_range = false;
1574fc7a7f3bSEnrico Granata                                 const char* first_unparsed;
157585933ed4SEnrico Granata                                 bool was_plain_var = false;
157685933ed4SEnrico Granata                                 bool was_var_format = false;
1577a777dc2aSEnrico Granata                                 bool was_var_indexed = false;
1578fc7a7f3bSEnrico Granata 
1579c482a192SEnrico Granata                                 if (!valobj) break;
1580c482a192SEnrico Granata                                 // simplest case ${var}, just print valobj's value
15810769b2b1SMichael Sartain                                 if (IsToken (var_name_begin, "var}"))
15820a3958e0SEnrico Granata                                 {
158385933ed4SEnrico Granata                                     was_plain_var = true;
1584c482a192SEnrico Granata                                     target = valobj;
158586cc9829SEnrico Granata                                     val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
15860a3958e0SEnrico Granata                                 }
15870769b2b1SMichael Sartain                                 else if (IsToken (var_name_begin,"var%"))
15889fc1944eSEnrico Granata                                 {
158985933ed4SEnrico Granata                                     was_var_format = true;
15909fc1944eSEnrico Granata                                     // this is a variable with some custom format applied to it
15919fc1944eSEnrico Granata                                     const char* percent_position;
1592c482a192SEnrico Granata                                     target = valobj;
159386cc9829SEnrico Granata                                     val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
15949fc1944eSEnrico Granata                                     ScanFormatDescriptor (var_name_begin,
15959fc1944eSEnrico Granata                                                           var_name_end,
15969fc1944eSEnrico Granata                                                           &var_name_final,
15979fc1944eSEnrico Granata                                                           &percent_position,
15989fc1944eSEnrico Granata                                                           &custom_format,
15999fc1944eSEnrico Granata                                                           &val_obj_display);
16000a3958e0SEnrico Granata                                 }
16019fc1944eSEnrico Granata                                     // this is ${var.something} or multiple .something nested
16020769b2b1SMichael Sartain                                 else if (IsToken (var_name_begin, "var"))
16039fc1944eSEnrico Granata                                 {
16040769b2b1SMichael Sartain                                     if (IsToken (var_name_begin, "var["))
1605a777dc2aSEnrico Granata                                         was_var_indexed = true;
16069fc1944eSEnrico Granata                                     const char* percent_position;
16079fc1944eSEnrico Granata                                     ScanFormatDescriptor (var_name_begin,
16089fc1944eSEnrico Granata                                                           var_name_end,
16099fc1944eSEnrico Granata                                                           &var_name_final,
16109fc1944eSEnrico Granata                                                           &percent_position,
16119fc1944eSEnrico Granata                                                           &custom_format,
16129fc1944eSEnrico Granata                                                           &val_obj_display);
16139fc1944eSEnrico Granata 
16149fc1944eSEnrico Granata                                     const char* open_bracket_position;
16159fc1944eSEnrico Granata                                     const char* separator_position;
16169fc1944eSEnrico Granata                                     ScanBracketedRange (var_name_begin,
16179fc1944eSEnrico Granata                                                         var_name_end,
16189fc1944eSEnrico Granata                                                         var_name_final,
16199fc1944eSEnrico Granata                                                         &open_bracket_position,
16209fc1944eSEnrico Granata                                                         &separator_position,
16219fc1944eSEnrico Granata                                                         &close_bracket_position,
16229fc1944eSEnrico Granata                                                         &var_name_final_if_array_range,
16239fc1944eSEnrico Granata                                                         &index_lower,
16249fc1944eSEnrico Granata                                                         &index_higher);
16259fc1944eSEnrico Granata 
16269fc1944eSEnrico Granata                                     Error error;
16279fc1944eSEnrico Granata 
1628599171adSEnrico Granata                                     std::string expr_path(var_name_final-var_name_begin-1,0);
1629599171adSEnrico Granata                                     memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3);
1630fc7a7f3bSEnrico Granata 
1631e992a089SEnrico Granata                                     if (log)
1632599171adSEnrico Granata                                         log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str());
1633fc7a7f3bSEnrico Granata 
1634599171adSEnrico Granata                                     target = valobj->GetValueForExpressionPath(expr_path.c_str(),
1635fc7a7f3bSEnrico Granata                                                                              &first_unparsed,
1636fc7a7f3bSEnrico Granata                                                                              &reason_to_stop,
1637fc7a7f3bSEnrico Granata                                                                              &final_value_type,
1638fc7a7f3bSEnrico Granata                                                                              options,
1639fc7a7f3bSEnrico Granata                                                                              &what_next).get();
1640fc7a7f3bSEnrico Granata 
1641fc7a7f3bSEnrico Granata                                     if (!target)
16429fc1944eSEnrico Granata                                     {
1643e992a089SEnrico Granata                                         if (log)
1644d228483dSEnrico Granata                                             log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d,"
1645e992a089SEnrico Granata                                                " final_value_type %d",
1646fc7a7f3bSEnrico Granata                                                first_unparsed, reason_to_stop, final_value_type);
1647fc7a7f3bSEnrico Granata                                         break;
16480a3958e0SEnrico Granata                                     }
1649a7187d00SEnrico Granata                                     else
1650fc7a7f3bSEnrico Granata                                     {
1651e992a089SEnrico Granata                                         if (log)
1652d228483dSEnrico Granata                                             log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
1653e992a089SEnrico Granata                                                " final_value_type %d",
1654fc7a7f3bSEnrico Granata                                                first_unparsed, reason_to_stop, final_value_type);
1655a7187d00SEnrico Granata                                     }
16560a3958e0SEnrico Granata                                 }
16570a3958e0SEnrico Granata                                 else
16580a3958e0SEnrico Granata                                     break;
16599fc1944eSEnrico Granata 
166086cc9829SEnrico Granata                                 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange ||
166186cc9829SEnrico Granata                                                   final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange);
1662fc7a7f3bSEnrico Granata 
166386cc9829SEnrico Granata                                 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference);
1664fc7a7f3bSEnrico Granata 
1665a7187d00SEnrico Granata                                 if (do_deref_pointer && !is_array_range)
16660a3958e0SEnrico Granata                                 {
16679fc1944eSEnrico Granata                                     // I have not deref-ed yet, let's do it
16689fc1944eSEnrico Granata                                     // this happens when we are not going through GetValueForVariableExpressionPath
16699fc1944eSEnrico Granata                                     // to get to the target ValueObject
16709fc1944eSEnrico Granata                                     Error error;
16719fc1944eSEnrico Granata                                     target = target->Dereference(error).get();
1672dc940730SEnrico Granata                                     if (error.Fail())
1673dc940730SEnrico Granata                                     {
1674dc940730SEnrico Granata                                         if (log)
1675d228483dSEnrico Granata                                             log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \
1676dc940730SEnrico Granata                                         break;
1677dc940730SEnrico Granata                                     }
16789fc1944eSEnrico Granata                                     do_deref_pointer = false;
16790a3958e0SEnrico Granata                                 }
16800a3958e0SEnrico Granata 
1681a777dc2aSEnrico Granata                                 // we do not want to use the summary for a bitfield of type T:n
1682a777dc2aSEnrico Granata                                 // if we were originally dealing with just a T - that would get
1683a777dc2aSEnrico Granata                                 // us into an endless recursion
1684a777dc2aSEnrico Granata                                 if (target->IsBitfield() && was_var_indexed)
1685a777dc2aSEnrico Granata                                 {
1686a777dc2aSEnrico Granata                                     // TODO: check for a (T:n)-specific summary - we should still obey that
1687a777dc2aSEnrico Granata                                     StreamString bitfield_name;
1688a777dc2aSEnrico Granata                                     bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize());
1689a777dc2aSEnrico Granata                                     lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false));
1690a777dc2aSEnrico Granata                                     if (!DataVisualization::GetSummaryForType(type_sp))
1691a777dc2aSEnrico Granata                                         val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1692a777dc2aSEnrico Granata                                 }
1693a777dc2aSEnrico Granata 
169485933ed4SEnrico Granata                                 // TODO use flags for these
169557ee3067SGreg Clayton                                 const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL);
169657ee3067SGreg Clayton                                 bool is_array = (type_info_flags & ClangASTType::eTypeIsArray) != 0;
169757ee3067SGreg Clayton                                 bool is_pointer = (type_info_flags & ClangASTType::eTypeIsPointer) != 0;
169857ee3067SGreg Clayton                                 bool is_aggregate = target->GetClangType().IsAggregateType();
1699f4efecd9SEnrico Granata 
170086cc9829SEnrico Granata                                 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
1701f4efecd9SEnrico Granata                                 {
170285933ed4SEnrico Granata                                     StreamString str_temp;
1703e992a089SEnrico Granata                                     if (log)
1704d228483dSEnrico Granata                                         log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range");
1705d64d0bc0SEnrico Granata 
17065088c486SGreg Clayton                                     if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format))
1707d64d0bc0SEnrico Granata                                     {
1708f4efecd9SEnrico Granata                                         // try to use the special cases
170985933ed4SEnrico Granata                                         var_success = target->DumpPrintableRepresentation(str_temp,
171085933ed4SEnrico Granata                                                                                           val_obj_display,
171185933ed4SEnrico Granata                                                                                           custom_format);
1712e992a089SEnrico Granata                                         if (log)
1713d228483dSEnrico Granata                                             log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't");
1714d64d0bc0SEnrico Granata 
1715d64d0bc0SEnrico Granata                                         // should not happen
17165088c486SGreg Clayton                                         if (var_success)
171785933ed4SEnrico Granata                                             s << str_temp.GetData();
1718d64d0bc0SEnrico Granata                                         var_success = true;
1719d64d0bc0SEnrico Granata                                         break;
1720d64d0bc0SEnrico Granata                                     }
1721d64d0bc0SEnrico Granata                                     else
1722d64d0bc0SEnrico Granata                                     {
172388da35f8SEnrico Granata                                         if (was_plain_var) // if ${var}
1724d64d0bc0SEnrico Granata                                         {
1725d64d0bc0SEnrico Granata                                             s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
1726d64d0bc0SEnrico Granata                                         }
172788da35f8SEnrico Granata                                         else if (is_pointer) // if pointer, value is the address stored
172888da35f8SEnrico Granata                                         {
172923f59509SGreg Clayton                                             target->DumpPrintableRepresentation (s,
173088da35f8SEnrico Granata                                                                                  val_obj_display,
173186cc9829SEnrico Granata                                                                                  custom_format,
173286cc9829SEnrico Granata                                                                                  ValueObject::ePrintableRepresentationSpecialCasesDisable);
173388da35f8SEnrico Granata                                         }
1734d64d0bc0SEnrico Granata                                         var_success = true;
1735d64d0bc0SEnrico Granata                                         break;
1736d64d0bc0SEnrico Granata                                     }
1737d64d0bc0SEnrico Granata                                 }
1738d64d0bc0SEnrico Granata 
1739d64d0bc0SEnrico Granata                                 // if directly trying to print ${var}, and this is an aggregate, display a nice
1740d64d0bc0SEnrico Granata                                 // type @ location message
1741d64d0bc0SEnrico Granata                                 if (is_aggregate && was_plain_var)
1742d64d0bc0SEnrico Granata                                 {
1743d64d0bc0SEnrico Granata                                     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
1744d64d0bc0SEnrico Granata                                     var_success = true;
174585933ed4SEnrico Granata                                     break;
174685933ed4SEnrico Granata                                 }
174785933ed4SEnrico Granata 
1748d64d0bc0SEnrico Granata                                 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
174986cc9829SEnrico Granata                                 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)))
175085933ed4SEnrico Granata                                 {
175185933ed4SEnrico Granata                                     s << "<invalid use of aggregate type>";
175285933ed4SEnrico Granata                                     var_success = true;
1753f4efecd9SEnrico Granata                                     break;
1754f4efecd9SEnrico Granata                                 }
1755f4efecd9SEnrico Granata 
17569fc1944eSEnrico Granata                                 if (!is_array_range)
1757e992a089SEnrico Granata                                 {
1758e992a089SEnrico Granata                                     if (log)
1759d228483dSEnrico Granata                                         log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
17609fc1944eSEnrico Granata                                     var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
1761e992a089SEnrico Granata                                 }
17629fc1944eSEnrico Granata                                 else
17639fc1944eSEnrico Granata                                 {
1764e992a089SEnrico Granata                                     if (log)
1765d228483dSEnrico Granata                                         log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
17669fc1944eSEnrico Granata                                     if (!is_array && !is_pointer)
17679fc1944eSEnrico Granata                                         break;
1768e992a089SEnrico Granata                                     if (log)
1769d228483dSEnrico Granata                                         log->Printf("[Debugger::FormatPrompt] handle as array");
1770fc7a7f3bSEnrico Granata                                     const char* special_directions = NULL;
1771fc7a7f3bSEnrico Granata                                     StreamString special_directions_writer;
17720a3958e0SEnrico Granata                                     if (close_bracket_position && (var_name_end-close_bracket_position > 1))
17730a3958e0SEnrico Granata                                     {
1774fc7a7f3bSEnrico Granata                                         ConstString additional_data;
1775fc7a7f3bSEnrico Granata                                         additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1);
1776fc7a7f3bSEnrico Granata                                         special_directions_writer.Printf("${%svar%s}",
1777fc7a7f3bSEnrico Granata                                                                          do_deref_pointer ? "*" : "",
1778fc7a7f3bSEnrico Granata                                                                          additional_data.GetCString());
1779fc7a7f3bSEnrico Granata                                         special_directions = special_directions_writer.GetData();
17800a3958e0SEnrico Granata                                     }
17810a3958e0SEnrico Granata 
17820a3958e0SEnrico Granata                                     // let us display items index_lower thru index_higher of this array
17830a3958e0SEnrico Granata                                     s.PutChar('[');
17840a3958e0SEnrico Granata                                     var_success = true;
17850a3958e0SEnrico Granata 
17869fc1944eSEnrico Granata                                     if (index_higher < 0)
1787c482a192SEnrico Granata                                         index_higher = valobj->GetNumChildren() - 1;
17880a3958e0SEnrico Granata 
1789cc4d0146SGreg Clayton                                     uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
179022c55d18SEnrico Granata 
17910a3958e0SEnrico Granata                                     for (;index_lower<=index_higher;index_lower++)
17920a3958e0SEnrico Granata                                     {
1793fc7a7f3bSEnrico Granata                                         ValueObject* item = ExpandIndexedExpression (target,
17949fc1944eSEnrico Granata                                                                                      index_lower,
1795c14ee32dSGreg Clayton                                                                                      exe_ctx->GetFramePtr(),
1796fc7a7f3bSEnrico Granata                                                                                      false).get();
17970a3958e0SEnrico Granata 
1798fc7a7f3bSEnrico Granata                                         if (!item)
1799fc7a7f3bSEnrico Granata                                         {
1800e992a089SEnrico Granata                                             if (log)
1801d01b2953SDaniel Malea                                                 log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower);
1802fc7a7f3bSEnrico Granata                                         }
1803fc7a7f3bSEnrico Granata                                         else
1804fc7a7f3bSEnrico Granata                                         {
1805e992a089SEnrico Granata                                             if (log)
1806d228483dSEnrico Granata                                                 log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions);
1807fc7a7f3bSEnrico Granata                                         }
1808fc7a7f3bSEnrico Granata 
18090a3958e0SEnrico Granata                                         if (!special_directions)
18109fc1944eSEnrico Granata                                             var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
18110a3958e0SEnrico Granata                                         else
1812c3ce7f27SMichael Sartain                                             var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item);
18130a3958e0SEnrico Granata 
181422c55d18SEnrico Granata                                         if (--max_num_children == 0)
181522c55d18SEnrico Granata                                         {
181622c55d18SEnrico Granata                                             s.PutCString(", ...");
181722c55d18SEnrico Granata                                             break;
181822c55d18SEnrico Granata                                         }
181922c55d18SEnrico Granata 
18200a3958e0SEnrico Granata                                         if (index_lower < index_higher)
18210a3958e0SEnrico Granata                                             s.PutChar(',');
18220a3958e0SEnrico Granata                                     }
18230a3958e0SEnrico Granata                                     s.PutChar(']');
18244becb37eSEnrico Granata                                 }
18254becb37eSEnrico Granata                             }
182634132754SGreg Clayton                             break;
18271b654882SGreg Clayton                         case 'a':
18280769b2b1SMichael Sartain                             if (IsToken (var_name_begin, "addr}"))
18291b654882SGreg Clayton                             {
18301b654882SGreg Clayton                                 if (addr && addr->IsValid())
18311b654882SGreg Clayton                                 {
18321b654882SGreg Clayton                                     var_success = true;
18331b654882SGreg Clayton                                     format_addr = *addr;
18341b654882SGreg Clayton                                 }
18351b654882SGreg Clayton                             }
18361b654882SGreg Clayton                             break;
18371b654882SGreg Clayton 
18381b654882SGreg Clayton                         case 'p':
18390769b2b1SMichael Sartain                             if (IsToken (var_name_begin, "process."))
18401b654882SGreg Clayton                             {
1841c14ee32dSGreg Clayton                                 if (exe_ctx)
1842c14ee32dSGreg Clayton                                 {
1843c14ee32dSGreg Clayton                                     Process *process = exe_ctx->GetProcessPtr();
1844c14ee32dSGreg Clayton                                     if (process)
18451b654882SGreg Clayton                                     {
18461b654882SGreg Clayton                                         var_name_begin += ::strlen ("process.");
18470769b2b1SMichael Sartain                                         if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc))
18481b654882SGreg Clayton                                         {
18490769b2b1SMichael Sartain                                             s.Printf(token_format.c_str(), process->GetID());
18501b654882SGreg Clayton                                             var_success = true;
18511b654882SGreg Clayton                                         }
18520769b2b1SMichael Sartain                                         else if ((IsToken (var_name_begin, "name}")) ||
18530769b2b1SMichael Sartain                                                 (IsToken (var_name_begin, "file.basename}")) ||
18540769b2b1SMichael Sartain                                                 (IsToken (var_name_begin, "file.fullpath}")))
18551b654882SGreg Clayton                                         {
1856c14ee32dSGreg Clayton                                             Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1857aa149cbdSGreg Clayton                                             if (exe_module)
18581b654882SGreg Clayton                                             {
18591b654882SGreg Clayton                                                 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f')
18601b654882SGreg Clayton                                                 {
1861aa149cbdSGreg Clayton                                                     format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename();
18629076c0ffSSean Callanan                                                     var_success = (bool)format_file_spec;
18631b654882SGreg Clayton                                                 }
18641b654882SGreg Clayton                                                 else
18651b654882SGreg Clayton                                                 {
1866aa149cbdSGreg Clayton                                                     format_file_spec = exe_module->GetFileSpec();
18679076c0ffSSean Callanan                                                     var_success = (bool)format_file_spec;
18681b654882SGreg Clayton                                                 }
18691b654882SGreg Clayton                                             }
18701b654882SGreg Clayton                                         }
18710769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "script:"))
1872aad8e480SEnrico Granata                                         {
1873aad8e480SEnrico Granata                                             var_name_begin += ::strlen("script:");
1874aad8e480SEnrico Granata                                             std::string script_name(var_name_begin,var_name_end);
1875aad8e480SEnrico Granata                                             ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
18760769b2b1SMichael Sartain                                             if (RunScriptFormatKeyword (s, script_interpreter, process, script_name))
1877aad8e480SEnrico Granata                                                 var_success = true;
1878aad8e480SEnrico Granata                                         }
18791b654882SGreg Clayton                                     }
18801b654882SGreg Clayton                                 }
1881c14ee32dSGreg Clayton                             }
18821b654882SGreg Clayton                             break;
18831b654882SGreg Clayton 
18841b654882SGreg Clayton                         case 't':
18850769b2b1SMichael Sartain                            if (IsToken (var_name_begin, "thread."))
18861b654882SGreg Clayton                             {
1887c14ee32dSGreg Clayton                                 if (exe_ctx)
1888c14ee32dSGreg Clayton                                 {
1889c14ee32dSGreg Clayton                                     Thread *thread = exe_ctx->GetThreadPtr();
1890c14ee32dSGreg Clayton                                     if (thread)
18911b654882SGreg Clayton                                     {
18921b654882SGreg Clayton                                         var_name_begin += ::strlen ("thread.");
18930769b2b1SMichael Sartain                                         if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc))
18941b654882SGreg Clayton                                         {
18950769b2b1SMichael Sartain                                             s.Printf(token_format.c_str(), thread->GetID());
18961b654882SGreg Clayton                                             var_success = true;
18971b654882SGreg Clayton                                         }
18980769b2b1SMichael Sartain                                         else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc))
1899160c9d81SGreg Clayton                                         {
19000769b2b1SMichael Sartain                                             s.Printf(token_format.c_str(), thread->GetProtocolID());
1901160c9d81SGreg Clayton                                             var_success = true;
1902160c9d81SGreg Clayton                                         }
19030769b2b1SMichael Sartain                                         else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc))
19041b654882SGreg Clayton                                         {
19050769b2b1SMichael Sartain                                             s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID());
19061b654882SGreg Clayton                                             var_success = true;
19071b654882SGreg Clayton                                         }
19080769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "name}"))
19091b654882SGreg Clayton                                         {
1910c14ee32dSGreg Clayton                                             cstr = thread->GetName();
19111b654882SGreg Clayton                                             var_success = cstr && cstr[0];
19121b654882SGreg Clayton                                             if (var_success)
19131b654882SGreg Clayton                                                 s.PutCString(cstr);
19141b654882SGreg Clayton                                         }
19150769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "queue}"))
19161b654882SGreg Clayton                                         {
1917c14ee32dSGreg Clayton                                             cstr = thread->GetQueueName();
19181b654882SGreg Clayton                                             var_success = cstr && cstr[0];
19191b654882SGreg Clayton                                             if (var_success)
19201b654882SGreg Clayton                                                 s.PutCString(cstr);
19211b654882SGreg Clayton                                         }
19220769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "stop-reason}"))
19231b654882SGreg Clayton                                         {
1924c14ee32dSGreg Clayton                                             StopInfoSP stop_info_sp = thread->GetStopInfo ();
19255d88a068SJim Ingham                                             if (stop_info_sp && stop_info_sp->IsValid())
19261b654882SGreg Clayton                                             {
1927b15bfc75SJim Ingham                                                 cstr = stop_info_sp->GetDescription();
19281b654882SGreg Clayton                                                 if (cstr && cstr[0])
19291b654882SGreg Clayton                                                 {
19301b654882SGreg Clayton                                                     s.PutCString(cstr);
19311b654882SGreg Clayton                                                     var_success = true;
19321b654882SGreg Clayton                                                 }
19331b654882SGreg Clayton                                             }
19341b654882SGreg Clayton                                         }
19350769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "return-value}"))
193673ca05a2SJim Ingham                                         {
193773ca05a2SJim Ingham                                             StopInfoSP stop_info_sp = thread->GetStopInfo ();
19385d88a068SJim Ingham                                             if (stop_info_sp && stop_info_sp->IsValid())
193973ca05a2SJim Ingham                                             {
194073ca05a2SJim Ingham                                                 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
194173ca05a2SJim Ingham                                                 if (return_valobj_sp)
194273ca05a2SJim Ingham                                                 {
19434d93b8cdSEnrico Granata                                                     return_valobj_sp->Dump(s);
194473ca05a2SJim Ingham                                                     var_success = true;
194573ca05a2SJim Ingham                                                 }
194673ca05a2SJim Ingham                                             }
194773ca05a2SJim Ingham                                         }
19480769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "script:"))
1949aad8e480SEnrico Granata                                         {
1950aad8e480SEnrico Granata                                             var_name_begin += ::strlen("script:");
1951aad8e480SEnrico Granata                                             std::string script_name(var_name_begin,var_name_end);
1952aad8e480SEnrico Granata                                             ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
19530769b2b1SMichael Sartain                                             if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name))
1954aad8e480SEnrico Granata                                                 var_success = true;
1955aad8e480SEnrico Granata                                         }
1956aad8e480SEnrico Granata                                     }
1957aad8e480SEnrico Granata                                 }
195873ca05a2SJim Ingham                             }
19590769b2b1SMichael Sartain                             else if (IsToken (var_name_begin, "target."))
19601b654882SGreg Clayton                             {
196167cc0636SGreg Clayton                                 // TODO: hookup properties
196267cc0636SGreg Clayton //                                if (!target_properties_sp)
196367cc0636SGreg Clayton //                                {
196467cc0636SGreg Clayton //                                    Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
196567cc0636SGreg Clayton //                                    if (target)
196667cc0636SGreg Clayton //                                        target_properties_sp = target->GetProperties();
196767cc0636SGreg Clayton //                                }
196867cc0636SGreg Clayton //
196967cc0636SGreg Clayton //                                if (target_properties_sp)
197067cc0636SGreg Clayton //                                {
197167cc0636SGreg Clayton //                                    var_name_begin += ::strlen ("target.");
197267cc0636SGreg Clayton //                                    const char *end_property = strchr(var_name_begin, '}');
197367cc0636SGreg Clayton //                                    if (end_property)
197467cc0636SGreg Clayton //                                    {
197567cc0636SGreg Clayton //                                        ConstString property_name(var_name_begin, end_property - var_name_begin);
197667cc0636SGreg Clayton //                                        std::string property_value (target_properties_sp->GetPropertyValue(property_name));
197767cc0636SGreg Clayton //                                        if (!property_value.empty())
197867cc0636SGreg Clayton //                                        {
197967cc0636SGreg Clayton //                                            s.PutCString (property_value.c_str());
198067cc0636SGreg Clayton //                                            var_success = true;
198167cc0636SGreg Clayton //                                        }
198267cc0636SGreg Clayton //                                    }
198367cc0636SGreg Clayton //                                }
19840603aa9dSGreg Clayton                                 Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
19850603aa9dSGreg Clayton                                 if (target)
19861b654882SGreg Clayton                                 {
19871b654882SGreg Clayton                                     var_name_begin += ::strlen ("target.");
19880769b2b1SMichael Sartain                                     if (IsToken (var_name_begin, "arch}"))
19891b654882SGreg Clayton                                     {
19901b654882SGreg Clayton                                         ArchSpec arch (target->GetArchitecture ());
19911b654882SGreg Clayton                                         if (arch.IsValid())
19921b654882SGreg Clayton                                         {
199364195a2cSGreg Clayton                                             s.PutCString (arch.GetArchitectureName());
19941b654882SGreg Clayton                                             var_success = true;
19951b654882SGreg Clayton                                         }
19961b654882SGreg Clayton                                     }
19970769b2b1SMichael Sartain                                     else if (IsToken (var_name_begin, "script:"))
1998aad8e480SEnrico Granata                                     {
1999aad8e480SEnrico Granata                                         var_name_begin += ::strlen("script:");
2000aad8e480SEnrico Granata                                         std::string script_name(var_name_begin,var_name_end);
2001aad8e480SEnrico Granata                                         ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
20020769b2b1SMichael Sartain                                         if (RunScriptFormatKeyword (s, script_interpreter, target, script_name))
2003aad8e480SEnrico Granata                                             var_success = true;
2004aad8e480SEnrico Granata                                     }
20051b654882SGreg Clayton                                 }
20061b654882SGreg Clayton                             }
20071b654882SGreg Clayton                             break;
20081b654882SGreg Clayton 
20091b654882SGreg Clayton 
20101b654882SGreg Clayton                         case 'm':
20110769b2b1SMichael Sartain                            if (IsToken (var_name_begin, "module."))
20121b654882SGreg Clayton                             {
20130603aa9dSGreg Clayton                                 if (sc && sc->module_sp.get())
20141b654882SGreg Clayton                                 {
20150603aa9dSGreg Clayton                                     Module *module = sc->module_sp.get();
20161b654882SGreg Clayton                                     var_name_begin += ::strlen ("module.");
20171b654882SGreg Clayton 
20180769b2b1SMichael Sartain                                     if (IsToken (var_name_begin, "file."))
20191b654882SGreg Clayton                                     {
20201b654882SGreg Clayton                                         if (module->GetFileSpec())
20211b654882SGreg Clayton                                         {
20221b654882SGreg Clayton                                             var_name_begin += ::strlen ("file.");
20231b654882SGreg Clayton 
20240769b2b1SMichael Sartain                                             if (IsToken (var_name_begin, "basename}"))
20251b654882SGreg Clayton                                             {
20261b654882SGreg Clayton                                                 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename();
20279076c0ffSSean Callanan                                                 var_success = (bool)format_file_spec;
20281b654882SGreg Clayton                                             }
20290769b2b1SMichael Sartain                                             else if (IsToken (var_name_begin, "fullpath}"))
20301b654882SGreg Clayton                                             {
20311b654882SGreg Clayton                                                 format_file_spec = module->GetFileSpec();
20329076c0ffSSean Callanan                                                 var_success = (bool)format_file_spec;
20331b654882SGreg Clayton                                             }
20341b654882SGreg Clayton                                         }
20351b654882SGreg Clayton                                     }
20361b654882SGreg Clayton                                 }
20371b654882SGreg Clayton                             }
20381b654882SGreg Clayton                             break;
20391b654882SGreg Clayton 
20401b654882SGreg Clayton 
20411b654882SGreg Clayton                         case 'f':
20420769b2b1SMichael Sartain                            if (IsToken (var_name_begin, "file."))
20431b654882SGreg Clayton                             {
20441b654882SGreg Clayton                                 if (sc && sc->comp_unit != NULL)
20451b654882SGreg Clayton                                 {
20461b654882SGreg Clayton                                     var_name_begin += ::strlen ("file.");
20471b654882SGreg Clayton 
20480769b2b1SMichael Sartain                                     if (IsToken (var_name_begin, "basename}"))
20491b654882SGreg Clayton                                     {
20501b654882SGreg Clayton                                         format_file_spec.GetFilename() = sc->comp_unit->GetFilename();
20519076c0ffSSean Callanan                                         var_success = (bool)format_file_spec;
20521b654882SGreg Clayton                                     }
20530769b2b1SMichael Sartain                                     else if (IsToken (var_name_begin, "fullpath}"))
20541b654882SGreg Clayton                                     {
20551b654882SGreg Clayton                                         format_file_spec = *sc->comp_unit;
20569076c0ffSSean Callanan                                         var_success = (bool)format_file_spec;
20571b654882SGreg Clayton                                     }
20581b654882SGreg Clayton                                 }
20591b654882SGreg Clayton                             }
20600769b2b1SMichael Sartain                            else if (IsToken (var_name_begin, "frame."))
20611b654882SGreg Clayton                             {
2062c14ee32dSGreg Clayton                                 if (exe_ctx)
2063c14ee32dSGreg Clayton                                 {
2064b57e4a1bSJason Molenda                                     StackFrame *frame = exe_ctx->GetFramePtr();
2065c14ee32dSGreg Clayton                                     if (frame)
20661b654882SGreg Clayton                                     {
20671b654882SGreg Clayton                                         var_name_begin += ::strlen ("frame.");
20680769b2b1SMichael Sartain                                         if (IsToken (var_name_begin, "index}"))
20691b654882SGreg Clayton                                         {
2070c14ee32dSGreg Clayton                                             s.Printf("%u", frame->GetFrameIndex());
20711b654882SGreg Clayton                                             var_success = true;
20721b654882SGreg Clayton                                         }
20730769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "pc}"))
20741b654882SGreg Clayton                                         {
20751b654882SGreg Clayton                                             reg_kind = eRegisterKindGeneric;
20761b654882SGreg Clayton                                             reg_num = LLDB_REGNUM_GENERIC_PC;
20771b654882SGreg Clayton                                             var_success = true;
20781b654882SGreg Clayton                                         }
20790769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "sp}"))
20801b654882SGreg Clayton                                         {
20811b654882SGreg Clayton                                             reg_kind = eRegisterKindGeneric;
20821b654882SGreg Clayton                                             reg_num = LLDB_REGNUM_GENERIC_SP;
20831b654882SGreg Clayton                                             var_success = true;
20841b654882SGreg Clayton                                         }
20850769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "fp}"))
20861b654882SGreg Clayton                                         {
20871b654882SGreg Clayton                                             reg_kind = eRegisterKindGeneric;
20881b654882SGreg Clayton                                             reg_num = LLDB_REGNUM_GENERIC_FP;
20891b654882SGreg Clayton                                             var_success = true;
20901b654882SGreg Clayton                                         }
20910769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "flags}"))
20921b654882SGreg Clayton                                         {
20931b654882SGreg Clayton                                             reg_kind = eRegisterKindGeneric;
20941b654882SGreg Clayton                                             reg_num = LLDB_REGNUM_GENERIC_FLAGS;
20951b654882SGreg Clayton                                             var_success = true;
20961b654882SGreg Clayton                                         }
20970769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "reg."))
20981b654882SGreg Clayton                                         {
2099c14ee32dSGreg Clayton                                             reg_ctx = frame->GetRegisterContext().get();
21001b654882SGreg Clayton                                             if (reg_ctx)
21011b654882SGreg Clayton                                             {
21021b654882SGreg Clayton                                                 var_name_begin += ::strlen ("reg.");
21031b654882SGreg Clayton                                                 if (var_name_begin < var_name_end)
21041b654882SGreg Clayton                                                 {
21051b654882SGreg Clayton                                                     std::string reg_name (var_name_begin, var_name_end);
21061b654882SGreg Clayton                                                     reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str());
21071b654882SGreg Clayton                                                     if (reg_info)
21081b654882SGreg Clayton                                                         var_success = true;
21091b654882SGreg Clayton                                                 }
21101b654882SGreg Clayton                                             }
21111b654882SGreg Clayton                                         }
21120769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "script:"))
2113aad8e480SEnrico Granata                                         {
2114aad8e480SEnrico Granata                                             var_name_begin += ::strlen("script:");
2115aad8e480SEnrico Granata                                             std::string script_name(var_name_begin,var_name_end);
2116aad8e480SEnrico Granata                                             ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
21170769b2b1SMichael Sartain                                             if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name))
2118aad8e480SEnrico Granata                                                 var_success = true;
2119aad8e480SEnrico Granata                                         }
2120aad8e480SEnrico Granata                                     }
2121aad8e480SEnrico Granata                                 }
21221b654882SGreg Clayton                             }
21230769b2b1SMichael Sartain                             else if (IsToken (var_name_begin, "function."))
21241b654882SGreg Clayton                             {
21251b654882SGreg Clayton                                 if (sc && (sc->function != NULL || sc->symbol != NULL))
21261b654882SGreg Clayton                                 {
21271b654882SGreg Clayton                                     var_name_begin += ::strlen ("function.");
21280769b2b1SMichael Sartain                                     if (IsToken (var_name_begin, "id}"))
21291b654882SGreg Clayton                                     {
21301b654882SGreg Clayton                                         if (sc->function)
2131d01b2953SDaniel Malea                                             s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
21321b654882SGreg Clayton                                         else
21331b654882SGreg Clayton                                             s.Printf("symbol[%u]", sc->symbol->GetID());
21341b654882SGreg Clayton 
21351b654882SGreg Clayton                                         var_success = true;
21361b654882SGreg Clayton                                     }
21370769b2b1SMichael Sartain                                     else if (IsToken (var_name_begin, "name}"))
21381b654882SGreg Clayton                                     {
21391b654882SGreg Clayton                                         if (sc->function)
21401b654882SGreg Clayton                                             cstr = sc->function->GetName().AsCString (NULL);
21411b654882SGreg Clayton                                         else if (sc->symbol)
21421b654882SGreg Clayton                                             cstr = sc->symbol->GetName().AsCString (NULL);
21431b654882SGreg Clayton                                         if (cstr)
21441b654882SGreg Clayton                                         {
21451b654882SGreg Clayton                                             s.PutCString(cstr);
21460d9c9934SGreg Clayton 
21470d9c9934SGreg Clayton                                             if (sc->block)
21480d9c9934SGreg Clayton                                             {
21490d9c9934SGreg Clayton                                                 Block *inline_block = sc->block->GetContainingInlinedBlock ();
21500d9c9934SGreg Clayton                                                 if (inline_block)
21510d9c9934SGreg Clayton                                                 {
21520d9c9934SGreg Clayton                                                     const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
21530d9c9934SGreg Clayton                                                     if (inline_info)
21540d9c9934SGreg Clayton                                                     {
21550d9c9934SGreg Clayton                                                         s.PutCString(" [inlined] ");
21560d9c9934SGreg Clayton                                                         inline_info->GetName().Dump(&s);
21570d9c9934SGreg Clayton                                                     }
21580d9c9934SGreg Clayton                                                 }
21590d9c9934SGreg Clayton                                             }
21601b654882SGreg Clayton                                             var_success = true;
21611b654882SGreg Clayton                                         }
21621b654882SGreg Clayton                                     }
21630769b2b1SMichael Sartain                                     else if (IsToken (var_name_begin, "name-with-args}"))
21646d3dbf51SGreg Clayton                                     {
21656d3dbf51SGreg Clayton                                         // Print the function name with arguments in it
21666d3dbf51SGreg Clayton 
21676d3dbf51SGreg Clayton                                         if (sc->function)
21686d3dbf51SGreg Clayton                                         {
21696d3dbf51SGreg Clayton                                             var_success = true;
21706d3dbf51SGreg Clayton                                             ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
21716d3dbf51SGreg Clayton                                             cstr = sc->function->GetName().AsCString (NULL);
21726d3dbf51SGreg Clayton                                             if (cstr)
21736d3dbf51SGreg Clayton                                             {
21746d3dbf51SGreg Clayton                                                 const InlineFunctionInfo *inline_info = NULL;
21756d3dbf51SGreg Clayton                                                 VariableListSP variable_list_sp;
21766d3dbf51SGreg Clayton                                                 bool get_function_vars = true;
21776d3dbf51SGreg Clayton                                                 if (sc->block)
21786d3dbf51SGreg Clayton                                                 {
21796d3dbf51SGreg Clayton                                                     Block *inline_block = sc->block->GetContainingInlinedBlock ();
21806d3dbf51SGreg Clayton 
21816d3dbf51SGreg Clayton                                                     if (inline_block)
21826d3dbf51SGreg Clayton                                                     {
21836d3dbf51SGreg Clayton                                                         get_function_vars = false;
21846d3dbf51SGreg Clayton                                                         inline_info = sc->block->GetInlinedFunctionInfo();
21856d3dbf51SGreg Clayton                                                         if (inline_info)
21866d3dbf51SGreg Clayton                                                             variable_list_sp = inline_block->GetBlockVariableList (true);
21876d3dbf51SGreg Clayton                                                     }
21886d3dbf51SGreg Clayton                                                 }
21896d3dbf51SGreg Clayton 
21906d3dbf51SGreg Clayton                                                 if (get_function_vars)
21916d3dbf51SGreg Clayton                                                 {
21926d3dbf51SGreg Clayton                                                     variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
21936d3dbf51SGreg Clayton                                                 }
21946d3dbf51SGreg Clayton 
21956d3dbf51SGreg Clayton                                                 if (inline_info)
21966d3dbf51SGreg Clayton                                                 {
21976d3dbf51SGreg Clayton                                                     s.PutCString (cstr);
21986d3dbf51SGreg Clayton                                                     s.PutCString (" [inlined] ");
21996d3dbf51SGreg Clayton                                                     cstr = inline_info->GetName().GetCString();
22006d3dbf51SGreg Clayton                                                 }
22016d3dbf51SGreg Clayton 
22026d3dbf51SGreg Clayton                                                 VariableList args;
22036d3dbf51SGreg Clayton                                                 if (variable_list_sp)
2204cc7f9bf5SEnrico Granata                                                     variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
22056d3dbf51SGreg Clayton                                                 if (args.GetSize() > 0)
22066d3dbf51SGreg Clayton                                                 {
22076d3dbf51SGreg Clayton                                                     const char *open_paren = strchr (cstr, '(');
22086d3dbf51SGreg Clayton                                                     const char *close_paren = NULL;
22096d3dbf51SGreg Clayton                                                     if (open_paren)
2210855958caSGreg Clayton                                                     {
22110769b2b1SMichael Sartain                                                         if (IsToken (open_paren, "(anonymous namespace)"))
2212855958caSGreg Clayton                                                         {
2213855958caSGreg Clayton                                                             open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
2214855958caSGreg Clayton                                                             if (open_paren)
22156d3dbf51SGreg Clayton                                                                 close_paren = strchr (open_paren, ')');
2216855958caSGreg Clayton                                                         }
2217855958caSGreg Clayton                                                         else
2218855958caSGreg Clayton                                                             close_paren = strchr (open_paren, ')');
2219855958caSGreg Clayton                                                     }
22206d3dbf51SGreg Clayton 
22216d3dbf51SGreg Clayton                                                     if (open_paren)
22226d3dbf51SGreg Clayton                                                         s.Write(cstr, open_paren - cstr + 1);
22236d3dbf51SGreg Clayton                                                     else
22246d3dbf51SGreg Clayton                                                     {
22256d3dbf51SGreg Clayton                                                         s.PutCString (cstr);
22266d3dbf51SGreg Clayton                                                         s.PutChar ('(');
22276d3dbf51SGreg Clayton                                                     }
22285b6889b1SGreg Clayton                                                     const size_t num_args = args.GetSize();
22296d3dbf51SGreg Clayton                                                     for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
22306d3dbf51SGreg Clayton                                                     {
22316d3dbf51SGreg Clayton                                                         VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
22326d3dbf51SGreg Clayton                                                         ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
22336d3dbf51SGreg Clayton                                                         const char *var_name = var_value_sp->GetName().GetCString();
22346d3dbf51SGreg Clayton                                                         const char *var_value = var_value_sp->GetValueAsCString();
22356d3dbf51SGreg Clayton                                                         if (arg_idx > 0)
22366d3dbf51SGreg Clayton                                                             s.PutCString (", ");
22373b188b17SGreg Clayton                                                         if (var_value_sp->GetError().Success())
2238cc7f9bf5SEnrico Granata                                                         {
2239cc7f9bf5SEnrico Granata                                                             if (var_value)
22406d3dbf51SGreg Clayton                                                                 s.Printf ("%s=%s", var_name, var_value);
22413b188b17SGreg Clayton                                                             else
2242cc7f9bf5SEnrico Granata                                                                 s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
2243cc7f9bf5SEnrico Granata                                                         }
2244cc7f9bf5SEnrico Granata                                                         else
22453b188b17SGreg Clayton                                                             s.Printf ("%s=<unavailable>", var_name);
22466d3dbf51SGreg Clayton                                                     }
22476d3dbf51SGreg Clayton 
22486d3dbf51SGreg Clayton                                                     if (close_paren)
22496d3dbf51SGreg Clayton                                                         s.PutCString (close_paren);
22506d3dbf51SGreg Clayton                                                     else
22516d3dbf51SGreg Clayton                                                         s.PutChar(')');
22526d3dbf51SGreg Clayton 
22536d3dbf51SGreg Clayton                                                 }
22546d3dbf51SGreg Clayton                                                 else
22556d3dbf51SGreg Clayton                                                 {
22566d3dbf51SGreg Clayton                                                     s.PutCString(cstr);
22576d3dbf51SGreg Clayton                                                 }
22586d3dbf51SGreg Clayton                                             }
22596d3dbf51SGreg Clayton                                         }
22606d3dbf51SGreg Clayton                                         else if (sc->symbol)
22616d3dbf51SGreg Clayton                                         {
22626d3dbf51SGreg Clayton                                             cstr = sc->symbol->GetName().AsCString (NULL);
22636d3dbf51SGreg Clayton                                             if (cstr)
22646d3dbf51SGreg Clayton                                             {
22656d3dbf51SGreg Clayton                                                 s.PutCString(cstr);
22666d3dbf51SGreg Clayton                                                 var_success = true;
22676d3dbf51SGreg Clayton                                             }
22686d3dbf51SGreg Clayton                                         }
22696d3dbf51SGreg Clayton                                     }
22700769b2b1SMichael Sartain                                     else if (IsToken (var_name_begin, "addr-offset}"))
22711b654882SGreg Clayton                                     {
22721b654882SGreg Clayton                                         var_success = addr != NULL;
22731b654882SGreg Clayton                                         if (var_success)
22741b654882SGreg Clayton                                         {
22751b654882SGreg Clayton                                             format_addr = *addr;
22761b654882SGreg Clayton                                             calculate_format_addr_function_offset = true;
22771b654882SGreg Clayton                                         }
22781b654882SGreg Clayton                                     }
22790769b2b1SMichael Sartain                                     else if (IsToken (var_name_begin, "line-offset}"))
22801b654882SGreg Clayton                                     {
22811b654882SGreg Clayton                                         var_success = sc->line_entry.range.GetBaseAddress().IsValid();
22821b654882SGreg Clayton                                         if (var_success)
22831b654882SGreg Clayton                                         {
22841b654882SGreg Clayton                                             format_addr = sc->line_entry.range.GetBaseAddress();
22851b654882SGreg Clayton                                             calculate_format_addr_function_offset = true;
22861b654882SGreg Clayton                                         }
22871b654882SGreg Clayton                                     }
22880769b2b1SMichael Sartain                                     else if (IsToken (var_name_begin, "pc-offset}"))
22891b654882SGreg Clayton                                     {
2290b57e4a1bSJason Molenda                                         StackFrame *frame = exe_ctx->GetFramePtr();
2291c14ee32dSGreg Clayton                                         var_success = frame != NULL;
22921b654882SGreg Clayton                                         if (var_success)
22931b654882SGreg Clayton                                         {
2294c14ee32dSGreg Clayton                                             format_addr = frame->GetFrameCodeAddress();
22951b654882SGreg Clayton                                             calculate_format_addr_function_offset = true;
22961b654882SGreg Clayton                                         }
22971b654882SGreg Clayton                                     }
22981b654882SGreg Clayton                                 }
22991b654882SGreg Clayton                             }
23001b654882SGreg Clayton                             break;
23011b654882SGreg Clayton 
23021b654882SGreg Clayton                         case 'l':
23030769b2b1SMichael Sartain                             if (IsToken (var_name_begin, "line."))
23041b654882SGreg Clayton                             {
23051b654882SGreg Clayton                                 if (sc && sc->line_entry.IsValid())
23061b654882SGreg Clayton                                 {
23071b654882SGreg Clayton                                     var_name_begin += ::strlen ("line.");
23080769b2b1SMichael Sartain                                     if (IsToken (var_name_begin, "file."))
23091b654882SGreg Clayton                                     {
23101b654882SGreg Clayton                                         var_name_begin += ::strlen ("file.");
23111b654882SGreg Clayton 
23120769b2b1SMichael Sartain                                         if (IsToken (var_name_begin, "basename}"))
23131b654882SGreg Clayton                                         {
23141b654882SGreg Clayton                                             format_file_spec.GetFilename() = sc->line_entry.file.GetFilename();
23159076c0ffSSean Callanan                                             var_success = (bool)format_file_spec;
23161b654882SGreg Clayton                                         }
23170769b2b1SMichael Sartain                                         else if (IsToken (var_name_begin, "fullpath}"))
23181b654882SGreg Clayton                                         {
23191b654882SGreg Clayton                                             format_file_spec = sc->line_entry.file;
23209076c0ffSSean Callanan                                             var_success = (bool)format_file_spec;
23211b654882SGreg Clayton                                         }
23221b654882SGreg Clayton                                     }
23230769b2b1SMichael Sartain                                     else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc))
23241b654882SGreg Clayton                                     {
23251b654882SGreg Clayton                                         var_success = true;
23260769b2b1SMichael Sartain                                         s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line);
23271b654882SGreg Clayton                                     }
23280769b2b1SMichael Sartain                                     else if ((IsToken (var_name_begin, "start-addr}")) ||
23290769b2b1SMichael Sartain                                              (IsToken (var_name_begin, "end-addr}")))
23301b654882SGreg Clayton                                     {
23311b654882SGreg Clayton                                         var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid();
23321b654882SGreg Clayton                                         if (var_success)
23331b654882SGreg Clayton                                         {
23341b654882SGreg Clayton                                             format_addr = sc->line_entry.range.GetBaseAddress();
23351b654882SGreg Clayton                                             if (var_name_begin[0] == 'e')
23361b654882SGreg Clayton                                                 format_addr.Slide (sc->line_entry.range.GetByteSize());
23371b654882SGreg Clayton                                         }
23381b654882SGreg Clayton                                     }
23391b654882SGreg Clayton                                 }
23401b654882SGreg Clayton                             }
23411b654882SGreg Clayton                             break;
23421b654882SGreg Clayton                         }
23431b654882SGreg Clayton 
23441b654882SGreg Clayton                         if (var_success)
23451b654882SGreg Clayton                         {
23461b654882SGreg Clayton                             // If format addr is valid, then we need to print an address
23471b654882SGreg Clayton                             if (reg_num != LLDB_INVALID_REGNUM)
23481b654882SGreg Clayton                             {
2349b57e4a1bSJason Molenda                                 StackFrame *frame = exe_ctx->GetFramePtr();
23501b654882SGreg Clayton                                 // We have a register value to display...
23511b654882SGreg Clayton                                 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric)
23521b654882SGreg Clayton                                 {
2353c14ee32dSGreg Clayton                                     format_addr = frame->GetFrameCodeAddress();
23541b654882SGreg Clayton                                 }
23551b654882SGreg Clayton                                 else
23561b654882SGreg Clayton                                 {
23571b654882SGreg Clayton                                     if (reg_ctx == NULL)
2358c14ee32dSGreg Clayton                                         reg_ctx = frame->GetRegisterContext().get();
23591b654882SGreg Clayton 
23601b654882SGreg Clayton                                     if (reg_ctx)
23611b654882SGreg Clayton                                     {
23621b654882SGreg Clayton                                         if (reg_kind != kNumRegisterKinds)
23631b654882SGreg Clayton                                             reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
23641b654882SGreg Clayton                                         reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
23651b654882SGreg Clayton                                         var_success = reg_info != NULL;
23661b654882SGreg Clayton                                     }
23671b654882SGreg Clayton                                 }
23681b654882SGreg Clayton                             }
23691b654882SGreg Clayton 
23701b654882SGreg Clayton                             if (reg_info != NULL)
23711b654882SGreg Clayton                             {
23727349bd90SGreg Clayton                                 RegisterValue reg_value;
23737349bd90SGreg Clayton                                 var_success = reg_ctx->ReadRegister (reg_info, reg_value);
23747349bd90SGreg Clayton                                 if (var_success)
23751b654882SGreg Clayton                                 {
23769a8fa916SGreg Clayton                                     reg_value.Dump(&s, reg_info, false, false, eFormatDefault);
23771b654882SGreg Clayton                                 }
23781b654882SGreg Clayton                             }
23791b654882SGreg Clayton 
23801b654882SGreg Clayton                             if (format_file_spec)
23811b654882SGreg Clayton                             {
23821b654882SGreg Clayton                                 s << format_file_spec;
23831b654882SGreg Clayton                             }
23841b654882SGreg Clayton 
23851b654882SGreg Clayton                             // If format addr is valid, then we need to print an address
23861b654882SGreg Clayton                             if (format_addr.IsValid())
23871b654882SGreg Clayton                             {
23880603aa9dSGreg Clayton                                 var_success = false;
23890603aa9dSGreg Clayton 
23901b654882SGreg Clayton                                 if (calculate_format_addr_function_offset)
23911b654882SGreg Clayton                                 {
23921b654882SGreg Clayton                                     Address func_addr;
23930603aa9dSGreg Clayton 
23940603aa9dSGreg Clayton                                     if (sc)
23950603aa9dSGreg Clayton                                     {
23961b654882SGreg Clayton                                         if (sc->function)
23970d9c9934SGreg Clayton                                         {
23981b654882SGreg Clayton                                             func_addr = sc->function->GetAddressRange().GetBaseAddress();
23990d9c9934SGreg Clayton                                             if (sc->block)
24000d9c9934SGreg Clayton                                             {
24010d9c9934SGreg Clayton                                                 // Check to make sure we aren't in an inline
24020d9c9934SGreg Clayton                                                 // function. If we are, use the inline block
24030d9c9934SGreg Clayton                                                 // range that contains "format_addr" since
24040d9c9934SGreg Clayton                                                 // blocks can be discontiguous.
24050d9c9934SGreg Clayton                                                 Block *inline_block = sc->block->GetContainingInlinedBlock ();
24060d9c9934SGreg Clayton                                                 AddressRange inline_range;
24070d9c9934SGreg Clayton                                                 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range))
24080d9c9934SGreg Clayton                                                     func_addr = inline_range.GetBaseAddress();
24090d9c9934SGreg Clayton                                             }
24100d9c9934SGreg Clayton                                         }
2411e7612134SGreg Clayton                                         else if (sc->symbol && sc->symbol->ValueIsAddress())
2412e7612134SGreg Clayton                                             func_addr = sc->symbol->GetAddress();
24130603aa9dSGreg Clayton                                     }
24141b654882SGreg Clayton 
24150603aa9dSGreg Clayton                                     if (func_addr.IsValid())
24161b654882SGreg Clayton                                     {
24171b654882SGreg Clayton                                         if (func_addr.GetSection() == format_addr.GetSection())
24181b654882SGreg Clayton                                         {
24191b654882SGreg Clayton                                             addr_t func_file_addr = func_addr.GetFileAddress();
24201b654882SGreg Clayton                                             addr_t addr_file_addr = format_addr.GetFileAddress();
24211b654882SGreg Clayton                                             if (addr_file_addr > func_file_addr)
2422d01b2953SDaniel Malea                                                 s.Printf(" + %" PRIu64, addr_file_addr - func_file_addr);
24231b654882SGreg Clayton                                             else if (addr_file_addr < func_file_addr)
2424d01b2953SDaniel Malea                                                 s.Printf(" - %" PRIu64, func_file_addr - addr_file_addr);
24250603aa9dSGreg Clayton                                             var_success = true;
24261b654882SGreg Clayton                                         }
24271b654882SGreg Clayton                                         else
24280603aa9dSGreg Clayton                                         {
24290603aa9dSGreg Clayton                                             Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
24300603aa9dSGreg Clayton                                             if (target)
24310603aa9dSGreg Clayton                                             {
24320603aa9dSGreg Clayton                                                 addr_t func_load_addr = func_addr.GetLoadAddress (target);
24330603aa9dSGreg Clayton                                                 addr_t addr_load_addr = format_addr.GetLoadAddress (target);
24340603aa9dSGreg Clayton                                                 if (addr_load_addr > func_load_addr)
2435d01b2953SDaniel Malea                                                     s.Printf(" + %" PRIu64, addr_load_addr - func_load_addr);
24360603aa9dSGreg Clayton                                                 else if (addr_load_addr < func_load_addr)
2437d01b2953SDaniel Malea                                                     s.Printf(" - %" PRIu64, func_load_addr - addr_load_addr);
24380603aa9dSGreg Clayton                                                 var_success = true;
24390603aa9dSGreg Clayton                                             }
24400603aa9dSGreg Clayton                                         }
24411b654882SGreg Clayton                                     }
24421b654882SGreg Clayton                                 }
24431b654882SGreg Clayton                                 else
24441b654882SGreg Clayton                                 {
24450603aa9dSGreg Clayton                                     Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
24461b654882SGreg Clayton                                     addr_t vaddr = LLDB_INVALID_ADDRESS;
24470603aa9dSGreg Clayton                                     if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
24480603aa9dSGreg Clayton                                         vaddr = format_addr.GetLoadAddress (target);
24491b654882SGreg Clayton                                     if (vaddr == LLDB_INVALID_ADDRESS)
24501b654882SGreg Clayton                                         vaddr = format_addr.GetFileAddress ();
24511b654882SGreg Clayton 
24521b654882SGreg Clayton                                     if (vaddr != LLDB_INVALID_ADDRESS)
24530603aa9dSGreg Clayton                                     {
2454514487e8SGreg Clayton                                         int addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
245535f1a0d5SGreg Clayton                                         if (addr_width == 0)
245635f1a0d5SGreg Clayton                                             addr_width = 16;
2457d01b2953SDaniel Malea                                         s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
24580603aa9dSGreg Clayton                                         var_success = true;
24590603aa9dSGreg Clayton                                     }
24601b654882SGreg Clayton                                 }
24611b654882SGreg Clayton                             }
24621b654882SGreg Clayton                         }
24631b654882SGreg Clayton 
24641b654882SGreg Clayton                         if (var_success == false)
24651b654882SGreg Clayton                             success = false;
24661b654882SGreg Clayton                     }
24671b654882SGreg Clayton                     p = var_name_end;
24681b654882SGreg Clayton                 }
24691b654882SGreg Clayton                 else
24701b654882SGreg Clayton                     break;
24711b654882SGreg Clayton             }
24721b654882SGreg Clayton             else
24731b654882SGreg Clayton             {
24741b654882SGreg Clayton                 // We got a dollar sign with no '{' after it, it must just be a dollar sign
24751b654882SGreg Clayton                 s.PutChar(*p);
24761b654882SGreg Clayton             }
24771b654882SGreg Clayton         }
24781b654882SGreg Clayton         else if (*p == '\\')
24791b654882SGreg Clayton         {
24801b654882SGreg Clayton             ++p; // skip the slash
24811b654882SGreg Clayton             switch (*p)
24821b654882SGreg Clayton             {
24831b654882SGreg Clayton             case 'a': s.PutChar ('\a'); break;
24841b654882SGreg Clayton             case 'b': s.PutChar ('\b'); break;
24851b654882SGreg Clayton             case 'f': s.PutChar ('\f'); break;
24861b654882SGreg Clayton             case 'n': s.PutChar ('\n'); break;
24871b654882SGreg Clayton             case 'r': s.PutChar ('\r'); break;
24881b654882SGreg Clayton             case 't': s.PutChar ('\t'); break;
24891b654882SGreg Clayton             case 'v': s.PutChar ('\v'); break;
24901b654882SGreg Clayton             case '\'': s.PutChar ('\''); break;
24911b654882SGreg Clayton             case '\\': s.PutChar ('\\'); break;
24921b654882SGreg Clayton             case '0':
24931b654882SGreg Clayton                 // 1 to 3 octal chars
24941b654882SGreg Clayton                 {
24950603aa9dSGreg Clayton                     // Make a string that can hold onto the initial zero char,
24960603aa9dSGreg Clayton                     // up to 3 octal digits, and a terminating NULL.
24970603aa9dSGreg Clayton                     char oct_str[5] = { 0, 0, 0, 0, 0 };
24980603aa9dSGreg Clayton 
24990603aa9dSGreg Clayton                     int i;
25000603aa9dSGreg Clayton                     for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
25010603aa9dSGreg Clayton                         oct_str[i] = p[i];
25020603aa9dSGreg Clayton 
25030603aa9dSGreg Clayton                     // We don't want to consume the last octal character since
25040603aa9dSGreg Clayton                     // the main for loop will do this for us, so we advance p by
25050603aa9dSGreg Clayton                     // one less than i (even if i is zero)
25060603aa9dSGreg Clayton                     p += i - 1;
25070603aa9dSGreg Clayton                     unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
25080603aa9dSGreg Clayton                     if (octal_value <= UINT8_MAX)
25091b654882SGreg Clayton                     {
2510c7bece56SGreg Clayton                         s.PutChar((char)octal_value);
25111b654882SGreg Clayton                     }
25121b654882SGreg Clayton                 }
25131b654882SGreg Clayton                 break;
25141b654882SGreg Clayton 
25151b654882SGreg Clayton             case 'x':
25161b654882SGreg Clayton                 // hex number in the format
25170603aa9dSGreg Clayton                 if (isxdigit(p[1]))
25181b654882SGreg Clayton                 {
25190603aa9dSGreg Clayton                     ++p;    // Skip the 'x'
25201b654882SGreg Clayton 
25210603aa9dSGreg Clayton                     // Make a string that can hold onto two hex chars plus a
25220603aa9dSGreg Clayton                     // NULL terminator
25231b654882SGreg Clayton                     char hex_str[3] = { 0,0,0 };
25241b654882SGreg Clayton                     hex_str[0] = *p;
25250603aa9dSGreg Clayton                     if (isxdigit(p[1]))
25260603aa9dSGreg Clayton                     {
25270603aa9dSGreg Clayton                         ++p; // Skip the first of the two hex chars
25281b654882SGreg Clayton                         hex_str[1] = *p;
25290603aa9dSGreg Clayton                     }
25300603aa9dSGreg Clayton 
25311b654882SGreg Clayton                     unsigned long hex_value = strtoul (hex_str, NULL, 16);
25320603aa9dSGreg Clayton                     if (hex_value <= UINT8_MAX)
2533c7bece56SGreg Clayton                         s.PutChar ((char)hex_value);
25341b654882SGreg Clayton                 }
25351b654882SGreg Clayton                 else
25361b654882SGreg Clayton                 {
25370603aa9dSGreg Clayton                     s.PutChar('x');
25381b654882SGreg Clayton                 }
25391b654882SGreg Clayton                 break;
25401b654882SGreg Clayton 
25411b654882SGreg Clayton             default:
25420603aa9dSGreg Clayton                 // Just desensitize any other character by just printing what
25430603aa9dSGreg Clayton                 // came after the '\'
25440603aa9dSGreg Clayton                 s << *p;
25451b654882SGreg Clayton                 break;
25461b654882SGreg Clayton 
25471b654882SGreg Clayton             }
25481b654882SGreg Clayton 
25491b654882SGreg Clayton         }
25501b654882SGreg Clayton     }
25511b654882SGreg Clayton     if (end)
25521b654882SGreg Clayton         *end = p;
25531b654882SGreg Clayton     return success;
25541b654882SGreg Clayton }
25551b654882SGreg Clayton 
2556c3ce7f27SMichael Sartain bool
2557c3ce7f27SMichael Sartain Debugger::FormatPrompt
2558c3ce7f27SMichael Sartain (
2559c3ce7f27SMichael Sartain     const char *format,
2560c3ce7f27SMichael Sartain     const SymbolContext *sc,
2561c3ce7f27SMichael Sartain     const ExecutionContext *exe_ctx,
2562c3ce7f27SMichael Sartain     const Address *addr,
2563c3ce7f27SMichael Sartain     Stream &s,
2564c3ce7f27SMichael Sartain     ValueObject* valobj
2565c3ce7f27SMichael Sartain )
2566c3ce7f27SMichael Sartain {
2567c3ce7f27SMichael Sartain     bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true;
2568c3ce7f27SMichael Sartain     std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color);
2569c3ce7f27SMichael Sartain     if (format_str.length())
2570c3ce7f27SMichael Sartain         format = format_str.c_str();
2571c3ce7f27SMichael Sartain     return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj);
2572c3ce7f27SMichael Sartain }
2573c3ce7f27SMichael Sartain 
2574228063cdSJim Ingham void
2575228063cdSJim Ingham Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton)
2576228063cdSJim Ingham {
25774f02b22dSJim Ingham     // For simplicity's sake, I am not going to deal with how to close down any
25784f02b22dSJim Ingham     // open logging streams, I just redirect everything from here on out to the
25794f02b22dSJim Ingham     // callback.
2580228063cdSJim Ingham     m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton));
2581228063cdSJim Ingham }
2582228063cdSJim Ingham 
2583228063cdSJim Ingham bool
2584228063cdSJim Ingham Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream)
2585228063cdSJim Ingham {
2586228063cdSJim Ingham     Log::Callbacks log_callbacks;
2587228063cdSJim Ingham 
2588228063cdSJim Ingham     StreamSP log_stream_sp;
25899a028519SSean Callanan     if (m_log_callback_stream_sp)
2590228063cdSJim Ingham     {
2591228063cdSJim Ingham         log_stream_sp = m_log_callback_stream_sp;
2592228063cdSJim Ingham         // For now when using the callback mode you always get thread & timestamp.
2593228063cdSJim Ingham         log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
2594228063cdSJim Ingham     }
2595228063cdSJim Ingham     else if (log_file == NULL || *log_file == '\0')
2596228063cdSJim Ingham     {
259744d93782SGreg Clayton         log_stream_sp = GetOutputFile();
2598228063cdSJim Ingham     }
2599228063cdSJim Ingham     else
2600228063cdSJim Ingham     {
2601228063cdSJim Ingham         LogStreamMap::iterator pos = m_log_streams.find(log_file);
2602c1b2ccfdSGreg Clayton         if (pos != m_log_streams.end())
2603c1b2ccfdSGreg Clayton             log_stream_sp = pos->second.lock();
2604c1b2ccfdSGreg Clayton         if (!log_stream_sp)
2605228063cdSJim Ingham         {
2606228063cdSJim Ingham             log_stream_sp.reset (new StreamFile (log_file));
2607228063cdSJim Ingham             m_log_streams[log_file] = log_stream_sp;
2608228063cdSJim Ingham         }
2609228063cdSJim Ingham     }
2610228063cdSJim Ingham     assert (log_stream_sp.get());
2611228063cdSJim Ingham 
2612228063cdSJim Ingham     if (log_options == 0)
2613228063cdSJim Ingham         log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
2614228063cdSJim Ingham 
261557abc5d6SGreg Clayton     if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks))
2616228063cdSJim Ingham     {
2617228063cdSJim Ingham         log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream);
2618228063cdSJim Ingham         return true;
2619228063cdSJim Ingham     }
2620228063cdSJim Ingham     else
2621228063cdSJim Ingham     {
2622228063cdSJim Ingham         LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel));
2623228063cdSJim Ingham         if (log_channel_sp)
2624228063cdSJim Ingham         {
2625228063cdSJim Ingham             if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories))
2626228063cdSJim Ingham             {
2627228063cdSJim Ingham                 return true;
2628228063cdSJim Ingham             }
2629228063cdSJim Ingham             else
2630228063cdSJim Ingham             {
2631228063cdSJim Ingham                 error_stream.Printf ("Invalid log channel '%s'.\n", channel);
2632228063cdSJim Ingham                 return false;
2633228063cdSJim Ingham             }
2634228063cdSJim Ingham         }
2635228063cdSJim Ingham         else
2636228063cdSJim Ingham         {
2637228063cdSJim Ingham             error_stream.Printf ("Invalid log channel '%s'.\n", channel);
2638228063cdSJim Ingham             return false;
2639228063cdSJim Ingham         }
2640228063cdSJim Ingham     }
2641228063cdSJim Ingham     return false;
2642228063cdSJim Ingham }
2643228063cdSJim Ingham 
26449585fbfcSGreg Clayton SourceManager &
26459585fbfcSGreg Clayton Debugger::GetSourceManager ()
26469585fbfcSGreg Clayton {
26479585fbfcSGreg Clayton     if (m_source_manager_ap.get() == NULL)
26489585fbfcSGreg Clayton         m_source_manager_ap.reset (new SourceManager (shared_from_this()));
26499585fbfcSGreg Clayton     return *m_source_manager_ap;
26509585fbfcSGreg Clayton }
26519585fbfcSGreg Clayton 
26529585fbfcSGreg Clayton 
265344d93782SGreg Clayton 
265444d93782SGreg Clayton // This function handles events that were broadcast by the process.
265544d93782SGreg Clayton void
265644d93782SGreg Clayton Debugger::HandleBreakpointEvent (const EventSP &event_sp)
265744d93782SGreg Clayton {
265844d93782SGreg Clayton     using namespace lldb;
265944d93782SGreg Clayton     const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp);
266044d93782SGreg Clayton 
266144d93782SGreg Clayton //    if (event_type & eBreakpointEventTypeAdded
266244d93782SGreg Clayton //        || event_type & eBreakpointEventTypeRemoved
266344d93782SGreg Clayton //        || event_type & eBreakpointEventTypeEnabled
266444d93782SGreg Clayton //        || event_type & eBreakpointEventTypeDisabled
266544d93782SGreg Clayton //        || event_type & eBreakpointEventTypeCommandChanged
266644d93782SGreg Clayton //        || event_type & eBreakpointEventTypeConditionChanged
266744d93782SGreg Clayton //        || event_type & eBreakpointEventTypeIgnoreChanged
266844d93782SGreg Clayton //        || event_type & eBreakpointEventTypeLocationsResolved)
266944d93782SGreg Clayton //    {
267044d93782SGreg Clayton //        // Don't do anything about these events, since the breakpoint commands already echo these actions.
267144d93782SGreg Clayton //    }
267244d93782SGreg Clayton //
267344d93782SGreg Clayton     if (event_type & eBreakpointEventTypeLocationsAdded)
267444d93782SGreg Clayton     {
267544d93782SGreg Clayton         uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp);
267644d93782SGreg Clayton         if (num_new_locations > 0)
267744d93782SGreg Clayton         {
267844d93782SGreg Clayton             BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
267944d93782SGreg Clayton             StreamFileSP output_sp (GetOutputFile());
268044d93782SGreg Clayton             if (output_sp)
268144d93782SGreg Clayton             {
268244d93782SGreg Clayton                 output_sp->Printf("%d location%s added to breakpoint %d\n",
268344d93782SGreg Clayton                                   num_new_locations,
268444d93782SGreg Clayton                                   num_new_locations == 1 ? "" : "s",
268544d93782SGreg Clayton                                   breakpoint->GetID());
268644d93782SGreg Clayton                 RefreshTopIOHandler();
268744d93782SGreg Clayton             }
268844d93782SGreg Clayton         }
268944d93782SGreg Clayton     }
269044d93782SGreg Clayton //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
269144d93782SGreg Clayton //    {
269244d93782SGreg Clayton //        // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
269344d93782SGreg Clayton //    }
269444d93782SGreg Clayton //    else if (event_type & eBreakpointEventTypeLocationsResolved)
269544d93782SGreg Clayton //    {
269644d93782SGreg Clayton //        // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
269744d93782SGreg Clayton //    }
269844d93782SGreg Clayton }
269944d93782SGreg Clayton 
270044d93782SGreg Clayton size_t
270144d93782SGreg Clayton Debugger::GetProcessSTDOUT (Process *process, Stream *stream)
270244d93782SGreg Clayton {
270344d93782SGreg Clayton     size_t total_bytes = 0;
270444d93782SGreg Clayton     if (stream == NULL)
270544d93782SGreg Clayton         stream = GetOutputFile().get();
270644d93782SGreg Clayton 
270744d93782SGreg Clayton     if (stream)
270844d93782SGreg Clayton     {
270944d93782SGreg Clayton         //  The process has stuff waiting for stdout; get it and write it out to the appropriate place.
271044d93782SGreg Clayton         if (process == NULL)
271144d93782SGreg Clayton         {
271244d93782SGreg Clayton             TargetSP target_sp = GetTargetList().GetSelectedTarget();
271344d93782SGreg Clayton             if (target_sp)
271444d93782SGreg Clayton                 process = target_sp->GetProcessSP().get();
271544d93782SGreg Clayton         }
271644d93782SGreg Clayton         if (process)
271744d93782SGreg Clayton         {
271844d93782SGreg Clayton             Error error;
271944d93782SGreg Clayton             size_t len;
272044d93782SGreg Clayton             char stdio_buffer[1024];
272144d93782SGreg Clayton             while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
272244d93782SGreg Clayton             {
272344d93782SGreg Clayton                 stream->Write(stdio_buffer, len);
272444d93782SGreg Clayton                 total_bytes += len;
272544d93782SGreg Clayton             }
272644d93782SGreg Clayton         }
272744d93782SGreg Clayton         stream->Flush();
272844d93782SGreg Clayton     }
272944d93782SGreg Clayton     return total_bytes;
273044d93782SGreg Clayton }
273144d93782SGreg Clayton 
273244d93782SGreg Clayton size_t
273344d93782SGreg Clayton Debugger::GetProcessSTDERR (Process *process, Stream *stream)
273444d93782SGreg Clayton {
273544d93782SGreg Clayton     size_t total_bytes = 0;
273644d93782SGreg Clayton     if (stream == NULL)
273744d93782SGreg Clayton         stream = GetOutputFile().get();
273844d93782SGreg Clayton 
273944d93782SGreg Clayton     if (stream)
274044d93782SGreg Clayton     {
274144d93782SGreg Clayton         //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
274244d93782SGreg Clayton         if (process == NULL)
274344d93782SGreg Clayton         {
274444d93782SGreg Clayton             TargetSP target_sp = GetTargetList().GetSelectedTarget();
274544d93782SGreg Clayton             if (target_sp)
274644d93782SGreg Clayton                 process = target_sp->GetProcessSP().get();
274744d93782SGreg Clayton         }
274844d93782SGreg Clayton         if (process)
274944d93782SGreg Clayton         {
275044d93782SGreg Clayton             Error error;
275144d93782SGreg Clayton             size_t len;
275244d93782SGreg Clayton             char stdio_buffer[1024];
275344d93782SGreg Clayton             while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
275444d93782SGreg Clayton             {
275544d93782SGreg Clayton                 stream->Write(stdio_buffer, len);
275644d93782SGreg Clayton                 total_bytes += len;
275744d93782SGreg Clayton             }
275844d93782SGreg Clayton         }
275944d93782SGreg Clayton         stream->Flush();
276044d93782SGreg Clayton     }
276144d93782SGreg Clayton     return total_bytes;
276244d93782SGreg Clayton }
276344d93782SGreg Clayton 
276444d93782SGreg Clayton // This function handles events that were broadcast by the process.
276544d93782SGreg Clayton void
276644d93782SGreg Clayton Debugger::HandleProcessEvent (const EventSP &event_sp)
276744d93782SGreg Clayton {
276844d93782SGreg Clayton     using namespace lldb;
276944d93782SGreg Clayton     const uint32_t event_type = event_sp->GetType();
277044d93782SGreg Clayton     ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
277144d93782SGreg Clayton 
277244d93782SGreg Clayton     const bool gui_enabled = IsForwardingEvents();
277344d93782SGreg Clayton     bool top_io_handler_hid = false;
277444d93782SGreg Clayton     if (gui_enabled == false)
277544d93782SGreg Clayton         top_io_handler_hid = HideTopIOHandler();
277644d93782SGreg Clayton 
277744d93782SGreg Clayton     assert (process_sp);
277844d93782SGreg Clayton 
277944d93782SGreg Clayton     if (event_type & Process::eBroadcastBitSTDOUT)
278044d93782SGreg Clayton     {
278144d93782SGreg Clayton         // The process has stdout available, get it and write it out to the
278244d93782SGreg Clayton         // appropriate place.
278344d93782SGreg Clayton         if (top_io_handler_hid)
278444d93782SGreg Clayton             GetProcessSTDOUT (process_sp.get(), NULL);
278544d93782SGreg Clayton     }
278644d93782SGreg Clayton     else if (event_type & Process::eBroadcastBitSTDERR)
278744d93782SGreg Clayton     {
278844d93782SGreg Clayton         // The process has stderr available, get it and write it out to the
278944d93782SGreg Clayton         // appropriate place.
279044d93782SGreg Clayton         if (top_io_handler_hid)
279144d93782SGreg Clayton             GetProcessSTDERR (process_sp.get(), NULL);
279244d93782SGreg Clayton     }
279344d93782SGreg Clayton     else if (event_type & Process::eBroadcastBitStateChanged)
279444d93782SGreg Clayton     {
279544d93782SGreg Clayton         // Drain all stout and stderr so we don't see any output come after
279644d93782SGreg Clayton         // we print our prompts
279744d93782SGreg Clayton         if (top_io_handler_hid)
279844d93782SGreg Clayton         {
279944d93782SGreg Clayton             StreamFileSP stream_sp (GetOutputFile());
280044d93782SGreg Clayton             GetProcessSTDOUT (process_sp.get(), stream_sp.get());
280144d93782SGreg Clayton             GetProcessSTDERR (process_sp.get(), NULL);
280244d93782SGreg Clayton             // Something changed in the process;  get the event and report the process's current status and location to
280344d93782SGreg Clayton             // the user.
280444d93782SGreg Clayton             StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get());
280544d93782SGreg Clayton             if (event_state == eStateInvalid)
280644d93782SGreg Clayton                 return;
280744d93782SGreg Clayton 
280844d93782SGreg Clayton             switch (event_state)
280944d93782SGreg Clayton             {
281044d93782SGreg Clayton                 case eStateInvalid:
281144d93782SGreg Clayton                 case eStateUnloaded:
281244d93782SGreg Clayton                 case eStateConnected:
281344d93782SGreg Clayton                 case eStateAttaching:
281444d93782SGreg Clayton                 case eStateLaunching:
281544d93782SGreg Clayton                 case eStateStepping:
281644d93782SGreg Clayton                 case eStateDetached:
281744d93782SGreg Clayton                     {
281844d93782SGreg Clayton                         stream_sp->Printf("Process %" PRIu64 " %s\n",
281944d93782SGreg Clayton                                           process_sp->GetID(),
282044d93782SGreg Clayton                                           StateAsCString (event_state));
282144d93782SGreg Clayton                     }
282244d93782SGreg Clayton                     break;
282344d93782SGreg Clayton 
282444d93782SGreg Clayton                 case eStateRunning:
282544d93782SGreg Clayton                     // Don't be chatty when we run...
282644d93782SGreg Clayton                     break;
282744d93782SGreg Clayton 
282844d93782SGreg Clayton                 case eStateExited:
282944d93782SGreg Clayton                     process_sp->GetStatus(*stream_sp);
283044d93782SGreg Clayton                     break;
283144d93782SGreg Clayton 
283244d93782SGreg Clayton                 case eStateStopped:
283344d93782SGreg Clayton                 case eStateCrashed:
283444d93782SGreg Clayton                 case eStateSuspended:
283544d93782SGreg Clayton                     // Make sure the program hasn't been auto-restarted:
283644d93782SGreg Clayton                     if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get()))
283744d93782SGreg Clayton                     {
283844d93782SGreg Clayton                         size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get());
283944d93782SGreg Clayton                         if (num_reasons > 0)
284044d93782SGreg Clayton                         {
284144d93782SGreg Clayton                             // FIXME: Do we want to report this, or would that just be annoyingly chatty?
284244d93782SGreg Clayton                             if (num_reasons == 1)
284344d93782SGreg Clayton                             {
284444d93782SGreg Clayton                                 const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0);
284544d93782SGreg Clayton                                 stream_sp->Printf("Process %" PRIu64 " stopped and restarted: %s\n",
284644d93782SGreg Clayton                                                   process_sp->GetID(),
284744d93782SGreg Clayton                                                   reason ? reason : "<UNKNOWN REASON>");
284844d93782SGreg Clayton                             }
284944d93782SGreg Clayton                             else
285044d93782SGreg Clayton                             {
285144d93782SGreg Clayton                                 stream_sp->Printf("Process %" PRIu64 " stopped and restarted, reasons:\n",
285244d93782SGreg Clayton                                                    process_sp->GetID());
285344d93782SGreg Clayton 
285444d93782SGreg Clayton 
285544d93782SGreg Clayton                                 for (size_t i = 0; i < num_reasons; i++)
285644d93782SGreg Clayton                                 {
285744d93782SGreg Clayton                                     const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i);
285844d93782SGreg Clayton                                     stream_sp->Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>");
285944d93782SGreg Clayton                                 }
286044d93782SGreg Clayton                             }
286144d93782SGreg Clayton                         }
286244d93782SGreg Clayton                     }
286344d93782SGreg Clayton                     else
286444d93782SGreg Clayton                     {
286544d93782SGreg Clayton                         // Lock the thread list so it doesn't change on us
286644d93782SGreg Clayton                         ThreadList &thread_list = process_sp->GetThreadList();
286744d93782SGreg Clayton                         Mutex::Locker locker (thread_list.GetMutex());
286844d93782SGreg Clayton 
286944d93782SGreg Clayton                         ThreadSP curr_thread (thread_list.GetSelectedThread());
287044d93782SGreg Clayton                         ThreadSP thread;
287144d93782SGreg Clayton                         StopReason curr_thread_stop_reason = eStopReasonInvalid;
287244d93782SGreg Clayton                         if (curr_thread)
287344d93782SGreg Clayton                             curr_thread_stop_reason = curr_thread->GetStopReason();
2874*c809cbcfSGreg Clayton                         if (!curr_thread ||
2875*c809cbcfSGreg Clayton                             !curr_thread->IsValid() ||
287644d93782SGreg Clayton                             curr_thread_stop_reason == eStopReasonInvalid ||
287744d93782SGreg Clayton                             curr_thread_stop_reason == eStopReasonNone)
287844d93782SGreg Clayton                         {
287944d93782SGreg Clayton                             // Prefer a thread that has just completed its plan over another thread as current thread.
288044d93782SGreg Clayton                             ThreadSP plan_thread;
288144d93782SGreg Clayton                             ThreadSP other_thread;
288244d93782SGreg Clayton                             const size_t num_threads = thread_list.GetSize();
288344d93782SGreg Clayton                             size_t i;
288444d93782SGreg Clayton                             for (i = 0; i < num_threads; ++i)
288544d93782SGreg Clayton                             {
288644d93782SGreg Clayton                                 thread = thread_list.GetThreadAtIndex(i);
288744d93782SGreg Clayton                                 StopReason thread_stop_reason = thread->GetStopReason();
288844d93782SGreg Clayton                                 switch (thread_stop_reason)
288944d93782SGreg Clayton                                 {
289044d93782SGreg Clayton                                     case eStopReasonInvalid:
289144d93782SGreg Clayton                                     case eStopReasonNone:
289244d93782SGreg Clayton                                         break;
289344d93782SGreg Clayton 
289444d93782SGreg Clayton                                     case eStopReasonTrace:
289544d93782SGreg Clayton                                     case eStopReasonBreakpoint:
289644d93782SGreg Clayton                                     case eStopReasonWatchpoint:
289744d93782SGreg Clayton                                     case eStopReasonSignal:
289844d93782SGreg Clayton                                     case eStopReasonException:
289944d93782SGreg Clayton                                     case eStopReasonExec:
290044d93782SGreg Clayton                                     case eStopReasonThreadExiting:
290144d93782SGreg Clayton                                         if (!other_thread)
290244d93782SGreg Clayton                                             other_thread = thread;
290344d93782SGreg Clayton                                         break;
290444d93782SGreg Clayton                                     case eStopReasonPlanComplete:
290544d93782SGreg Clayton                                         if (!plan_thread)
290644d93782SGreg Clayton                                             plan_thread = thread;
290744d93782SGreg Clayton                                         break;
290844d93782SGreg Clayton                                 }
290944d93782SGreg Clayton                             }
291044d93782SGreg Clayton                             if (plan_thread)
291144d93782SGreg Clayton                                 thread_list.SetSelectedThreadByID (plan_thread->GetID());
291244d93782SGreg Clayton                             else if (other_thread)
291344d93782SGreg Clayton                                 thread_list.SetSelectedThreadByID (other_thread->GetID());
291444d93782SGreg Clayton                             else
291544d93782SGreg Clayton                             {
291644d93782SGreg Clayton                                 if (curr_thread->IsValid())
291744d93782SGreg Clayton                                     thread = curr_thread;
291844d93782SGreg Clayton                                 else
291944d93782SGreg Clayton                                     thread = thread_list.GetThreadAtIndex(0);
292044d93782SGreg Clayton 
292144d93782SGreg Clayton                                 if (thread)
292244d93782SGreg Clayton                                     thread_list.SetSelectedThreadByID (thread->GetID());
292344d93782SGreg Clayton                             }
292444d93782SGreg Clayton                         }
292544d93782SGreg Clayton 
292644d93782SGreg Clayton                         if (GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget())
292744d93782SGreg Clayton                         {
292844d93782SGreg Clayton                             const bool only_threads_with_stop_reason = true;
292944d93782SGreg Clayton                             const uint32_t start_frame = 0;
293044d93782SGreg Clayton                             const uint32_t num_frames = 1;
293144d93782SGreg Clayton                             const uint32_t num_frames_with_source = 1;
293244d93782SGreg Clayton                             process_sp->GetStatus(*stream_sp);
293344d93782SGreg Clayton                             process_sp->GetThreadStatus (*stream_sp,
293444d93782SGreg Clayton                                                          only_threads_with_stop_reason,
293544d93782SGreg Clayton                                                          start_frame,
293644d93782SGreg Clayton                                                          num_frames,
293744d93782SGreg Clayton                                                          num_frames_with_source);
293844d93782SGreg Clayton                         }
293944d93782SGreg Clayton                         else
294044d93782SGreg Clayton                         {
294144d93782SGreg Clayton                             uint32_t target_idx = GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this());
294244d93782SGreg Clayton                             if (target_idx != UINT32_MAX)
294344d93782SGreg Clayton                                 stream_sp->Printf ("Target %d: (", target_idx);
294444d93782SGreg Clayton                             else
294544d93782SGreg Clayton                                 stream_sp->Printf ("Target <unknown index>: (");
294644d93782SGreg Clayton                             process_sp->GetTarget().Dump (stream_sp.get(), eDescriptionLevelBrief);
294744d93782SGreg Clayton                             stream_sp->Printf (") stopped.\n");
294844d93782SGreg Clayton                         }
294944d93782SGreg Clayton                     }
295044d93782SGreg Clayton                     break;
295144d93782SGreg Clayton             }
295244d93782SGreg Clayton         }
295344d93782SGreg Clayton     }
295444d93782SGreg Clayton 
295544d93782SGreg Clayton     if (top_io_handler_hid)
295644d93782SGreg Clayton         RefreshTopIOHandler();
295744d93782SGreg Clayton }
295844d93782SGreg Clayton 
295944d93782SGreg Clayton void
296044d93782SGreg Clayton Debugger::HandleThreadEvent (const EventSP &event_sp)
296144d93782SGreg Clayton {
296244d93782SGreg Clayton     // At present the only thread event we handle is the Frame Changed event,
296344d93782SGreg Clayton     // and all we do for that is just reprint the thread status for that thread.
296444d93782SGreg Clayton     using namespace lldb;
296544d93782SGreg Clayton     const uint32_t event_type = event_sp->GetType();
296644d93782SGreg Clayton     if (event_type == Thread::eBroadcastBitStackChanged   ||
296744d93782SGreg Clayton         event_type == Thread::eBroadcastBitThreadSelected )
296844d93782SGreg Clayton     {
296944d93782SGreg Clayton         ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get()));
297044d93782SGreg Clayton         if (thread_sp)
297144d93782SGreg Clayton         {
297244d93782SGreg Clayton             HideTopIOHandler();
297344d93782SGreg Clayton             StreamFileSP stream_sp (GetOutputFile());
297444d93782SGreg Clayton             thread_sp->GetStatus(*stream_sp, 0, 1, 1);
297544d93782SGreg Clayton             RefreshTopIOHandler();
297644d93782SGreg Clayton         }
297744d93782SGreg Clayton     }
297844d93782SGreg Clayton }
297944d93782SGreg Clayton 
298044d93782SGreg Clayton bool
298144d93782SGreg Clayton Debugger::IsForwardingEvents ()
298244d93782SGreg Clayton {
298344d93782SGreg Clayton     return (bool)m_forward_listener_sp;
298444d93782SGreg Clayton }
298544d93782SGreg Clayton 
298644d93782SGreg Clayton void
298744d93782SGreg Clayton Debugger::EnableForwardEvents (const ListenerSP &listener_sp)
298844d93782SGreg Clayton {
298944d93782SGreg Clayton     m_forward_listener_sp = listener_sp;
299044d93782SGreg Clayton }
299144d93782SGreg Clayton 
299244d93782SGreg Clayton void
299344d93782SGreg Clayton Debugger::CancelForwardEvents (const ListenerSP &listener_sp)
299444d93782SGreg Clayton {
299544d93782SGreg Clayton     m_forward_listener_sp.reset();
299644d93782SGreg Clayton }
299744d93782SGreg Clayton 
299844d93782SGreg Clayton 
299944d93782SGreg Clayton void
300044d93782SGreg Clayton Debugger::DefaultEventHandler()
300144d93782SGreg Clayton {
300244d93782SGreg Clayton     Listener& listener(GetListener());
300344d93782SGreg Clayton     ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
300444d93782SGreg Clayton     ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
300544d93782SGreg Clayton     ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
300644d93782SGreg Clayton     BroadcastEventSpec target_event_spec (broadcaster_class_target,
300744d93782SGreg Clayton                                           Target::eBroadcastBitBreakpointChanged);
300844d93782SGreg Clayton 
300944d93782SGreg Clayton     BroadcastEventSpec process_event_spec (broadcaster_class_process,
301044d93782SGreg Clayton                                            Process::eBroadcastBitStateChanged   |
301144d93782SGreg Clayton                                            Process::eBroadcastBitSTDOUT         |
301244d93782SGreg Clayton                                            Process::eBroadcastBitSTDERR);
301344d93782SGreg Clayton 
301444d93782SGreg Clayton     BroadcastEventSpec thread_event_spec (broadcaster_class_thread,
301544d93782SGreg Clayton                                           Thread::eBroadcastBitStackChanged     |
301644d93782SGreg Clayton                                           Thread::eBroadcastBitThreadSelected   );
301744d93782SGreg Clayton 
301844d93782SGreg Clayton     listener.StartListeningForEventSpec (*this, target_event_spec);
301944d93782SGreg Clayton     listener.StartListeningForEventSpec (*this, process_event_spec);
302044d93782SGreg Clayton     listener.StartListeningForEventSpec (*this, thread_event_spec);
302144d93782SGreg Clayton     listener.StartListeningForEvents (m_command_interpreter_ap.get(),
302244d93782SGreg Clayton                                       CommandInterpreter::eBroadcastBitQuitCommandReceived      |
302344d93782SGreg Clayton                                       CommandInterpreter::eBroadcastBitAsynchronousOutputData   |
302444d93782SGreg Clayton                                       CommandInterpreter::eBroadcastBitAsynchronousErrorData    );
302544d93782SGreg Clayton 
302644d93782SGreg Clayton     bool done = false;
302744d93782SGreg Clayton     while (!done)
302844d93782SGreg Clayton     {
302944d93782SGreg Clayton //        Mutex::Locker locker;
303044d93782SGreg Clayton //        if (locker.TryLock(m_input_reader_stack.GetMutex()))
303144d93782SGreg Clayton //        {
303244d93782SGreg Clayton //            if (m_input_reader_stack.IsEmpty())
303344d93782SGreg Clayton //                break;
303444d93782SGreg Clayton //        }
303544d93782SGreg Clayton //
303644d93782SGreg Clayton         EventSP event_sp;
303744d93782SGreg Clayton         if (listener.WaitForEvent(NULL, event_sp))
303844d93782SGreg Clayton         {
303944d93782SGreg Clayton             if (event_sp)
304044d93782SGreg Clayton             {
304144d93782SGreg Clayton                 Broadcaster *broadcaster = event_sp->GetBroadcaster();
304244d93782SGreg Clayton                 if (broadcaster)
304344d93782SGreg Clayton                 {
304444d93782SGreg Clayton                     uint32_t event_type = event_sp->GetType();
304544d93782SGreg Clayton                     ConstString broadcaster_class (broadcaster->GetBroadcasterClass());
304644d93782SGreg Clayton                     if (broadcaster_class == broadcaster_class_process)
304744d93782SGreg Clayton                     {
304844d93782SGreg Clayton                         HandleProcessEvent (event_sp);
304944d93782SGreg Clayton                     }
305044d93782SGreg Clayton                     else if (broadcaster_class == broadcaster_class_target)
305144d93782SGreg Clayton                     {
305244d93782SGreg Clayton                         if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get()))
305344d93782SGreg Clayton                         {
305444d93782SGreg Clayton                             HandleBreakpointEvent (event_sp);
305544d93782SGreg Clayton                         }
305644d93782SGreg Clayton                     }
305744d93782SGreg Clayton                     else if (broadcaster_class == broadcaster_class_thread)
305844d93782SGreg Clayton                     {
305944d93782SGreg Clayton                         HandleThreadEvent (event_sp);
306044d93782SGreg Clayton                     }
306144d93782SGreg Clayton                     else if (broadcaster == m_command_interpreter_ap.get())
306244d93782SGreg Clayton                     {
306344d93782SGreg Clayton                         if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived)
306444d93782SGreg Clayton                         {
306544d93782SGreg Clayton                             done = true;
306644d93782SGreg Clayton                         }
306744d93782SGreg Clayton                         else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData)
306844d93782SGreg Clayton                         {
306944d93782SGreg Clayton                             const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get()));
307044d93782SGreg Clayton                             if (data && data[0])
307144d93782SGreg Clayton                             {
307244d93782SGreg Clayton                                 StreamFileSP error_sp (GetErrorFile());
307344d93782SGreg Clayton                                 if (error_sp)
307444d93782SGreg Clayton                                 {
307544d93782SGreg Clayton                                     HideTopIOHandler();
307644d93782SGreg Clayton                                     error_sp->PutCString(data);
307744d93782SGreg Clayton                                     error_sp->Flush();
307844d93782SGreg Clayton                                     RefreshTopIOHandler();
307944d93782SGreg Clayton                                 }
308044d93782SGreg Clayton                             }
308144d93782SGreg Clayton                         }
308244d93782SGreg Clayton                         else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData)
308344d93782SGreg Clayton                         {
308444d93782SGreg Clayton                             const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get()));
308544d93782SGreg Clayton                             if (data && data[0])
308644d93782SGreg Clayton                             {
308744d93782SGreg Clayton                                 StreamFileSP output_sp (GetOutputFile());
308844d93782SGreg Clayton                                 if (output_sp)
308944d93782SGreg Clayton                                 {
309044d93782SGreg Clayton                                     HideTopIOHandler();
309144d93782SGreg Clayton                                     output_sp->PutCString(data);
309244d93782SGreg Clayton                                     output_sp->Flush();
309344d93782SGreg Clayton                                     RefreshTopIOHandler();
309444d93782SGreg Clayton                                 }
309544d93782SGreg Clayton                             }
309644d93782SGreg Clayton                         }
309744d93782SGreg Clayton                     }
309844d93782SGreg Clayton                 }
309944d93782SGreg Clayton 
310044d93782SGreg Clayton                 if (m_forward_listener_sp)
310144d93782SGreg Clayton                     m_forward_listener_sp->AddEvent(event_sp);
310244d93782SGreg Clayton             }
310344d93782SGreg Clayton         }
310444d93782SGreg Clayton     }
310544d93782SGreg Clayton }
310644d93782SGreg Clayton 
310744d93782SGreg Clayton lldb::thread_result_t
310844d93782SGreg Clayton Debugger::EventHandlerThread (lldb::thread_arg_t arg)
310944d93782SGreg Clayton {
311044d93782SGreg Clayton     ((Debugger *)arg)->DefaultEventHandler();
311144d93782SGreg Clayton     return NULL;
311244d93782SGreg Clayton }
311344d93782SGreg Clayton 
311444d93782SGreg Clayton bool
311544d93782SGreg Clayton Debugger::StartEventHandlerThread()
311644d93782SGreg Clayton {
311744d93782SGreg Clayton     if (!IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread))
311844d93782SGreg Clayton         m_event_handler_thread = Host::ThreadCreate("lldb.debugger.event-handler", EventHandlerThread, this, NULL);
311944d93782SGreg Clayton     return IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread);
312044d93782SGreg Clayton }
312144d93782SGreg Clayton 
312244d93782SGreg Clayton void
312344d93782SGreg Clayton Debugger::StopEventHandlerThread()
312444d93782SGreg Clayton {
312544d93782SGreg Clayton     if (IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread))
312644d93782SGreg Clayton     {
312744d93782SGreg Clayton         GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived);
312844d93782SGreg Clayton         Host::ThreadJoin(m_event_handler_thread, NULL, NULL);
312944d93782SGreg Clayton         m_event_handler_thread = LLDB_INVALID_HOST_THREAD;
313044d93782SGreg Clayton     }
313144d93782SGreg Clayton }
313244d93782SGreg Clayton 
313344d93782SGreg Clayton 
313444d93782SGreg Clayton lldb::thread_result_t
313544d93782SGreg Clayton Debugger::IOHandlerThread (lldb::thread_arg_t arg)
313644d93782SGreg Clayton {
313744d93782SGreg Clayton     Debugger *debugger = (Debugger *)arg;
313844d93782SGreg Clayton     debugger->ExecuteIOHanders();
313944d93782SGreg Clayton     debugger->StopEventHandlerThread();
314044d93782SGreg Clayton     return NULL;
314144d93782SGreg Clayton }
314244d93782SGreg Clayton 
314344d93782SGreg Clayton bool
314444d93782SGreg Clayton Debugger::StartIOHandlerThread()
314544d93782SGreg Clayton {
314644d93782SGreg Clayton     if (!IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread))
314744d93782SGreg Clayton         m_io_handler_thread = Host::ThreadCreate("lldb.debugger.io-handler", IOHandlerThread, this, NULL);
314844d93782SGreg Clayton     return IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread);
314944d93782SGreg Clayton }
315044d93782SGreg Clayton 
315144d93782SGreg Clayton void
315244d93782SGreg Clayton Debugger::StopIOHandlerThread()
315344d93782SGreg Clayton {
315444d93782SGreg Clayton     if (IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread))
315544d93782SGreg Clayton     {
315644d93782SGreg Clayton         if (m_input_file_sp)
315744d93782SGreg Clayton             m_input_file_sp->GetFile().Close();
315844d93782SGreg Clayton         Host::ThreadJoin(m_io_handler_thread, NULL, NULL);
315944d93782SGreg Clayton         m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
316044d93782SGreg Clayton     }
316144d93782SGreg Clayton }
316244d93782SGreg Clayton 
316344d93782SGreg Clayton 
3164