15ffd83dbSDimitry Andric //===-- FormatEntity.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/FormatEntity.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Address.h"
120b57cec5SDimitry Andric #include "lldb/Core/AddressRange.h"
130b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
140b57cec5SDimitry Andric #include "lldb/Core/DumpRegisterValue.h"
150b57cec5SDimitry Andric #include "lldb/Core/Module.h"
160b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
170b57cec5SDimitry Andric #include "lldb/Core/ValueObjectVariable.h"
180b57cec5SDimitry Andric #include "lldb/DataFormatters/DataVisualization.h"
190b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatClasses.h"
200b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h"
210b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
220b57cec5SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
230b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
240b57cec5SDimitry Andric #include "lldb/Symbol/Block.h"
250b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
260b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
270b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
280b57cec5SDimitry Andric #include "lldb/Symbol/LineEntry.h"
290b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
310b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h"
320b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
330b57cec5SDimitry Andric #include "lldb/Target/ExecutionContextScope.h"
340b57cec5SDimitry Andric #include "lldb/Target/Language.h"
350b57cec5SDimitry Andric #include "lldb/Target/Process.h"
360b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
370b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
380b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
390b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
400b57cec5SDimitry Andric #include "lldb/Target/Target.h"
410b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
420b57cec5SDimitry Andric #include "lldb/Utility/AnsiTerminal.h"
430b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h"
44fe6060f1SDimitry Andric #include "lldb/Utility/CompletionRequest.h"
450b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
460b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
4781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
480b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
490b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
50fe6060f1SDimitry Andric #include "lldb/Utility/Status.h"
510b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
520b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
530b57cec5SDimitry Andric #include "lldb/Utility/StringList.h"
540b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
550b57cec5SDimitry Andric #include "lldb/lldb-defines.h"
560b57cec5SDimitry Andric #include "lldb/lldb-forward.h"
570b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
580b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
590b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
60fe013be4SDimitry Andric #include "llvm/TargetParser/Triple.h"
610b57cec5SDimitry Andric 
62fe6060f1SDimitry Andric #include <cctype>
63fe6060f1SDimitry Andric #include <cinttypes>
64fe6060f1SDimitry Andric #include <cstdio>
65fe6060f1SDimitry Andric #include <cstdlib>
66fe6060f1SDimitry Andric #include <cstring>
670b57cec5SDimitry Andric #include <memory>
680b57cec5SDimitry Andric #include <type_traits>
690b57cec5SDimitry Andric #include <utility>
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric namespace lldb_private {
720b57cec5SDimitry Andric class ScriptInterpreter;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric namespace lldb_private {
750b57cec5SDimitry Andric struct RegisterInfo;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric using namespace lldb;
790b57cec5SDimitry Andric using namespace lldb_private;
800b57cec5SDimitry Andric 
81fe6060f1SDimitry Andric using Definition = lldb_private::FormatEntity::Entry::Definition;
82fe6060f1SDimitry Andric using Entry = FormatEntity::Entry;
83fe6060f1SDimitry Andric using EntryType = FormatEntity::Entry::Type;
84fe6060f1SDimitry Andric 
850b57cec5SDimitry Andric enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
860b57cec5SDimitry Andric 
87fe6060f1SDimitry Andric constexpr Definition g_string_entry[] = {
88fe6060f1SDimitry Andric     Definition("*", EntryType::ParentString)};
890b57cec5SDimitry Andric 
90fe6060f1SDimitry Andric constexpr Definition g_addr_entries[] = {
91fe6060f1SDimitry Andric     Definition("load", EntryType::AddressLoad),
92fe6060f1SDimitry Andric     Definition("file", EntryType::AddressFile)};
93fe6060f1SDimitry Andric 
94fe6060f1SDimitry Andric constexpr Definition g_file_child_entries[] = {
95fe6060f1SDimitry Andric     Definition("basename", EntryType::ParentNumber, FileKind::Basename),
96fe6060f1SDimitry Andric     Definition("dirname", EntryType::ParentNumber, FileKind::Dirname),
97fe6060f1SDimitry Andric     Definition("fullpath", EntryType::ParentNumber, FileKind::Fullpath)};
98fe6060f1SDimitry Andric 
99fe6060f1SDimitry Andric constexpr Definition g_frame_child_entries[] = {
100fe6060f1SDimitry Andric     Definition("index", EntryType::FrameIndex),
101fe6060f1SDimitry Andric     Definition("pc", EntryType::FrameRegisterPC),
102fe6060f1SDimitry Andric     Definition("fp", EntryType::FrameRegisterFP),
103fe6060f1SDimitry Andric     Definition("sp", EntryType::FrameRegisterSP),
104fe6060f1SDimitry Andric     Definition("flags", EntryType::FrameRegisterFlags),
105fe6060f1SDimitry Andric     Definition("no-debug", EntryType::FrameNoDebug),
106fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
107fe6060f1SDimitry Andric                                   g_string_entry),
108fe6060f1SDimitry Andric     Definition("is-artificial", EntryType::FrameIsArtificial),
1090b57cec5SDimitry Andric };
1100b57cec5SDimitry Andric 
111fe6060f1SDimitry Andric constexpr Definition g_function_child_entries[] = {
112fe6060f1SDimitry Andric     Definition("id", EntryType::FunctionID),
113fe6060f1SDimitry Andric     Definition("name", EntryType::FunctionName),
114fe6060f1SDimitry Andric     Definition("name-without-args", EntryType::FunctionNameNoArgs),
115fe6060f1SDimitry Andric     Definition("name-with-args", EntryType::FunctionNameWithArgs),
116fe6060f1SDimitry Andric     Definition("mangled-name", EntryType::FunctionMangledName),
117fe6060f1SDimitry Andric     Definition("addr-offset", EntryType::FunctionAddrOffset),
118fe6060f1SDimitry Andric     Definition("concrete-only-addr-offset-no-padding",
119fe6060f1SDimitry Andric                EntryType::FunctionAddrOffsetConcrete),
120fe6060f1SDimitry Andric     Definition("line-offset", EntryType::FunctionLineOffset),
121fe6060f1SDimitry Andric     Definition("pc-offset", EntryType::FunctionPCOffset),
122fe6060f1SDimitry Andric     Definition("initial-function", EntryType::FunctionInitial),
123fe6060f1SDimitry Andric     Definition("changed", EntryType::FunctionChanged),
124fe6060f1SDimitry Andric     Definition("is-optimized", EntryType::FunctionIsOptimized)};
1250b57cec5SDimitry Andric 
126fe6060f1SDimitry Andric constexpr Definition g_line_child_entries[] = {
127fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("file", EntryType::LineEntryFile,
128fe6060f1SDimitry Andric                                   g_file_child_entries),
129fe6060f1SDimitry Andric     Definition("number", EntryType::LineEntryLineNumber),
130fe6060f1SDimitry Andric     Definition("column", EntryType::LineEntryColumn),
131fe6060f1SDimitry Andric     Definition("start-addr", EntryType::LineEntryStartAddress),
132fe6060f1SDimitry Andric     Definition("end-addr", EntryType::LineEntryEndAddress),
1330b57cec5SDimitry Andric };
1340b57cec5SDimitry Andric 
135fe6060f1SDimitry Andric constexpr Definition g_module_child_entries[] = {Entry::DefinitionWithChildren(
136fe6060f1SDimitry Andric     "file", EntryType::ModuleFile, g_file_child_entries)};
1370b57cec5SDimitry Andric 
138fe6060f1SDimitry Andric constexpr Definition g_process_child_entries[] = {
139fe6060f1SDimitry Andric     Definition("id", EntryType::ProcessID),
140fe6060f1SDimitry Andric     Definition("name", EntryType::ProcessFile, FileKind::Basename),
141fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("file", EntryType::ProcessFile,
142fe6060f1SDimitry Andric                                   g_file_child_entries)};
1430b57cec5SDimitry Andric 
144fe6060f1SDimitry Andric constexpr Definition g_svar_child_entries[] = {
145fe6060f1SDimitry Andric     Definition("*", EntryType::ParentString)};
1460b57cec5SDimitry Andric 
147fe6060f1SDimitry Andric constexpr Definition g_var_child_entries[] = {
148fe6060f1SDimitry Andric     Definition("*", EntryType::ParentString)};
1490b57cec5SDimitry Andric 
150fe6060f1SDimitry Andric constexpr Definition g_thread_child_entries[] = {
151fe6060f1SDimitry Andric     Definition("id", EntryType::ThreadID),
152fe6060f1SDimitry Andric     Definition("protocol_id", EntryType::ThreadProtocolID),
153fe6060f1SDimitry Andric     Definition("index", EntryType::ThreadIndexID),
154fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("info", EntryType::ThreadInfo,
155fe6060f1SDimitry Andric                                   g_string_entry),
156fe6060f1SDimitry Andric     Definition("queue", EntryType::ThreadQueue),
157fe6060f1SDimitry Andric     Definition("name", EntryType::ThreadName),
158fe6060f1SDimitry Andric     Definition("stop-reason", EntryType::ThreadStopReason),
159fe6060f1SDimitry Andric     Definition("stop-reason-raw", EntryType::ThreadStopReasonRaw),
160fe6060f1SDimitry Andric     Definition("return-value", EntryType::ThreadReturnValue),
161fe6060f1SDimitry Andric     Definition("completed-expression", EntryType::ThreadCompletedExpression)};
1620b57cec5SDimitry Andric 
163fe6060f1SDimitry Andric constexpr Definition g_target_child_entries[] = {
164fe6060f1SDimitry Andric     Definition("arch", EntryType::TargetArch)};
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric #define _TO_STR2(_val) #_val
1670b57cec5SDimitry Andric #define _TO_STR(_val) _TO_STR2(_val)
1680b57cec5SDimitry Andric 
169fe6060f1SDimitry Andric constexpr Definition g_ansi_fg_entries[] = {
170fe6060f1SDimitry Andric     Definition("black",
1710b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
172fe6060f1SDimitry Andric     Definition("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
173fe6060f1SDimitry Andric     Definition("green",
1740b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
175fe6060f1SDimitry Andric     Definition("yellow",
1760b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
177fe6060f1SDimitry Andric     Definition("blue", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
178fe6060f1SDimitry Andric     Definition("purple",
1790b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
180fe6060f1SDimitry Andric     Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
181fe6060f1SDimitry Andric     Definition("white",
1820b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
1830b57cec5SDimitry Andric };
1840b57cec5SDimitry Andric 
185fe6060f1SDimitry Andric constexpr Definition g_ansi_bg_entries[] = {
186fe6060f1SDimitry Andric     Definition("black",
1870b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
188fe6060f1SDimitry Andric     Definition("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
189fe6060f1SDimitry Andric     Definition("green",
1900b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
191fe6060f1SDimitry Andric     Definition("yellow",
1920b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
193fe6060f1SDimitry Andric     Definition("blue", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
194fe6060f1SDimitry Andric     Definition("purple",
1950b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
196fe6060f1SDimitry Andric     Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
197fe6060f1SDimitry Andric     Definition("white",
1980b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
1990b57cec5SDimitry Andric };
2000b57cec5SDimitry Andric 
201fe6060f1SDimitry Andric constexpr Definition g_ansi_entries[] = {
202fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("fg", EntryType::Invalid, g_ansi_fg_entries),
203fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("bg", EntryType::Invalid, g_ansi_bg_entries),
204fe6060f1SDimitry Andric     Definition("normal", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
205fe6060f1SDimitry Andric     Definition("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
206fe6060f1SDimitry Andric     Definition("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
207fe6060f1SDimitry Andric     Definition("italic", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
208fe6060f1SDimitry Andric     Definition("underline",
2090b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
210fe6060f1SDimitry Andric     Definition("slow-blink",
2110b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
212fe6060f1SDimitry Andric     Definition("fast-blink",
2130b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
214fe6060f1SDimitry Andric     Definition("negative",
2150b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
216fe6060f1SDimitry Andric     Definition("conceal",
2170b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
218fe6060f1SDimitry Andric     Definition("crossed-out",
2190b57cec5SDimitry Andric                ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
2200b57cec5SDimitry Andric };
2210b57cec5SDimitry Andric 
222fe6060f1SDimitry Andric constexpr Definition g_script_child_entries[] = {
223fe6060f1SDimitry Andric     Definition("frame", EntryType::ScriptFrame),
224fe6060f1SDimitry Andric     Definition("process", EntryType::ScriptProcess),
225fe6060f1SDimitry Andric     Definition("target", EntryType::ScriptTarget),
226fe6060f1SDimitry Andric     Definition("thread", EntryType::ScriptThread),
227fe6060f1SDimitry Andric     Definition("var", EntryType::ScriptVariable),
228fe6060f1SDimitry Andric     Definition("svar", EntryType::ScriptVariableSynthetic),
229fe6060f1SDimitry Andric     Definition("thread", EntryType::ScriptThread)};
2300b57cec5SDimitry Andric 
231fe6060f1SDimitry Andric constexpr Definition g_top_level_entries[] = {
232fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("addr", EntryType::AddressLoadOrFile,
233fe6060f1SDimitry Andric                                   g_addr_entries),
234fe6060f1SDimitry Andric     Definition("addr-file-or-load", EntryType::AddressLoadOrFile),
235fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("ansi", EntryType::Invalid, g_ansi_entries),
236fe6060f1SDimitry Andric     Definition("current-pc-arrow", EntryType::CurrentPCArrow),
237fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("file", EntryType::File,
238fe6060f1SDimitry Andric                                   g_file_child_entries),
239fe6060f1SDimitry Andric     Definition("language", EntryType::Lang),
240fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("frame", EntryType::Invalid,
241fe6060f1SDimitry Andric                                   g_frame_child_entries),
242fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("function", EntryType::Invalid,
243fe6060f1SDimitry Andric                                   g_function_child_entries),
244fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("line", EntryType::Invalid,
245fe6060f1SDimitry Andric                                   g_line_child_entries),
246fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("module", EntryType::Invalid,
247fe6060f1SDimitry Andric                                   g_module_child_entries),
248fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("process", EntryType::Invalid,
249fe6060f1SDimitry Andric                                   g_process_child_entries),
250fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("script", EntryType::Invalid,
251fe6060f1SDimitry Andric                                   g_script_child_entries),
252fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("svar", EntryType::VariableSynthetic,
253fe6060f1SDimitry Andric                                   g_svar_child_entries, true),
254fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("thread", EntryType::Invalid,
255fe6060f1SDimitry Andric                                   g_thread_child_entries),
256fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("target", EntryType::Invalid,
257fe6060f1SDimitry Andric                                   g_target_child_entries),
258fe6060f1SDimitry Andric     Entry::DefinitionWithChildren("var", EntryType::Variable,
259fe6060f1SDimitry Andric                                   g_var_child_entries, true)};
2600b57cec5SDimitry Andric 
261fe6060f1SDimitry Andric constexpr Definition g_root = Entry::DefinitionWithChildren(
262fe6060f1SDimitry Andric     "<root>", EntryType::Root, g_top_level_entries);
2630b57cec5SDimitry Andric 
Entry(llvm::StringRef s)2640b57cec5SDimitry Andric FormatEntity::Entry::Entry(llvm::StringRef s)
2650b57cec5SDimitry Andric     : string(s.data(), s.size()), printf_format(), children(),
26681ad6265SDimitry Andric       type(Type::String) {}
2670b57cec5SDimitry Andric 
Entry(char ch)2680b57cec5SDimitry Andric FormatEntity::Entry::Entry(char ch)
26981ad6265SDimitry Andric     : string(1, ch), printf_format(), children(), type(Type::String) {}
2700b57cec5SDimitry Andric 
AppendChar(char ch)2710b57cec5SDimitry Andric void FormatEntity::Entry::AppendChar(char ch) {
2720b57cec5SDimitry Andric   if (children.empty() || children.back().type != Entry::Type::String)
2730b57cec5SDimitry Andric     children.push_back(Entry(ch));
2740b57cec5SDimitry Andric   else
2750b57cec5SDimitry Andric     children.back().string.append(1, ch);
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric 
AppendText(const llvm::StringRef & s)2780b57cec5SDimitry Andric void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
2790b57cec5SDimitry Andric   if (children.empty() || children.back().type != Entry::Type::String)
2800b57cec5SDimitry Andric     children.push_back(Entry(s));
2810b57cec5SDimitry Andric   else
2820b57cec5SDimitry Andric     children.back().string.append(s.data(), s.size());
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
AppendText(const char * cstr)2850b57cec5SDimitry Andric void FormatEntity::Entry::AppendText(const char *cstr) {
2860b57cec5SDimitry Andric   return AppendText(llvm::StringRef(cstr));
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric #define ENUM_TO_CSTR(eee)                                                      \
2900b57cec5SDimitry Andric   case FormatEntity::Entry::Type::eee:                                         \
2910b57cec5SDimitry Andric     return #eee
2920b57cec5SDimitry Andric 
TypeToCString(Type t)2930b57cec5SDimitry Andric const char *FormatEntity::Entry::TypeToCString(Type t) {
2940b57cec5SDimitry Andric   switch (t) {
2950b57cec5SDimitry Andric     ENUM_TO_CSTR(Invalid);
2960b57cec5SDimitry Andric     ENUM_TO_CSTR(ParentNumber);
2970b57cec5SDimitry Andric     ENUM_TO_CSTR(ParentString);
2980b57cec5SDimitry Andric     ENUM_TO_CSTR(EscapeCode);
2990b57cec5SDimitry Andric     ENUM_TO_CSTR(Root);
3000b57cec5SDimitry Andric     ENUM_TO_CSTR(String);
3010b57cec5SDimitry Andric     ENUM_TO_CSTR(Scope);
3020b57cec5SDimitry Andric     ENUM_TO_CSTR(Variable);
3030b57cec5SDimitry Andric     ENUM_TO_CSTR(VariableSynthetic);
3040b57cec5SDimitry Andric     ENUM_TO_CSTR(ScriptVariable);
3050b57cec5SDimitry Andric     ENUM_TO_CSTR(ScriptVariableSynthetic);
3060b57cec5SDimitry Andric     ENUM_TO_CSTR(AddressLoad);
3070b57cec5SDimitry Andric     ENUM_TO_CSTR(AddressFile);
3080b57cec5SDimitry Andric     ENUM_TO_CSTR(AddressLoadOrFile);
3090b57cec5SDimitry Andric     ENUM_TO_CSTR(ProcessID);
3100b57cec5SDimitry Andric     ENUM_TO_CSTR(ProcessFile);
3110b57cec5SDimitry Andric     ENUM_TO_CSTR(ScriptProcess);
3120b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadID);
3130b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadProtocolID);
3140b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadIndexID);
3150b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadName);
3160b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadQueue);
3170b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadStopReason);
3185ffd83dbSDimitry Andric     ENUM_TO_CSTR(ThreadStopReasonRaw);
3190b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadReturnValue);
3200b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadCompletedExpression);
3210b57cec5SDimitry Andric     ENUM_TO_CSTR(ScriptThread);
3220b57cec5SDimitry Andric     ENUM_TO_CSTR(ThreadInfo);
3230b57cec5SDimitry Andric     ENUM_TO_CSTR(TargetArch);
3240b57cec5SDimitry Andric     ENUM_TO_CSTR(ScriptTarget);
3250b57cec5SDimitry Andric     ENUM_TO_CSTR(ModuleFile);
3260b57cec5SDimitry Andric     ENUM_TO_CSTR(File);
3270b57cec5SDimitry Andric     ENUM_TO_CSTR(Lang);
3280b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameIndex);
3290b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameNoDebug);
3300b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameRegisterPC);
3310b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameRegisterSP);
3320b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameRegisterFP);
3330b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameRegisterFlags);
3340b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameRegisterByName);
3350b57cec5SDimitry Andric     ENUM_TO_CSTR(FrameIsArtificial);
3360b57cec5SDimitry Andric     ENUM_TO_CSTR(ScriptFrame);
3370b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionID);
3380b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionDidChange);
3390b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionInitialFunction);
3400b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionName);
3410b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionNameWithArgs);
3420b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionNameNoArgs);
343480093f4SDimitry Andric     ENUM_TO_CSTR(FunctionMangledName);
3440b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionAddrOffset);
3450b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
3460b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionLineOffset);
3470b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionPCOffset);
3480b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionInitial);
3490b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionChanged);
3500b57cec5SDimitry Andric     ENUM_TO_CSTR(FunctionIsOptimized);
3510b57cec5SDimitry Andric     ENUM_TO_CSTR(LineEntryFile);
3520b57cec5SDimitry Andric     ENUM_TO_CSTR(LineEntryLineNumber);
3530b57cec5SDimitry Andric     ENUM_TO_CSTR(LineEntryColumn);
3540b57cec5SDimitry Andric     ENUM_TO_CSTR(LineEntryStartAddress);
3550b57cec5SDimitry Andric     ENUM_TO_CSTR(LineEntryEndAddress);
3560b57cec5SDimitry Andric     ENUM_TO_CSTR(CurrentPCArrow);
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric   return "???";
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric #undef ENUM_TO_CSTR
3620b57cec5SDimitry Andric 
Dump(Stream & s,int depth) const3630b57cec5SDimitry Andric void FormatEntity::Entry::Dump(Stream &s, int depth) const {
3640b57cec5SDimitry Andric   s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
3650b57cec5SDimitry Andric   if (fmt != eFormatDefault)
3660b57cec5SDimitry Andric     s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
3670b57cec5SDimitry Andric   if (!string.empty())
3680b57cec5SDimitry Andric     s.Printf("string = \"%s\"", string.c_str());
3690b57cec5SDimitry Andric   if (!printf_format.empty())
3700b57cec5SDimitry Andric     s.Printf("printf_format = \"%s\"", printf_format.c_str());
3710b57cec5SDimitry Andric   if (number != 0)
3720b57cec5SDimitry Andric     s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
3730b57cec5SDimitry Andric   if (deref)
3740b57cec5SDimitry Andric     s.Printf("deref = true, ");
3750b57cec5SDimitry Andric   s.EOL();
3760b57cec5SDimitry Andric   for (const auto &child : children) {
3770b57cec5SDimitry Andric     child.Dump(s, depth + 1);
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric template <typename T>
RunScriptFormatKeyword(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,T t,const char * script_function_name)3820b57cec5SDimitry Andric static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
3830b57cec5SDimitry Andric                                    const ExecutionContext *exe_ctx, T t,
3840b57cec5SDimitry Andric                                    const char *script_function_name) {
3850b57cec5SDimitry Andric   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   if (target) {
3880b57cec5SDimitry Andric     ScriptInterpreter *script_interpreter =
3890b57cec5SDimitry Andric         target->GetDebugger().GetScriptInterpreter();
3900b57cec5SDimitry Andric     if (script_interpreter) {
3910b57cec5SDimitry Andric       Status error;
3920b57cec5SDimitry Andric       std::string script_output;
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric       if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
3950b57cec5SDimitry Andric                                                      script_output, error) &&
3960b57cec5SDimitry Andric           error.Success()) {
3970b57cec5SDimitry Andric         s.Printf("%s", script_output.c_str());
3980b57cec5SDimitry Andric         return true;
3990b57cec5SDimitry Andric       } else {
4000b57cec5SDimitry Andric         s.Printf("<error: %s>", error.AsCString());
4010b57cec5SDimitry Andric       }
4020b57cec5SDimitry Andric     }
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric   return false;
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
DumpAddressAndContent(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & addr,bool print_file_addr_or_load_addr)407480093f4SDimitry Andric static bool DumpAddressAndContent(Stream &s, const SymbolContext *sc,
408480093f4SDimitry Andric                                   const ExecutionContext *exe_ctx,
409480093f4SDimitry Andric                                   const Address &addr,
4100b57cec5SDimitry Andric                                   bool print_file_addr_or_load_addr) {
4110b57cec5SDimitry Andric   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
4120b57cec5SDimitry Andric   addr_t vaddr = LLDB_INVALID_ADDRESS;
4130b57cec5SDimitry Andric   if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
4140b57cec5SDimitry Andric     vaddr = addr.GetLoadAddress(target);
4150b57cec5SDimitry Andric   if (vaddr == LLDB_INVALID_ADDRESS)
4160b57cec5SDimitry Andric     vaddr = addr.GetFileAddress();
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   if (vaddr != LLDB_INVALID_ADDRESS) {
4190b57cec5SDimitry Andric     int addr_width = 0;
4200b57cec5SDimitry Andric     if (exe_ctx && target) {
4210b57cec5SDimitry Andric       addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
4220b57cec5SDimitry Andric     }
4230b57cec5SDimitry Andric     if (addr_width == 0)
4240b57cec5SDimitry Andric       addr_width = 16;
4250b57cec5SDimitry Andric     if (print_file_addr_or_load_addr) {
4260b57cec5SDimitry Andric       ExecutionContextScope *exe_scope = nullptr;
4270b57cec5SDimitry Andric       if (exe_ctx)
4280b57cec5SDimitry Andric         exe_scope = exe_ctx->GetBestExecutionContextScope();
4290b57cec5SDimitry Andric       addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
4300b57cec5SDimitry Andric                 Address::DumpStyleModuleWithFileAddress, 0);
4310b57cec5SDimitry Andric     } else {
4320b57cec5SDimitry Andric       s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
4330b57cec5SDimitry Andric     }
4340b57cec5SDimitry Andric     return true;
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric   return false;
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric 
DumpAddressOffsetFromFunction(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & format_addr,bool concrete_only,bool no_padding,bool print_zero_offsets)4390b57cec5SDimitry Andric static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
4400b57cec5SDimitry Andric                                           const ExecutionContext *exe_ctx,
4410b57cec5SDimitry Andric                                           const Address &format_addr,
4420b57cec5SDimitry Andric                                           bool concrete_only, bool no_padding,
4430b57cec5SDimitry Andric                                           bool print_zero_offsets) {
4440b57cec5SDimitry Andric   if (format_addr.IsValid()) {
4450b57cec5SDimitry Andric     Address func_addr;
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric     if (sc) {
4480b57cec5SDimitry Andric       if (sc->function) {
4490b57cec5SDimitry Andric         func_addr = sc->function->GetAddressRange().GetBaseAddress();
4500b57cec5SDimitry Andric         if (sc->block && !concrete_only) {
4510b57cec5SDimitry Andric           // Check to make sure we aren't in an inline function. If we are, use
4520b57cec5SDimitry Andric           // the inline block range that contains "format_addr" since blocks
4530b57cec5SDimitry Andric           // can be discontiguous.
4540b57cec5SDimitry Andric           Block *inline_block = sc->block->GetContainingInlinedBlock();
4550b57cec5SDimitry Andric           AddressRange inline_range;
4560b57cec5SDimitry Andric           if (inline_block && inline_block->GetRangeContainingAddress(
4570b57cec5SDimitry Andric                                   format_addr, inline_range))
4580b57cec5SDimitry Andric             func_addr = inline_range.GetBaseAddress();
4590b57cec5SDimitry Andric         }
4600b57cec5SDimitry Andric       } else if (sc->symbol && sc->symbol->ValueIsAddress())
4610b57cec5SDimitry Andric         func_addr = sc->symbol->GetAddressRef();
4620b57cec5SDimitry Andric     }
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric     if (func_addr.IsValid()) {
4650b57cec5SDimitry Andric       const char *addr_offset_padding = no_padding ? "" : " ";
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric       if (func_addr.GetSection() == format_addr.GetSection()) {
4680b57cec5SDimitry Andric         addr_t func_file_addr = func_addr.GetFileAddress();
4690b57cec5SDimitry Andric         addr_t addr_file_addr = format_addr.GetFileAddress();
4700b57cec5SDimitry Andric         if (addr_file_addr > func_file_addr ||
4710b57cec5SDimitry Andric             (addr_file_addr == func_file_addr && print_zero_offsets)) {
4720b57cec5SDimitry Andric           s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4730b57cec5SDimitry Andric                    addr_file_addr - func_file_addr);
4740b57cec5SDimitry Andric         } else if (addr_file_addr < func_file_addr) {
4750b57cec5SDimitry Andric           s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4760b57cec5SDimitry Andric                    func_file_addr - addr_file_addr);
4770b57cec5SDimitry Andric         }
4780b57cec5SDimitry Andric         return true;
4790b57cec5SDimitry Andric       } else {
4800b57cec5SDimitry Andric         Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
4810b57cec5SDimitry Andric         if (target) {
4820b57cec5SDimitry Andric           addr_t func_load_addr = func_addr.GetLoadAddress(target);
4830b57cec5SDimitry Andric           addr_t addr_load_addr = format_addr.GetLoadAddress(target);
4840b57cec5SDimitry Andric           if (addr_load_addr > func_load_addr ||
4850b57cec5SDimitry Andric               (addr_load_addr == func_load_addr && print_zero_offsets)) {
4860b57cec5SDimitry Andric             s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4870b57cec5SDimitry Andric                      addr_load_addr - func_load_addr);
4880b57cec5SDimitry Andric           } else if (addr_load_addr < func_load_addr) {
4890b57cec5SDimitry Andric             s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4900b57cec5SDimitry Andric                      func_load_addr - addr_load_addr);
4910b57cec5SDimitry Andric           }
4920b57cec5SDimitry Andric           return true;
4930b57cec5SDimitry Andric         }
4940b57cec5SDimitry Andric       }
4950b57cec5SDimitry Andric     }
4960b57cec5SDimitry Andric   }
4970b57cec5SDimitry Andric   return false;
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric 
ScanBracketedRange(llvm::StringRef subpath,size_t & close_bracket_index,const char * & var_name_final_if_array_range,int64_t & index_lower,int64_t & index_higher)5000b57cec5SDimitry Andric static bool ScanBracketedRange(llvm::StringRef subpath,
5010b57cec5SDimitry Andric                                size_t &close_bracket_index,
5020b57cec5SDimitry Andric                                const char *&var_name_final_if_array_range,
5030b57cec5SDimitry Andric                                int64_t &index_lower, int64_t &index_higher) {
50481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::DataFormatters);
5050b57cec5SDimitry Andric   close_bracket_index = llvm::StringRef::npos;
5060b57cec5SDimitry Andric   const size_t open_bracket_index = subpath.find('[');
5070b57cec5SDimitry Andric   if (open_bracket_index == llvm::StringRef::npos) {
5089dba64beSDimitry Andric     LLDB_LOGF(log,
5099dba64beSDimitry Andric               "[ScanBracketedRange] no bracketed range, skipping entirely");
5100b57cec5SDimitry Andric     return false;
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   close_bracket_index = subpath.find(']', open_bracket_index + 1);
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   if (close_bracket_index == llvm::StringRef::npos) {
5169dba64beSDimitry Andric     LLDB_LOGF(log,
5179dba64beSDimitry Andric               "[ScanBracketedRange] no bracketed range, skipping entirely");
5180b57cec5SDimitry Andric     return false;
5190b57cec5SDimitry Andric   } else {
5200b57cec5SDimitry Andric     var_name_final_if_array_range = subpath.data() + open_bracket_index;
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric     if (close_bracket_index - open_bracket_index == 1) {
5239dba64beSDimitry Andric       LLDB_LOGF(
5249dba64beSDimitry Andric           log,
5250b57cec5SDimitry Andric           "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
5260b57cec5SDimitry Andric       index_lower = 0;
5270b57cec5SDimitry Andric     } else {
5280b57cec5SDimitry Andric       const size_t separator_index = subpath.find('-', open_bracket_index + 1);
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric       if (separator_index == llvm::StringRef::npos) {
5310b57cec5SDimitry Andric         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
5320b57cec5SDimitry Andric         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
5330b57cec5SDimitry Andric         index_higher = index_lower;
5349dba64beSDimitry Andric         LLDB_LOGF(log,
5359dba64beSDimitry Andric                   "[ScanBracketedRange] [%" PRId64
5360b57cec5SDimitry Andric                   "] detected, high index is same",
5370b57cec5SDimitry Andric                   index_lower);
5380b57cec5SDimitry Andric       } else {
5390b57cec5SDimitry Andric         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
5400b57cec5SDimitry Andric         const char *index_higher_cstr = subpath.data() + separator_index + 1;
5410b57cec5SDimitry Andric         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
5420b57cec5SDimitry Andric         index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
5439dba64beSDimitry Andric         LLDB_LOGF(log,
5449dba64beSDimitry Andric                   "[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
5450b57cec5SDimitry Andric                   index_lower, index_higher);
5460b57cec5SDimitry Andric       }
5470b57cec5SDimitry Andric       if (index_lower > index_higher && index_higher > 0) {
5489dba64beSDimitry Andric         LLDB_LOGF(log, "[ScanBracketedRange] swapping indices");
5490b57cec5SDimitry Andric         const int64_t temp = index_lower;
5500b57cec5SDimitry Andric         index_lower = index_higher;
5510b57cec5SDimitry Andric         index_higher = temp;
5520b57cec5SDimitry Andric       }
5530b57cec5SDimitry Andric     }
5540b57cec5SDimitry Andric   }
5550b57cec5SDimitry Andric   return true;
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
DumpFile(Stream & s,const FileSpec & file,FileKind file_kind)5580b57cec5SDimitry Andric static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
5590b57cec5SDimitry Andric   switch (file_kind) {
5600b57cec5SDimitry Andric   case FileKind::FileError:
5610b57cec5SDimitry Andric     break;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   case FileKind::Basename:
5640b57cec5SDimitry Andric     if (file.GetFilename()) {
5650b57cec5SDimitry Andric       s << file.GetFilename();
5660b57cec5SDimitry Andric       return true;
5670b57cec5SDimitry Andric     }
5680b57cec5SDimitry Andric     break;
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   case FileKind::Dirname:
5710b57cec5SDimitry Andric     if (file.GetDirectory()) {
5720b57cec5SDimitry Andric       s << file.GetDirectory();
5730b57cec5SDimitry Andric       return true;
5740b57cec5SDimitry Andric     }
5750b57cec5SDimitry Andric     break;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   case FileKind::Fullpath:
5780b57cec5SDimitry Andric     if (file) {
5790b57cec5SDimitry Andric       s << file;
5800b57cec5SDimitry Andric       return true;
5810b57cec5SDimitry Andric     }
5820b57cec5SDimitry Andric     break;
5830b57cec5SDimitry Andric   }
5840b57cec5SDimitry Andric   return false;
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric 
DumpRegister(Stream & s,StackFrame * frame,RegisterKind reg_kind,uint32_t reg_num,Format format)5870b57cec5SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
588fe6060f1SDimitry Andric                          uint32_t reg_num, Format format) {
5890b57cec5SDimitry Andric   if (frame) {
5900b57cec5SDimitry Andric     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric     if (reg_ctx) {
5930b57cec5SDimitry Andric       const uint32_t lldb_reg_num =
5940b57cec5SDimitry Andric           reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
5950b57cec5SDimitry Andric       if (lldb_reg_num != LLDB_INVALID_REGNUM) {
5960b57cec5SDimitry Andric         const RegisterInfo *reg_info =
5970b57cec5SDimitry Andric             reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
5980b57cec5SDimitry Andric         if (reg_info) {
5990b57cec5SDimitry Andric           RegisterValue reg_value;
6000b57cec5SDimitry Andric           if (reg_ctx->ReadRegister(reg_info, reg_value)) {
601fe013be4SDimitry Andric             DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
6020b57cec5SDimitry Andric             return true;
6030b57cec5SDimitry Andric           }
6040b57cec5SDimitry Andric         }
6050b57cec5SDimitry Andric       }
6060b57cec5SDimitry Andric     }
6070b57cec5SDimitry Andric   }
6080b57cec5SDimitry Andric   return false;
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
ExpandIndexedExpression(ValueObject * valobj,size_t index,bool deref_pointer)6110b57cec5SDimitry Andric static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
6120b57cec5SDimitry Andric                                              bool deref_pointer) {
61381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::DataFormatters);
614bdd1243dSDimitry Andric   std::string name_to_deref = llvm::formatv("[{0}]", index);
615bdd1243dSDimitry Andric   LLDB_LOG(log, "[ExpandIndexedExpression] name to deref: {0}", name_to_deref);
6160b57cec5SDimitry Andric   ValueObject::GetValueForExpressionPathOptions options;
6170b57cec5SDimitry Andric   ValueObject::ExpressionPathEndResultType final_value_type;
6180b57cec5SDimitry Andric   ValueObject::ExpressionPathScanEndReason reason_to_stop;
6190b57cec5SDimitry Andric   ValueObject::ExpressionPathAftermath what_next =
6200b57cec5SDimitry Andric       (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
6210b57cec5SDimitry Andric                      : ValueObject::eExpressionPathAftermathNothing);
6220b57cec5SDimitry Andric   ValueObjectSP item = valobj->GetValueForExpressionPath(
623bdd1243dSDimitry Andric       name_to_deref, &reason_to_stop, &final_value_type, options, &what_next);
6240b57cec5SDimitry Andric   if (!item) {
6259dba64beSDimitry Andric     LLDB_LOGF(log,
6269dba64beSDimitry Andric               "[ExpandIndexedExpression] ERROR: why stopping = %d,"
6270b57cec5SDimitry Andric               " final_value_type %d",
6280b57cec5SDimitry Andric               reason_to_stop, final_value_type);
6290b57cec5SDimitry Andric   } else {
6309dba64beSDimitry Andric     LLDB_LOGF(log,
6319dba64beSDimitry Andric               "[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
6320b57cec5SDimitry Andric               " final_value_type %d",
6330b57cec5SDimitry Andric               reason_to_stop, final_value_type);
6340b57cec5SDimitry Andric   }
6350b57cec5SDimitry Andric   return item;
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric 
ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)6380b57cec5SDimitry Andric static char ConvertValueObjectStyleToChar(
6390b57cec5SDimitry Andric     ValueObject::ValueObjectRepresentationStyle style) {
6400b57cec5SDimitry Andric   switch (style) {
6410b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
6420b57cec5SDimitry Andric     return '@';
6430b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleValue:
6440b57cec5SDimitry Andric     return 'V';
6450b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleLocation:
6460b57cec5SDimitry Andric     return 'L';
6470b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleSummary:
6480b57cec5SDimitry Andric     return 'S';
6490b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleChildrenCount:
6500b57cec5SDimitry Andric     return '#';
6510b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleType:
6520b57cec5SDimitry Andric     return 'T';
6530b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleName:
6540b57cec5SDimitry Andric     return 'N';
6550b57cec5SDimitry Andric   case ValueObject::eValueObjectRepresentationStyleExpressionPath:
6560b57cec5SDimitry Andric     return '>';
6570b57cec5SDimitry Andric   }
6580b57cec5SDimitry Andric   return '\0';
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric 
DumpValue(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const FormatEntity::Entry & entry,ValueObject * valobj)6610b57cec5SDimitry Andric static bool DumpValue(Stream &s, const SymbolContext *sc,
6620b57cec5SDimitry Andric                       const ExecutionContext *exe_ctx,
6630b57cec5SDimitry Andric                       const FormatEntity::Entry &entry, ValueObject *valobj) {
6640b57cec5SDimitry Andric   if (valobj == nullptr)
6650b57cec5SDimitry Andric     return false;
6660b57cec5SDimitry Andric 
66781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::DataFormatters);
6680b57cec5SDimitry Andric   Format custom_format = eFormatInvalid;
6690b57cec5SDimitry Andric   ValueObject::ValueObjectRepresentationStyle val_obj_display =
6700b57cec5SDimitry Andric       entry.string.empty()
6710b57cec5SDimitry Andric           ? ValueObject::eValueObjectRepresentationStyleValue
6720b57cec5SDimitry Andric           : ValueObject::eValueObjectRepresentationStyleSummary;
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   bool do_deref_pointer = entry.deref;
6750b57cec5SDimitry Andric   bool is_script = false;
6760b57cec5SDimitry Andric   switch (entry.type) {
6770b57cec5SDimitry Andric   case FormatEntity::Entry::Type::ScriptVariable:
6780b57cec5SDimitry Andric     is_script = true;
6790b57cec5SDimitry Andric     break;
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   case FormatEntity::Entry::Type::Variable:
6820b57cec5SDimitry Andric     custom_format = entry.fmt;
6830b57cec5SDimitry Andric     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
6840b57cec5SDimitry Andric     break;
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric   case FormatEntity::Entry::Type::ScriptVariableSynthetic:
6870b57cec5SDimitry Andric     is_script = true;
688bdd1243dSDimitry Andric     [[fallthrough]];
6890b57cec5SDimitry Andric   case FormatEntity::Entry::Type::VariableSynthetic:
6900b57cec5SDimitry Andric     custom_format = entry.fmt;
6910b57cec5SDimitry Andric     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
6920b57cec5SDimitry Andric     if (!valobj->IsSynthetic()) {
6930b57cec5SDimitry Andric       valobj = valobj->GetSyntheticValue().get();
6940b57cec5SDimitry Andric       if (valobj == nullptr)
6950b57cec5SDimitry Andric         return false;
6960b57cec5SDimitry Andric     }
6970b57cec5SDimitry Andric     break;
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   default:
7000b57cec5SDimitry Andric     return false;
7010b57cec5SDimitry Andric   }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric   ValueObject::ExpressionPathAftermath what_next =
7040b57cec5SDimitry Andric       (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
7050b57cec5SDimitry Andric                         : ValueObject::eExpressionPathAftermathNothing);
7060b57cec5SDimitry Andric   ValueObject::GetValueForExpressionPathOptions options;
7070b57cec5SDimitry Andric   options.DontCheckDotVsArrowSyntax()
7080b57cec5SDimitry Andric       .DoAllowBitfieldSyntax()
7090b57cec5SDimitry Andric       .DoAllowFragileIVar()
7100b57cec5SDimitry Andric       .SetSyntheticChildrenTraversal(
7110b57cec5SDimitry Andric           ValueObject::GetValueForExpressionPathOptions::
7120b57cec5SDimitry Andric               SyntheticChildrenTraversal::Both);
7130b57cec5SDimitry Andric   ValueObject *target = nullptr;
7140b57cec5SDimitry Andric   const char *var_name_final_if_array_range = nullptr;
7150b57cec5SDimitry Andric   size_t close_bracket_index = llvm::StringRef::npos;
7160b57cec5SDimitry Andric   int64_t index_lower = -1;
7170b57cec5SDimitry Andric   int64_t index_higher = -1;
7180b57cec5SDimitry Andric   bool is_array_range = false;
7190b57cec5SDimitry Andric   bool was_plain_var = false;
7200b57cec5SDimitry Andric   bool was_var_format = false;
7210b57cec5SDimitry Andric   bool was_var_indexed = false;
7220b57cec5SDimitry Andric   ValueObject::ExpressionPathScanEndReason reason_to_stop =
7230b57cec5SDimitry Andric       ValueObject::eExpressionPathScanEndReasonEndOfString;
7240b57cec5SDimitry Andric   ValueObject::ExpressionPathEndResultType final_value_type =
7250b57cec5SDimitry Andric       ValueObject::eExpressionPathEndResultTypePlain;
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   if (is_script) {
7280b57cec5SDimitry Andric     return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
7290b57cec5SDimitry Andric   }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   llvm::StringRef subpath(entry.string);
7320b57cec5SDimitry Andric   // simplest case ${var}, just print valobj's value
7330b57cec5SDimitry Andric   if (entry.string.empty()) {
7340b57cec5SDimitry Andric     if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
7350b57cec5SDimitry Andric         entry.number == ValueObject::eValueObjectRepresentationStyleValue)
7360b57cec5SDimitry Andric       was_plain_var = true;
7370b57cec5SDimitry Andric     else
7380b57cec5SDimitry Andric       was_var_format = true;
7390b57cec5SDimitry Andric     target = valobj;
7400b57cec5SDimitry Andric   } else // this is ${var.something} or multiple .something nested
7410b57cec5SDimitry Andric   {
7420b57cec5SDimitry Andric     if (entry.string[0] == '[')
7430b57cec5SDimitry Andric       was_var_indexed = true;
7440b57cec5SDimitry Andric     ScanBracketedRange(subpath, close_bracket_index,
7450b57cec5SDimitry Andric                        var_name_final_if_array_range, index_lower,
7460b57cec5SDimitry Andric                        index_higher);
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric     Status error;
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric     const std::string &expr_path = entry.string;
7510b57cec5SDimitry Andric 
7529dba64beSDimitry Andric     LLDB_LOGF(log, "[Debugger::FormatPrompt] symbol to expand: %s",
7530b57cec5SDimitry Andric               expr_path.c_str());
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric     target =
7560b57cec5SDimitry Andric         valobj
7570b57cec5SDimitry Andric             ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
7580b57cec5SDimitry Andric                                         &final_value_type, options, &what_next)
7590b57cec5SDimitry Andric             .get();
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric     if (!target) {
7629dba64beSDimitry Andric       LLDB_LOGF(log,
7639dba64beSDimitry Andric                 "[Debugger::FormatPrompt] ERROR: why stopping = %d,"
7640b57cec5SDimitry Andric                 " final_value_type %d",
7650b57cec5SDimitry Andric                 reason_to_stop, final_value_type);
7660b57cec5SDimitry Andric       return false;
7670b57cec5SDimitry Andric     } else {
7689dba64beSDimitry Andric       LLDB_LOGF(log,
7699dba64beSDimitry Andric                 "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
7700b57cec5SDimitry Andric                 " final_value_type %d",
7710b57cec5SDimitry Andric                 reason_to_stop, final_value_type);
7720b57cec5SDimitry Andric       target = target
7730b57cec5SDimitry Andric                    ->GetQualifiedRepresentationIfAvailable(
7740b57cec5SDimitry Andric                        target->GetDynamicValueType(), true)
7750b57cec5SDimitry Andric                    .get();
7760b57cec5SDimitry Andric     }
7770b57cec5SDimitry Andric   }
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric   is_array_range =
7800b57cec5SDimitry Andric       (final_value_type ==
7810b57cec5SDimitry Andric            ValueObject::eExpressionPathEndResultTypeBoundedRange ||
7820b57cec5SDimitry Andric        final_value_type ==
7830b57cec5SDimitry Andric            ValueObject::eExpressionPathEndResultTypeUnboundedRange);
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   do_deref_pointer =
7860b57cec5SDimitry Andric       (what_next == ValueObject::eExpressionPathAftermathDereference);
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   if (do_deref_pointer && !is_array_range) {
7890b57cec5SDimitry Andric     // I have not deref-ed yet, let's do it
7900b57cec5SDimitry Andric     // this happens when we are not going through
7910b57cec5SDimitry Andric     // GetValueForVariableExpressionPath to get to the target ValueObject
7920b57cec5SDimitry Andric     Status error;
7930b57cec5SDimitry Andric     target = target->Dereference(error).get();
7940b57cec5SDimitry Andric     if (error.Fail()) {
7959dba64beSDimitry Andric       LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n",
7960b57cec5SDimitry Andric                 error.AsCString("unknown"));
7970b57cec5SDimitry Andric       return false;
7980b57cec5SDimitry Andric     }
7990b57cec5SDimitry Andric     do_deref_pointer = false;
8000b57cec5SDimitry Andric   }
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   if (!target) {
8039dba64beSDimitry Andric     LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for "
8040b57cec5SDimitry Andric                    "prompt expression");
8050b57cec5SDimitry Andric     return false;
8060b57cec5SDimitry Andric   }
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric   // we do not want to use the summary for a bitfield of type T:n if we were
8090b57cec5SDimitry Andric   // originally dealing with just a T - that would get us into an endless
8100b57cec5SDimitry Andric   // recursion
8110b57cec5SDimitry Andric   if (target->IsBitfield() && was_var_indexed) {
8120b57cec5SDimitry Andric     // TODO: check for a (T:n)-specific summary - we should still obey that
8130b57cec5SDimitry Andric     StreamString bitfield_name;
8140b57cec5SDimitry Andric     bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
8150b57cec5SDimitry Andric                          target->GetBitfieldBitSize());
8160b57cec5SDimitry Andric     auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
817bdd1243dSDimitry Andric         bitfield_name.GetString(), lldb::eFormatterMatchExact);
8180b57cec5SDimitry Andric     if (val_obj_display ==
8190b57cec5SDimitry Andric             ValueObject::eValueObjectRepresentationStyleSummary &&
8200b57cec5SDimitry Andric         !DataVisualization::GetSummaryForType(type_sp))
8210b57cec5SDimitry Andric       val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
8220b57cec5SDimitry Andric   }
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   // TODO use flags for these
8250b57cec5SDimitry Andric   const uint32_t type_info_flags =
8260b57cec5SDimitry Andric       target->GetCompilerType().GetTypeInfo(nullptr);
8270b57cec5SDimitry Andric   bool is_array = (type_info_flags & eTypeIsArray) != 0;
8280b57cec5SDimitry Andric   bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
8290b57cec5SDimitry Andric   bool is_aggregate = target->GetCompilerType().IsAggregateType();
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric   if ((is_array || is_pointer) && (!is_array_range) &&
8320b57cec5SDimitry Andric       val_obj_display ==
8330b57cec5SDimitry Andric           ValueObject::eValueObjectRepresentationStyleValue) // this should be
8340b57cec5SDimitry Andric                                                              // wrong, but there
8350b57cec5SDimitry Andric                                                              // are some
8360b57cec5SDimitry Andric                                                              // exceptions
8370b57cec5SDimitry Andric   {
8380b57cec5SDimitry Andric     StreamString str_temp;
8399dba64beSDimitry Andric     LLDB_LOGF(log,
8400b57cec5SDimitry Andric               "[Debugger::FormatPrompt] I am into array || pointer && !range");
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric     if (target->HasSpecialPrintableRepresentation(val_obj_display,
8430b57cec5SDimitry Andric                                                   custom_format)) {
8440b57cec5SDimitry Andric       // try to use the special cases
8450b57cec5SDimitry Andric       bool success = target->DumpPrintableRepresentation(
8460b57cec5SDimitry Andric           str_temp, val_obj_display, custom_format);
8479dba64beSDimitry Andric       LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match",
8480b57cec5SDimitry Andric                 success ? "" : "n't");
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric       // should not happen
8510b57cec5SDimitry Andric       if (success)
8520b57cec5SDimitry Andric         s << str_temp.GetString();
8530b57cec5SDimitry Andric       return true;
8540b57cec5SDimitry Andric     } else {
8550b57cec5SDimitry Andric       if (was_plain_var) // if ${var}
8560b57cec5SDimitry Andric       {
8570b57cec5SDimitry Andric         s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
8580b57cec5SDimitry Andric       } else if (is_pointer) // if pointer, value is the address stored
8590b57cec5SDimitry Andric       {
8600b57cec5SDimitry Andric         target->DumpPrintableRepresentation(
8610b57cec5SDimitry Andric             s, val_obj_display, custom_format,
8620b57cec5SDimitry Andric             ValueObject::PrintableRepresentationSpecialCases::eDisable);
8630b57cec5SDimitry Andric       }
8640b57cec5SDimitry Andric       return true;
8650b57cec5SDimitry Andric     }
8660b57cec5SDimitry Andric   }
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric   // if directly trying to print ${var}, and this is an aggregate, display a
8690b57cec5SDimitry Andric   // nice type @ location message
8700b57cec5SDimitry Andric   if (is_aggregate && was_plain_var) {
8710b57cec5SDimitry Andric     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
8720b57cec5SDimitry Andric     return true;
8730b57cec5SDimitry Andric   }
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric   // if directly trying to print ${var%V}, and this is an aggregate, do not let
8760b57cec5SDimitry Andric   // the user do it
8770b57cec5SDimitry Andric   if (is_aggregate &&
8780b57cec5SDimitry Andric       ((was_var_format &&
8790b57cec5SDimitry Andric         val_obj_display ==
8800b57cec5SDimitry Andric             ValueObject::eValueObjectRepresentationStyleValue))) {
8810b57cec5SDimitry Andric     s << "<invalid use of aggregate type>";
8820b57cec5SDimitry Andric     return true;
8830b57cec5SDimitry Andric   }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric   if (!is_array_range) {
8869dba64beSDimitry Andric     LLDB_LOGF(log,
8879dba64beSDimitry Andric               "[Debugger::FormatPrompt] dumping ordinary printable output");
8880b57cec5SDimitry Andric     return target->DumpPrintableRepresentation(s, val_obj_display,
8890b57cec5SDimitry Andric                                                custom_format);
8900b57cec5SDimitry Andric   } else {
8919dba64beSDimitry Andric     LLDB_LOGF(log,
8929dba64beSDimitry Andric               "[Debugger::FormatPrompt] checking if I can handle as array");
8930b57cec5SDimitry Andric     if (!is_array && !is_pointer)
8940b57cec5SDimitry Andric       return false;
8959dba64beSDimitry Andric     LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array");
8960b57cec5SDimitry Andric     StreamString special_directions_stream;
8970b57cec5SDimitry Andric     llvm::StringRef special_directions;
8980b57cec5SDimitry Andric     if (close_bracket_index != llvm::StringRef::npos &&
8990b57cec5SDimitry Andric         subpath.size() > close_bracket_index) {
9000b57cec5SDimitry Andric       ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
9010b57cec5SDimitry Andric       special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
9020b57cec5SDimitry Andric                                        additional_data.GetCString());
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric       if (entry.fmt != eFormatDefault) {
9050b57cec5SDimitry Andric         const char format_char =
9060b57cec5SDimitry Andric             FormatManager::GetFormatAsFormatChar(entry.fmt);
9070b57cec5SDimitry Andric         if (format_char != '\0')
9080b57cec5SDimitry Andric           special_directions_stream.Printf("%%%c", format_char);
9090b57cec5SDimitry Andric         else {
9100b57cec5SDimitry Andric           const char *format_cstr =
9110b57cec5SDimitry Andric               FormatManager::GetFormatAsCString(entry.fmt);
9120b57cec5SDimitry Andric           special_directions_stream.Printf("%%%s", format_cstr);
9130b57cec5SDimitry Andric         }
9140b57cec5SDimitry Andric       } else if (entry.number != 0) {
9150b57cec5SDimitry Andric         const char style_char = ConvertValueObjectStyleToChar(
9160b57cec5SDimitry Andric             (ValueObject::ValueObjectRepresentationStyle)entry.number);
9170b57cec5SDimitry Andric         if (style_char)
9180b57cec5SDimitry Andric           special_directions_stream.Printf("%%%c", style_char);
9190b57cec5SDimitry Andric       }
9200b57cec5SDimitry Andric       special_directions_stream.PutChar('}');
9210b57cec5SDimitry Andric       special_directions =
9220b57cec5SDimitry Andric           llvm::StringRef(special_directions_stream.GetString());
9230b57cec5SDimitry Andric     }
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric     // let us display items index_lower thru index_higher of this array
9260b57cec5SDimitry Andric     s.PutChar('[');
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric     if (index_higher < 0)
9290b57cec5SDimitry Andric       index_higher = valobj->GetNumChildren() - 1;
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric     uint32_t max_num_children =
9320b57cec5SDimitry Andric         target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric     bool success = true;
9350b57cec5SDimitry Andric     for (int64_t index = index_lower; index <= index_higher; ++index) {
936fe6060f1SDimitry Andric       ValueObject *item = ExpandIndexedExpression(target, index, false).get();
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric       if (!item) {
9399dba64beSDimitry Andric         LLDB_LOGF(log,
9409dba64beSDimitry Andric                   "[Debugger::FormatPrompt] ERROR in getting child item at "
9410b57cec5SDimitry Andric                   "index %" PRId64,
9420b57cec5SDimitry Andric                   index);
9430b57cec5SDimitry Andric       } else {
9449dba64beSDimitry Andric         LLDB_LOGF(
9459dba64beSDimitry Andric             log,
9460b57cec5SDimitry Andric             "[Debugger::FormatPrompt] special_directions for child item: %s",
9470b57cec5SDimitry Andric             special_directions.data() ? special_directions.data() : "");
9480b57cec5SDimitry Andric       }
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric       if (special_directions.empty()) {
9510b57cec5SDimitry Andric         success &= item->DumpPrintableRepresentation(s, val_obj_display,
9520b57cec5SDimitry Andric                                                      custom_format);
9530b57cec5SDimitry Andric       } else {
9540b57cec5SDimitry Andric         success &= FormatEntity::FormatStringRef(
9550b57cec5SDimitry Andric             special_directions, s, sc, exe_ctx, nullptr, item, false, false);
9560b57cec5SDimitry Andric       }
9570b57cec5SDimitry Andric 
9580b57cec5SDimitry Andric       if (--max_num_children == 0) {
9590b57cec5SDimitry Andric         s.PutCString(", ...");
9600b57cec5SDimitry Andric         break;
9610b57cec5SDimitry Andric       }
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric       if (index < index_higher)
9640b57cec5SDimitry Andric         s.PutChar(',');
9650b57cec5SDimitry Andric     }
9660b57cec5SDimitry Andric     s.PutChar(']');
9670b57cec5SDimitry Andric     return success;
9680b57cec5SDimitry Andric   }
9690b57cec5SDimitry Andric }
9700b57cec5SDimitry Andric 
DumpRegister(Stream & s,StackFrame * frame,const char * reg_name,Format format)9710b57cec5SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
9720b57cec5SDimitry Andric                          Format format) {
9730b57cec5SDimitry Andric   if (frame) {
9740b57cec5SDimitry Andric     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric     if (reg_ctx) {
9770b57cec5SDimitry Andric       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
9780b57cec5SDimitry Andric       if (reg_info) {
9790b57cec5SDimitry Andric         RegisterValue reg_value;
9800b57cec5SDimitry Andric         if (reg_ctx->ReadRegister(reg_info, reg_value)) {
981fe013be4SDimitry Andric           DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
9820b57cec5SDimitry Andric           return true;
9830b57cec5SDimitry Andric         }
9840b57cec5SDimitry Andric       }
9850b57cec5SDimitry Andric     }
9860b57cec5SDimitry Andric   }
9870b57cec5SDimitry Andric   return false;
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric 
FormatThreadExtendedInfoRecurse(const FormatEntity::Entry & entry,const StructuredData::ObjectSP & thread_info_dictionary,const SymbolContext * sc,const ExecutionContext * exe_ctx,Stream & s)9900b57cec5SDimitry Andric static bool FormatThreadExtendedInfoRecurse(
9910b57cec5SDimitry Andric     const FormatEntity::Entry &entry,
9920b57cec5SDimitry Andric     const StructuredData::ObjectSP &thread_info_dictionary,
9930b57cec5SDimitry Andric     const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
9940b57cec5SDimitry Andric   llvm::StringRef path(entry.string);
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric   StructuredData::ObjectSP value =
9970b57cec5SDimitry Andric       thread_info_dictionary->GetObjectForDotSeparatedPath(path);
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric   if (value) {
10000b57cec5SDimitry Andric     if (value->GetType() == eStructuredDataTypeInteger) {
10010b57cec5SDimitry Andric       const char *token_format = "0x%4.4" PRIx64;
10020b57cec5SDimitry Andric       if (!entry.printf_format.empty())
10030b57cec5SDimitry Andric         token_format = entry.printf_format.c_str();
1004fe013be4SDimitry Andric       s.Printf(token_format, value->GetUnsignedIntegerValue());
10050b57cec5SDimitry Andric       return true;
10060b57cec5SDimitry Andric     } else if (value->GetType() == eStructuredDataTypeFloat) {
10070b57cec5SDimitry Andric       s.Printf("%f", value->GetAsFloat()->GetValue());
10080b57cec5SDimitry Andric       return true;
10090b57cec5SDimitry Andric     } else if (value->GetType() == eStructuredDataTypeString) {
10100b57cec5SDimitry Andric       s.Format("{0}", value->GetAsString()->GetValue());
10110b57cec5SDimitry Andric       return true;
10120b57cec5SDimitry Andric     } else if (value->GetType() == eStructuredDataTypeArray) {
10130b57cec5SDimitry Andric       if (value->GetAsArray()->GetSize() > 0) {
10140b57cec5SDimitry Andric         s.Printf("%zu", value->GetAsArray()->GetSize());
10150b57cec5SDimitry Andric         return true;
10160b57cec5SDimitry Andric       }
10170b57cec5SDimitry Andric     } else if (value->GetType() == eStructuredDataTypeDictionary) {
10180b57cec5SDimitry Andric       s.Printf("%zu",
10190b57cec5SDimitry Andric                value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
10200b57cec5SDimitry Andric       return true;
10210b57cec5SDimitry Andric     }
10220b57cec5SDimitry Andric   }
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   return false;
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric 
IsToken(const char * var_name_begin,const char * var)10270b57cec5SDimitry Andric static inline bool IsToken(const char *var_name_begin, const char *var) {
10280b57cec5SDimitry Andric   return (::strncmp(var_name_begin, var, strlen(var)) == 0);
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric 
1031bdd1243dSDimitry Andric /// Parses the basename out of a demangled function name
1032bdd1243dSDimitry Andric /// that may include function arguments. Supports
1033bdd1243dSDimitry Andric /// template functions.
1034bdd1243dSDimitry Andric ///
1035bdd1243dSDimitry Andric /// Returns pointers to the opening and closing parenthesis of
1036bdd1243dSDimitry Andric /// `full_name`. Can return nullptr for either parenthesis if
1037bdd1243dSDimitry Andric /// none is exists.
1038bdd1243dSDimitry Andric static std::pair<char const *, char const *>
ParseBaseName(char const * full_name)1039bdd1243dSDimitry Andric ParseBaseName(char const *full_name) {
1040bdd1243dSDimitry Andric   const char *open_paren = strchr(full_name, '(');
1041bdd1243dSDimitry Andric   const char *close_paren = nullptr;
1042bdd1243dSDimitry Andric   const char *generic = strchr(full_name, '<');
1043bdd1243dSDimitry Andric   // if before the arguments list begins there is a template sign
1044bdd1243dSDimitry Andric   // then scan to the end of the generic args before you try to find
1045bdd1243dSDimitry Andric   // the arguments list
1046bdd1243dSDimitry Andric   if (generic && open_paren && generic < open_paren) {
1047bdd1243dSDimitry Andric     int generic_depth = 1;
1048bdd1243dSDimitry Andric     ++generic;
1049bdd1243dSDimitry Andric     for (; *generic && generic_depth > 0; generic++) {
1050bdd1243dSDimitry Andric       if (*generic == '<')
1051bdd1243dSDimitry Andric         generic_depth++;
1052bdd1243dSDimitry Andric       if (*generic == '>')
1053bdd1243dSDimitry Andric         generic_depth--;
1054bdd1243dSDimitry Andric     }
1055bdd1243dSDimitry Andric     if (*generic)
1056bdd1243dSDimitry Andric       open_paren = strchr(generic, '(');
1057bdd1243dSDimitry Andric     else
1058bdd1243dSDimitry Andric       open_paren = nullptr;
1059bdd1243dSDimitry Andric   }
1060bdd1243dSDimitry Andric 
1061bdd1243dSDimitry Andric   if (open_paren) {
1062bdd1243dSDimitry Andric     if (IsToken(open_paren, "(anonymous namespace)")) {
1063bdd1243dSDimitry Andric       open_paren = strchr(open_paren + strlen("(anonymous namespace)"), '(');
1064bdd1243dSDimitry Andric       if (open_paren)
1065bdd1243dSDimitry Andric         close_paren = strchr(open_paren, ')');
1066bdd1243dSDimitry Andric     } else
1067bdd1243dSDimitry Andric       close_paren = strchr(open_paren, ')');
1068bdd1243dSDimitry Andric   }
1069bdd1243dSDimitry Andric 
1070bdd1243dSDimitry Andric   return {open_paren, close_paren};
1071bdd1243dSDimitry Andric }
1072bdd1243dSDimitry Andric 
1073bdd1243dSDimitry Andric /// Writes out the function name in 'full_name' to 'out_stream'
1074bdd1243dSDimitry Andric /// but replaces each argument type with the variable name
1075bdd1243dSDimitry Andric /// and the corresponding pretty-printed value
PrettyPrintFunctionNameWithArgs(Stream & out_stream,char const * full_name,ExecutionContextScope * exe_scope,VariableList const & args)1076bdd1243dSDimitry Andric static void PrettyPrintFunctionNameWithArgs(Stream &out_stream,
1077bdd1243dSDimitry Andric                                             char const *full_name,
1078bdd1243dSDimitry Andric                                             ExecutionContextScope *exe_scope,
1079bdd1243dSDimitry Andric                                             VariableList const &args) {
1080bdd1243dSDimitry Andric   auto [open_paren, close_paren] = ParseBaseName(full_name);
1081bdd1243dSDimitry Andric   if (open_paren)
1082bdd1243dSDimitry Andric     out_stream.Write(full_name, open_paren - full_name + 1);
1083bdd1243dSDimitry Andric   else {
1084bdd1243dSDimitry Andric     out_stream.PutCString(full_name);
1085bdd1243dSDimitry Andric     out_stream.PutChar('(');
1086bdd1243dSDimitry Andric   }
1087bdd1243dSDimitry Andric 
1088bdd1243dSDimitry Andric   FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
1089bdd1243dSDimitry Andric 
1090bdd1243dSDimitry Andric   if (close_paren)
1091bdd1243dSDimitry Andric     out_stream.PutCString(close_paren);
1092bdd1243dSDimitry Andric   else
1093bdd1243dSDimitry Andric     out_stream.PutChar(')');
1094bdd1243dSDimitry Andric }
1095bdd1243dSDimitry Andric 
FormatInlinedBlock(Stream & out_stream,Block * block)1096*a58f00eaSDimitry Andric static void FormatInlinedBlock(Stream &out_stream, Block *block) {
1097*a58f00eaSDimitry Andric   if (!block)
1098*a58f00eaSDimitry Andric     return;
1099*a58f00eaSDimitry Andric   Block *inline_block = block->GetContainingInlinedBlock();
1100*a58f00eaSDimitry Andric   if (inline_block) {
1101*a58f00eaSDimitry Andric     if (const InlineFunctionInfo *inline_info =
1102*a58f00eaSDimitry Andric             inline_block->GetInlinedFunctionInfo()) {
1103*a58f00eaSDimitry Andric       out_stream.PutCString(" [inlined] ");
1104*a58f00eaSDimitry Andric       inline_info->GetName().Dump(&out_stream);
1105*a58f00eaSDimitry Andric     }
1106*a58f00eaSDimitry Andric   }
1107*a58f00eaSDimitry Andric }
1108*a58f00eaSDimitry Andric 
FormatStringRef(const llvm::StringRef & format_str,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)11090b57cec5SDimitry Andric bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
11100b57cec5SDimitry Andric                                    const SymbolContext *sc,
11110b57cec5SDimitry Andric                                    const ExecutionContext *exe_ctx,
11120b57cec5SDimitry Andric                                    const Address *addr, ValueObject *valobj,
11130b57cec5SDimitry Andric                                    bool function_changed,
11140b57cec5SDimitry Andric                                    bool initial_function) {
11150b57cec5SDimitry Andric   if (!format_str.empty()) {
11160b57cec5SDimitry Andric     FormatEntity::Entry root;
11170b57cec5SDimitry Andric     Status error = FormatEntity::Parse(format_str, root);
11180b57cec5SDimitry Andric     if (error.Success()) {
11190b57cec5SDimitry Andric       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
11200b57cec5SDimitry Andric                                   function_changed, initial_function);
11210b57cec5SDimitry Andric     }
11220b57cec5SDimitry Andric   }
11230b57cec5SDimitry Andric   return false;
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric 
FormatCString(const char * format,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)11260b57cec5SDimitry Andric bool FormatEntity::FormatCString(const char *format, Stream &s,
11270b57cec5SDimitry Andric                                  const SymbolContext *sc,
11280b57cec5SDimitry Andric                                  const ExecutionContext *exe_ctx,
11290b57cec5SDimitry Andric                                  const Address *addr, ValueObject *valobj,
11300b57cec5SDimitry Andric                                  bool function_changed, bool initial_function) {
11310b57cec5SDimitry Andric   if (format && format[0]) {
11320b57cec5SDimitry Andric     FormatEntity::Entry root;
11330b57cec5SDimitry Andric     llvm::StringRef format_str(format);
11340b57cec5SDimitry Andric     Status error = FormatEntity::Parse(format_str, root);
11350b57cec5SDimitry Andric     if (error.Success()) {
11360b57cec5SDimitry Andric       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
11370b57cec5SDimitry Andric                                   function_changed, initial_function);
11380b57cec5SDimitry Andric     }
11390b57cec5SDimitry Andric   }
11400b57cec5SDimitry Andric   return false;
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric 
Format(const Entry & entry,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)11430b57cec5SDimitry Andric bool FormatEntity::Format(const Entry &entry, Stream &s,
11440b57cec5SDimitry Andric                           const SymbolContext *sc,
11450b57cec5SDimitry Andric                           const ExecutionContext *exe_ctx, const Address *addr,
11460b57cec5SDimitry Andric                           ValueObject *valobj, bool function_changed,
11470b57cec5SDimitry Andric                           bool initial_function) {
11480b57cec5SDimitry Andric   switch (entry.type) {
11490b57cec5SDimitry Andric   case Entry::Type::Invalid:
11500b57cec5SDimitry Andric   case Entry::Type::ParentNumber: // Only used for
11510b57cec5SDimitry Andric                                   // FormatEntity::Entry::Definition encoding
11520b57cec5SDimitry Andric   case Entry::Type::ParentString: // Only used for
11530b57cec5SDimitry Andric                                   // FormatEntity::Entry::Definition encoding
11540b57cec5SDimitry Andric     return false;
11550b57cec5SDimitry Andric   case Entry::Type::EscapeCode:
11560b57cec5SDimitry Andric     if (exe_ctx) {
11570b57cec5SDimitry Andric       if (Target *target = exe_ctx->GetTargetPtr()) {
11580b57cec5SDimitry Andric         Debugger &debugger = target->GetDebugger();
11590b57cec5SDimitry Andric         if (debugger.GetUseColor()) {
11600b57cec5SDimitry Andric           s.PutCString(entry.string);
11610b57cec5SDimitry Andric         }
11620b57cec5SDimitry Andric       }
11630b57cec5SDimitry Andric     }
11640b57cec5SDimitry Andric     // Always return true, so colors being disabled is transparent.
11650b57cec5SDimitry Andric     return true;
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   case Entry::Type::Root:
11680b57cec5SDimitry Andric     for (const auto &child : entry.children) {
11690b57cec5SDimitry Andric       if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
11700b57cec5SDimitry Andric                   initial_function)) {
11710b57cec5SDimitry Andric         return false; // If any item of root fails, then the formatting fails
11720b57cec5SDimitry Andric       }
11730b57cec5SDimitry Andric     }
11740b57cec5SDimitry Andric     return true; // Only return true if all items succeeded
11750b57cec5SDimitry Andric 
11760b57cec5SDimitry Andric   case Entry::Type::String:
11770b57cec5SDimitry Andric     s.PutCString(entry.string);
11780b57cec5SDimitry Andric     return true;
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric   case Entry::Type::Scope: {
11810b57cec5SDimitry Andric     StreamString scope_stream;
11820b57cec5SDimitry Andric     bool success = false;
11830b57cec5SDimitry Andric     for (const auto &child : entry.children) {
11840b57cec5SDimitry Andric       success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
11850b57cec5SDimitry Andric                        function_changed, initial_function);
11860b57cec5SDimitry Andric       if (!success)
11870b57cec5SDimitry Andric         break;
11880b57cec5SDimitry Andric     }
11890b57cec5SDimitry Andric     // Only if all items in a scope succeed, then do we print the output into
11900b57cec5SDimitry Andric     // the main stream
11910b57cec5SDimitry Andric     if (success)
11920b57cec5SDimitry Andric       s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
11930b57cec5SDimitry Andric   }
11940b57cec5SDimitry Andric     return true; // Scopes always successfully print themselves
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric   case Entry::Type::Variable:
11970b57cec5SDimitry Andric   case Entry::Type::VariableSynthetic:
11980b57cec5SDimitry Andric   case Entry::Type::ScriptVariable:
11990b57cec5SDimitry Andric   case Entry::Type::ScriptVariableSynthetic:
12000b57cec5SDimitry Andric     return DumpValue(s, sc, exe_ctx, entry, valobj);
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   case Entry::Type::AddressFile:
12030b57cec5SDimitry Andric   case Entry::Type::AddressLoad:
12040b57cec5SDimitry Andric   case Entry::Type::AddressLoadOrFile:
1205480093f4SDimitry Andric     return (
1206480093f4SDimitry Andric         addr != nullptr && addr->IsValid() &&
1207480093f4SDimitry Andric         DumpAddressAndContent(s, sc, exe_ctx, *addr,
12080b57cec5SDimitry Andric                               entry.type == Entry::Type::AddressLoadOrFile));
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric   case Entry::Type::ProcessID:
12110b57cec5SDimitry Andric     if (exe_ctx) {
12120b57cec5SDimitry Andric       Process *process = exe_ctx->GetProcessPtr();
12130b57cec5SDimitry Andric       if (process) {
12140b57cec5SDimitry Andric         const char *format = "%" PRIu64;
12150b57cec5SDimitry Andric         if (!entry.printf_format.empty())
12160b57cec5SDimitry Andric           format = entry.printf_format.c_str();
12170b57cec5SDimitry Andric         s.Printf(format, process->GetID());
12180b57cec5SDimitry Andric         return true;
12190b57cec5SDimitry Andric       }
12200b57cec5SDimitry Andric     }
12210b57cec5SDimitry Andric     return false;
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric   case Entry::Type::ProcessFile:
12240b57cec5SDimitry Andric     if (exe_ctx) {
12250b57cec5SDimitry Andric       Process *process = exe_ctx->GetProcessPtr();
12260b57cec5SDimitry Andric       if (process) {
12270b57cec5SDimitry Andric         Module *exe_module = process->GetTarget().GetExecutableModulePointer();
12280b57cec5SDimitry Andric         if (exe_module) {
12290b57cec5SDimitry Andric           if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
12300b57cec5SDimitry Andric             return true;
12310b57cec5SDimitry Andric         }
12320b57cec5SDimitry Andric       }
12330b57cec5SDimitry Andric     }
12340b57cec5SDimitry Andric     return false;
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric   case Entry::Type::ScriptProcess:
12370b57cec5SDimitry Andric     if (exe_ctx) {
12380b57cec5SDimitry Andric       Process *process = exe_ctx->GetProcessPtr();
12390b57cec5SDimitry Andric       if (process)
12400b57cec5SDimitry Andric         return RunScriptFormatKeyword(s, sc, exe_ctx, process,
12410b57cec5SDimitry Andric                                       entry.string.c_str());
12420b57cec5SDimitry Andric     }
12430b57cec5SDimitry Andric     return false;
12440b57cec5SDimitry Andric 
12450b57cec5SDimitry Andric   case Entry::Type::ThreadID:
12460b57cec5SDimitry Andric     if (exe_ctx) {
12470b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
12480b57cec5SDimitry Andric       if (thread) {
12490b57cec5SDimitry Andric         const char *format = "0x%4.4" PRIx64;
12500b57cec5SDimitry Andric         if (!entry.printf_format.empty()) {
12510b57cec5SDimitry Andric           // Watch for the special "tid" format...
12520b57cec5SDimitry Andric           if (entry.printf_format == "tid") {
12530b57cec5SDimitry Andric             // TODO(zturner): Rather than hardcoding this to be platform
12540b57cec5SDimitry Andric             // specific, it should be controlled by a setting and the default
12550b57cec5SDimitry Andric             // value of the setting can be different depending on the platform.
12560b57cec5SDimitry Andric             Target &target = thread->GetProcess()->GetTarget();
12570b57cec5SDimitry Andric             ArchSpec arch(target.GetArchitecture());
12580b57cec5SDimitry Andric             llvm::Triple::OSType ostype = arch.IsValid()
12590b57cec5SDimitry Andric                                               ? arch.GetTriple().getOS()
12600b57cec5SDimitry Andric                                               : llvm::Triple::UnknownOS;
1261c9157d92SDimitry Andric             if (ostype == llvm::Triple::FreeBSD ||
1262c9157d92SDimitry Andric                 ostype == llvm::Triple::Linux ||
1263c9157d92SDimitry Andric                 ostype == llvm::Triple::NetBSD ||
1264c9157d92SDimitry Andric                 ostype == llvm::Triple::OpenBSD) {
12650b57cec5SDimitry Andric               format = "%" PRIu64;
12660b57cec5SDimitry Andric             }
12670b57cec5SDimitry Andric           } else {
12680b57cec5SDimitry Andric             format = entry.printf_format.c_str();
12690b57cec5SDimitry Andric           }
12700b57cec5SDimitry Andric         }
12710b57cec5SDimitry Andric         s.Printf(format, thread->GetID());
12720b57cec5SDimitry Andric         return true;
12730b57cec5SDimitry Andric       }
12740b57cec5SDimitry Andric     }
12750b57cec5SDimitry Andric     return false;
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric   case Entry::Type::ThreadProtocolID:
12780b57cec5SDimitry Andric     if (exe_ctx) {
12790b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
12800b57cec5SDimitry Andric       if (thread) {
12810b57cec5SDimitry Andric         const char *format = "0x%4.4" PRIx64;
12820b57cec5SDimitry Andric         if (!entry.printf_format.empty())
12830b57cec5SDimitry Andric           format = entry.printf_format.c_str();
12840b57cec5SDimitry Andric         s.Printf(format, thread->GetProtocolID());
12850b57cec5SDimitry Andric         return true;
12860b57cec5SDimitry Andric       }
12870b57cec5SDimitry Andric     }
12880b57cec5SDimitry Andric     return false;
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric   case Entry::Type::ThreadIndexID:
12910b57cec5SDimitry Andric     if (exe_ctx) {
12920b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
12930b57cec5SDimitry Andric       if (thread) {
12940b57cec5SDimitry Andric         const char *format = "%" PRIu32;
12950b57cec5SDimitry Andric         if (!entry.printf_format.empty())
12960b57cec5SDimitry Andric           format = entry.printf_format.c_str();
12970b57cec5SDimitry Andric         s.Printf(format, thread->GetIndexID());
12980b57cec5SDimitry Andric         return true;
12990b57cec5SDimitry Andric       }
13000b57cec5SDimitry Andric     }
13010b57cec5SDimitry Andric     return false;
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric   case Entry::Type::ThreadName:
13040b57cec5SDimitry Andric     if (exe_ctx) {
13050b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
13060b57cec5SDimitry Andric       if (thread) {
13070b57cec5SDimitry Andric         const char *cstr = thread->GetName();
13080b57cec5SDimitry Andric         if (cstr && cstr[0]) {
13090b57cec5SDimitry Andric           s.PutCString(cstr);
13100b57cec5SDimitry Andric           return true;
13110b57cec5SDimitry Andric         }
13120b57cec5SDimitry Andric       }
13130b57cec5SDimitry Andric     }
13140b57cec5SDimitry Andric     return false;
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric   case Entry::Type::ThreadQueue:
13170b57cec5SDimitry Andric     if (exe_ctx) {
13180b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
13190b57cec5SDimitry Andric       if (thread) {
13200b57cec5SDimitry Andric         const char *cstr = thread->GetQueueName();
13210b57cec5SDimitry Andric         if (cstr && cstr[0]) {
13220b57cec5SDimitry Andric           s.PutCString(cstr);
13230b57cec5SDimitry Andric           return true;
13240b57cec5SDimitry Andric         }
13250b57cec5SDimitry Andric       }
13260b57cec5SDimitry Andric     }
13270b57cec5SDimitry Andric     return false;
13280b57cec5SDimitry Andric 
13290b57cec5SDimitry Andric   case Entry::Type::ThreadStopReason:
13300b57cec5SDimitry Andric     if (exe_ctx) {
13315ffd83dbSDimitry Andric       if (Thread *thread = exe_ctx->GetThreadPtr()) {
13325ffd83dbSDimitry Andric         std::string stop_description = thread->GetStopDescription();
13335ffd83dbSDimitry Andric         if (!stop_description.empty()) {
13345ffd83dbSDimitry Andric           s.PutCString(stop_description);
13350b57cec5SDimitry Andric           return true;
13360b57cec5SDimitry Andric         }
13370b57cec5SDimitry Andric       }
13380b57cec5SDimitry Andric     }
13395ffd83dbSDimitry Andric     return false;
13405ffd83dbSDimitry Andric 
13415ffd83dbSDimitry Andric   case Entry::Type::ThreadStopReasonRaw:
13425ffd83dbSDimitry Andric     if (exe_ctx) {
13435ffd83dbSDimitry Andric       if (Thread *thread = exe_ctx->GetThreadPtr()) {
13445ffd83dbSDimitry Andric         std::string stop_description = thread->GetStopDescriptionRaw();
13455ffd83dbSDimitry Andric         if (!stop_description.empty()) {
13465ffd83dbSDimitry Andric           s.PutCString(stop_description);
13475ffd83dbSDimitry Andric           return true;
13485ffd83dbSDimitry Andric         }
13495ffd83dbSDimitry Andric       }
13500b57cec5SDimitry Andric     }
13510b57cec5SDimitry Andric     return false;
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric   case Entry::Type::ThreadReturnValue:
13540b57cec5SDimitry Andric     if (exe_ctx) {
13550b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
13560b57cec5SDimitry Andric       if (thread) {
13570b57cec5SDimitry Andric         StopInfoSP stop_info_sp = thread->GetStopInfo();
13580b57cec5SDimitry Andric         if (stop_info_sp && stop_info_sp->IsValid()) {
13590b57cec5SDimitry Andric           ValueObjectSP return_valobj_sp =
13600b57cec5SDimitry Andric               StopInfo::GetReturnValueObject(stop_info_sp);
13610b57cec5SDimitry Andric           if (return_valobj_sp) {
13620b57cec5SDimitry Andric             return_valobj_sp->Dump(s);
13630b57cec5SDimitry Andric             return true;
13640b57cec5SDimitry Andric           }
13650b57cec5SDimitry Andric         }
13660b57cec5SDimitry Andric       }
13670b57cec5SDimitry Andric     }
13680b57cec5SDimitry Andric     return false;
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric   case Entry::Type::ThreadCompletedExpression:
13710b57cec5SDimitry Andric     if (exe_ctx) {
13720b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
13730b57cec5SDimitry Andric       if (thread) {
13740b57cec5SDimitry Andric         StopInfoSP stop_info_sp = thread->GetStopInfo();
13750b57cec5SDimitry Andric         if (stop_info_sp && stop_info_sp->IsValid()) {
13760b57cec5SDimitry Andric           ExpressionVariableSP expression_var_sp =
13770b57cec5SDimitry Andric               StopInfo::GetExpressionVariable(stop_info_sp);
13780b57cec5SDimitry Andric           if (expression_var_sp && expression_var_sp->GetValueObject()) {
13790b57cec5SDimitry Andric             expression_var_sp->GetValueObject()->Dump(s);
13800b57cec5SDimitry Andric             return true;
13810b57cec5SDimitry Andric           }
13820b57cec5SDimitry Andric         }
13830b57cec5SDimitry Andric       }
13840b57cec5SDimitry Andric     }
13850b57cec5SDimitry Andric     return false;
13860b57cec5SDimitry Andric 
13870b57cec5SDimitry Andric   case Entry::Type::ScriptThread:
13880b57cec5SDimitry Andric     if (exe_ctx) {
13890b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
13900b57cec5SDimitry Andric       if (thread)
13910b57cec5SDimitry Andric         return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
13920b57cec5SDimitry Andric                                       entry.string.c_str());
13930b57cec5SDimitry Andric     }
13940b57cec5SDimitry Andric     return false;
13950b57cec5SDimitry Andric 
13960b57cec5SDimitry Andric   case Entry::Type::ThreadInfo:
13970b57cec5SDimitry Andric     if (exe_ctx) {
13980b57cec5SDimitry Andric       Thread *thread = exe_ctx->GetThreadPtr();
13990b57cec5SDimitry Andric       if (thread) {
14000b57cec5SDimitry Andric         StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
14010b57cec5SDimitry Andric         if (object_sp &&
14020b57cec5SDimitry Andric             object_sp->GetType() == eStructuredDataTypeDictionary) {
14030b57cec5SDimitry Andric           if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
14040b57cec5SDimitry Andric             return true;
14050b57cec5SDimitry Andric         }
14060b57cec5SDimitry Andric       }
14070b57cec5SDimitry Andric     }
14080b57cec5SDimitry Andric     return false;
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric   case Entry::Type::TargetArch:
14110b57cec5SDimitry Andric     if (exe_ctx) {
14120b57cec5SDimitry Andric       Target *target = exe_ctx->GetTargetPtr();
14130b57cec5SDimitry Andric       if (target) {
14140b57cec5SDimitry Andric         const ArchSpec &arch = target->GetArchitecture();
14150b57cec5SDimitry Andric         if (arch.IsValid()) {
14160b57cec5SDimitry Andric           s.PutCString(arch.GetArchitectureName());
14170b57cec5SDimitry Andric           return true;
14180b57cec5SDimitry Andric         }
14190b57cec5SDimitry Andric       }
14200b57cec5SDimitry Andric     }
14210b57cec5SDimitry Andric     return false;
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric   case Entry::Type::ScriptTarget:
14240b57cec5SDimitry Andric     if (exe_ctx) {
14250b57cec5SDimitry Andric       Target *target = exe_ctx->GetTargetPtr();
14260b57cec5SDimitry Andric       if (target)
14270b57cec5SDimitry Andric         return RunScriptFormatKeyword(s, sc, exe_ctx, target,
14280b57cec5SDimitry Andric                                       entry.string.c_str());
14290b57cec5SDimitry Andric     }
14300b57cec5SDimitry Andric     return false;
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric   case Entry::Type::ModuleFile:
14330b57cec5SDimitry Andric     if (sc) {
14340b57cec5SDimitry Andric       Module *module = sc->module_sp.get();
14350b57cec5SDimitry Andric       if (module) {
14360b57cec5SDimitry Andric         if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
14370b57cec5SDimitry Andric           return true;
14380b57cec5SDimitry Andric       }
14390b57cec5SDimitry Andric     }
14400b57cec5SDimitry Andric     return false;
14410b57cec5SDimitry Andric 
14420b57cec5SDimitry Andric   case Entry::Type::File:
14430b57cec5SDimitry Andric     if (sc) {
14440b57cec5SDimitry Andric       CompileUnit *cu = sc->comp_unit;
14450b57cec5SDimitry Andric       if (cu) {
1446480093f4SDimitry Andric         if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
14470b57cec5SDimitry Andric           return true;
14480b57cec5SDimitry Andric       }
14490b57cec5SDimitry Andric     }
14500b57cec5SDimitry Andric     return false;
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric   case Entry::Type::Lang:
14530b57cec5SDimitry Andric     if (sc) {
14540b57cec5SDimitry Andric       CompileUnit *cu = sc->comp_unit;
14550b57cec5SDimitry Andric       if (cu) {
14560b57cec5SDimitry Andric         const char *lang_name =
14570b57cec5SDimitry Andric             Language::GetNameForLanguageType(cu->GetLanguage());
14580b57cec5SDimitry Andric         if (lang_name) {
14590b57cec5SDimitry Andric           s.PutCString(lang_name);
14600b57cec5SDimitry Andric           return true;
14610b57cec5SDimitry Andric         }
14620b57cec5SDimitry Andric       }
14630b57cec5SDimitry Andric     }
14640b57cec5SDimitry Andric     return false;
14650b57cec5SDimitry Andric 
14660b57cec5SDimitry Andric   case Entry::Type::FrameIndex:
14670b57cec5SDimitry Andric     if (exe_ctx) {
14680b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
14690b57cec5SDimitry Andric       if (frame) {
14700b57cec5SDimitry Andric         const char *format = "%" PRIu32;
14710b57cec5SDimitry Andric         if (!entry.printf_format.empty())
14720b57cec5SDimitry Andric           format = entry.printf_format.c_str();
14730b57cec5SDimitry Andric         s.Printf(format, frame->GetFrameIndex());
14740b57cec5SDimitry Andric         return true;
14750b57cec5SDimitry Andric       }
14760b57cec5SDimitry Andric     }
14770b57cec5SDimitry Andric     return false;
14780b57cec5SDimitry Andric 
14790b57cec5SDimitry Andric   case Entry::Type::FrameRegisterPC:
14800b57cec5SDimitry Andric     if (exe_ctx) {
14810b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
14820b57cec5SDimitry Andric       if (frame) {
14830b57cec5SDimitry Andric         const Address &pc_addr = frame->GetFrameCodeAddress();
14840b57cec5SDimitry Andric         if (pc_addr.IsValid()) {
1485480093f4SDimitry Andric           if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false))
14860b57cec5SDimitry Andric             return true;
14870b57cec5SDimitry Andric         }
14880b57cec5SDimitry Andric       }
14890b57cec5SDimitry Andric     }
14900b57cec5SDimitry Andric     return false;
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric   case Entry::Type::FrameRegisterSP:
14930b57cec5SDimitry Andric     if (exe_ctx) {
14940b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
14950b57cec5SDimitry Andric       if (frame) {
14960b57cec5SDimitry Andric         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
14970b57cec5SDimitry Andric                          (lldb::Format)entry.number))
14980b57cec5SDimitry Andric           return true;
14990b57cec5SDimitry Andric       }
15000b57cec5SDimitry Andric     }
15010b57cec5SDimitry Andric     return false;
15020b57cec5SDimitry Andric 
15030b57cec5SDimitry Andric   case Entry::Type::FrameRegisterFP:
15040b57cec5SDimitry Andric     if (exe_ctx) {
15050b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
15060b57cec5SDimitry Andric       if (frame) {
15070b57cec5SDimitry Andric         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
15080b57cec5SDimitry Andric                          (lldb::Format)entry.number))
15090b57cec5SDimitry Andric           return true;
15100b57cec5SDimitry Andric       }
15110b57cec5SDimitry Andric     }
15120b57cec5SDimitry Andric     return false;
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric   case Entry::Type::FrameRegisterFlags:
15150b57cec5SDimitry Andric     if (exe_ctx) {
15160b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
15170b57cec5SDimitry Andric       if (frame) {
15180b57cec5SDimitry Andric         if (DumpRegister(s, frame, eRegisterKindGeneric,
15190b57cec5SDimitry Andric                          LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
15200b57cec5SDimitry Andric           return true;
15210b57cec5SDimitry Andric       }
15220b57cec5SDimitry Andric     }
15230b57cec5SDimitry Andric     return false;
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric   case Entry::Type::FrameNoDebug:
15260b57cec5SDimitry Andric     if (exe_ctx) {
15270b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
15280b57cec5SDimitry Andric       if (frame) {
15290b57cec5SDimitry Andric         return !frame->HasDebugInformation();
15300b57cec5SDimitry Andric       }
15310b57cec5SDimitry Andric     }
15320b57cec5SDimitry Andric     return true;
15330b57cec5SDimitry Andric 
15340b57cec5SDimitry Andric   case Entry::Type::FrameRegisterByName:
15350b57cec5SDimitry Andric     if (exe_ctx) {
15360b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
15370b57cec5SDimitry Andric       if (frame) {
15380b57cec5SDimitry Andric         if (DumpRegister(s, frame, entry.string.c_str(),
15390b57cec5SDimitry Andric                          (lldb::Format)entry.number))
15400b57cec5SDimitry Andric           return true;
15410b57cec5SDimitry Andric       }
15420b57cec5SDimitry Andric     }
15430b57cec5SDimitry Andric     return false;
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric   case Entry::Type::FrameIsArtificial: {
15460b57cec5SDimitry Andric     if (exe_ctx)
15470b57cec5SDimitry Andric       if (StackFrame *frame = exe_ctx->GetFramePtr())
15480b57cec5SDimitry Andric         return frame->IsArtificial();
15490b57cec5SDimitry Andric     return false;
15500b57cec5SDimitry Andric   }
15510b57cec5SDimitry Andric 
15520b57cec5SDimitry Andric   case Entry::Type::ScriptFrame:
15530b57cec5SDimitry Andric     if (exe_ctx) {
15540b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
15550b57cec5SDimitry Andric       if (frame)
15560b57cec5SDimitry Andric         return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
15570b57cec5SDimitry Andric                                       entry.string.c_str());
15580b57cec5SDimitry Andric     }
15590b57cec5SDimitry Andric     return false;
15600b57cec5SDimitry Andric 
15610b57cec5SDimitry Andric   case Entry::Type::FunctionID:
15620b57cec5SDimitry Andric     if (sc) {
15630b57cec5SDimitry Andric       if (sc->function) {
15640b57cec5SDimitry Andric         s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
15650b57cec5SDimitry Andric         return true;
15660b57cec5SDimitry Andric       } else if (sc->symbol) {
15670b57cec5SDimitry Andric         s.Printf("symbol[%u]", sc->symbol->GetID());
15680b57cec5SDimitry Andric         return true;
15690b57cec5SDimitry Andric       }
15700b57cec5SDimitry Andric     }
15710b57cec5SDimitry Andric     return false;
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric   case Entry::Type::FunctionDidChange:
15740b57cec5SDimitry Andric     return function_changed;
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   case Entry::Type::FunctionInitialFunction:
15770b57cec5SDimitry Andric     return initial_function;
15780b57cec5SDimitry Andric 
15790b57cec5SDimitry Andric   case Entry::Type::FunctionName: {
1580fe6060f1SDimitry Andric     if (!sc)
1581fe6060f1SDimitry Andric       return false;
1582fe6060f1SDimitry Andric 
15830b57cec5SDimitry Andric     Language *language_plugin = nullptr;
15840b57cec5SDimitry Andric     bool language_plugin_handled = false;
15850b57cec5SDimitry Andric     StreamString ss;
1586fe6060f1SDimitry Andric 
15870b57cec5SDimitry Andric     if (sc->function)
15880b57cec5SDimitry Andric       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
15890b57cec5SDimitry Andric     else if (sc->symbol)
15900b57cec5SDimitry Andric       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1591fe6060f1SDimitry Andric 
1592fe6060f1SDimitry Andric     if (language_plugin)
15930b57cec5SDimitry Andric       language_plugin_handled = language_plugin->GetFunctionDisplayName(
15940b57cec5SDimitry Andric           sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1595fe6060f1SDimitry Andric 
15960b57cec5SDimitry Andric     if (language_plugin_handled) {
15970b57cec5SDimitry Andric       s << ss.GetString();
15980b57cec5SDimitry Andric       return true;
15990b57cec5SDimitry Andric     } else {
16000b57cec5SDimitry Andric       const char *name = nullptr;
16010b57cec5SDimitry Andric       if (sc->function)
16020b57cec5SDimitry Andric         name = sc->function->GetName().AsCString(nullptr);
16030b57cec5SDimitry Andric       else if (sc->symbol)
16040b57cec5SDimitry Andric         name = sc->symbol->GetName().AsCString(nullptr);
1605fe6060f1SDimitry Andric 
16060b57cec5SDimitry Andric       if (name) {
16070b57cec5SDimitry Andric         s.PutCString(name);
1608*a58f00eaSDimitry Andric         FormatInlinedBlock(s, sc->block);
16090b57cec5SDimitry Andric         return true;
16100b57cec5SDimitry Andric       }
16110b57cec5SDimitry Andric     }
16120b57cec5SDimitry Andric   }
16130b57cec5SDimitry Andric     return false;
16140b57cec5SDimitry Andric 
16150b57cec5SDimitry Andric   case Entry::Type::FunctionNameNoArgs: {
1616fe6060f1SDimitry Andric     if (!sc)
1617fe6060f1SDimitry Andric       return false;
1618fe6060f1SDimitry Andric 
16190b57cec5SDimitry Andric     Language *language_plugin = nullptr;
16200b57cec5SDimitry Andric     bool language_plugin_handled = false;
16210b57cec5SDimitry Andric     StreamString ss;
16220b57cec5SDimitry Andric     if (sc->function)
16230b57cec5SDimitry Andric       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
16240b57cec5SDimitry Andric     else if (sc->symbol)
16250b57cec5SDimitry Andric       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1626fe6060f1SDimitry Andric 
1627fe6060f1SDimitry Andric     if (language_plugin)
16280b57cec5SDimitry Andric       language_plugin_handled = language_plugin->GetFunctionDisplayName(
16290b57cec5SDimitry Andric           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
16300b57cec5SDimitry Andric           ss);
1631fe6060f1SDimitry Andric 
16320b57cec5SDimitry Andric     if (language_plugin_handled) {
16330b57cec5SDimitry Andric       s << ss.GetString();
16340b57cec5SDimitry Andric       return true;
16350b57cec5SDimitry Andric     } else {
16360b57cec5SDimitry Andric       ConstString name;
16370b57cec5SDimitry Andric       if (sc->function)
16380b57cec5SDimitry Andric         name = sc->function->GetNameNoArguments();
16390b57cec5SDimitry Andric       else if (sc->symbol)
16400b57cec5SDimitry Andric         name = sc->symbol->GetNameNoArguments();
16410b57cec5SDimitry Andric       if (name) {
16420b57cec5SDimitry Andric         s.PutCString(name.GetCString());
1643*a58f00eaSDimitry Andric         FormatInlinedBlock(s, sc->block);
16440b57cec5SDimitry Andric         return true;
16450b57cec5SDimitry Andric       }
16460b57cec5SDimitry Andric     }
16470b57cec5SDimitry Andric   }
16480b57cec5SDimitry Andric     return false;
16490b57cec5SDimitry Andric 
16500b57cec5SDimitry Andric   case Entry::Type::FunctionNameWithArgs: {
1651fe6060f1SDimitry Andric     if (!sc)
1652fe6060f1SDimitry Andric       return false;
1653fe6060f1SDimitry Andric 
16540b57cec5SDimitry Andric     Language *language_plugin = nullptr;
16550b57cec5SDimitry Andric     bool language_plugin_handled = false;
16560b57cec5SDimitry Andric     StreamString ss;
16570b57cec5SDimitry Andric     if (sc->function)
16580b57cec5SDimitry Andric       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
16590b57cec5SDimitry Andric     else if (sc->symbol)
16600b57cec5SDimitry Andric       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1661fe6060f1SDimitry Andric 
1662fe6060f1SDimitry Andric     if (language_plugin)
16630b57cec5SDimitry Andric       language_plugin_handled = language_plugin->GetFunctionDisplayName(
16640b57cec5SDimitry Andric           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1665fe6060f1SDimitry Andric 
16660b57cec5SDimitry Andric     if (language_plugin_handled) {
16670b57cec5SDimitry Andric       s << ss.GetString();
16680b57cec5SDimitry Andric       return true;
16690b57cec5SDimitry Andric     } else {
16700b57cec5SDimitry Andric       // Print the function name with arguments in it
16710b57cec5SDimitry Andric       if (sc->function) {
16720b57cec5SDimitry Andric         ExecutionContextScope *exe_scope =
16730b57cec5SDimitry Andric             exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
16740b57cec5SDimitry Andric         const char *cstr = sc->function->GetName().AsCString(nullptr);
16750b57cec5SDimitry Andric         if (cstr) {
16760b57cec5SDimitry Andric           const InlineFunctionInfo *inline_info = nullptr;
16770b57cec5SDimitry Andric           VariableListSP variable_list_sp;
16780b57cec5SDimitry Andric           bool get_function_vars = true;
16790b57cec5SDimitry Andric           if (sc->block) {
16800b57cec5SDimitry Andric             Block *inline_block = sc->block->GetContainingInlinedBlock();
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric             if (inline_block) {
16830b57cec5SDimitry Andric               get_function_vars = false;
1684*a58f00eaSDimitry Andric               inline_info = inline_block->GetInlinedFunctionInfo();
16850b57cec5SDimitry Andric               if (inline_info)
16860b57cec5SDimitry Andric                 variable_list_sp = inline_block->GetBlockVariableList(true);
16870b57cec5SDimitry Andric             }
16880b57cec5SDimitry Andric           }
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric           if (get_function_vars) {
16910b57cec5SDimitry Andric             variable_list_sp =
16920b57cec5SDimitry Andric                 sc->function->GetBlock(true).GetBlockVariableList(true);
16930b57cec5SDimitry Andric           }
16940b57cec5SDimitry Andric 
16950b57cec5SDimitry Andric           if (inline_info) {
16960b57cec5SDimitry Andric             s.PutCString(cstr);
16970b57cec5SDimitry Andric             s.PutCString(" [inlined] ");
16985ffd83dbSDimitry Andric             cstr = inline_info->GetName().GetCString();
16990b57cec5SDimitry Andric           }
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric           VariableList args;
17020b57cec5SDimitry Andric           if (variable_list_sp)
17030b57cec5SDimitry Andric             variable_list_sp->AppendVariablesWithScope(
17040b57cec5SDimitry Andric                 eValueTypeVariableArgument, args);
17050b57cec5SDimitry Andric           if (args.GetSize() > 0) {
1706bdd1243dSDimitry Andric             PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args);
17070b57cec5SDimitry Andric           } else {
17080b57cec5SDimitry Andric             s.PutCString(cstr);
17090b57cec5SDimitry Andric           }
17100b57cec5SDimitry Andric           return true;
17110b57cec5SDimitry Andric         }
17120b57cec5SDimitry Andric       } else if (sc->symbol) {
17130b57cec5SDimitry Andric         const char *cstr = sc->symbol->GetName().AsCString(nullptr);
17140b57cec5SDimitry Andric         if (cstr) {
17150b57cec5SDimitry Andric           s.PutCString(cstr);
17160b57cec5SDimitry Andric           return true;
17170b57cec5SDimitry Andric         }
17180b57cec5SDimitry Andric       }
17190b57cec5SDimitry Andric     }
17200b57cec5SDimitry Andric   }
17210b57cec5SDimitry Andric     return false;
17220b57cec5SDimitry Andric 
1723480093f4SDimitry Andric   case Entry::Type::FunctionMangledName: {
1724fe6060f1SDimitry Andric     if (!sc)
1725fe6060f1SDimitry Andric       return false;
1726fe6060f1SDimitry Andric 
1727480093f4SDimitry Andric     const char *name = nullptr;
1728480093f4SDimitry Andric     if (sc->symbol)
17295ffd83dbSDimitry Andric       name =
17305ffd83dbSDimitry Andric           sc->symbol->GetMangled().GetName(Mangled::ePreferMangled).AsCString();
1731480093f4SDimitry Andric     else if (sc->function)
1732480093f4SDimitry Andric       name = sc->function->GetMangled()
17335ffd83dbSDimitry Andric                  .GetName(Mangled::ePreferMangled)
1734480093f4SDimitry Andric                  .AsCString();
1735480093f4SDimitry Andric 
1736480093f4SDimitry Andric     if (!name)
1737480093f4SDimitry Andric       return false;
1738480093f4SDimitry Andric     s.PutCString(name);
1739*a58f00eaSDimitry Andric     FormatInlinedBlock(s, sc->block);
1740480093f4SDimitry Andric     return true;
1741480093f4SDimitry Andric   }
17420b57cec5SDimitry Andric   case Entry::Type::FunctionAddrOffset:
17430b57cec5SDimitry Andric     if (addr) {
17440b57cec5SDimitry Andric       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
17450b57cec5SDimitry Andric                                         false))
17460b57cec5SDimitry Andric         return true;
17470b57cec5SDimitry Andric     }
17480b57cec5SDimitry Andric     return false;
17490b57cec5SDimitry Andric 
17500b57cec5SDimitry Andric   case Entry::Type::FunctionAddrOffsetConcrete:
17510b57cec5SDimitry Andric     if (addr) {
17520b57cec5SDimitry Andric       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
17530b57cec5SDimitry Andric                                         true))
17540b57cec5SDimitry Andric         return true;
17550b57cec5SDimitry Andric     }
17560b57cec5SDimitry Andric     return false;
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric   case Entry::Type::FunctionLineOffset:
1759fe6060f1SDimitry Andric     if (sc)
1760fe6060f1SDimitry Andric       return (DumpAddressOffsetFromFunction(
1761fe6060f1SDimitry Andric           s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false,
1762fe6060f1SDimitry Andric           false));
1763fe6060f1SDimitry Andric     return false;
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric   case Entry::Type::FunctionPCOffset:
17660b57cec5SDimitry Andric     if (exe_ctx) {
17670b57cec5SDimitry Andric       StackFrame *frame = exe_ctx->GetFramePtr();
17680b57cec5SDimitry Andric       if (frame) {
17690b57cec5SDimitry Andric         if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
17700b57cec5SDimitry Andric                                           frame->GetFrameCodeAddress(), false,
17710b57cec5SDimitry Andric                                           false, false))
17720b57cec5SDimitry Andric           return true;
17730b57cec5SDimitry Andric       }
17740b57cec5SDimitry Andric     }
17750b57cec5SDimitry Andric     return false;
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric   case Entry::Type::FunctionChanged:
17780b57cec5SDimitry Andric     return function_changed;
17790b57cec5SDimitry Andric 
17800b57cec5SDimitry Andric   case Entry::Type::FunctionIsOptimized: {
17810b57cec5SDimitry Andric     bool is_optimized = false;
1782fe6060f1SDimitry Andric     if (sc && sc->function && sc->function->GetIsOptimized()) {
17830b57cec5SDimitry Andric       is_optimized = true;
17840b57cec5SDimitry Andric     }
17850b57cec5SDimitry Andric     return is_optimized;
17860b57cec5SDimitry Andric   }
17870b57cec5SDimitry Andric 
17880b57cec5SDimitry Andric   case Entry::Type::FunctionInitial:
17890b57cec5SDimitry Andric     return initial_function;
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric   case Entry::Type::LineEntryFile:
17920b57cec5SDimitry Andric     if (sc && sc->line_entry.IsValid()) {
17930b57cec5SDimitry Andric       Module *module = sc->module_sp.get();
17940b57cec5SDimitry Andric       if (module) {
17950b57cec5SDimitry Andric         if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
17960b57cec5SDimitry Andric           return true;
17970b57cec5SDimitry Andric       }
17980b57cec5SDimitry Andric     }
17990b57cec5SDimitry Andric     return false;
18000b57cec5SDimitry Andric 
18010b57cec5SDimitry Andric   case Entry::Type::LineEntryLineNumber:
18020b57cec5SDimitry Andric     if (sc && sc->line_entry.IsValid()) {
18030b57cec5SDimitry Andric       const char *format = "%" PRIu32;
18040b57cec5SDimitry Andric       if (!entry.printf_format.empty())
18050b57cec5SDimitry Andric         format = entry.printf_format.c_str();
18060b57cec5SDimitry Andric       s.Printf(format, sc->line_entry.line);
18070b57cec5SDimitry Andric       return true;
18080b57cec5SDimitry Andric     }
18090b57cec5SDimitry Andric     return false;
18100b57cec5SDimitry Andric 
18110b57cec5SDimitry Andric   case Entry::Type::LineEntryColumn:
18120b57cec5SDimitry Andric     if (sc && sc->line_entry.IsValid() && sc->line_entry.column) {
18130b57cec5SDimitry Andric       const char *format = "%" PRIu32;
18140b57cec5SDimitry Andric       if (!entry.printf_format.empty())
18150b57cec5SDimitry Andric         format = entry.printf_format.c_str();
18160b57cec5SDimitry Andric       s.Printf(format, sc->line_entry.column);
18170b57cec5SDimitry Andric       return true;
18180b57cec5SDimitry Andric     }
18190b57cec5SDimitry Andric     return false;
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric   case Entry::Type::LineEntryStartAddress:
18220b57cec5SDimitry Andric   case Entry::Type::LineEntryEndAddress:
18230b57cec5SDimitry Andric     if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
18240b57cec5SDimitry Andric       Address addr = sc->line_entry.range.GetBaseAddress();
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric       if (entry.type == Entry::Type::LineEntryEndAddress)
18270b57cec5SDimitry Andric         addr.Slide(sc->line_entry.range.GetByteSize());
1828480093f4SDimitry Andric       if (DumpAddressAndContent(s, sc, exe_ctx, addr, false))
18290b57cec5SDimitry Andric         return true;
18300b57cec5SDimitry Andric     }
18310b57cec5SDimitry Andric     return false;
18320b57cec5SDimitry Andric 
18330b57cec5SDimitry Andric   case Entry::Type::CurrentPCArrow:
18340b57cec5SDimitry Andric     if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
18350b57cec5SDimitry Andric       RegisterContextSP reg_ctx =
18360b57cec5SDimitry Andric           exe_ctx->GetFramePtr()->GetRegisterContextSP();
18370b57cec5SDimitry Andric       if (reg_ctx) {
18380b57cec5SDimitry Andric         addr_t pc_loadaddr = reg_ctx->GetPC();
18390b57cec5SDimitry Andric         if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
18400b57cec5SDimitry Andric           Address pc;
18410b57cec5SDimitry Andric           pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
18420b57cec5SDimitry Andric           if (pc == *addr) {
18430b57cec5SDimitry Andric             s.Printf("-> ");
18440b57cec5SDimitry Andric             return true;
18450b57cec5SDimitry Andric           }
18460b57cec5SDimitry Andric         }
18470b57cec5SDimitry Andric       }
18480b57cec5SDimitry Andric       s.Printf("   ");
18490b57cec5SDimitry Andric       return true;
18500b57cec5SDimitry Andric     }
18510b57cec5SDimitry Andric     return false;
18520b57cec5SDimitry Andric   }
18530b57cec5SDimitry Andric   return false;
18540b57cec5SDimitry Andric }
18550b57cec5SDimitry Andric 
DumpCommaSeparatedChildEntryNames(Stream & s,const Definition * parent)1856fe6060f1SDimitry Andric static bool DumpCommaSeparatedChildEntryNames(Stream &s,
1857fe6060f1SDimitry Andric                                               const Definition *parent) {
18580b57cec5SDimitry Andric   if (parent->children) {
18590b57cec5SDimitry Andric     const size_t n = parent->num_children;
18600b57cec5SDimitry Andric     for (size_t i = 0; i < n; ++i) {
18610b57cec5SDimitry Andric       if (i > 0)
18620b57cec5SDimitry Andric         s.PutCString(", ");
18630b57cec5SDimitry Andric       s.Printf("\"%s\"", parent->children[i].name);
18640b57cec5SDimitry Andric     }
18650b57cec5SDimitry Andric     return true;
18660b57cec5SDimitry Andric   }
18670b57cec5SDimitry Andric   return false;
18680b57cec5SDimitry Andric }
18690b57cec5SDimitry Andric 
ParseEntry(const llvm::StringRef & format_str,const Definition * parent,FormatEntity::Entry & entry)18700b57cec5SDimitry Andric static Status ParseEntry(const llvm::StringRef &format_str,
1871fe6060f1SDimitry Andric                          const Definition *parent, FormatEntity::Entry &entry) {
18720b57cec5SDimitry Andric   Status error;
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric   const size_t sep_pos = format_str.find_first_of(".[:");
18750b57cec5SDimitry Andric   const char sep_char =
18760b57cec5SDimitry Andric       (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
18770b57cec5SDimitry Andric   llvm::StringRef key = format_str.substr(0, sep_pos);
18780b57cec5SDimitry Andric 
18790b57cec5SDimitry Andric   const size_t n = parent->num_children;
18800b57cec5SDimitry Andric   for (size_t i = 0; i < n; ++i) {
1881fe6060f1SDimitry Andric     const Definition *entry_def = parent->children + i;
18820b57cec5SDimitry Andric     if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
18830b57cec5SDimitry Andric       llvm::StringRef value;
18840b57cec5SDimitry Andric       if (sep_char)
18850b57cec5SDimitry Andric         value =
18860b57cec5SDimitry Andric             format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
18870b57cec5SDimitry Andric       switch (entry_def->type) {
18880b57cec5SDimitry Andric       case FormatEntity::Entry::Type::ParentString:
18890b57cec5SDimitry Andric         entry.string = format_str.str();
18900b57cec5SDimitry Andric         return error; // Success
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric       case FormatEntity::Entry::Type::ParentNumber:
18930b57cec5SDimitry Andric         entry.number = entry_def->data;
18940b57cec5SDimitry Andric         return error; // Success
18950b57cec5SDimitry Andric 
18960b57cec5SDimitry Andric       case FormatEntity::Entry::Type::EscapeCode:
18970b57cec5SDimitry Andric         entry.type = entry_def->type;
18980b57cec5SDimitry Andric         entry.string = entry_def->string;
18990b57cec5SDimitry Andric         return error; // Success
19000b57cec5SDimitry Andric 
19010b57cec5SDimitry Andric       default:
19020b57cec5SDimitry Andric         entry.type = entry_def->type;
19030b57cec5SDimitry Andric         break;
19040b57cec5SDimitry Andric       }
19050b57cec5SDimitry Andric 
19060b57cec5SDimitry Andric       if (value.empty()) {
19070b57cec5SDimitry Andric         if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
19080b57cec5SDimitry Andric           if (entry_def->children) {
19090b57cec5SDimitry Andric             StreamString error_strm;
19100b57cec5SDimitry Andric             error_strm.Printf("'%s' can't be specified on its own, you must "
19110b57cec5SDimitry Andric                               "access one of its children: ",
19120b57cec5SDimitry Andric                               entry_def->name);
19130b57cec5SDimitry Andric             DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
19140b57cec5SDimitry Andric             error.SetErrorStringWithFormat("%s", error_strm.GetData());
19150b57cec5SDimitry Andric           } else if (sep_char == ':') {
19160b57cec5SDimitry Andric             // Any value whose separator is a with a ':' means this value has a
19170b57cec5SDimitry Andric             // string argument that needs to be stored in the entry (like
19180b57cec5SDimitry Andric             // "${script.var:}"). In this case the string value is the empty
19190b57cec5SDimitry Andric             // string which is ok.
19200b57cec5SDimitry Andric           } else {
19210b57cec5SDimitry Andric             error.SetErrorStringWithFormat("%s", "invalid entry definitions");
19220b57cec5SDimitry Andric           }
19230b57cec5SDimitry Andric         }
19240b57cec5SDimitry Andric       } else {
19250b57cec5SDimitry Andric         if (entry_def->children) {
19260b57cec5SDimitry Andric           error = ParseEntry(value, entry_def, entry);
19270b57cec5SDimitry Andric         } else if (sep_char == ':') {
19280b57cec5SDimitry Andric           // Any value whose separator is a with a ':' means this value has a
19290b57cec5SDimitry Andric           // string argument that needs to be stored in the entry (like
19300b57cec5SDimitry Andric           // "${script.var:modulename.function}")
19310b57cec5SDimitry Andric           entry.string = value.str();
19320b57cec5SDimitry Andric         } else {
19330b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
19340b57cec5SDimitry Andric               "'%s' followed by '%s' but it has no children", key.str().c_str(),
19350b57cec5SDimitry Andric               value.str().c_str());
19360b57cec5SDimitry Andric         }
19370b57cec5SDimitry Andric       }
19380b57cec5SDimitry Andric       return error;
19390b57cec5SDimitry Andric     }
19400b57cec5SDimitry Andric   }
19410b57cec5SDimitry Andric   StreamString error_strm;
19420b57cec5SDimitry Andric   if (parent->type == FormatEntity::Entry::Type::Root)
19430b57cec5SDimitry Andric     error_strm.Printf(
19440b57cec5SDimitry Andric         "invalid top level item '%s'. Valid top level items are: ",
19450b57cec5SDimitry Andric         key.str().c_str());
19460b57cec5SDimitry Andric   else
19470b57cec5SDimitry Andric     error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
19480b57cec5SDimitry Andric                       key.str().c_str(), parent->name);
19490b57cec5SDimitry Andric   DumpCommaSeparatedChildEntryNames(error_strm, parent);
19500b57cec5SDimitry Andric   error.SetErrorStringWithFormat("%s", error_strm.GetData());
19510b57cec5SDimitry Andric   return error;
19520b57cec5SDimitry Andric }
19530b57cec5SDimitry Andric 
FindEntry(const llvm::StringRef & format_str,const Definition * parent,llvm::StringRef & remainder)1954fe6060f1SDimitry Andric static const Definition *FindEntry(const llvm::StringRef &format_str,
1955fe6060f1SDimitry Andric                                    const Definition *parent,
19560b57cec5SDimitry Andric                                    llvm::StringRef &remainder) {
19570b57cec5SDimitry Andric   Status error;
19580b57cec5SDimitry Andric 
19590b57cec5SDimitry Andric   std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
19600b57cec5SDimitry Andric   const size_t n = parent->num_children;
19610b57cec5SDimitry Andric   for (size_t i = 0; i < n; ++i) {
1962fe6060f1SDimitry Andric     const Definition *entry_def = parent->children + i;
19630b57cec5SDimitry Andric     if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
19640b57cec5SDimitry Andric       if (p.second.empty()) {
19650b57cec5SDimitry Andric         if (format_str.back() == '.')
19660b57cec5SDimitry Andric           remainder = format_str.drop_front(format_str.size() - 1);
19670b57cec5SDimitry Andric         else
19680b57cec5SDimitry Andric           remainder = llvm::StringRef(); // Exact match
19690b57cec5SDimitry Andric         return entry_def;
19700b57cec5SDimitry Andric       } else {
19710b57cec5SDimitry Andric         if (entry_def->children) {
19720b57cec5SDimitry Andric           return FindEntry(p.second, entry_def, remainder);
19730b57cec5SDimitry Andric         } else {
19740b57cec5SDimitry Andric           remainder = p.second;
19750b57cec5SDimitry Andric           return entry_def;
19760b57cec5SDimitry Andric         }
19770b57cec5SDimitry Andric       }
19780b57cec5SDimitry Andric     }
19790b57cec5SDimitry Andric   }
19800b57cec5SDimitry Andric   remainder = format_str;
19810b57cec5SDimitry Andric   return parent;
19820b57cec5SDimitry Andric }
19830b57cec5SDimitry Andric 
ParseInternal(llvm::StringRef & format,Entry & parent_entry,uint32_t depth)1984c9157d92SDimitry Andric static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
19850b57cec5SDimitry Andric                             uint32_t depth) {
19860b57cec5SDimitry Andric   Status error;
19870b57cec5SDimitry Andric   while (!format.empty() && error.Success()) {
19880b57cec5SDimitry Andric     const size_t non_special_chars = format.find_first_of("${}\\");
19890b57cec5SDimitry Andric 
19900b57cec5SDimitry Andric     if (non_special_chars == llvm::StringRef::npos) {
19910b57cec5SDimitry Andric       // No special characters, just string bytes so add them and we are done
19920b57cec5SDimitry Andric       parent_entry.AppendText(format);
19930b57cec5SDimitry Andric       return error;
19940b57cec5SDimitry Andric     }
19950b57cec5SDimitry Andric 
19960b57cec5SDimitry Andric     if (non_special_chars > 0) {
19970b57cec5SDimitry Andric       // We have a special character, so add all characters before these as a
19980b57cec5SDimitry Andric       // plain string
19990b57cec5SDimitry Andric       parent_entry.AppendText(format.substr(0, non_special_chars));
20000b57cec5SDimitry Andric       format = format.drop_front(non_special_chars);
20010b57cec5SDimitry Andric     }
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric     switch (format[0]) {
20040b57cec5SDimitry Andric     case '\0':
20050b57cec5SDimitry Andric       return error;
20060b57cec5SDimitry Andric 
20070b57cec5SDimitry Andric     case '{': {
20080b57cec5SDimitry Andric       format = format.drop_front(); // Skip the '{'
20090b57cec5SDimitry Andric       Entry scope_entry(Entry::Type::Scope);
2010c9157d92SDimitry Andric       error = ParseInternal(format, scope_entry, depth + 1);
20110b57cec5SDimitry Andric       if (error.Fail())
20120b57cec5SDimitry Andric         return error;
20130b57cec5SDimitry Andric       parent_entry.AppendEntry(std::move(scope_entry));
20140b57cec5SDimitry Andric     } break;
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric     case '}':
20170b57cec5SDimitry Andric       if (depth == 0)
20180b57cec5SDimitry Andric         error.SetErrorString("unmatched '}' character");
20190b57cec5SDimitry Andric       else
20200b57cec5SDimitry Andric         format =
20210b57cec5SDimitry Andric             format
20220b57cec5SDimitry Andric                 .drop_front(); // Skip the '}' as we are at the end of the scope
20230b57cec5SDimitry Andric       return error;
20240b57cec5SDimitry Andric 
20250b57cec5SDimitry Andric     case '\\': {
20260b57cec5SDimitry Andric       format = format.drop_front(); // Skip the '\' character
20270b57cec5SDimitry Andric       if (format.empty()) {
20280b57cec5SDimitry Andric         error.SetErrorString(
20290b57cec5SDimitry Andric             "'\\' character was not followed by another character");
20300b57cec5SDimitry Andric         return error;
20310b57cec5SDimitry Andric       }
20320b57cec5SDimitry Andric 
20330b57cec5SDimitry Andric       const char desens_char = format[0];
20340b57cec5SDimitry Andric       format = format.drop_front(); // Skip the desensitized char character
20350b57cec5SDimitry Andric       switch (desens_char) {
20360b57cec5SDimitry Andric       case 'a':
20370b57cec5SDimitry Andric         parent_entry.AppendChar('\a');
20380b57cec5SDimitry Andric         break;
20390b57cec5SDimitry Andric       case 'b':
20400b57cec5SDimitry Andric         parent_entry.AppendChar('\b');
20410b57cec5SDimitry Andric         break;
20420b57cec5SDimitry Andric       case 'f':
20430b57cec5SDimitry Andric         parent_entry.AppendChar('\f');
20440b57cec5SDimitry Andric         break;
20450b57cec5SDimitry Andric       case 'n':
20460b57cec5SDimitry Andric         parent_entry.AppendChar('\n');
20470b57cec5SDimitry Andric         break;
20480b57cec5SDimitry Andric       case 'r':
20490b57cec5SDimitry Andric         parent_entry.AppendChar('\r');
20500b57cec5SDimitry Andric         break;
20510b57cec5SDimitry Andric       case 't':
20520b57cec5SDimitry Andric         parent_entry.AppendChar('\t');
20530b57cec5SDimitry Andric         break;
20540b57cec5SDimitry Andric       case 'v':
20550b57cec5SDimitry Andric         parent_entry.AppendChar('\v');
20560b57cec5SDimitry Andric         break;
20570b57cec5SDimitry Andric       case '\'':
20580b57cec5SDimitry Andric         parent_entry.AppendChar('\'');
20590b57cec5SDimitry Andric         break;
20600b57cec5SDimitry Andric       case '\\':
20610b57cec5SDimitry Andric         parent_entry.AppendChar('\\');
20620b57cec5SDimitry Andric         break;
20630b57cec5SDimitry Andric       case '0':
20640b57cec5SDimitry Andric         // 1 to 3 octal chars
20650b57cec5SDimitry Andric         {
20660b57cec5SDimitry Andric           // Make a string that can hold onto the initial zero char, up to 3
20670b57cec5SDimitry Andric           // octal digits, and a terminating NULL.
20680b57cec5SDimitry Andric           char oct_str[5] = {0, 0, 0, 0, 0};
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric           int i;
20710b57cec5SDimitry Andric           for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
20720b57cec5SDimitry Andric             oct_str[i] = format[i];
20730b57cec5SDimitry Andric 
20740b57cec5SDimitry Andric           // We don't want to consume the last octal character since the main
20750b57cec5SDimitry Andric           // for loop will do this for us, so we advance p by one less than i
20760b57cec5SDimitry Andric           // (even if i is zero)
20770b57cec5SDimitry Andric           format = format.drop_front(i);
20780b57cec5SDimitry Andric           unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
20790b57cec5SDimitry Andric           if (octal_value <= UINT8_MAX) {
20800b57cec5SDimitry Andric             parent_entry.AppendChar((char)octal_value);
20810b57cec5SDimitry Andric           } else {
20820b57cec5SDimitry Andric             error.SetErrorString("octal number is larger than a single byte");
20830b57cec5SDimitry Andric             return error;
20840b57cec5SDimitry Andric           }
20850b57cec5SDimitry Andric         }
20860b57cec5SDimitry Andric         break;
20870b57cec5SDimitry Andric 
20880b57cec5SDimitry Andric       case 'x':
20890b57cec5SDimitry Andric         // hex number in the format
20900b57cec5SDimitry Andric         if (isxdigit(format[0])) {
20910b57cec5SDimitry Andric           // Make a string that can hold onto two hex chars plus a
20920b57cec5SDimitry Andric           // NULL terminator
20930b57cec5SDimitry Andric           char hex_str[3] = {0, 0, 0};
20940b57cec5SDimitry Andric           hex_str[0] = format[0];
20950b57cec5SDimitry Andric 
20960b57cec5SDimitry Andric           format = format.drop_front();
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric           if (isxdigit(format[0])) {
20990b57cec5SDimitry Andric             hex_str[1] = format[0];
21000b57cec5SDimitry Andric             format = format.drop_front();
21010b57cec5SDimitry Andric           }
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric           unsigned long hex_value = strtoul(hex_str, nullptr, 16);
21040b57cec5SDimitry Andric           if (hex_value <= UINT8_MAX) {
21050b57cec5SDimitry Andric             parent_entry.AppendChar((char)hex_value);
21060b57cec5SDimitry Andric           } else {
21070b57cec5SDimitry Andric             error.SetErrorString("hex number is larger than a single byte");
21080b57cec5SDimitry Andric             return error;
21090b57cec5SDimitry Andric           }
21100b57cec5SDimitry Andric         } else {
21110b57cec5SDimitry Andric           parent_entry.AppendChar(desens_char);
21120b57cec5SDimitry Andric         }
21130b57cec5SDimitry Andric         break;
21140b57cec5SDimitry Andric 
21150b57cec5SDimitry Andric       default:
21160b57cec5SDimitry Andric         // Just desensitize any other character by just printing what came
21170b57cec5SDimitry Andric         // after the '\'
21180b57cec5SDimitry Andric         parent_entry.AppendChar(desens_char);
21190b57cec5SDimitry Andric         break;
21200b57cec5SDimitry Andric       }
21210b57cec5SDimitry Andric     } break;
21220b57cec5SDimitry Andric 
21230b57cec5SDimitry Andric     case '$':
21240b57cec5SDimitry Andric       if (format.size() == 1) {
21250b57cec5SDimitry Andric         // '$' at the end of a format string, just print the '$'
21260b57cec5SDimitry Andric         parent_entry.AppendText("$");
21270b57cec5SDimitry Andric       } else {
21280b57cec5SDimitry Andric         format = format.drop_front(); // Skip the '$'
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric         if (format[0] == '{') {
21310b57cec5SDimitry Andric           format = format.drop_front(); // Skip the '{'
21320b57cec5SDimitry Andric 
21330b57cec5SDimitry Andric           llvm::StringRef variable, variable_format;
21340b57cec5SDimitry Andric           error = FormatEntity::ExtractVariableInfo(format, variable,
21350b57cec5SDimitry Andric                                                     variable_format);
21360b57cec5SDimitry Andric           if (error.Fail())
21370b57cec5SDimitry Andric             return error;
21380b57cec5SDimitry Andric           bool verify_is_thread_id = false;
21390b57cec5SDimitry Andric           Entry entry;
21400b57cec5SDimitry Andric           if (!variable_format.empty()) {
21410b57cec5SDimitry Andric             entry.printf_format = variable_format.str();
21420b57cec5SDimitry Andric 
21430b57cec5SDimitry Andric             // If the format contains a '%' we are going to assume this is a
21440b57cec5SDimitry Andric             // printf style format. So if you want to format your thread ID
21450b57cec5SDimitry Andric             // using "0x%llx" you can use: ${thread.id%0x%llx}
21460b57cec5SDimitry Andric             //
21470b57cec5SDimitry Andric             // If there is no '%' in the format, then it is assumed to be a
21480b57cec5SDimitry Andric             // LLDB format name, or one of the extended formats specified in
21490b57cec5SDimitry Andric             // the switch statement below.
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric             if (entry.printf_format.find('%') == std::string::npos) {
21520b57cec5SDimitry Andric               bool clear_printf = false;
21530b57cec5SDimitry Andric 
21540b57cec5SDimitry Andric               if (FormatManager::GetFormatFromCString(
21550b57cec5SDimitry Andric                       entry.printf_format.c_str(), false, entry.fmt)) {
21560b57cec5SDimitry Andric                 // We have an LLDB format, so clear the printf format
21570b57cec5SDimitry Andric                 clear_printf = true;
21580b57cec5SDimitry Andric               } else if (entry.printf_format.size() == 1) {
21590b57cec5SDimitry Andric                 switch (entry.printf_format[0]) {
21600b57cec5SDimitry Andric                 case '@': // if this is an @ sign, print ObjC description
21610b57cec5SDimitry Andric                   entry.number = ValueObject::
21620b57cec5SDimitry Andric                       eValueObjectRepresentationStyleLanguageSpecific;
21630b57cec5SDimitry Andric                   clear_printf = true;
21640b57cec5SDimitry Andric                   break;
21650b57cec5SDimitry Andric                 case 'V': // if this is a V, print the value using the default
21660b57cec5SDimitry Andric                           // format
21670b57cec5SDimitry Andric                   entry.number =
21680b57cec5SDimitry Andric                       ValueObject::eValueObjectRepresentationStyleValue;
21690b57cec5SDimitry Andric                   clear_printf = true;
21700b57cec5SDimitry Andric                   break;
21710b57cec5SDimitry Andric                 case 'L': // if this is an L, print the location of the value
21720b57cec5SDimitry Andric                   entry.number =
21730b57cec5SDimitry Andric                       ValueObject::eValueObjectRepresentationStyleLocation;
21740b57cec5SDimitry Andric                   clear_printf = true;
21750b57cec5SDimitry Andric                   break;
21760b57cec5SDimitry Andric                 case 'S': // if this is an S, print the summary after all
21770b57cec5SDimitry Andric                   entry.number =
21780b57cec5SDimitry Andric                       ValueObject::eValueObjectRepresentationStyleSummary;
21790b57cec5SDimitry Andric                   clear_printf = true;
21800b57cec5SDimitry Andric                   break;
21810b57cec5SDimitry Andric                 case '#': // if this is a '#', print the number of children
21820b57cec5SDimitry Andric                   entry.number =
21830b57cec5SDimitry Andric                       ValueObject::eValueObjectRepresentationStyleChildrenCount;
21840b57cec5SDimitry Andric                   clear_printf = true;
21850b57cec5SDimitry Andric                   break;
21860b57cec5SDimitry Andric                 case 'T': // if this is a 'T', print the type
21870b57cec5SDimitry Andric                   entry.number =
21880b57cec5SDimitry Andric                       ValueObject::eValueObjectRepresentationStyleType;
21890b57cec5SDimitry Andric                   clear_printf = true;
21900b57cec5SDimitry Andric                   break;
21910b57cec5SDimitry Andric                 case 'N': // if this is a 'N', print the name
21920b57cec5SDimitry Andric                   entry.number =
21930b57cec5SDimitry Andric                       ValueObject::eValueObjectRepresentationStyleName;
21940b57cec5SDimitry Andric                   clear_printf = true;
21950b57cec5SDimitry Andric                   break;
21960b57cec5SDimitry Andric                 case '>': // if this is a '>', print the expression path
21970b57cec5SDimitry Andric                   entry.number = ValueObject::
21980b57cec5SDimitry Andric                       eValueObjectRepresentationStyleExpressionPath;
21990b57cec5SDimitry Andric                   clear_printf = true;
22000b57cec5SDimitry Andric                   break;
22010b57cec5SDimitry Andric                 default:
22020b57cec5SDimitry Andric                   error.SetErrorStringWithFormat("invalid format: '%s'",
22030b57cec5SDimitry Andric                                                  entry.printf_format.c_str());
22040b57cec5SDimitry Andric                   return error;
22050b57cec5SDimitry Andric                 }
22060b57cec5SDimitry Andric               } else if (FormatManager::GetFormatFromCString(
22070b57cec5SDimitry Andric                              entry.printf_format.c_str(), true, entry.fmt)) {
22080b57cec5SDimitry Andric                 clear_printf = true;
22090b57cec5SDimitry Andric               } else if (entry.printf_format == "tid") {
22100b57cec5SDimitry Andric                 verify_is_thread_id = true;
22110b57cec5SDimitry Andric               } else {
22120b57cec5SDimitry Andric                 error.SetErrorStringWithFormat("invalid format: '%s'",
22130b57cec5SDimitry Andric                                                entry.printf_format.c_str());
22140b57cec5SDimitry Andric                 return error;
22150b57cec5SDimitry Andric               }
22160b57cec5SDimitry Andric 
22170b57cec5SDimitry Andric               // Our format string turned out to not be a printf style format
22180b57cec5SDimitry Andric               // so lets clear the string
22190b57cec5SDimitry Andric               if (clear_printf)
22200b57cec5SDimitry Andric                 entry.printf_format.clear();
22210b57cec5SDimitry Andric             }
22220b57cec5SDimitry Andric           }
22230b57cec5SDimitry Andric 
22240b57cec5SDimitry Andric           // Check for dereferences
22250b57cec5SDimitry Andric           if (variable[0] == '*') {
22260b57cec5SDimitry Andric             entry.deref = true;
22270b57cec5SDimitry Andric             variable = variable.drop_front();
22280b57cec5SDimitry Andric           }
22290b57cec5SDimitry Andric 
22300b57cec5SDimitry Andric           error = ParseEntry(variable, &g_root, entry);
22310b57cec5SDimitry Andric           if (error.Fail())
22320b57cec5SDimitry Andric             return error;
22330b57cec5SDimitry Andric 
22340b57cec5SDimitry Andric           if (verify_is_thread_id) {
22350b57cec5SDimitry Andric             if (entry.type != Entry::Type::ThreadID &&
22360b57cec5SDimitry Andric                 entry.type != Entry::Type::ThreadProtocolID) {
22370b57cec5SDimitry Andric               error.SetErrorString("the 'tid' format can only be used on "
22380b57cec5SDimitry Andric                                    "${thread.id} and ${thread.protocol_id}");
22390b57cec5SDimitry Andric             }
22400b57cec5SDimitry Andric           }
22410b57cec5SDimitry Andric 
22420b57cec5SDimitry Andric           switch (entry.type) {
22430b57cec5SDimitry Andric           case Entry::Type::Variable:
22440b57cec5SDimitry Andric           case Entry::Type::VariableSynthetic:
22450b57cec5SDimitry Andric             if (entry.number == 0) {
22460b57cec5SDimitry Andric               if (entry.string.empty())
22470b57cec5SDimitry Andric                 entry.number =
22480b57cec5SDimitry Andric                     ValueObject::eValueObjectRepresentationStyleValue;
22490b57cec5SDimitry Andric               else
22500b57cec5SDimitry Andric                 entry.number =
22510b57cec5SDimitry Andric                     ValueObject::eValueObjectRepresentationStyleSummary;
22520b57cec5SDimitry Andric             }
22530b57cec5SDimitry Andric             break;
22540b57cec5SDimitry Andric           default:
22550b57cec5SDimitry Andric             // Make sure someone didn't try to dereference anything but ${var}
22560b57cec5SDimitry Andric             // or ${svar}
22570b57cec5SDimitry Andric             if (entry.deref) {
22580b57cec5SDimitry Andric               error.SetErrorStringWithFormat(
22590b57cec5SDimitry Andric                   "${%s} can't be dereferenced, only ${var} and ${svar} can.",
22600b57cec5SDimitry Andric                   variable.str().c_str());
22610b57cec5SDimitry Andric               return error;
22620b57cec5SDimitry Andric             }
22630b57cec5SDimitry Andric           }
22640b57cec5SDimitry Andric           parent_entry.AppendEntry(std::move(entry));
22650b57cec5SDimitry Andric         }
22660b57cec5SDimitry Andric       }
22670b57cec5SDimitry Andric       break;
22680b57cec5SDimitry Andric     }
22690b57cec5SDimitry Andric   }
22700b57cec5SDimitry Andric   return error;
22710b57cec5SDimitry Andric }
22720b57cec5SDimitry Andric 
ExtractVariableInfo(llvm::StringRef & format_str,llvm::StringRef & variable_name,llvm::StringRef & variable_format)22730b57cec5SDimitry Andric Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
22740b57cec5SDimitry Andric                                          llvm::StringRef &variable_name,
22750b57cec5SDimitry Andric                                          llvm::StringRef &variable_format) {
22760b57cec5SDimitry Andric   Status error;
22770b57cec5SDimitry Andric   variable_name = llvm::StringRef();
22780b57cec5SDimitry Andric   variable_format = llvm::StringRef();
22790b57cec5SDimitry Andric 
22800b57cec5SDimitry Andric   const size_t paren_pos = format_str.find('}');
22810b57cec5SDimitry Andric   if (paren_pos != llvm::StringRef::npos) {
22820b57cec5SDimitry Andric     const size_t percent_pos = format_str.find('%');
22830b57cec5SDimitry Andric     if (percent_pos < paren_pos) {
22840b57cec5SDimitry Andric       if (percent_pos > 0) {
22850b57cec5SDimitry Andric         if (percent_pos > 1)
22860b57cec5SDimitry Andric           variable_name = format_str.substr(0, percent_pos);
22870b57cec5SDimitry Andric         variable_format =
22880b57cec5SDimitry Andric             format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
22890b57cec5SDimitry Andric       }
22900b57cec5SDimitry Andric     } else {
22910b57cec5SDimitry Andric       variable_name = format_str.substr(0, paren_pos);
22920b57cec5SDimitry Andric     }
22930b57cec5SDimitry Andric     // Strip off elements and the formatting and the trailing '}'
22940b57cec5SDimitry Andric     format_str = format_str.substr(paren_pos + 1);
22950b57cec5SDimitry Andric   } else {
22960b57cec5SDimitry Andric     error.SetErrorStringWithFormat(
22970b57cec5SDimitry Andric         "missing terminating '}' character for '${%s'",
22980b57cec5SDimitry Andric         format_str.str().c_str());
22990b57cec5SDimitry Andric   }
23000b57cec5SDimitry Andric   return error;
23010b57cec5SDimitry Andric }
23020b57cec5SDimitry Andric 
FormatFileSpec(const FileSpec & file_spec,Stream & s,llvm::StringRef variable_name,llvm::StringRef variable_format)23030b57cec5SDimitry Andric bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
23040b57cec5SDimitry Andric                                   llvm::StringRef variable_name,
23050b57cec5SDimitry Andric                                   llvm::StringRef variable_format) {
23060b57cec5SDimitry Andric   if (variable_name.empty() || variable_name.equals(".fullpath")) {
2307480093f4SDimitry Andric     file_spec.Dump(s.AsRawOstream());
23080b57cec5SDimitry Andric     return true;
23090b57cec5SDimitry Andric   } else if (variable_name.equals(".basename")) {
23105ffd83dbSDimitry Andric     s.PutCString(file_spec.GetFilename().GetStringRef());
23110b57cec5SDimitry Andric     return true;
23120b57cec5SDimitry Andric   } else if (variable_name.equals(".dirname")) {
23135ffd83dbSDimitry Andric     s.PutCString(file_spec.GetFilename().GetStringRef());
23140b57cec5SDimitry Andric     return true;
23150b57cec5SDimitry Andric   }
23160b57cec5SDimitry Andric   return false;
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric 
MakeMatch(const llvm::StringRef & prefix,const char * suffix)23190b57cec5SDimitry Andric static std::string MakeMatch(const llvm::StringRef &prefix,
23200b57cec5SDimitry Andric                              const char *suffix) {
23210b57cec5SDimitry Andric   std::string match(prefix.str());
23220b57cec5SDimitry Andric   match.append(suffix);
23230b57cec5SDimitry Andric   return match;
23240b57cec5SDimitry Andric }
23250b57cec5SDimitry Andric 
AddMatches(const Definition * def,const llvm::StringRef & prefix,const llvm::StringRef & match_prefix,StringList & matches)2326fe6060f1SDimitry Andric static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
23270b57cec5SDimitry Andric                        const llvm::StringRef &match_prefix,
23280b57cec5SDimitry Andric                        StringList &matches) {
23290b57cec5SDimitry Andric   const size_t n = def->num_children;
23300b57cec5SDimitry Andric   if (n > 0) {
23310b57cec5SDimitry Andric     for (size_t i = 0; i < n; ++i) {
23320b57cec5SDimitry Andric       std::string match = prefix.str();
23330b57cec5SDimitry Andric       if (match_prefix.empty())
23340b57cec5SDimitry Andric         matches.AppendString(MakeMatch(prefix, def->children[i].name));
23350b57cec5SDimitry Andric       else if (strncmp(def->children[i].name, match_prefix.data(),
23360b57cec5SDimitry Andric                        match_prefix.size()) == 0)
23370b57cec5SDimitry Andric         matches.AppendString(
23380b57cec5SDimitry Andric             MakeMatch(prefix, def->children[i].name + match_prefix.size()));
23390b57cec5SDimitry Andric     }
23400b57cec5SDimitry Andric   }
23410b57cec5SDimitry Andric }
23420b57cec5SDimitry Andric 
AutoComplete(CompletionRequest & request)23439dba64beSDimitry Andric void FormatEntity::AutoComplete(CompletionRequest &request) {
23449dba64beSDimitry Andric   llvm::StringRef str = request.GetCursorArgumentPrefix();
23450b57cec5SDimitry Andric 
23460b57cec5SDimitry Andric   const size_t dollar_pos = str.rfind('$');
23470b57cec5SDimitry Andric   if (dollar_pos == llvm::StringRef::npos)
23489dba64beSDimitry Andric     return;
23490b57cec5SDimitry Andric 
23500b57cec5SDimitry Andric   // Hitting TAB after $ at the end of the string add a "{"
23510b57cec5SDimitry Andric   if (dollar_pos == str.size() - 1) {
23520b57cec5SDimitry Andric     std::string match = str.str();
23530b57cec5SDimitry Andric     match.append("{");
23540b57cec5SDimitry Andric     request.AddCompletion(match);
23559dba64beSDimitry Andric     return;
23560b57cec5SDimitry Andric   }
23570b57cec5SDimitry Andric 
23580b57cec5SDimitry Andric   if (str[dollar_pos + 1] != '{')
23599dba64beSDimitry Andric     return;
23600b57cec5SDimitry Andric 
23610b57cec5SDimitry Andric   const size_t close_pos = str.find('}', dollar_pos + 2);
23620b57cec5SDimitry Andric   if (close_pos != llvm::StringRef::npos)
23639dba64beSDimitry Andric     return;
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric   const size_t format_pos = str.find('%', dollar_pos + 2);
23660b57cec5SDimitry Andric   if (format_pos != llvm::StringRef::npos)
23679dba64beSDimitry Andric     return;
23680b57cec5SDimitry Andric 
23690b57cec5SDimitry Andric   llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
23700b57cec5SDimitry Andric   if (partial_variable.empty()) {
23715ffd83dbSDimitry Andric     // Suggest all top level entities as we are just past "${"
23720b57cec5SDimitry Andric     StringList new_matches;
23730b57cec5SDimitry Andric     AddMatches(&g_root, str, llvm::StringRef(), new_matches);
23740b57cec5SDimitry Andric     request.AddCompletions(new_matches);
23759dba64beSDimitry Andric     return;
23760b57cec5SDimitry Andric   }
23770b57cec5SDimitry Andric 
23780b57cec5SDimitry Andric   // We have a partially specified variable, find it
23790b57cec5SDimitry Andric   llvm::StringRef remainder;
2380fe6060f1SDimitry Andric   const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
23810b57cec5SDimitry Andric   if (!entry_def)
23829dba64beSDimitry Andric     return;
23830b57cec5SDimitry Andric 
23840b57cec5SDimitry Andric   const size_t n = entry_def->num_children;
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric   if (remainder.empty()) {
23870b57cec5SDimitry Andric     // Exact match
23880b57cec5SDimitry Andric     if (n > 0) {
23890b57cec5SDimitry Andric       // "${thread.info" <TAB>
23900b57cec5SDimitry Andric       request.AddCompletion(MakeMatch(str, "."));
23910b57cec5SDimitry Andric     } else {
23920b57cec5SDimitry Andric       // "${thread.id" <TAB>
23930b57cec5SDimitry Andric       request.AddCompletion(MakeMatch(str, "}"));
23940b57cec5SDimitry Andric     }
23950b57cec5SDimitry Andric   } else if (remainder.equals(".")) {
23960b57cec5SDimitry Andric     // "${thread." <TAB>
23970b57cec5SDimitry Andric     StringList new_matches;
23980b57cec5SDimitry Andric     AddMatches(entry_def, str, llvm::StringRef(), new_matches);
23990b57cec5SDimitry Andric     request.AddCompletions(new_matches);
24000b57cec5SDimitry Andric   } else {
24010b57cec5SDimitry Andric     // We have a partial match
24020b57cec5SDimitry Andric     // "${thre" <TAB>
24030b57cec5SDimitry Andric     StringList new_matches;
24040b57cec5SDimitry Andric     AddMatches(entry_def, str, remainder, new_matches);
24050b57cec5SDimitry Andric     request.AddCompletions(new_matches);
24060b57cec5SDimitry Andric   }
24070b57cec5SDimitry Andric }
2408bdd1243dSDimitry Andric 
PrettyPrintFunctionArguments(Stream & out_stream,VariableList const & args,ExecutionContextScope * exe_scope)2409bdd1243dSDimitry Andric void FormatEntity::PrettyPrintFunctionArguments(
2410bdd1243dSDimitry Andric     Stream &out_stream, VariableList const &args,
2411bdd1243dSDimitry Andric     ExecutionContextScope *exe_scope) {
2412bdd1243dSDimitry Andric   const size_t num_args = args.GetSize();
2413bdd1243dSDimitry Andric   for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
2414bdd1243dSDimitry Andric     std::string buffer;
2415bdd1243dSDimitry Andric 
2416bdd1243dSDimitry Andric     VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
2417bdd1243dSDimitry Andric     ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
2418bdd1243dSDimitry Andric     StreamString ss;
2419bdd1243dSDimitry Andric     llvm::StringRef var_representation;
2420bdd1243dSDimitry Andric     const char *var_name = var_value_sp->GetName().GetCString();
2421bdd1243dSDimitry Andric     if (var_value_sp->GetCompilerType().IsValid()) {
2422bdd1243dSDimitry Andric       if (exe_scope && exe_scope->CalculateTarget())
2423bdd1243dSDimitry Andric         var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
2424bdd1243dSDimitry Andric             exe_scope->CalculateTarget()
2425bdd1243dSDimitry Andric                 ->TargetProperties::GetPreferDynamicValue(),
2426bdd1243dSDimitry Andric             exe_scope->CalculateTarget()
2427bdd1243dSDimitry Andric                 ->TargetProperties::GetEnableSyntheticValue());
2428bdd1243dSDimitry Andric       if (var_value_sp->GetCompilerType().IsAggregateType() &&
2429bdd1243dSDimitry Andric           DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
2430bdd1243dSDimitry Andric         static StringSummaryFormat format(TypeSummaryImpl::Flags()
2431bdd1243dSDimitry Andric                                               .SetHideItemNames(false)
2432bdd1243dSDimitry Andric                                               .SetShowMembersOneLiner(true),
2433bdd1243dSDimitry Andric                                           "");
2434bdd1243dSDimitry Andric         format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2435bdd1243dSDimitry Andric         var_representation = buffer;
2436bdd1243dSDimitry Andric       } else
2437bdd1243dSDimitry Andric         var_value_sp->DumpPrintableRepresentation(
2438bdd1243dSDimitry Andric             ss,
2439bdd1243dSDimitry Andric             ValueObject::ValueObjectRepresentationStyle::
2440bdd1243dSDimitry Andric                 eValueObjectRepresentationStyleSummary,
2441bdd1243dSDimitry Andric             eFormatDefault,
2442bdd1243dSDimitry Andric             ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
2443bdd1243dSDimitry Andric     }
2444bdd1243dSDimitry Andric 
2445bdd1243dSDimitry Andric     if (!ss.GetString().empty())
2446bdd1243dSDimitry Andric       var_representation = ss.GetString();
2447bdd1243dSDimitry Andric     if (arg_idx > 0)
2448bdd1243dSDimitry Andric       out_stream.PutCString(", ");
2449bdd1243dSDimitry Andric     if (var_value_sp->GetError().Success()) {
2450bdd1243dSDimitry Andric       if (!var_representation.empty())
2451bdd1243dSDimitry Andric         out_stream.Printf("%s=%s", var_name, var_representation.str().c_str());
2452bdd1243dSDimitry Andric       else
2453bdd1243dSDimitry Andric         out_stream.Printf("%s=%s at %s", var_name,
2454bdd1243dSDimitry Andric                           var_value_sp->GetTypeName().GetCString(),
2455bdd1243dSDimitry Andric                           var_value_sp->GetLocationAsCString());
2456bdd1243dSDimitry Andric     } else
2457bdd1243dSDimitry Andric       out_stream.Printf("%s=<unavailable>", var_name);
2458bdd1243dSDimitry Andric   }
2459bdd1243dSDimitry Andric }
2460c9157d92SDimitry Andric 
Parse(const llvm::StringRef & format_str,Entry & entry)2461c9157d92SDimitry Andric Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
2462c9157d92SDimitry Andric   entry.Clear();
2463c9157d92SDimitry Andric   entry.type = Entry::Type::Root;
2464c9157d92SDimitry Andric   llvm::StringRef modifiable_format(format_str);
2465c9157d92SDimitry Andric   return ParseInternal(modifiable_format, entry, 0);
2466c9157d92SDimitry Andric }
2467