1554f68d3SGreg Clayton //===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===//
2554f68d3SGreg Clayton //
3554f68d3SGreg Clayton //                     The LLVM Compiler Infrastructure
4554f68d3SGreg Clayton //
5554f68d3SGreg Clayton // This file is distributed under the University of Illinois Open Source
6554f68d3SGreg Clayton // License. See LICENSE.TXT for details.
7554f68d3SGreg Clayton //
8554f68d3SGreg Clayton //===----------------------------------------------------------------------===//
9554f68d3SGreg Clayton 
10554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h"
11554f68d3SGreg Clayton 
12554f68d3SGreg Clayton #include "lldb/Core/Address.h"
13*2f3df613SZachary Turner #include "lldb/Core/AddressRange.h" // for AddressRange
14*2f3df613SZachary Turner #include "lldb/Core/ArchSpec.h"     // for ArchSpec
15554f68d3SGreg Clayton #include "lldb/Core/Debugger.h"
16554f68d3SGreg Clayton #include "lldb/Core/Module.h"
17*2f3df613SZachary Turner #include "lldb/Core/RegisterValue.h"  // for RegisterValue
18*2f3df613SZachary Turner #include "lldb/Core/StructuredData.h" // for StructuredData::O...
19554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h"
20554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h"
21554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h"
22*2f3df613SZachary Turner #include "lldb/DataFormatters/FormatClasses.h" // for TypeNameSpecifier...
23554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h"
24*2f3df613SZachary Turner #include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryImpl::...
25937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h"
26554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
27554f68d3SGreg Clayton #include "lldb/Symbol/Block.h"
28554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
29*2f3df613SZachary Turner #include "lldb/Symbol/CompilerType.h" // for CompilerType
30554f68d3SGreg Clayton #include "lldb/Symbol/Function.h"
31554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h"
32554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h"
33*2f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext
34554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h"
35554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h"
36*2f3df613SZachary Turner #include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextS...
370e0984eeSJim Ingham #include "lldb/Target/Language.h"
38554f68d3SGreg Clayton #include "lldb/Target/Process.h"
39554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h"
40554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h"
41554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h"
42554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h"
43554f68d3SGreg Clayton #include "lldb/Target/Target.h"
44554f68d3SGreg Clayton #include "lldb/Target/Thread.h"
45554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
46*2f3df613SZachary Turner #include "lldb/Utility/ConstString.h" // for ConstString, oper...
475713a05bSZachary Turner #include "lldb/Utility/FileSpec.h"
48*2f3df613SZachary Turner #include "lldb/Utility/Log.h"        // for Log
49*2f3df613SZachary Turner #include "lldb/Utility/Logging.h"    // for GetLogIfAllCatego...
50*2f3df613SZachary Turner #include "lldb/Utility/SharingPtr.h" // for SharingPtr
51bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
52bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
53*2f3df613SZachary Turner #include "lldb/Utility/StringList.h" // for StringList
54*2f3df613SZachary Turner #include "lldb/lldb-defines.h"       // for LLDB_INVALID_ADDRESS
55*2f3df613SZachary Turner #include "lldb/lldb-forward.h"       // for ValueObjectSP
56*2f3df613SZachary Turner #include "llvm/ADT/STLExtras.h"
57*2f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
58*2f3df613SZachary Turner #include "llvm/ADT/Triple.h"       // for Triple, Triple::O...
59*2f3df613SZachary Turner #include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
60*2f3df613SZachary Turner 
61*2f3df613SZachary Turner #include <ctype.h>     // for isxdigit
62*2f3df613SZachary Turner #include <inttypes.h>  // for PRIu64, PRIx64
63*2f3df613SZachary Turner #include <memory>      // for shared_ptr, opera...
64*2f3df613SZachary Turner #include <stdio.h>     // for sprintf
65*2f3df613SZachary Turner #include <stdlib.h>    // for strtoul
66*2f3df613SZachary Turner #include <string.h>    // for size_t, strchr
67*2f3df613SZachary Turner #include <type_traits> // for move
68*2f3df613SZachary Turner #include <utility>     // for pair
69*2f3df613SZachary Turner 
70*2f3df613SZachary Turner namespace lldb_private {
71*2f3df613SZachary Turner class ScriptInterpreter;
72*2f3df613SZachary Turner }
73*2f3df613SZachary Turner namespace lldb_private {
74*2f3df613SZachary Turner struct RegisterInfo;
75*2f3df613SZachary Turner }
76554f68d3SGreg Clayton 
77554f68d3SGreg Clayton using namespace lldb;
78554f68d3SGreg Clayton using namespace lldb_private;
79554f68d3SGreg Clayton 
80b9c1b51eSKate Stone enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
81554f68d3SGreg Clayton 
82b9c1b51eSKate Stone #define ENTRY(n, t, f)                                                         \
83b9c1b51eSKate Stone   {                                                                            \
84b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
85b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false               \
86b9c1b51eSKate Stone   }
87b9c1b51eSKate Stone #define ENTRY_VALUE(n, t, f, v)                                                \
88b9c1b51eSKate Stone   {                                                                            \
89b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
90b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, v, 0, nullptr, false               \
91b9c1b51eSKate Stone   }
92b9c1b51eSKate Stone #define ENTRY_CHILDREN(n, t, f, c)                                             \
93b9c1b51eSKate Stone   {                                                                            \
94b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
95e28558f0SZachary Turner         FormatEntity::Entry::FormatType::f, 0,                                 \
96e28558f0SZachary Turner         static_cast<uint32_t>(llvm::array_lengthof(c)), c, false               \
97b9c1b51eSKate Stone   }
98b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c)                                    \
99b9c1b51eSKate Stone   {                                                                            \
100b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
101e28558f0SZachary Turner         FormatEntity::Entry::FormatType::f, 0,                                 \
102e28558f0SZachary Turner         static_cast<uint32_t>(llvm::array_lengthof(c)), c, true                \
103b9c1b51eSKate Stone   }
104b9c1b51eSKate Stone #define ENTRY_STRING(n, s)                                                     \
105b9c1b51eSKate Stone   {                                                                            \
106b9c1b51eSKate Stone     n, s, FormatEntity::Entry::Type::InsertString,                             \
107b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false            \
108b9c1b51eSKate Stone   }
109b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_string_entry[] = {
110b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
111554f68d3SGreg Clayton 
112b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_addr_entries[] = {
113b9c1b51eSKate Stone     ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64),
114554f68d3SGreg Clayton     ENTRY("load", AddressLoadOrFile, UInt64),
115554f68d3SGreg Clayton };
116554f68d3SGreg Clayton 
117b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_file_child_entries[] = {
118554f68d3SGreg Clayton     ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename),
119554f68d3SGreg Clayton     ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname),
120b9c1b51eSKate Stone     ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)};
121554f68d3SGreg Clayton 
122b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_frame_child_entries[] = {
123554f68d3SGreg Clayton     ENTRY("index", FrameIndex, UInt32),
124554f68d3SGreg Clayton     ENTRY("pc", FrameRegisterPC, UInt64),
125554f68d3SGreg Clayton     ENTRY("fp", FrameRegisterFP, UInt64),
126554f68d3SGreg Clayton     ENTRY("sp", FrameRegisterSP, UInt64),
127554f68d3SGreg Clayton     ENTRY("flags", FrameRegisterFlags, UInt64),
1286a9767c7SJim Ingham     ENTRY("no-debug", FrameNoDebug, None),
129554f68d3SGreg Clayton     ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry),
130554f68d3SGreg Clayton };
131554f68d3SGreg Clayton 
132b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = {
133b9c1b51eSKate Stone     ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString),
134554f68d3SGreg Clayton     ENTRY("name-without-args", FunctionNameNoArgs, CString),
135554f68d3SGreg Clayton     ENTRY("name-with-args", FunctionNameWithArgs, CString),
136554f68d3SGreg Clayton     ENTRY("addr-offset", FunctionAddrOffset, UInt64),
137b9c1b51eSKate Stone     ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete,
138b9c1b51eSKate Stone           UInt64),
139554f68d3SGreg Clayton     ENTRY("line-offset", FunctionLineOffset, UInt64),
140c980fa92SJason Molenda     ENTRY("pc-offset", FunctionPCOffset, UInt64),
141c980fa92SJason Molenda     ENTRY("initial-function", FunctionInitial, None),
1426ab659a9SJason Molenda     ENTRY("changed", FunctionChanged, None),
143b9c1b51eSKate Stone     ENTRY("is-optimized", FunctionIsOptimized, None)};
144554f68d3SGreg Clayton 
145b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = {
146554f68d3SGreg Clayton     ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries),
147554f68d3SGreg Clayton     ENTRY("number", LineEntryLineNumber, UInt32),
148554f68d3SGreg Clayton     ENTRY("start-addr", LineEntryStartAddress, UInt64),
149554f68d3SGreg Clayton     ENTRY("end-addr", LineEntryEndAddress, UInt64),
150554f68d3SGreg Clayton };
151554f68d3SGreg Clayton 
152b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = {
153554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
154554f68d3SGreg Clayton };
155554f68d3SGreg Clayton 
156b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = {
157554f68d3SGreg Clayton     ENTRY("id", ProcessID, UInt64),
158554f68d3SGreg Clayton     ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename),
159554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries),
160554f68d3SGreg Clayton };
161554f68d3SGreg Clayton 
162b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = {
163b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
164554f68d3SGreg Clayton 
165b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = {
166b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
167554f68d3SGreg Clayton 
168b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = {
169554f68d3SGreg Clayton     ENTRY("id", ThreadID, UInt64),
170554f68d3SGreg Clayton     ENTRY("protocol_id", ThreadProtocolID, UInt64),
171554f68d3SGreg Clayton     ENTRY("index", ThreadIndexID, UInt32),
172554f68d3SGreg Clayton     ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry),
173554f68d3SGreg Clayton     ENTRY("queue", ThreadQueue, CString),
174554f68d3SGreg Clayton     ENTRY("name", ThreadName, CString),
175554f68d3SGreg Clayton     ENTRY("stop-reason", ThreadStopReason, CString),
176554f68d3SGreg Clayton     ENTRY("return-value", ThreadReturnValue, CString),
177554f68d3SGreg Clayton     ENTRY("completed-expression", ThreadCompletedExpression, CString),
178554f68d3SGreg Clayton };
179554f68d3SGreg Clayton 
180b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = {
181554f68d3SGreg Clayton     ENTRY("arch", TargetArch, CString),
182554f68d3SGreg Clayton };
183554f68d3SGreg Clayton 
184554f68d3SGreg Clayton #define _TO_STR2(_val) #_val
185554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val)
186554f68d3SGreg Clayton 
187b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
188b9c1b51eSKate Stone     ENTRY_STRING("black",
189b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
190554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
191b9c1b51eSKate Stone     ENTRY_STRING("green",
192b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
193b9c1b51eSKate Stone     ENTRY_STRING("yellow",
194b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
195b9c1b51eSKate Stone     ENTRY_STRING("blue",
196b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
197b9c1b51eSKate Stone     ENTRY_STRING("purple",
198b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
199b9c1b51eSKate Stone     ENTRY_STRING("cyan",
200b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
201b9c1b51eSKate Stone     ENTRY_STRING("white",
202b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
203554f68d3SGreg Clayton };
204554f68d3SGreg Clayton 
205b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
206b9c1b51eSKate Stone     ENTRY_STRING("black",
207b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
208554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
209b9c1b51eSKate Stone     ENTRY_STRING("green",
210b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
211b9c1b51eSKate Stone     ENTRY_STRING("yellow",
212b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
213b9c1b51eSKate Stone     ENTRY_STRING("blue",
214b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
215b9c1b51eSKate Stone     ENTRY_STRING("purple",
216b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
217b9c1b51eSKate Stone     ENTRY_STRING("cyan",
218b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
219b9c1b51eSKate Stone     ENTRY_STRING("white",
220b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
221554f68d3SGreg Clayton };
222554f68d3SGreg Clayton 
223b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = {
224554f68d3SGreg Clayton     ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries),
225554f68d3SGreg Clayton     ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries),
226b9c1b51eSKate Stone     ENTRY_STRING("normal",
227b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
228554f68d3SGreg Clayton     ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
229554f68d3SGreg Clayton     ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
230b9c1b51eSKate Stone     ENTRY_STRING("italic",
231b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
232b9c1b51eSKate Stone     ENTRY_STRING("underline",
233b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
234b9c1b51eSKate Stone     ENTRY_STRING("slow-blink",
235b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
236b9c1b51eSKate Stone     ENTRY_STRING("fast-blink",
237b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
238b9c1b51eSKate Stone     ENTRY_STRING("negative",
239b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
240b9c1b51eSKate Stone     ENTRY_STRING("conceal",
241b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
242b9c1b51eSKate Stone     ENTRY_STRING("crossed-out",
243b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
244554f68d3SGreg Clayton };
245554f68d3SGreg Clayton 
246b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = {
247554f68d3SGreg Clayton     ENTRY("frame", ScriptFrame, None),
248554f68d3SGreg Clayton     ENTRY("process", ScriptProcess, None),
249554f68d3SGreg Clayton     ENTRY("target", ScriptTarget, None),
250554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
251554f68d3SGreg Clayton     ENTRY("var", ScriptVariable, None),
252554f68d3SGreg Clayton     ENTRY("svar", ScriptVariableSynthetic, None),
253554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
254554f68d3SGreg Clayton };
255554f68d3SGreg Clayton 
256b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = {
257554f68d3SGreg Clayton     ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries),
258554f68d3SGreg Clayton     ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64),
259554f68d3SGreg Clayton     ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries),
260554f68d3SGreg Clayton     ENTRY("current-pc-arrow", CurrentPCArrow, CString),
261554f68d3SGreg Clayton     ENTRY_CHILDREN("file", File, CString, g_file_child_entries),
262dc975670SDawn Perchik     ENTRY("language", Lang, CString),
263554f68d3SGreg Clayton     ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries),
264554f68d3SGreg Clayton     ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries),
265554f68d3SGreg Clayton     ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries),
266554f68d3SGreg Clayton     ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries),
267554f68d3SGreg Clayton     ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries),
268554f68d3SGreg Clayton     ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries),
269b9c1b51eSKate Stone     ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None,
270b9c1b51eSKate Stone                             g_svar_child_entries),
271554f68d3SGreg Clayton     ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries),
272554f68d3SGreg Clayton     ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries),
273554f68d3SGreg Clayton     ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries),
274554f68d3SGreg Clayton };
275554f68d3SGreg Clayton 
276b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root =
277b9c1b51eSKate Stone     ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries);
278554f68d3SGreg Clayton 
279b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s)
280b9c1b51eSKate Stone     : string(s.data(), s.size()), printf_format(), children(),
281b9c1b51eSKate Stone       definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
282b9c1b51eSKate Stone       number(0), deref(false) {}
283554f68d3SGreg Clayton 
284b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch)
285b9c1b51eSKate Stone     : string(1, ch), printf_format(), children(), definition(nullptr),
286b9c1b51eSKate Stone       type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
287554f68d3SGreg Clayton 
288b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) {
289554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
290554f68d3SGreg Clayton     children.push_back(Entry(ch));
291554f68d3SGreg Clayton   else
292554f68d3SGreg Clayton     children.back().string.append(1, ch);
293554f68d3SGreg Clayton }
294554f68d3SGreg Clayton 
295b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
296554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
297554f68d3SGreg Clayton     children.push_back(Entry(s));
298554f68d3SGreg Clayton   else
299554f68d3SGreg Clayton     children.back().string.append(s.data(), s.size());
300554f68d3SGreg Clayton }
301554f68d3SGreg Clayton 
302b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) {
303554f68d3SGreg Clayton   return AppendText(llvm::StringRef(cstr));
304554f68d3SGreg Clayton }
305554f68d3SGreg Clayton 
306b9c1b51eSKate Stone Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
307554f68d3SGreg Clayton   entry.Clear();
308554f68d3SGreg Clayton   entry.type = Entry::Type::Root;
309554f68d3SGreg Clayton   llvm::StringRef modifiable_format(format_str);
310554f68d3SGreg Clayton   return ParseInternal(modifiable_format, entry, 0);
311554f68d3SGreg Clayton }
312554f68d3SGreg Clayton 
313b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee)                                                      \
314b9c1b51eSKate Stone   case FormatEntity::Entry::Type::eee:                                         \
315b9c1b51eSKate Stone     return #eee
316554f68d3SGreg Clayton 
317b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) {
318b9c1b51eSKate Stone   switch (t) {
319554f68d3SGreg Clayton     ENUM_TO_CSTR(Invalid);
320554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentNumber);
321554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentString);
322554f68d3SGreg Clayton     ENUM_TO_CSTR(InsertString);
323554f68d3SGreg Clayton     ENUM_TO_CSTR(Root);
324554f68d3SGreg Clayton     ENUM_TO_CSTR(String);
325554f68d3SGreg Clayton     ENUM_TO_CSTR(Scope);
326554f68d3SGreg Clayton     ENUM_TO_CSTR(Variable);
327554f68d3SGreg Clayton     ENUM_TO_CSTR(VariableSynthetic);
328554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariable);
329554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariableSynthetic);
330554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoad);
331554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressFile);
332554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoadOrFile);
333554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessID);
334554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessFile);
335554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptProcess);
336554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadID);
337554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadProtocolID);
338554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadIndexID);
339554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadName);
340554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadQueue);
341554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadStopReason);
342554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadReturnValue);
343554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadCompletedExpression);
344554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptThread);
345554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadInfo);
346554f68d3SGreg Clayton     ENUM_TO_CSTR(TargetArch);
347554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptTarget);
348554f68d3SGreg Clayton     ENUM_TO_CSTR(ModuleFile);
349554f68d3SGreg Clayton     ENUM_TO_CSTR(File);
350dc975670SDawn Perchik     ENUM_TO_CSTR(Lang);
351554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameIndex);
3526a9767c7SJim Ingham     ENUM_TO_CSTR(FrameNoDebug);
353554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterPC);
354554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterSP);
355554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFP);
356554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFlags);
357554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterByName);
358554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptFrame);
359554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionID);
360554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionDidChange);
361554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionInitialFunction);
362554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionName);
363554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameWithArgs);
364554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameNoArgs);
365554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffset);
366554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
367554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionLineOffset);
368554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionPCOffset);
369c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionInitial);
370c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionChanged);
3716ab659a9SJason Molenda     ENUM_TO_CSTR(FunctionIsOptimized);
372554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryFile);
373554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryLineNumber);
374554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryStartAddress);
375554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryEndAddress);
376554f68d3SGreg Clayton     ENUM_TO_CSTR(CurrentPCArrow);
377554f68d3SGreg Clayton   }
378554f68d3SGreg Clayton   return "???";
379554f68d3SGreg Clayton }
380554f68d3SGreg Clayton 
381554f68d3SGreg Clayton #undef ENUM_TO_CSTR
382554f68d3SGreg Clayton 
383b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const {
384554f68d3SGreg Clayton   s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
385554f68d3SGreg Clayton   if (fmt != eFormatDefault)
386554f68d3SGreg Clayton     s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
387554f68d3SGreg Clayton   if (!string.empty())
388554f68d3SGreg Clayton     s.Printf("string = \"%s\"", string.c_str());
389554f68d3SGreg Clayton   if (!printf_format.empty())
390554f68d3SGreg Clayton     s.Printf("printf_format = \"%s\"", printf_format.c_str());
391554f68d3SGreg Clayton   if (number != 0)
392554f68d3SGreg Clayton     s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
393554f68d3SGreg Clayton   if (deref)
394554f68d3SGreg Clayton     s.Printf("deref = true, ");
395554f68d3SGreg Clayton   s.EOL();
396b9c1b51eSKate Stone   for (const auto &child : children) {
397554f68d3SGreg Clayton     child.Dump(s, depth + 1);
398554f68d3SGreg Clayton   }
399554f68d3SGreg Clayton }
400554f68d3SGreg Clayton 
401554f68d3SGreg Clayton template <typename T>
402b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
403b9c1b51eSKate Stone                                    const ExecutionContext *exe_ctx, T t,
404b9c1b51eSKate Stone                                    const char *script_function_name) {
405554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
406554f68d3SGreg Clayton 
407b9c1b51eSKate Stone   if (target) {
408b9c1b51eSKate Stone     ScriptInterpreter *script_interpreter =
409b9c1b51eSKate Stone         target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
410b9c1b51eSKate Stone     if (script_interpreter) {
411554f68d3SGreg Clayton       Error error;
412554f68d3SGreg Clayton       std::string script_output;
413554f68d3SGreg Clayton 
414b9c1b51eSKate Stone       if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
415b9c1b51eSKate Stone                                                      script_output, error) &&
416b9c1b51eSKate Stone           error.Success()) {
417554f68d3SGreg Clayton         s.Printf("%s", script_output.c_str());
418554f68d3SGreg Clayton         return true;
419b9c1b51eSKate Stone       } else {
420554f68d3SGreg Clayton         s.Printf("<error: %s>", error.AsCString());
421554f68d3SGreg Clayton       }
422554f68d3SGreg Clayton     }
423554f68d3SGreg Clayton   }
424554f68d3SGreg Clayton   return false;
425554f68d3SGreg Clayton }
426554f68d3SGreg Clayton 
427b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc,
428b9c1b51eSKate Stone                         const ExecutionContext *exe_ctx, const Address &addr,
429b9c1b51eSKate Stone                         bool print_file_addr_or_load_addr) {
430554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
431554f68d3SGreg Clayton   addr_t vaddr = LLDB_INVALID_ADDRESS;
432554f68d3SGreg Clayton   if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
433554f68d3SGreg Clayton     vaddr = addr.GetLoadAddress(target);
434554f68d3SGreg Clayton   if (vaddr == LLDB_INVALID_ADDRESS)
435554f68d3SGreg Clayton     vaddr = addr.GetFileAddress();
436554f68d3SGreg Clayton 
437b9c1b51eSKate Stone   if (vaddr != LLDB_INVALID_ADDRESS) {
438554f68d3SGreg Clayton     int addr_width = 0;
439b9c1b51eSKate Stone     if (exe_ctx && target) {
440554f68d3SGreg Clayton       addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
441554f68d3SGreg Clayton     }
442554f68d3SGreg Clayton     if (addr_width == 0)
443554f68d3SGreg Clayton       addr_width = 16;
444b9c1b51eSKate Stone     if (print_file_addr_or_load_addr) {
445a74f37a5SEugene Zelenko       ExecutionContextScope *exe_scope = nullptr;
446554f68d3SGreg Clayton       if (exe_ctx)
447554f68d3SGreg Clayton         exe_scope = exe_ctx->GetBestExecutionContextScope();
448b9c1b51eSKate Stone       addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
449b9c1b51eSKate Stone                 Address::DumpStyleModuleWithFileAddress, 0);
450b9c1b51eSKate Stone     } else {
451554f68d3SGreg Clayton       s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
452554f68d3SGreg Clayton     }
453554f68d3SGreg Clayton     return true;
454554f68d3SGreg Clayton   }
455554f68d3SGreg Clayton   return false;
456554f68d3SGreg Clayton }
457554f68d3SGreg Clayton 
458b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
459554f68d3SGreg Clayton                                           const ExecutionContext *exe_ctx,
460554f68d3SGreg Clayton                                           const Address &format_addr,
461b9c1b51eSKate Stone                                           bool concrete_only, bool no_padding,
462b9c1b51eSKate Stone                                           bool print_zero_offsets) {
463b9c1b51eSKate Stone   if (format_addr.IsValid()) {
464554f68d3SGreg Clayton     Address func_addr;
465554f68d3SGreg Clayton 
466b9c1b51eSKate Stone     if (sc) {
467b9c1b51eSKate Stone       if (sc->function) {
468554f68d3SGreg Clayton         func_addr = sc->function->GetAddressRange().GetBaseAddress();
469b9c1b51eSKate Stone         if (sc->block && !concrete_only) {
470554f68d3SGreg Clayton           // Check to make sure we aren't in an inline
471554f68d3SGreg Clayton           // function. If we are, use the inline block
472554f68d3SGreg Clayton           // range that contains "format_addr" since
473554f68d3SGreg Clayton           // blocks can be discontiguous.
474554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
475554f68d3SGreg Clayton           AddressRange inline_range;
476b9c1b51eSKate Stone           if (inline_block &&
477b9c1b51eSKate Stone               inline_block->GetRangeContainingAddress(format_addr,
478b9c1b51eSKate Stone                                                       inline_range))
479554f68d3SGreg Clayton             func_addr = inline_range.GetBaseAddress();
480554f68d3SGreg Clayton         }
481b9c1b51eSKate Stone       } else if (sc->symbol && sc->symbol->ValueIsAddress())
482358cf1eaSGreg Clayton         func_addr = sc->symbol->GetAddressRef();
483554f68d3SGreg Clayton     }
484554f68d3SGreg Clayton 
485b9c1b51eSKate Stone     if (func_addr.IsValid()) {
486554f68d3SGreg Clayton       const char *addr_offset_padding = no_padding ? "" : " ";
487554f68d3SGreg Clayton 
488b9c1b51eSKate Stone       if (func_addr.GetSection() == format_addr.GetSection()) {
489554f68d3SGreg Clayton         addr_t func_file_addr = func_addr.GetFileAddress();
490554f68d3SGreg Clayton         addr_t addr_file_addr = format_addr.GetFileAddress();
491b9c1b51eSKate Stone         if (addr_file_addr > func_file_addr ||
492b9c1b51eSKate Stone             (addr_file_addr == func_file_addr && print_zero_offsets)) {
493b9c1b51eSKate Stone           s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
494b9c1b51eSKate Stone                    addr_file_addr - func_file_addr);
495b9c1b51eSKate Stone         } else if (addr_file_addr < func_file_addr) {
496b9c1b51eSKate Stone           s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
497b9c1b51eSKate Stone                    func_file_addr - addr_file_addr);
498c980fa92SJason Molenda         }
499554f68d3SGreg Clayton         return true;
500b9c1b51eSKate Stone       } else {
501554f68d3SGreg Clayton         Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
502b9c1b51eSKate Stone         if (target) {
503554f68d3SGreg Clayton           addr_t func_load_addr = func_addr.GetLoadAddress(target);
504554f68d3SGreg Clayton           addr_t addr_load_addr = format_addr.GetLoadAddress(target);
505b9c1b51eSKate Stone           if (addr_load_addr > func_load_addr ||
506b9c1b51eSKate Stone               (addr_load_addr == func_load_addr && print_zero_offsets)) {
507b9c1b51eSKate Stone             s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
508b9c1b51eSKate Stone                      addr_load_addr - func_load_addr);
509b9c1b51eSKate Stone           } else if (addr_load_addr < func_load_addr) {
510b9c1b51eSKate Stone             s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
511b9c1b51eSKate Stone                      func_load_addr - addr_load_addr);
512c980fa92SJason Molenda           }
513554f68d3SGreg Clayton           return true;
514554f68d3SGreg Clayton         }
515554f68d3SGreg Clayton       }
516554f68d3SGreg Clayton     }
517554f68d3SGreg Clayton   }
518554f68d3SGreg Clayton   return false;
519554f68d3SGreg Clayton }
520554f68d3SGreg Clayton 
521b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath,
522554f68d3SGreg Clayton                                size_t &close_bracket_index,
523554f68d3SGreg Clayton                                const char *&var_name_final_if_array_range,
524b9c1b51eSKate Stone                                int64_t &index_lower, int64_t &index_higher) {
5254edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
526554f68d3SGreg Clayton   close_bracket_index = llvm::StringRef::npos;
527554f68d3SGreg Clayton   const size_t open_bracket_index = subpath.find('[');
528b9c1b51eSKate Stone   if (open_bracket_index == llvm::StringRef::npos) {
529554f68d3SGreg Clayton     if (log)
530554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
531554f68d3SGreg Clayton     return false;
532554f68d3SGreg Clayton   }
533554f68d3SGreg Clayton 
534554f68d3SGreg Clayton   close_bracket_index = subpath.find(']', open_bracket_index + 1);
535554f68d3SGreg Clayton 
536b9c1b51eSKate Stone   if (close_bracket_index == llvm::StringRef::npos) {
537554f68d3SGreg Clayton     if (log)
538554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
539554f68d3SGreg Clayton     return false;
540b9c1b51eSKate Stone   } else {
541554f68d3SGreg Clayton     var_name_final_if_array_range = subpath.data() + open_bracket_index;
542554f68d3SGreg Clayton 
543b9c1b51eSKate Stone     if (close_bracket_index - open_bracket_index == 1) {
544554f68d3SGreg Clayton       if (log)
545b9c1b51eSKate Stone         log->Printf(
546b9c1b51eSKate Stone             "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
547554f68d3SGreg Clayton       index_lower = 0;
548b9c1b51eSKate Stone     } else {
549554f68d3SGreg Clayton       const size_t separator_index = subpath.find('-', open_bracket_index + 1);
550554f68d3SGreg Clayton 
551b9c1b51eSKate Stone       if (separator_index == llvm::StringRef::npos) {
552554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
553a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
554554f68d3SGreg Clayton         index_higher = index_lower;
555554f68d3SGreg Clayton         if (log)
556b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64
557b9c1b51eSKate Stone                       "] detected, high index is same",
558b9c1b51eSKate Stone                       index_lower);
559b9c1b51eSKate Stone       } else {
560554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
561554f68d3SGreg Clayton         const char *index_higher_cstr = subpath.data() + separator_index + 1;
562a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
563a74f37a5SEugene Zelenko         index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
564554f68d3SGreg Clayton         if (log)
565b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
566b9c1b51eSKate Stone                       index_lower, index_higher);
567554f68d3SGreg Clayton       }
568b9c1b51eSKate Stone       if (index_lower > index_higher && index_higher > 0) {
569554f68d3SGreg Clayton         if (log)
570554f68d3SGreg Clayton           log->Printf("[ScanBracketedRange] swapping indices");
571554f68d3SGreg Clayton         const int64_t temp = index_lower;
572554f68d3SGreg Clayton         index_lower = index_higher;
573554f68d3SGreg Clayton         index_higher = temp;
574554f68d3SGreg Clayton       }
575554f68d3SGreg Clayton     }
576554f68d3SGreg Clayton   }
577554f68d3SGreg Clayton   return true;
578554f68d3SGreg Clayton }
579554f68d3SGreg Clayton 
580b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
581b9c1b51eSKate Stone   switch (file_kind) {
582554f68d3SGreg Clayton   case FileKind::FileError:
583554f68d3SGreg Clayton     break;
584554f68d3SGreg Clayton 
585554f68d3SGreg Clayton   case FileKind::Basename:
586b9c1b51eSKate Stone     if (file.GetFilename()) {
587554f68d3SGreg Clayton       s << file.GetFilename();
588554f68d3SGreg Clayton       return true;
589554f68d3SGreg Clayton     }
590554f68d3SGreg Clayton     break;
591554f68d3SGreg Clayton 
592554f68d3SGreg Clayton   case FileKind::Dirname:
593b9c1b51eSKate Stone     if (file.GetDirectory()) {
594554f68d3SGreg Clayton       s << file.GetDirectory();
595554f68d3SGreg Clayton       return true;
596554f68d3SGreg Clayton     }
597554f68d3SGreg Clayton     break;
598554f68d3SGreg Clayton 
599554f68d3SGreg Clayton   case FileKind::Fullpath:
600b9c1b51eSKate Stone     if (file) {
601554f68d3SGreg Clayton       s << file;
602554f68d3SGreg Clayton       return true;
603554f68d3SGreg Clayton     }
604554f68d3SGreg Clayton     break;
605554f68d3SGreg Clayton   }
606554f68d3SGreg Clayton   return false;
607554f68d3SGreg Clayton }
608554f68d3SGreg Clayton 
609b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
610b9c1b51eSKate Stone                          uint32_t reg_num, Format format)
611554f68d3SGreg Clayton 
612554f68d3SGreg Clayton {
613b9c1b51eSKate Stone   if (frame) {
614554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
615554f68d3SGreg Clayton 
616b9c1b51eSKate Stone     if (reg_ctx) {
617b9c1b51eSKate Stone       const uint32_t lldb_reg_num =
618b9c1b51eSKate Stone           reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
619b9c1b51eSKate Stone       if (lldb_reg_num != LLDB_INVALID_REGNUM) {
620b9c1b51eSKate Stone         const RegisterInfo *reg_info =
621b9c1b51eSKate Stone             reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
622b9c1b51eSKate Stone         if (reg_info) {
623554f68d3SGreg Clayton           RegisterValue reg_value;
624b9c1b51eSKate Stone           if (reg_ctx->ReadRegister(reg_info, reg_value)) {
625554f68d3SGreg Clayton             reg_value.Dump(&s, reg_info, false, false, format);
626554f68d3SGreg Clayton             return true;
627554f68d3SGreg Clayton           }
628554f68d3SGreg Clayton         }
629554f68d3SGreg Clayton       }
630554f68d3SGreg Clayton     }
631554f68d3SGreg Clayton   }
632554f68d3SGreg Clayton   return false;
633554f68d3SGreg Clayton }
634554f68d3SGreg Clayton 
635b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
636554f68d3SGreg Clayton                                              StackFrame *frame,
637b9c1b51eSKate Stone                                              bool deref_pointer) {
6384edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
639554f68d3SGreg Clayton   const char *ptr_deref_format = "[%d]";
640554f68d3SGreg Clayton   std::string ptr_deref_buffer(10, 0);
641554f68d3SGreg Clayton   ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
642554f68d3SGreg Clayton   if (log)
643b9c1b51eSKate Stone     log->Printf("[ExpandIndexedExpression] name to deref: %s",
644b9c1b51eSKate Stone                 ptr_deref_buffer.c_str());
645554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
646554f68d3SGreg Clayton   ValueObject::ExpressionPathEndResultType final_value_type;
647554f68d3SGreg Clayton   ValueObject::ExpressionPathScanEndReason reason_to_stop;
648b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
649b9c1b51eSKate Stone       (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
650b9c1b51eSKate Stone                      : ValueObject::eExpressionPathAftermathNothing);
651b9c1b51eSKate Stone   ValueObjectSP item = valobj->GetValueForExpressionPath(
652d2daca77SZachary Turner       ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options,
653d2daca77SZachary Turner       &what_next);
654b9c1b51eSKate Stone   if (!item) {
655554f68d3SGreg Clayton     if (log)
656d2daca77SZachary Turner       log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d,"
657554f68d3SGreg Clayton                   " final_value_type %d",
658d2daca77SZachary Turner                   reason_to_stop, final_value_type);
659b9c1b51eSKate Stone   } else {
660554f68d3SGreg Clayton     if (log)
661d2daca77SZachary Turner       log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
662554f68d3SGreg Clayton                   " final_value_type %d",
663d2daca77SZachary Turner                   reason_to_stop, final_value_type);
664554f68d3SGreg Clayton   }
665554f68d3SGreg Clayton   return item;
666554f68d3SGreg Clayton }
667554f68d3SGreg Clayton 
668b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar(
669b9c1b51eSKate Stone     ValueObject::ValueObjectRepresentationStyle style) {
670b9c1b51eSKate Stone   switch (style) {
671b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
672b9c1b51eSKate Stone     return '@';
673b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleValue:
674b9c1b51eSKate Stone     return 'V';
675b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLocation:
676b9c1b51eSKate Stone     return 'L';
677b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleSummary:
678b9c1b51eSKate Stone     return 'S';
679b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleChildrenCount:
680b9c1b51eSKate Stone     return '#';
681b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleType:
682b9c1b51eSKate Stone     return 'T';
683b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleName:
684b9c1b51eSKate Stone     return 'N';
685b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleExpressionPath:
686b9c1b51eSKate Stone     return '>';
687554f68d3SGreg Clayton   }
688554f68d3SGreg Clayton   return '\0';
689554f68d3SGreg Clayton }
690554f68d3SGreg Clayton 
691b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc,
692554f68d3SGreg Clayton                       const ExecutionContext *exe_ctx,
693b9c1b51eSKate Stone                       const FormatEntity::Entry &entry, ValueObject *valobj) {
694a74f37a5SEugene Zelenko   if (valobj == nullptr)
695554f68d3SGreg Clayton     return false;
696554f68d3SGreg Clayton 
6974edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
698554f68d3SGreg Clayton   Format custom_format = eFormatInvalid;
699b9c1b51eSKate Stone   ValueObject::ValueObjectRepresentationStyle val_obj_display =
700b9c1b51eSKate Stone       entry.string.empty()
701b9c1b51eSKate Stone           ? ValueObject::eValueObjectRepresentationStyleValue
702b9c1b51eSKate Stone           : ValueObject::eValueObjectRepresentationStyleSummary;
703554f68d3SGreg Clayton 
704554f68d3SGreg Clayton   bool do_deref_pointer = entry.deref;
705554f68d3SGreg Clayton   bool is_script = false;
706b9c1b51eSKate Stone   switch (entry.type) {
707554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariable:
708554f68d3SGreg Clayton     is_script = true;
709554f68d3SGreg Clayton     break;
710554f68d3SGreg Clayton 
711554f68d3SGreg Clayton   case FormatEntity::Entry::Type::Variable:
712554f68d3SGreg Clayton     custom_format = entry.fmt;
713554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
714554f68d3SGreg Clayton     break;
715554f68d3SGreg Clayton 
716554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariableSynthetic:
717554f68d3SGreg Clayton     is_script = true;
71862e0681aSJason Molenda     LLVM_FALLTHROUGH;
719554f68d3SGreg Clayton   case FormatEntity::Entry::Type::VariableSynthetic:
720554f68d3SGreg Clayton     custom_format = entry.fmt;
721554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
722b9c1b51eSKate Stone     if (!valobj->IsSynthetic()) {
723554f68d3SGreg Clayton       valobj = valobj->GetSyntheticValue().get();
724554f68d3SGreg Clayton       if (valobj == nullptr)
725554f68d3SGreg Clayton         return false;
726554f68d3SGreg Clayton     }
727554f68d3SGreg Clayton     break;
728554f68d3SGreg Clayton 
729554f68d3SGreg Clayton   default:
730554f68d3SGreg Clayton     return false;
731554f68d3SGreg Clayton   }
732554f68d3SGreg Clayton 
733a74f37a5SEugene Zelenko   if (valobj == nullptr)
734554f68d3SGreg Clayton     return false;
735554f68d3SGreg Clayton 
736b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
737b9c1b51eSKate Stone       (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
738b9c1b51eSKate Stone                         : ValueObject::eExpressionPathAftermathNothing);
739554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
740b9c1b51eSKate Stone   options.DontCheckDotVsArrowSyntax()
741b9c1b51eSKate Stone       .DoAllowBitfieldSyntax()
742b9c1b51eSKate Stone       .DoAllowFragileIVar()
743b9c1b51eSKate Stone       .SetSyntheticChildrenTraversal(
744b9c1b51eSKate Stone           ValueObject::GetValueForExpressionPathOptions::
745b9c1b51eSKate Stone               SyntheticChildrenTraversal::Both);
746a74f37a5SEugene Zelenko   ValueObject *target = nullptr;
747a74f37a5SEugene Zelenko   const char *var_name_final_if_array_range = nullptr;
748554f68d3SGreg Clayton   size_t close_bracket_index = llvm::StringRef::npos;
749554f68d3SGreg Clayton   int64_t index_lower = -1;
750554f68d3SGreg Clayton   int64_t index_higher = -1;
751554f68d3SGreg Clayton   bool is_array_range = false;
752554f68d3SGreg Clayton   bool was_plain_var = false;
753554f68d3SGreg Clayton   bool was_var_format = false;
754554f68d3SGreg Clayton   bool was_var_indexed = false;
755b9c1b51eSKate Stone   ValueObject::ExpressionPathScanEndReason reason_to_stop =
756b9c1b51eSKate Stone       ValueObject::eExpressionPathScanEndReasonEndOfString;
757b9c1b51eSKate Stone   ValueObject::ExpressionPathEndResultType final_value_type =
758b9c1b51eSKate Stone       ValueObject::eExpressionPathEndResultTypePlain;
759554f68d3SGreg Clayton 
760b9c1b51eSKate Stone   if (is_script) {
761554f68d3SGreg Clayton     return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
762554f68d3SGreg Clayton   }
763554f68d3SGreg Clayton 
764554f68d3SGreg Clayton   llvm::StringRef subpath(entry.string);
765554f68d3SGreg Clayton   // simplest case ${var}, just print valobj's value
766b9c1b51eSKate Stone   if (entry.string.empty()) {
767b9c1b51eSKate Stone     if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
768b9c1b51eSKate Stone         entry.number == ValueObject::eValueObjectRepresentationStyleValue)
769554f68d3SGreg Clayton       was_plain_var = true;
770554f68d3SGreg Clayton     else
771554f68d3SGreg Clayton       was_var_format = true;
772554f68d3SGreg Clayton     target = valobj;
773b9c1b51eSKate Stone   } else // this is ${var.something} or multiple .something nested
774554f68d3SGreg Clayton   {
775554f68d3SGreg Clayton     if (entry.string[0] == '[')
776554f68d3SGreg Clayton       was_var_indexed = true;
777b9c1b51eSKate Stone     ScanBracketedRange(subpath, close_bracket_index,
778b9c1b51eSKate Stone                        var_name_final_if_array_range, index_lower,
779554f68d3SGreg Clayton                        index_higher);
780554f68d3SGreg Clayton 
781554f68d3SGreg Clayton     Error error;
782554f68d3SGreg Clayton 
783554f68d3SGreg Clayton     const std::string &expr_path = entry.string;
784554f68d3SGreg Clayton 
785554f68d3SGreg Clayton     if (log)
786b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",
787b9c1b51eSKate Stone                   expr_path.c_str());
788554f68d3SGreg Clayton 
789d2daca77SZachary Turner     target =
790d2daca77SZachary Turner         valobj
791d2daca77SZachary Turner             ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
792d2daca77SZachary Turner                                         &final_value_type, options, &what_next)
793b9c1b51eSKate Stone             .get();
794554f68d3SGreg Clayton 
795b9c1b51eSKate Stone     if (!target) {
796554f68d3SGreg Clayton       if (log)
797d2daca77SZachary Turner         log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d,"
798655c4525SZachary Turner                     " final_value_type %d",
799d2daca77SZachary Turner                     reason_to_stop, final_value_type);
800554f68d3SGreg Clayton       return false;
801b9c1b51eSKate Stone     } else {
802554f68d3SGreg Clayton       if (log)
803d2daca77SZachary Turner         log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
804655c4525SZachary Turner                     " final_value_type %d",
805d2daca77SZachary Turner                     reason_to_stop, final_value_type);
806b9c1b51eSKate Stone       target = target
807b9c1b51eSKate Stone                    ->GetQualifiedRepresentationIfAvailable(
808b9c1b51eSKate Stone                        target->GetDynamicValueType(), true)
809b9c1b51eSKate Stone                    .get();
810554f68d3SGreg Clayton     }
811554f68d3SGreg Clayton   }
812554f68d3SGreg Clayton 
813b9c1b51eSKate Stone   is_array_range =
814b9c1b51eSKate Stone       (final_value_type ==
815b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeBoundedRange ||
816b9c1b51eSKate Stone        final_value_type ==
817b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeUnboundedRange);
818554f68d3SGreg Clayton 
819b9c1b51eSKate Stone   do_deref_pointer =
820b9c1b51eSKate Stone       (what_next == ValueObject::eExpressionPathAftermathDereference);
821554f68d3SGreg Clayton 
822b9c1b51eSKate Stone   if (do_deref_pointer && !is_array_range) {
823554f68d3SGreg Clayton     // I have not deref-ed yet, let's do it
824b9c1b51eSKate Stone     // this happens when we are not going through
825b9c1b51eSKate Stone     // GetValueForVariableExpressionPath
826554f68d3SGreg Clayton     // to get to the target ValueObject
827554f68d3SGreg Clayton     Error error;
828554f68d3SGreg Clayton     target = target->Dereference(error).get();
829b9c1b51eSKate Stone     if (error.Fail()) {
830554f68d3SGreg Clayton       if (log)
831b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] ERROR: %s\n",
832b9c1b51eSKate Stone                     error.AsCString("unknown"));
833554f68d3SGreg Clayton       return false;
834554f68d3SGreg Clayton     }
835554f68d3SGreg Clayton     do_deref_pointer = false;
836554f68d3SGreg Clayton   }
837554f68d3SGreg Clayton 
838b9c1b51eSKate Stone   if (!target) {
839554f68d3SGreg Clayton     if (log)
840b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] could not calculate target for "
841b9c1b51eSKate Stone                   "prompt expression");
842554f68d3SGreg Clayton     return false;
843554f68d3SGreg Clayton   }
844554f68d3SGreg Clayton 
845554f68d3SGreg Clayton   // we do not want to use the summary for a bitfield of type T:n
846554f68d3SGreg Clayton   // if we were originally dealing with just a T - that would get
847554f68d3SGreg Clayton   // us into an endless recursion
848b9c1b51eSKate Stone   if (target->IsBitfield() && was_var_indexed) {
849554f68d3SGreg Clayton     // TODO: check for a (T:n)-specific summary - we should still obey that
850554f68d3SGreg Clayton     StreamString bitfield_name;
851b9c1b51eSKate Stone     bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
852b9c1b51eSKate Stone                          target->GetBitfieldBitSize());
853*2f3df613SZachary Turner     auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
854*2f3df613SZachary Turner         bitfield_name.GetString(), false);
855b9c1b51eSKate Stone     if (val_obj_display ==
856b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleSummary &&
857b9c1b51eSKate Stone         !DataVisualization::GetSummaryForType(type_sp))
858554f68d3SGreg Clayton       val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
859554f68d3SGreg Clayton   }
860554f68d3SGreg Clayton 
861554f68d3SGreg Clayton   // TODO use flags for these
862b9c1b51eSKate Stone   const uint32_t type_info_flags =
863b9c1b51eSKate Stone       target->GetCompilerType().GetTypeInfo(nullptr);
864554f68d3SGreg Clayton   bool is_array = (type_info_flags & eTypeIsArray) != 0;
865554f68d3SGreg Clayton   bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
86699558cc4SGreg Clayton   bool is_aggregate = target->GetCompilerType().IsAggregateType();
867554f68d3SGreg Clayton 
868b9c1b51eSKate Stone   if ((is_array || is_pointer) && (!is_array_range) &&
869b9c1b51eSKate Stone       val_obj_display ==
870b9c1b51eSKate Stone           ValueObject::eValueObjectRepresentationStyleValue) // this should be
871b9c1b51eSKate Stone                                                              // wrong, but there
872b9c1b51eSKate Stone                                                              // are some
873b9c1b51eSKate Stone                                                              // exceptions
874554f68d3SGreg Clayton   {
875554f68d3SGreg Clayton     StreamString str_temp;
876554f68d3SGreg Clayton     if (log)
877b9c1b51eSKate Stone       log->Printf(
878b9c1b51eSKate Stone           "[Debugger::FormatPrompt] I am into array || pointer && !range");
879554f68d3SGreg Clayton 
880b9c1b51eSKate Stone     if (target->HasSpecialPrintableRepresentation(val_obj_display,
881b9c1b51eSKate Stone                                                   custom_format)) {
882554f68d3SGreg Clayton       // try to use the special cases
883b9c1b51eSKate Stone       bool success = target->DumpPrintableRepresentation(
884b9c1b51eSKate Stone           str_temp, val_obj_display, custom_format);
885554f68d3SGreg Clayton       if (log)
886b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] special cases did%s match",
887b9c1b51eSKate Stone                     success ? "" : "n't");
888554f68d3SGreg Clayton 
889554f68d3SGreg Clayton       // should not happen
890554f68d3SGreg Clayton       if (success)
891c156427dSZachary Turner         s << str_temp.GetString();
892554f68d3SGreg Clayton       return true;
893b9c1b51eSKate Stone     } else {
894554f68d3SGreg Clayton       if (was_plain_var) // if ${var}
895554f68d3SGreg Clayton       {
896554f68d3SGreg Clayton         s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
897b9c1b51eSKate Stone       } else if (is_pointer) // if pointer, value is the address stored
898554f68d3SGreg Clayton       {
899b9c1b51eSKate Stone         target->DumpPrintableRepresentation(
900b9c1b51eSKate Stone             s, val_obj_display, custom_format,
90165d86e4fSEnrico Granata             ValueObject::PrintableRepresentationSpecialCases::eDisable);
902554f68d3SGreg Clayton       }
903554f68d3SGreg Clayton       return true;
904554f68d3SGreg Clayton     }
905554f68d3SGreg Clayton   }
906554f68d3SGreg Clayton 
907b9c1b51eSKate Stone   // if directly trying to print ${var}, and this is an aggregate, display a
908b9c1b51eSKate Stone   // nice
909554f68d3SGreg Clayton   // type @ location message
910b9c1b51eSKate Stone   if (is_aggregate && was_plain_var) {
911554f68d3SGreg Clayton     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
912554f68d3SGreg Clayton     return true;
913554f68d3SGreg Clayton   }
914554f68d3SGreg Clayton 
915b9c1b51eSKate Stone   // if directly trying to print ${var%V}, and this is an aggregate, do not let
916b9c1b51eSKate Stone   // the user do it
917b9c1b51eSKate Stone   if (is_aggregate &&
918b9c1b51eSKate Stone       ((was_var_format &&
919b9c1b51eSKate Stone         val_obj_display ==
920b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleValue))) {
921554f68d3SGreg Clayton     s << "<invalid use of aggregate type>";
922554f68d3SGreg Clayton     return true;
923554f68d3SGreg Clayton   }
924554f68d3SGreg Clayton 
925b9c1b51eSKate Stone   if (!is_array_range) {
926554f68d3SGreg Clayton     if (log)
927554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
928b9c1b51eSKate Stone     return target->DumpPrintableRepresentation(s, val_obj_display,
929b9c1b51eSKate Stone                                                custom_format);
930b9c1b51eSKate Stone   } else {
931554f68d3SGreg Clayton     if (log)
932554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
933554f68d3SGreg Clayton     if (!is_array && !is_pointer)
934554f68d3SGreg Clayton       return false;
935554f68d3SGreg Clayton     if (log)
936554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] handle as array");
937e8376261SVince Harron     StreamString special_directions_stream;
938554f68d3SGreg Clayton     llvm::StringRef special_directions;
939b9c1b51eSKate Stone     if (close_bracket_index != llvm::StringRef::npos &&
940b9c1b51eSKate Stone         subpath.size() > close_bracket_index) {
941554f68d3SGreg Clayton       ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
942b9c1b51eSKate Stone       special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
943554f68d3SGreg Clayton                                        additional_data.GetCString());
944554f68d3SGreg Clayton 
945b9c1b51eSKate Stone       if (entry.fmt != eFormatDefault) {
946b9c1b51eSKate Stone         const char format_char =
947b9c1b51eSKate Stone             FormatManager::GetFormatAsFormatChar(entry.fmt);
948554f68d3SGreg Clayton         if (format_char != '\0')
949554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", format_char);
950b9c1b51eSKate Stone         else {
951b9c1b51eSKate Stone           const char *format_cstr =
952b9c1b51eSKate Stone               FormatManager::GetFormatAsCString(entry.fmt);
953554f68d3SGreg Clayton           special_directions_stream.Printf("%%%s", format_cstr);
954554f68d3SGreg Clayton         }
955b9c1b51eSKate Stone       } else if (entry.number != 0) {
956b9c1b51eSKate Stone         const char style_char = ConvertValueObjectStyleToChar(
957b9c1b51eSKate Stone             (ValueObject::ValueObjectRepresentationStyle)entry.number);
958554f68d3SGreg Clayton         if (style_char)
959554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", style_char);
960554f68d3SGreg Clayton       }
961554f68d3SGreg Clayton       special_directions_stream.PutChar('}');
962b9c1b51eSKate Stone       special_directions =
963b9c1b51eSKate Stone           llvm::StringRef(special_directions_stream.GetString());
964554f68d3SGreg Clayton     }
965554f68d3SGreg Clayton 
966554f68d3SGreg Clayton     // let us display items index_lower thru index_higher of this array
967554f68d3SGreg Clayton     s.PutChar('[');
968554f68d3SGreg Clayton 
969554f68d3SGreg Clayton     if (index_higher < 0)
970554f68d3SGreg Clayton       index_higher = valobj->GetNumChildren() - 1;
971554f68d3SGreg Clayton 
972b9c1b51eSKate Stone     uint32_t max_num_children =
973b9c1b51eSKate Stone         target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
974554f68d3SGreg Clayton 
975554f68d3SGreg Clayton     bool success = true;
976b9c1b51eSKate Stone     for (int64_t index = index_lower; index <= index_higher; ++index) {
977b9c1b51eSKate Stone       ValueObject *item =
978b9c1b51eSKate Stone           ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
979b9c1b51eSKate Stone               .get();
980554f68d3SGreg Clayton 
981b9c1b51eSKate Stone       if (!item) {
982554f68d3SGreg Clayton         if (log)
983b9c1b51eSKate Stone           log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at "
984b9c1b51eSKate Stone                       "index %" PRId64,
985b9c1b51eSKate Stone                       index);
986b9c1b51eSKate Stone       } else {
987554f68d3SGreg Clayton         if (log)
988b9c1b51eSKate Stone           log->Printf(
989b9c1b51eSKate Stone               "[Debugger::FormatPrompt] special_directions for child item: %s",
990b9c1b51eSKate Stone               special_directions.data() ? special_directions.data() : "");
991554f68d3SGreg Clayton       }
992554f68d3SGreg Clayton 
993b9c1b51eSKate Stone       if (special_directions.empty()) {
994b9c1b51eSKate Stone         success &= item->DumpPrintableRepresentation(s, val_obj_display,
995b9c1b51eSKate Stone                                                      custom_format);
996b9c1b51eSKate Stone       } else {
997b9c1b51eSKate Stone         success &= FormatEntity::FormatStringRef(
998b9c1b51eSKate Stone             special_directions, s, sc, exe_ctx, nullptr, item, false, false);
999554f68d3SGreg Clayton       }
1000554f68d3SGreg Clayton 
1001b9c1b51eSKate Stone       if (--max_num_children == 0) {
1002554f68d3SGreg Clayton         s.PutCString(", ...");
1003554f68d3SGreg Clayton         break;
1004554f68d3SGreg Clayton       }
1005554f68d3SGreg Clayton 
1006554f68d3SGreg Clayton       if (index < index_higher)
1007554f68d3SGreg Clayton         s.PutChar(',');
1008554f68d3SGreg Clayton     }
1009554f68d3SGreg Clayton     s.PutChar(']');
1010554f68d3SGreg Clayton     return success;
1011554f68d3SGreg Clayton   }
1012554f68d3SGreg Clayton }
1013554f68d3SGreg Clayton 
1014b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
1015b9c1b51eSKate Stone                          Format format) {
1016b9c1b51eSKate Stone   if (frame) {
1017554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
1018554f68d3SGreg Clayton 
1019b9c1b51eSKate Stone     if (reg_ctx) {
1020554f68d3SGreg Clayton       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
1021b9c1b51eSKate Stone       if (reg_info) {
1022554f68d3SGreg Clayton         RegisterValue reg_value;
1023b9c1b51eSKate Stone         if (reg_ctx->ReadRegister(reg_info, reg_value)) {
1024554f68d3SGreg Clayton           reg_value.Dump(&s, reg_info, false, false, format);
1025554f68d3SGreg Clayton           return true;
1026554f68d3SGreg Clayton         }
1027554f68d3SGreg Clayton       }
1028554f68d3SGreg Clayton     }
1029554f68d3SGreg Clayton   }
1030554f68d3SGreg Clayton   return false;
1031554f68d3SGreg Clayton }
1032554f68d3SGreg Clayton 
1033b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse(
1034b9c1b51eSKate Stone     const FormatEntity::Entry &entry,
1035554f68d3SGreg Clayton     const StructuredData::ObjectSP &thread_info_dictionary,
1036b9c1b51eSKate Stone     const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
1037554f68d3SGreg Clayton   llvm::StringRef path(entry.string);
1038554f68d3SGreg Clayton 
1039b9c1b51eSKate Stone   StructuredData::ObjectSP value =
1040b9c1b51eSKate Stone       thread_info_dictionary->GetObjectForDotSeparatedPath(path);
1041554f68d3SGreg Clayton 
1042b9c1b51eSKate Stone   if (value) {
1043b9c1b51eSKate Stone     if (value->GetType() == StructuredData::Type::eTypeInteger) {
1044554f68d3SGreg Clayton       const char *token_format = "0x%4.4" PRIx64;
1045554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1046554f68d3SGreg Clayton         token_format = entry.printf_format.c_str();
1047554f68d3SGreg Clayton       s.Printf(token_format, value->GetAsInteger()->GetValue());
1048554f68d3SGreg Clayton       return true;
1049b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeFloat) {
1050554f68d3SGreg Clayton       s.Printf("%f", value->GetAsFloat()->GetValue());
1051554f68d3SGreg Clayton       return true;
1052b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeString) {
1053554f68d3SGreg Clayton       s.Printf("%s", value->GetAsString()->GetValue().c_str());
1054554f68d3SGreg Clayton       return true;
1055b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeArray) {
1056b9c1b51eSKate Stone       if (value->GetAsArray()->GetSize() > 0) {
1057554f68d3SGreg Clayton         s.Printf("%zu", value->GetAsArray()->GetSize());
1058554f68d3SGreg Clayton         return true;
1059554f68d3SGreg Clayton       }
1060b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeDictionary) {
1061b9c1b51eSKate Stone       s.Printf("%zu",
1062b9c1b51eSKate Stone                value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1063554f68d3SGreg Clayton       return true;
1064554f68d3SGreg Clayton     }
1065554f68d3SGreg Clayton   }
1066554f68d3SGreg Clayton 
1067554f68d3SGreg Clayton   return false;
1068554f68d3SGreg Clayton }
1069554f68d3SGreg Clayton 
1070b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) {
1071554f68d3SGreg Clayton   return (::strncmp(var_name_begin, var, strlen(var)) == 0);
1072554f68d3SGreg Clayton }
1073554f68d3SGreg Clayton 
1074b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
1075554f68d3SGreg Clayton                                    const SymbolContext *sc,
1076554f68d3SGreg Clayton                                    const ExecutionContext *exe_ctx,
1077b9c1b51eSKate Stone                                    const Address *addr, ValueObject *valobj,
1078554f68d3SGreg Clayton                                    bool function_changed,
1079b9c1b51eSKate Stone                                    bool initial_function) {
1080b9c1b51eSKate Stone   if (!format_str.empty()) {
1081554f68d3SGreg Clayton     FormatEntity::Entry root;
1082554f68d3SGreg Clayton     Error error = FormatEntity::Parse(format_str, root);
1083b9c1b51eSKate Stone     if (error.Success()) {
1084b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1085b9c1b51eSKate Stone                                   function_changed, initial_function);
1086554f68d3SGreg Clayton     }
1087554f68d3SGreg Clayton   }
1088554f68d3SGreg Clayton   return false;
1089554f68d3SGreg Clayton }
1090a74f37a5SEugene Zelenko 
1091b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s,
1092554f68d3SGreg Clayton                                  const SymbolContext *sc,
1093554f68d3SGreg Clayton                                  const ExecutionContext *exe_ctx,
1094b9c1b51eSKate Stone                                  const Address *addr, ValueObject *valobj,
1095b9c1b51eSKate Stone                                  bool function_changed, bool initial_function) {
1096b9c1b51eSKate Stone   if (format && format[0]) {
1097554f68d3SGreg Clayton     FormatEntity::Entry root;
1098554f68d3SGreg Clayton     llvm::StringRef format_str(format);
1099554f68d3SGreg Clayton     Error error = FormatEntity::Parse(format_str, root);
1100b9c1b51eSKate Stone     if (error.Success()) {
1101b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1102b9c1b51eSKate Stone                                   function_changed, initial_function);
1103554f68d3SGreg Clayton     }
1104554f68d3SGreg Clayton   }
1105554f68d3SGreg Clayton   return false;
1106554f68d3SGreg Clayton }
1107554f68d3SGreg Clayton 
1108b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s,
1109554f68d3SGreg Clayton                           const SymbolContext *sc,
1110b9c1b51eSKate Stone                           const ExecutionContext *exe_ctx, const Address *addr,
1111b9c1b51eSKate Stone                           ValueObject *valobj, bool function_changed,
1112b9c1b51eSKate Stone                           bool initial_function) {
1113b9c1b51eSKate Stone   switch (entry.type) {
1114554f68d3SGreg Clayton   case Entry::Type::Invalid:
1115b9c1b51eSKate Stone   case Entry::Type::ParentNumber: // Only used for
1116b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1117b9c1b51eSKate Stone   case Entry::Type::ParentString: // Only used for
1118b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1119b9c1b51eSKate Stone   case Entry::Type::InsertString: // Only used for
1120b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1121554f68d3SGreg Clayton     return false;
1122554f68d3SGreg Clayton 
1123554f68d3SGreg Clayton   case Entry::Type::Root:
1124b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1125b9c1b51eSKate Stone       if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
1126b9c1b51eSKate Stone                   initial_function)) {
1127554f68d3SGreg Clayton         return false; // If any item of root fails, then the formatting fails
1128554f68d3SGreg Clayton       }
1129554f68d3SGreg Clayton     }
1130554f68d3SGreg Clayton     return true; // Only return true if all items succeeded
1131554f68d3SGreg Clayton 
1132554f68d3SGreg Clayton   case Entry::Type::String:
1133771ef6d4SMalcolm Parsons     s.PutCString(entry.string);
1134554f68d3SGreg Clayton     return true;
1135554f68d3SGreg Clayton 
1136b9c1b51eSKate Stone   case Entry::Type::Scope: {
1137554f68d3SGreg Clayton     StreamString scope_stream;
1138554f68d3SGreg Clayton     bool success = false;
1139b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1140b9c1b51eSKate Stone       success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
1141b9c1b51eSKate Stone                        function_changed, initial_function);
1142554f68d3SGreg Clayton       if (!success)
1143554f68d3SGreg Clayton         break;
1144554f68d3SGreg Clayton     }
1145554f68d3SGreg Clayton     // Only if all items in a scope succeed, then do we
1146554f68d3SGreg Clayton     // print the output into the main stream
1147554f68d3SGreg Clayton     if (success)
1148554f68d3SGreg Clayton       s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
1149554f68d3SGreg Clayton   }
1150554f68d3SGreg Clayton     return true; // Scopes always successfully print themselves
1151554f68d3SGreg Clayton 
1152554f68d3SGreg Clayton   case Entry::Type::Variable:
1153554f68d3SGreg Clayton   case Entry::Type::VariableSynthetic:
1154554f68d3SGreg Clayton   case Entry::Type::ScriptVariable:
1155554f68d3SGreg Clayton   case Entry::Type::ScriptVariableSynthetic:
1156a74f37a5SEugene Zelenko     return DumpValue(s, sc, exe_ctx, entry, valobj);
1157554f68d3SGreg Clayton 
1158554f68d3SGreg Clayton   case Entry::Type::AddressFile:
1159554f68d3SGreg Clayton   case Entry::Type::AddressLoad:
1160554f68d3SGreg Clayton   case Entry::Type::AddressLoadOrFile:
1161a74f37a5SEugene Zelenko     return (addr != nullptr && addr->IsValid() &&
1162b9c1b51eSKate Stone             DumpAddress(s, sc, exe_ctx, *addr,
1163b9c1b51eSKate Stone                         entry.type == Entry::Type::AddressLoadOrFile));
1164554f68d3SGreg Clayton 
1165554f68d3SGreg Clayton   case Entry::Type::ProcessID:
1166b9c1b51eSKate Stone     if (exe_ctx) {
1167554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1168b9c1b51eSKate Stone       if (process) {
1169554f68d3SGreg Clayton         const char *format = "%" PRIu64;
1170554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1171554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1172554f68d3SGreg Clayton         s.Printf(format, process->GetID());
1173554f68d3SGreg Clayton         return true;
1174554f68d3SGreg Clayton       }
1175554f68d3SGreg Clayton     }
1176554f68d3SGreg Clayton     return false;
1177554f68d3SGreg Clayton 
1178554f68d3SGreg Clayton   case Entry::Type::ProcessFile:
1179b9c1b51eSKate Stone     if (exe_ctx) {
1180554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1181b9c1b51eSKate Stone       if (process) {
1182554f68d3SGreg Clayton         Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1183b9c1b51eSKate Stone         if (exe_module) {
1184554f68d3SGreg Clayton           if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1185554f68d3SGreg Clayton             return true;
1186554f68d3SGreg Clayton         }
1187554f68d3SGreg Clayton       }
1188554f68d3SGreg Clayton     }
1189554f68d3SGreg Clayton     return false;
1190554f68d3SGreg Clayton 
1191554f68d3SGreg Clayton   case Entry::Type::ScriptProcess:
1192b9c1b51eSKate Stone     if (exe_ctx) {
1193554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1194554f68d3SGreg Clayton       if (process)
1195b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, process,
1196b9c1b51eSKate Stone                                       entry.string.c_str());
1197554f68d3SGreg Clayton     }
1198554f68d3SGreg Clayton     return false;
1199554f68d3SGreg Clayton 
1200554f68d3SGreg Clayton   case Entry::Type::ThreadID:
1201b9c1b51eSKate Stone     if (exe_ctx) {
1202554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1203b9c1b51eSKate Stone       if (thread) {
1204554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1205b9c1b51eSKate Stone         if (!entry.printf_format.empty()) {
1206554f68d3SGreg Clayton           // Watch for the special "tid" format...
1207b9c1b51eSKate Stone           if (entry.printf_format == "tid") {
1208b9c1b51eSKate Stone             // TODO(zturner): Rather than hardcoding this to be platform
1209b9c1b51eSKate Stone             // specific, it should be controlled by a
1210b9c1b51eSKate Stone             // setting and the default value of the setting can be different
1211b9c1b51eSKate Stone             // depending on the platform.
1212554f68d3SGreg Clayton             Target &target = thread->GetProcess()->GetTarget();
1213554f68d3SGreg Clayton             ArchSpec arch(target.GetArchitecture());
1214b9c1b51eSKate Stone             llvm::Triple::OSType ostype = arch.IsValid()
1215b9c1b51eSKate Stone                                               ? arch.GetTriple().getOS()
1216b9c1b51eSKate Stone                                               : llvm::Triple::UnknownOS;
1217b9c1b51eSKate Stone             if ((ostype == llvm::Triple::FreeBSD) ||
1218750228a6SKamil Rytarowski                 (ostype == llvm::Triple::Linux) ||
1219750228a6SKamil Rytarowski                 (ostype == llvm::Triple::NetBSD)) {
1220554f68d3SGreg Clayton               format = "%" PRIu64;
1221554f68d3SGreg Clayton             }
1222b9c1b51eSKate Stone           } else {
1223554f68d3SGreg Clayton             format = entry.printf_format.c_str();
1224554f68d3SGreg Clayton           }
1225554f68d3SGreg Clayton         }
1226554f68d3SGreg Clayton         s.Printf(format, thread->GetID());
1227554f68d3SGreg Clayton         return true;
1228554f68d3SGreg Clayton       }
1229554f68d3SGreg Clayton     }
1230554f68d3SGreg Clayton     return false;
1231554f68d3SGreg Clayton 
1232554f68d3SGreg Clayton   case Entry::Type::ThreadProtocolID:
1233b9c1b51eSKate Stone     if (exe_ctx) {
1234554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1235b9c1b51eSKate Stone       if (thread) {
1236554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1237554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1238554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1239554f68d3SGreg Clayton         s.Printf(format, thread->GetProtocolID());
1240554f68d3SGreg Clayton         return true;
1241554f68d3SGreg Clayton       }
1242554f68d3SGreg Clayton     }
1243554f68d3SGreg Clayton     return false;
1244554f68d3SGreg Clayton 
1245554f68d3SGreg Clayton   case Entry::Type::ThreadIndexID:
1246b9c1b51eSKate Stone     if (exe_ctx) {
1247554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1248b9c1b51eSKate Stone       if (thread) {
1249554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1250554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1251554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1252554f68d3SGreg Clayton         s.Printf(format, thread->GetIndexID());
1253554f68d3SGreg Clayton         return true;
1254554f68d3SGreg Clayton       }
1255554f68d3SGreg Clayton     }
1256554f68d3SGreg Clayton     return false;
1257554f68d3SGreg Clayton 
1258554f68d3SGreg Clayton   case Entry::Type::ThreadName:
1259b9c1b51eSKate Stone     if (exe_ctx) {
1260554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1261b9c1b51eSKate Stone       if (thread) {
1262554f68d3SGreg Clayton         const char *cstr = thread->GetName();
1263b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1264554f68d3SGreg Clayton           s.PutCString(cstr);
1265554f68d3SGreg Clayton           return true;
1266554f68d3SGreg Clayton         }
1267554f68d3SGreg Clayton       }
1268554f68d3SGreg Clayton     }
1269554f68d3SGreg Clayton     return false;
1270554f68d3SGreg Clayton 
1271554f68d3SGreg Clayton   case Entry::Type::ThreadQueue:
1272b9c1b51eSKate Stone     if (exe_ctx) {
1273554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1274b9c1b51eSKate Stone       if (thread) {
1275554f68d3SGreg Clayton         const char *cstr = thread->GetQueueName();
1276b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1277554f68d3SGreg Clayton           s.PutCString(cstr);
1278554f68d3SGreg Clayton           return true;
1279554f68d3SGreg Clayton         }
1280554f68d3SGreg Clayton       }
1281554f68d3SGreg Clayton     }
1282554f68d3SGreg Clayton     return false;
1283554f68d3SGreg Clayton 
1284554f68d3SGreg Clayton   case Entry::Type::ThreadStopReason:
1285b9c1b51eSKate Stone     if (exe_ctx) {
1286554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1287b9c1b51eSKate Stone       if (thread) {
1288554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1289b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1290554f68d3SGreg Clayton           const char *cstr = stop_info_sp->GetDescription();
1291b9c1b51eSKate Stone           if (cstr && cstr[0]) {
1292554f68d3SGreg Clayton             s.PutCString(cstr);
1293554f68d3SGreg Clayton             return true;
1294554f68d3SGreg Clayton           }
1295554f68d3SGreg Clayton         }
1296554f68d3SGreg Clayton       }
1297554f68d3SGreg Clayton     }
1298554f68d3SGreg Clayton     return false;
1299554f68d3SGreg Clayton 
1300554f68d3SGreg Clayton   case Entry::Type::ThreadReturnValue:
1301b9c1b51eSKate Stone     if (exe_ctx) {
1302554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1303b9c1b51eSKate Stone       if (thread) {
1304554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1305b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1306b9c1b51eSKate Stone           ValueObjectSP return_valobj_sp =
1307b9c1b51eSKate Stone               StopInfo::GetReturnValueObject(stop_info_sp);
1308b9c1b51eSKate Stone           if (return_valobj_sp) {
1309554f68d3SGreg Clayton             return_valobj_sp->Dump(s);
1310554f68d3SGreg Clayton             return true;
1311554f68d3SGreg Clayton           }
1312554f68d3SGreg Clayton         }
1313554f68d3SGreg Clayton       }
1314554f68d3SGreg Clayton     }
1315554f68d3SGreg Clayton     return false;
1316554f68d3SGreg Clayton 
1317554f68d3SGreg Clayton   case Entry::Type::ThreadCompletedExpression:
1318b9c1b51eSKate Stone     if (exe_ctx) {
1319554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1320b9c1b51eSKate Stone       if (thread) {
1321554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1322b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1323b9c1b51eSKate Stone           ExpressionVariableSP expression_var_sp =
1324b9c1b51eSKate Stone               StopInfo::GetExpressionVariable(stop_info_sp);
1325b9c1b51eSKate Stone           if (expression_var_sp && expression_var_sp->GetValueObject()) {
1326554f68d3SGreg Clayton             expression_var_sp->GetValueObject()->Dump(s);
1327554f68d3SGreg Clayton             return true;
1328554f68d3SGreg Clayton           }
1329554f68d3SGreg Clayton         }
1330554f68d3SGreg Clayton       }
1331554f68d3SGreg Clayton     }
1332554f68d3SGreg Clayton     return false;
1333554f68d3SGreg Clayton 
1334554f68d3SGreg Clayton   case Entry::Type::ScriptThread:
1335b9c1b51eSKate Stone     if (exe_ctx) {
1336554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1337554f68d3SGreg Clayton       if (thread)
1338b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
1339b9c1b51eSKate Stone                                       entry.string.c_str());
1340554f68d3SGreg Clayton     }
1341554f68d3SGreg Clayton     return false;
1342554f68d3SGreg Clayton 
1343554f68d3SGreg Clayton   case Entry::Type::ThreadInfo:
1344b9c1b51eSKate Stone     if (exe_ctx) {
1345554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1346b9c1b51eSKate Stone       if (thread) {
1347554f68d3SGreg Clayton         StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1348b9c1b51eSKate Stone         if (object_sp &&
1349b9c1b51eSKate Stone             object_sp->GetType() == StructuredData::Type::eTypeDictionary) {
1350554f68d3SGreg Clayton           if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
1351554f68d3SGreg Clayton             return true;
1352554f68d3SGreg Clayton         }
1353554f68d3SGreg Clayton       }
1354554f68d3SGreg Clayton     }
1355554f68d3SGreg Clayton     return false;
1356554f68d3SGreg Clayton 
1357554f68d3SGreg Clayton   case Entry::Type::TargetArch:
1358b9c1b51eSKate Stone     if (exe_ctx) {
1359554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1360b9c1b51eSKate Stone       if (target) {
1361554f68d3SGreg Clayton         const ArchSpec &arch = target->GetArchitecture();
1362b9c1b51eSKate Stone         if (arch.IsValid()) {
1363554f68d3SGreg Clayton           s.PutCString(arch.GetArchitectureName());
1364554f68d3SGreg Clayton           return true;
1365554f68d3SGreg Clayton         }
1366554f68d3SGreg Clayton       }
1367554f68d3SGreg Clayton     }
1368554f68d3SGreg Clayton     return false;
1369554f68d3SGreg Clayton 
1370554f68d3SGreg Clayton   case Entry::Type::ScriptTarget:
1371b9c1b51eSKate Stone     if (exe_ctx) {
1372554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1373554f68d3SGreg Clayton       if (target)
1374b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, target,
1375b9c1b51eSKate Stone                                       entry.string.c_str());
1376554f68d3SGreg Clayton     }
1377554f68d3SGreg Clayton     return false;
1378554f68d3SGreg Clayton 
1379554f68d3SGreg Clayton   case Entry::Type::ModuleFile:
1380b9c1b51eSKate Stone     if (sc) {
1381554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1382b9c1b51eSKate Stone       if (module) {
1383554f68d3SGreg Clayton         if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1384554f68d3SGreg Clayton           return true;
1385554f68d3SGreg Clayton       }
1386554f68d3SGreg Clayton     }
1387554f68d3SGreg Clayton     return false;
1388554f68d3SGreg Clayton 
1389554f68d3SGreg Clayton   case Entry::Type::File:
1390b9c1b51eSKate Stone     if (sc) {
1391554f68d3SGreg Clayton       CompileUnit *cu = sc->comp_unit;
1392b9c1b51eSKate Stone       if (cu) {
1393554f68d3SGreg Clayton         // CompileUnit is a FileSpec
1394554f68d3SGreg Clayton         if (DumpFile(s, *cu, (FileKind)entry.number))
1395554f68d3SGreg Clayton           return true;
1396554f68d3SGreg Clayton       }
1397554f68d3SGreg Clayton     }
1398554f68d3SGreg Clayton     return false;
1399554f68d3SGreg Clayton 
1400dc975670SDawn Perchik   case Entry::Type::Lang:
1401b9c1b51eSKate Stone     if (sc) {
1402dc975670SDawn Perchik       CompileUnit *cu = sc->comp_unit;
1403b9c1b51eSKate Stone       if (cu) {
1404b9c1b51eSKate Stone         const char *lang_name =
1405b9c1b51eSKate Stone             Language::GetNameForLanguageType(cu->GetLanguage());
1406b9c1b51eSKate Stone         if (lang_name) {
1407dc975670SDawn Perchik           s.PutCString(lang_name);
1408dc975670SDawn Perchik           return true;
1409dc975670SDawn Perchik         }
1410dc975670SDawn Perchik       }
1411dc975670SDawn Perchik     }
1412dc975670SDawn Perchik     return false;
1413dc975670SDawn Perchik 
1414554f68d3SGreg Clayton   case Entry::Type::FrameIndex:
1415b9c1b51eSKate Stone     if (exe_ctx) {
1416554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1417b9c1b51eSKate Stone       if (frame) {
1418554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1419554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1420554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1421554f68d3SGreg Clayton         s.Printf(format, frame->GetFrameIndex());
1422554f68d3SGreg Clayton         return true;
1423554f68d3SGreg Clayton       }
1424554f68d3SGreg Clayton     }
1425554f68d3SGreg Clayton     return false;
1426554f68d3SGreg Clayton 
1427554f68d3SGreg Clayton   case Entry::Type::FrameRegisterPC:
1428b9c1b51eSKate Stone     if (exe_ctx) {
1429554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1430b9c1b51eSKate Stone       if (frame) {
1431554f68d3SGreg Clayton         const Address &pc_addr = frame->GetFrameCodeAddress();
1432b9c1b51eSKate Stone         if (pc_addr.IsValid()) {
1433554f68d3SGreg Clayton           if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
1434554f68d3SGreg Clayton             return true;
1435554f68d3SGreg Clayton         }
1436554f68d3SGreg Clayton       }
1437554f68d3SGreg Clayton     }
1438554f68d3SGreg Clayton     return false;
1439554f68d3SGreg Clayton 
1440554f68d3SGreg Clayton   case Entry::Type::FrameRegisterSP:
1441b9c1b51eSKate Stone     if (exe_ctx) {
1442554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1443b9c1b51eSKate Stone       if (frame) {
1444b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
1445b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1446554f68d3SGreg Clayton           return true;
1447554f68d3SGreg Clayton       }
1448554f68d3SGreg Clayton     }
1449554f68d3SGreg Clayton     return false;
1450554f68d3SGreg Clayton 
1451554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFP:
1452b9c1b51eSKate Stone     if (exe_ctx) {
1453554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1454b9c1b51eSKate Stone       if (frame) {
1455b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
1456b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1457554f68d3SGreg Clayton           return true;
1458554f68d3SGreg Clayton       }
1459554f68d3SGreg Clayton     }
1460554f68d3SGreg Clayton     return false;
1461554f68d3SGreg Clayton 
1462554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFlags:
1463b9c1b51eSKate Stone     if (exe_ctx) {
1464554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1465b9c1b51eSKate Stone       if (frame) {
1466b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric,
1467b9c1b51eSKate Stone                          LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
1468554f68d3SGreg Clayton           return true;
1469554f68d3SGreg Clayton       }
1470554f68d3SGreg Clayton     }
1471554f68d3SGreg Clayton     return false;
1472554f68d3SGreg Clayton 
14736a9767c7SJim Ingham   case Entry::Type::FrameNoDebug:
14746a9767c7SJim Ingham     if (exe_ctx) {
14756a9767c7SJim Ingham       StackFrame *frame = exe_ctx->GetFramePtr();
14766a9767c7SJim Ingham       if (frame) {
14776a9767c7SJim Ingham         return !frame->HasDebugInformation();
14786a9767c7SJim Ingham       }
14796a9767c7SJim Ingham     }
14806a9767c7SJim Ingham     return true;
14816a9767c7SJim Ingham 
1482554f68d3SGreg Clayton   case Entry::Type::FrameRegisterByName:
1483b9c1b51eSKate Stone     if (exe_ctx) {
1484554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1485b9c1b51eSKate Stone       if (frame) {
1486b9c1b51eSKate Stone         if (DumpRegister(s, frame, entry.string.c_str(),
1487b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1488554f68d3SGreg Clayton           return true;
1489554f68d3SGreg Clayton       }
1490554f68d3SGreg Clayton     }
1491554f68d3SGreg Clayton     return false;
1492554f68d3SGreg Clayton 
1493554f68d3SGreg Clayton   case Entry::Type::ScriptFrame:
1494b9c1b51eSKate Stone     if (exe_ctx) {
1495554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1496554f68d3SGreg Clayton       if (frame)
1497b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
1498b9c1b51eSKate Stone                                       entry.string.c_str());
1499554f68d3SGreg Clayton     }
1500554f68d3SGreg Clayton     return false;
1501554f68d3SGreg Clayton 
1502554f68d3SGreg Clayton   case Entry::Type::FunctionID:
1503b9c1b51eSKate Stone     if (sc) {
1504b9c1b51eSKate Stone       if (sc->function) {
1505554f68d3SGreg Clayton         s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
1506554f68d3SGreg Clayton         return true;
1507b9c1b51eSKate Stone       } else if (sc->symbol) {
1508554f68d3SGreg Clayton         s.Printf("symbol[%u]", sc->symbol->GetID());
1509554f68d3SGreg Clayton         return true;
1510554f68d3SGreg Clayton       }
1511554f68d3SGreg Clayton     }
1512554f68d3SGreg Clayton     return false;
1513554f68d3SGreg Clayton 
1514554f68d3SGreg Clayton   case Entry::Type::FunctionDidChange:
1515554f68d3SGreg Clayton     return function_changed;
1516554f68d3SGreg Clayton 
1517554f68d3SGreg Clayton   case Entry::Type::FunctionInitialFunction:
1518554f68d3SGreg Clayton     return initial_function;
1519554f68d3SGreg Clayton 
1520b9c1b51eSKate Stone   case Entry::Type::FunctionName: {
1521d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1522d4129b47SEnrico Granata     bool language_plugin_handled = false;
1523d4129b47SEnrico Granata     StreamString ss;
1524d4129b47SEnrico Granata     if (sc->function)
1525d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1526d4129b47SEnrico Granata     else if (sc->symbol)
1527d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1528b9c1b51eSKate Stone     if (language_plugin) {
1529b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1530b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1531d4129b47SEnrico Granata     }
1532b9c1b51eSKate Stone     if (language_plugin_handled) {
1533c156427dSZachary Turner       s << ss.GetString();
1534d4129b47SEnrico Granata       return true;
1535b9c1b51eSKate Stone     } else {
1536a74f37a5SEugene Zelenko       const char *name = nullptr;
1537554f68d3SGreg Clayton       if (sc->function)
1538a74f37a5SEugene Zelenko         name = sc->function->GetName().AsCString(nullptr);
1539554f68d3SGreg Clayton       else if (sc->symbol)
1540a74f37a5SEugene Zelenko         name = sc->symbol->GetName().AsCString(nullptr);
1541b9c1b51eSKate Stone       if (name) {
1542554f68d3SGreg Clayton         s.PutCString(name);
1543554f68d3SGreg Clayton 
1544b9c1b51eSKate Stone         if (sc->block) {
1545554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
1546b9c1b51eSKate Stone           if (inline_block) {
1547b9c1b51eSKate Stone             const InlineFunctionInfo *inline_info =
1548b9c1b51eSKate Stone                 sc->block->GetInlinedFunctionInfo();
1549b9c1b51eSKate Stone             if (inline_info) {
1550554f68d3SGreg Clayton               s.PutCString(" [inlined] ");
1551ddaf6a72SGreg Clayton               inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
1552554f68d3SGreg Clayton             }
1553554f68d3SGreg Clayton           }
1554554f68d3SGreg Clayton         }
1555554f68d3SGreg Clayton         return true;
1556554f68d3SGreg Clayton       }
1557554f68d3SGreg Clayton     }
1558d4129b47SEnrico Granata   }
1559554f68d3SGreg Clayton     return false;
1560554f68d3SGreg Clayton 
1561b9c1b51eSKate Stone   case Entry::Type::FunctionNameNoArgs: {
1562d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1563d4129b47SEnrico Granata     bool language_plugin_handled = false;
1564d4129b47SEnrico Granata     StreamString ss;
1565d4129b47SEnrico Granata     if (sc->function)
1566d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1567d4129b47SEnrico Granata     else if (sc->symbol)
1568d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1569b9c1b51eSKate Stone     if (language_plugin) {
1570b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1571b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1572d4129b47SEnrico Granata           ss);
1573d4129b47SEnrico Granata     }
1574b9c1b51eSKate Stone     if (language_plugin_handled) {
1575c156427dSZachary Turner       s << ss.GetString();
1576d4129b47SEnrico Granata       return true;
1577b9c1b51eSKate Stone     } else {
1578554f68d3SGreg Clayton       ConstString name;
1579554f68d3SGreg Clayton       if (sc->function)
1580ddaf6a72SGreg Clayton         name = sc->function->GetNameNoArguments();
1581554f68d3SGreg Clayton       else if (sc->symbol)
1582ddaf6a72SGreg Clayton         name = sc->symbol->GetNameNoArguments();
1583b9c1b51eSKate Stone       if (name) {
1584554f68d3SGreg Clayton         s.PutCString(name.GetCString());
1585554f68d3SGreg Clayton         return true;
1586554f68d3SGreg Clayton       }
1587554f68d3SGreg Clayton     }
1588d4129b47SEnrico Granata   }
1589554f68d3SGreg Clayton     return false;
1590554f68d3SGreg Clayton 
1591b9c1b51eSKate Stone   case Entry::Type::FunctionNameWithArgs: {
1592d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1593d4129b47SEnrico Granata     bool language_plugin_handled = false;
1594d4129b47SEnrico Granata     StreamString ss;
1595d4129b47SEnrico Granata     if (sc->function)
1596d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1597d4129b47SEnrico Granata     else if (sc->symbol)
1598d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1599b9c1b51eSKate Stone     if (language_plugin) {
1600b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1601b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1602d4129b47SEnrico Granata     }
1603b9c1b51eSKate Stone     if (language_plugin_handled) {
1604c156427dSZachary Turner       s << ss.GetString();
1605d4129b47SEnrico Granata       return true;
1606b9c1b51eSKate Stone     } else {
1607554f68d3SGreg Clayton       // Print the function name with arguments in it
1608b9c1b51eSKate Stone       if (sc->function) {
1609b9c1b51eSKate Stone         ExecutionContextScope *exe_scope =
1610b9c1b51eSKate Stone             exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1611a74f37a5SEugene Zelenko         const char *cstr = sc->function->GetName().AsCString(nullptr);
1612b9c1b51eSKate Stone         if (cstr) {
1613a74f37a5SEugene Zelenko           const InlineFunctionInfo *inline_info = nullptr;
1614554f68d3SGreg Clayton           VariableListSP variable_list_sp;
1615554f68d3SGreg Clayton           bool get_function_vars = true;
1616b9c1b51eSKate Stone           if (sc->block) {
1617554f68d3SGreg Clayton             Block *inline_block = sc->block->GetContainingInlinedBlock();
1618554f68d3SGreg Clayton 
1619b9c1b51eSKate Stone             if (inline_block) {
1620554f68d3SGreg Clayton               get_function_vars = false;
1621554f68d3SGreg Clayton               inline_info = sc->block->GetInlinedFunctionInfo();
1622554f68d3SGreg Clayton               if (inline_info)
1623554f68d3SGreg Clayton                 variable_list_sp = inline_block->GetBlockVariableList(true);
1624554f68d3SGreg Clayton             }
1625554f68d3SGreg Clayton           }
1626554f68d3SGreg Clayton 
1627b9c1b51eSKate Stone           if (get_function_vars) {
1628b9c1b51eSKate Stone             variable_list_sp =
1629b9c1b51eSKate Stone                 sc->function->GetBlock(true).GetBlockVariableList(true);
1630554f68d3SGreg Clayton           }
1631554f68d3SGreg Clayton 
1632b9c1b51eSKate Stone           if (inline_info) {
1633554f68d3SGreg Clayton             s.PutCString(cstr);
1634554f68d3SGreg Clayton             s.PutCString(" [inlined] ");
1635b9c1b51eSKate Stone             cstr =
1636b9c1b51eSKate Stone                 inline_info->GetName(sc->function->GetLanguage()).GetCString();
1637554f68d3SGreg Clayton           }
1638554f68d3SGreg Clayton 
1639554f68d3SGreg Clayton           VariableList args;
1640554f68d3SGreg Clayton           if (variable_list_sp)
1641b9c1b51eSKate Stone             variable_list_sp->AppendVariablesWithScope(
1642b9c1b51eSKate Stone                 eValueTypeVariableArgument, args);
1643b9c1b51eSKate Stone           if (args.GetSize() > 0) {
1644554f68d3SGreg Clayton             const char *open_paren = strchr(cstr, '(');
1645554f68d3SGreg Clayton             const char *close_paren = nullptr;
1646554f68d3SGreg Clayton             const char *generic = strchr(cstr, '<');
1647554f68d3SGreg Clayton             // if before the arguments list begins there is a template sign
1648554f68d3SGreg Clayton             // then scan to the end of the generic args before you try to find
1649554f68d3SGreg Clayton             // the arguments list
1650b9c1b51eSKate Stone             if (generic && open_paren && generic < open_paren) {
1651554f68d3SGreg Clayton               int generic_depth = 1;
1652554f68d3SGreg Clayton               ++generic;
1653b9c1b51eSKate Stone               for (; *generic && generic_depth > 0; generic++) {
1654554f68d3SGreg Clayton                 if (*generic == '<')
1655554f68d3SGreg Clayton                   generic_depth++;
1656554f68d3SGreg Clayton                 if (*generic == '>')
1657554f68d3SGreg Clayton                   generic_depth--;
1658554f68d3SGreg Clayton               }
1659554f68d3SGreg Clayton               if (*generic)
1660554f68d3SGreg Clayton                 open_paren = strchr(generic, '(');
1661554f68d3SGreg Clayton               else
1662554f68d3SGreg Clayton                 open_paren = nullptr;
1663554f68d3SGreg Clayton             }
1664b9c1b51eSKate Stone             if (open_paren) {
1665b9c1b51eSKate Stone               if (IsToken(open_paren, "(anonymous namespace)")) {
1666b9c1b51eSKate Stone                 open_paren =
1667b9c1b51eSKate Stone                     strchr(open_paren + strlen("(anonymous namespace)"), '(');
1668554f68d3SGreg Clayton                 if (open_paren)
1669554f68d3SGreg Clayton                   close_paren = strchr(open_paren, ')');
1670b9c1b51eSKate Stone               } else
1671554f68d3SGreg Clayton                 close_paren = strchr(open_paren, ')');
1672554f68d3SGreg Clayton             }
1673554f68d3SGreg Clayton 
1674554f68d3SGreg Clayton             if (open_paren)
1675554f68d3SGreg Clayton               s.Write(cstr, open_paren - cstr + 1);
1676b9c1b51eSKate Stone             else {
1677554f68d3SGreg Clayton               s.PutCString(cstr);
1678554f68d3SGreg Clayton               s.PutChar('(');
1679554f68d3SGreg Clayton             }
1680554f68d3SGreg Clayton             const size_t num_args = args.GetSize();
1681b9c1b51eSKate Stone             for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1682554f68d3SGreg Clayton               std::string buffer;
1683554f68d3SGreg Clayton 
1684554f68d3SGreg Clayton               VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1685b9c1b51eSKate Stone               ValueObjectSP var_value_sp(
1686b9c1b51eSKate Stone                   ValueObjectVariable::Create(exe_scope, var_sp));
1687ad91c7ceSEnrico Granata               StreamString ss;
1688c156427dSZachary Turner               llvm::StringRef var_representation;
1689554f68d3SGreg Clayton               const char *var_name = var_value_sp->GetName().GetCString();
1690b9c1b51eSKate Stone               if (var_value_sp->GetCompilerType().IsValid()) {
1691ad91c7ceSEnrico Granata                 if (var_value_sp && exe_scope->CalculateTarget())
1692b9c1b51eSKate Stone                   var_value_sp =
1693b9c1b51eSKate Stone                       var_value_sp->GetQualifiedRepresentationIfAvailable(
1694b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1695b9c1b51eSKate Stone                               ->TargetProperties::GetPreferDynamicValue(),
1696b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1697b9c1b51eSKate Stone                               ->TargetProperties::GetEnableSyntheticValue());
169899558cc4SGreg Clayton                 if (var_value_sp->GetCompilerType().IsAggregateType() &&
1699b9c1b51eSKate Stone                     DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
1700b9c1b51eSKate Stone                   static StringSummaryFormat format(
1701b9c1b51eSKate Stone                       TypeSummaryImpl::Flags()
1702554f68d3SGreg Clayton                           .SetHideItemNames(false)
1703554f68d3SGreg Clayton                           .SetShowMembersOneLiner(true),
1704554f68d3SGreg Clayton                       "");
1705b9c1b51eSKate Stone                   format.FormatObject(var_value_sp.get(), buffer,
1706b9c1b51eSKate Stone                                       TypeSummaryOptions());
1707c156427dSZachary Turner                   var_representation = buffer;
1708b9c1b51eSKate Stone                 } else
1709b9c1b51eSKate Stone                   var_value_sp->DumpPrintableRepresentation(
1710b9c1b51eSKate Stone                       ss, ValueObject::ValueObjectRepresentationStyle::
1711b9c1b51eSKate Stone                               eValueObjectRepresentationStyleSummary,
1712ad91c7ceSEnrico Granata                       eFormatDefault,
171365d86e4fSEnrico Granata                       ValueObject::PrintableRepresentationSpecialCases::eAllow,
1714ad91c7ceSEnrico Granata                       false);
1715ad91c7ceSEnrico Granata               }
1716ad91c7ceSEnrico Granata 
1717c156427dSZachary Turner               if (!ss.GetString().empty())
1718c156427dSZachary Turner                 var_representation = ss.GetString();
1719554f68d3SGreg Clayton               if (arg_idx > 0)
1720554f68d3SGreg Clayton                 s.PutCString(", ");
1721b9c1b51eSKate Stone               if (var_value_sp->GetError().Success()) {
1722c156427dSZachary Turner                 if (!var_representation.empty())
1723c156427dSZachary Turner                   s.Printf("%s=%s", var_name, var_representation.str().c_str());
1724554f68d3SGreg Clayton                 else
1725b9c1b51eSKate Stone                   s.Printf("%s=%s at %s", var_name,
1726b9c1b51eSKate Stone                            var_value_sp->GetTypeName().GetCString(),
1727b9c1b51eSKate Stone                            var_value_sp->GetLocationAsCString());
1728b9c1b51eSKate Stone               } else
1729554f68d3SGreg Clayton                 s.Printf("%s=<unavailable>", var_name);
1730554f68d3SGreg Clayton             }
1731554f68d3SGreg Clayton 
1732554f68d3SGreg Clayton             if (close_paren)
1733554f68d3SGreg Clayton               s.PutCString(close_paren);
1734554f68d3SGreg Clayton             else
1735554f68d3SGreg Clayton               s.PutChar(')');
1736554f68d3SGreg Clayton 
1737b9c1b51eSKate Stone           } else {
1738554f68d3SGreg Clayton             s.PutCString(cstr);
1739554f68d3SGreg Clayton           }
1740554f68d3SGreg Clayton           return true;
1741554f68d3SGreg Clayton         }
1742b9c1b51eSKate Stone       } else if (sc->symbol) {
1743a74f37a5SEugene Zelenko         const char *cstr = sc->symbol->GetName().AsCString(nullptr);
1744b9c1b51eSKate Stone         if (cstr) {
1745554f68d3SGreg Clayton           s.PutCString(cstr);
1746554f68d3SGreg Clayton           return true;
1747554f68d3SGreg Clayton         }
1748554f68d3SGreg Clayton       }
1749554f68d3SGreg Clayton     }
1750d4129b47SEnrico Granata   }
1751554f68d3SGreg Clayton     return false;
1752554f68d3SGreg Clayton 
1753554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffset:
1754b9c1b51eSKate Stone     if (addr) {
1755b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
1756b9c1b51eSKate Stone                                         false))
1757554f68d3SGreg Clayton         return true;
1758554f68d3SGreg Clayton     }
1759554f68d3SGreg Clayton     return false;
1760554f68d3SGreg Clayton 
1761554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffsetConcrete:
1762b9c1b51eSKate Stone     if (addr) {
1763b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
1764b9c1b51eSKate Stone                                         true))
1765554f68d3SGreg Clayton         return true;
1766554f68d3SGreg Clayton     }
1767554f68d3SGreg Clayton     return false;
1768554f68d3SGreg Clayton 
1769554f68d3SGreg Clayton   case Entry::Type::FunctionLineOffset:
1770b9c1b51eSKate Stone     return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1771b9c1b51eSKate Stone                                           sc->line_entry.range.GetBaseAddress(),
1772b9c1b51eSKate Stone                                           false, false, false));
1773554f68d3SGreg Clayton 
1774554f68d3SGreg Clayton   case Entry::Type::FunctionPCOffset:
1775b9c1b51eSKate Stone     if (exe_ctx) {
1776554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1777b9c1b51eSKate Stone       if (frame) {
1778b9c1b51eSKate Stone         if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1779b9c1b51eSKate Stone                                           frame->GetFrameCodeAddress(), false,
1780b9c1b51eSKate Stone                                           false, false))
1781554f68d3SGreg Clayton           return true;
1782554f68d3SGreg Clayton       }
1783554f68d3SGreg Clayton     }
1784554f68d3SGreg Clayton     return false;
1785554f68d3SGreg Clayton 
1786c980fa92SJason Molenda   case Entry::Type::FunctionChanged:
1787a74f37a5SEugene Zelenko     return function_changed;
1788c980fa92SJason Molenda 
1789b9c1b51eSKate Stone   case Entry::Type::FunctionIsOptimized: {
17906ab659a9SJason Molenda     bool is_optimized = false;
1791b9c1b51eSKate Stone     if (sc->function && sc->function->GetIsOptimized()) {
17926ab659a9SJason Molenda       is_optimized = true;
17936ab659a9SJason Molenda     }
17946ab659a9SJason Molenda     return is_optimized;
17956ab659a9SJason Molenda   }
17966ab659a9SJason Molenda 
1797c980fa92SJason Molenda   case Entry::Type::FunctionInitial:
1798a74f37a5SEugene Zelenko     return initial_function;
1799c980fa92SJason Molenda 
1800554f68d3SGreg Clayton   case Entry::Type::LineEntryFile:
1801b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1802554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1803b9c1b51eSKate Stone       if (module) {
1804554f68d3SGreg Clayton         if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
1805554f68d3SGreg Clayton           return true;
1806554f68d3SGreg Clayton       }
1807554f68d3SGreg Clayton     }
1808554f68d3SGreg Clayton     return false;
1809554f68d3SGreg Clayton 
1810554f68d3SGreg Clayton   case Entry::Type::LineEntryLineNumber:
1811b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1812554f68d3SGreg Clayton       const char *format = "%" PRIu32;
1813554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1814554f68d3SGreg Clayton         format = entry.printf_format.c_str();
1815554f68d3SGreg Clayton       s.Printf(format, sc->line_entry.line);
1816554f68d3SGreg Clayton       return true;
1817554f68d3SGreg Clayton     }
1818554f68d3SGreg Clayton     return false;
1819554f68d3SGreg Clayton 
1820554f68d3SGreg Clayton   case Entry::Type::LineEntryStartAddress:
1821554f68d3SGreg Clayton   case Entry::Type::LineEntryEndAddress:
1822b9c1b51eSKate Stone     if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
1823554f68d3SGreg Clayton       Address addr = sc->line_entry.range.GetBaseAddress();
1824554f68d3SGreg Clayton 
1825554f68d3SGreg Clayton       if (entry.type == Entry::Type::LineEntryEndAddress)
1826554f68d3SGreg Clayton         addr.Slide(sc->line_entry.range.GetByteSize());
1827554f68d3SGreg Clayton       if (DumpAddress(s, sc, exe_ctx, addr, false))
1828554f68d3SGreg Clayton         return true;
1829554f68d3SGreg Clayton     }
1830554f68d3SGreg Clayton     return false;
1831554f68d3SGreg Clayton 
1832554f68d3SGreg Clayton   case Entry::Type::CurrentPCArrow:
1833b9c1b51eSKate Stone     if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
1834b9c1b51eSKate Stone       RegisterContextSP reg_ctx =
1835b9c1b51eSKate Stone           exe_ctx->GetFramePtr()->GetRegisterContextSP();
1836b9c1b51eSKate Stone       if (reg_ctx) {
1837554f68d3SGreg Clayton         addr_t pc_loadaddr = reg_ctx->GetPC();
1838b9c1b51eSKate Stone         if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
1839554f68d3SGreg Clayton           Address pc;
1840554f68d3SGreg Clayton           pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
1841b9c1b51eSKate Stone           if (pc == *addr) {
1842554f68d3SGreg Clayton             s.Printf("-> ");
1843554f68d3SGreg Clayton             return true;
1844554f68d3SGreg Clayton           }
1845554f68d3SGreg Clayton         }
1846554f68d3SGreg Clayton       }
1847554f68d3SGreg Clayton       s.Printf("   ");
1848554f68d3SGreg Clayton       return true;
1849554f68d3SGreg Clayton     }
1850554f68d3SGreg Clayton     return false;
1851554f68d3SGreg Clayton   }
1852554f68d3SGreg Clayton   return false;
1853554f68d3SGreg Clayton }
1854554f68d3SGreg Clayton 
1855b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames(
1856b9c1b51eSKate Stone     Stream &s, const FormatEntity::Entry::Definition *parent) {
1857b9c1b51eSKate Stone   if (parent->children) {
1858554f68d3SGreg Clayton     const size_t n = parent->num_children;
1859b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
1860554f68d3SGreg Clayton       if (i > 0)
1861554f68d3SGreg Clayton         s.PutCString(", ");
1862554f68d3SGreg Clayton       s.Printf("\"%s\"", parent->children[i].name);
1863554f68d3SGreg Clayton     }
1864554f68d3SGreg Clayton     return true;
1865554f68d3SGreg Clayton   }
1866554f68d3SGreg Clayton   return false;
1867554f68d3SGreg Clayton }
1868554f68d3SGreg Clayton 
1869b9c1b51eSKate Stone static Error ParseEntry(const llvm::StringRef &format_str,
1870554f68d3SGreg Clayton                         const FormatEntity::Entry::Definition *parent,
1871b9c1b51eSKate Stone                         FormatEntity::Entry &entry) {
1872554f68d3SGreg Clayton   Error error;
1873554f68d3SGreg Clayton 
1874554f68d3SGreg Clayton   const size_t sep_pos = format_str.find_first_of(".[:");
1875b9c1b51eSKate Stone   const char sep_char =
1876b9c1b51eSKate Stone       (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
1877554f68d3SGreg Clayton   llvm::StringRef key = format_str.substr(0, sep_pos);
1878554f68d3SGreg Clayton 
1879554f68d3SGreg Clayton   const size_t n = parent->num_children;
1880b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1881554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1882b9c1b51eSKate Stone     if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
1883554f68d3SGreg Clayton       llvm::StringRef value;
1884554f68d3SGreg Clayton       if (sep_char)
1885b9c1b51eSKate Stone         value =
1886b9c1b51eSKate Stone             format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
1887b9c1b51eSKate Stone       switch (entry_def->type) {
1888554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentString:
18893a29f8b9SPavel Labath         entry.string = format_str.str();
1890554f68d3SGreg Clayton         return error; // Success
1891554f68d3SGreg Clayton 
1892554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentNumber:
1893554f68d3SGreg Clayton         entry.number = entry_def->data;
1894554f68d3SGreg Clayton         return error; // Success
1895554f68d3SGreg Clayton 
1896554f68d3SGreg Clayton       case FormatEntity::Entry::Type::InsertString:
1897554f68d3SGreg Clayton         entry.type = entry_def->type;
1898554f68d3SGreg Clayton         entry.string = entry_def->string;
1899554f68d3SGreg Clayton         return error; // Success
1900554f68d3SGreg Clayton 
1901554f68d3SGreg Clayton       default:
1902554f68d3SGreg Clayton         entry.type = entry_def->type;
1903554f68d3SGreg Clayton         break;
1904554f68d3SGreg Clayton       }
1905554f68d3SGreg Clayton 
1906b9c1b51eSKate Stone       if (value.empty()) {
1907b9c1b51eSKate Stone         if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
1908b9c1b51eSKate Stone           if (entry_def->children) {
1909554f68d3SGreg Clayton             StreamString error_strm;
1910b9c1b51eSKate Stone             error_strm.Printf("'%s' can't be specified on its own, you must "
1911b9c1b51eSKate Stone                               "access one of its children: ",
1912b9c1b51eSKate Stone                               entry_def->name);
1913554f68d3SGreg Clayton             DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
1914c156427dSZachary Turner             error.SetErrorStringWithFormat("%s", error_strm.GetData());
1915b9c1b51eSKate Stone           } else if (sep_char == ':') {
1916b9c1b51eSKate Stone             // Any value whose separator is a with a ':' means this value has a
1917b9c1b51eSKate Stone             // string argument
1918554f68d3SGreg Clayton             // that needs to be stored in the entry (like "${script.var:}").
1919554f68d3SGreg Clayton             // In this case the string value is the empty string which is ok.
1920b9c1b51eSKate Stone           } else {
1921554f68d3SGreg Clayton             error.SetErrorStringWithFormat("%s", "invalid entry definitions");
1922554f68d3SGreg Clayton           }
1923554f68d3SGreg Clayton         }
1924b9c1b51eSKate Stone       } else {
1925b9c1b51eSKate Stone         if (entry_def->children) {
1926554f68d3SGreg Clayton           error = ParseEntry(value, entry_def, entry);
1927b9c1b51eSKate Stone         } else if (sep_char == ':') {
1928b9c1b51eSKate Stone           // Any value whose separator is a with a ':' means this value has a
1929b9c1b51eSKate Stone           // string argument
1930b9c1b51eSKate Stone           // that needs to be stored in the entry (like
1931b9c1b51eSKate Stone           // "${script.var:modulename.function}")
19323a29f8b9SPavel Labath           entry.string = value.str();
1933b9c1b51eSKate Stone         } else {
1934b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1935b9c1b51eSKate Stone               "'%s' followed by '%s' but it has no children", key.str().c_str(),
1936554f68d3SGreg Clayton               value.str().c_str());
1937554f68d3SGreg Clayton         }
1938554f68d3SGreg Clayton       }
1939554f68d3SGreg Clayton       return error;
1940554f68d3SGreg Clayton     }
1941554f68d3SGreg Clayton   }
1942554f68d3SGreg Clayton   StreamString error_strm;
1943554f68d3SGreg Clayton   if (parent->type == FormatEntity::Entry::Type::Root)
1944b9c1b51eSKate Stone     error_strm.Printf(
1945b9c1b51eSKate Stone         "invalid top level item '%s'. Valid top level items are: ",
1946b9c1b51eSKate Stone         key.str().c_str());
1947554f68d3SGreg Clayton   else
1948b9c1b51eSKate Stone     error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
1949b9c1b51eSKate Stone                       key.str().c_str(), parent->name);
1950554f68d3SGreg Clayton   DumpCommaSeparatedChildEntryNames(error_strm, parent);
1951c156427dSZachary Turner   error.SetErrorStringWithFormat("%s", error_strm.GetData());
1952554f68d3SGreg Clayton   return error;
1953554f68d3SGreg Clayton }
1954554f68d3SGreg Clayton 
1955554f68d3SGreg Clayton static const FormatEntity::Entry::Definition *
1956b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str,
1957b9c1b51eSKate Stone           const FormatEntity::Entry::Definition *parent,
1958b9c1b51eSKate Stone           llvm::StringRef &remainder) {
1959554f68d3SGreg Clayton   Error error;
1960554f68d3SGreg Clayton 
1961554f68d3SGreg Clayton   std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
1962554f68d3SGreg Clayton   const size_t n = parent->num_children;
1963b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1964554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1965b9c1b51eSKate Stone     if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
1966b9c1b51eSKate Stone       if (p.second.empty()) {
1967554f68d3SGreg Clayton         if (format_str.back() == '.')
1968554f68d3SGreg Clayton           remainder = format_str.drop_front(format_str.size() - 1);
1969554f68d3SGreg Clayton         else
1970554f68d3SGreg Clayton           remainder = llvm::StringRef(); // Exact match
1971554f68d3SGreg Clayton         return entry_def;
1972b9c1b51eSKate Stone       } else {
1973b9c1b51eSKate Stone         if (entry_def->children) {
1974554f68d3SGreg Clayton           return FindEntry(p.second, entry_def, remainder);
1975b9c1b51eSKate Stone         } else {
1976554f68d3SGreg Clayton           remainder = p.second;
1977554f68d3SGreg Clayton           return entry_def;
1978554f68d3SGreg Clayton         }
1979554f68d3SGreg Clayton       }
1980554f68d3SGreg Clayton     }
1981554f68d3SGreg Clayton   }
1982554f68d3SGreg Clayton   remainder = format_str;
1983554f68d3SGreg Clayton   return parent;
1984554f68d3SGreg Clayton }
1985554f68d3SGreg Clayton 
1986b9c1b51eSKate Stone Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
1987b9c1b51eSKate Stone                                   uint32_t depth) {
1988554f68d3SGreg Clayton   Error error;
1989b9c1b51eSKate Stone   while (!format.empty() && error.Success()) {
1990554f68d3SGreg Clayton     const size_t non_special_chars = format.find_first_of("${}\\");
1991554f68d3SGreg Clayton 
1992b9c1b51eSKate Stone     if (non_special_chars == llvm::StringRef::npos) {
1993554f68d3SGreg Clayton       // No special characters, just string bytes so add them and we are done
1994554f68d3SGreg Clayton       parent_entry.AppendText(format);
1995554f68d3SGreg Clayton       return error;
1996554f68d3SGreg Clayton     }
1997554f68d3SGreg Clayton 
1998b9c1b51eSKate Stone     if (non_special_chars > 0) {
1999b9c1b51eSKate Stone       // We have a special character, so add all characters before these as a
2000b9c1b51eSKate Stone       // plain string
2001554f68d3SGreg Clayton       parent_entry.AppendText(format.substr(0, non_special_chars));
2002554f68d3SGreg Clayton       format = format.drop_front(non_special_chars);
2003554f68d3SGreg Clayton     }
2004554f68d3SGreg Clayton 
2005b9c1b51eSKate Stone     switch (format[0]) {
2006554f68d3SGreg Clayton     case '\0':
2007554f68d3SGreg Clayton       return error;
2008554f68d3SGreg Clayton 
2009b9c1b51eSKate Stone     case '{': {
2010554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '{'
2011554f68d3SGreg Clayton       Entry scope_entry(Entry::Type::Scope);
2012554f68d3SGreg Clayton       error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
2013554f68d3SGreg Clayton       if (error.Fail())
2014554f68d3SGreg Clayton         return error;
2015554f68d3SGreg Clayton       parent_entry.AppendEntry(std::move(scope_entry));
2016b9c1b51eSKate Stone     } break;
2017554f68d3SGreg Clayton 
2018554f68d3SGreg Clayton     case '}':
2019554f68d3SGreg Clayton       if (depth == 0)
2020554f68d3SGreg Clayton         error.SetErrorString("unmatched '}' character");
2021554f68d3SGreg Clayton       else
2022b9c1b51eSKate Stone         format =
2023b9c1b51eSKate Stone             format
2024b9c1b51eSKate Stone                 .drop_front(); // Skip the '}' as we are at the end of the scope
2025554f68d3SGreg Clayton       return error;
2026554f68d3SGreg Clayton 
2027b9c1b51eSKate Stone     case '\\': {
2028554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '\' character
2029b9c1b51eSKate Stone       if (format.empty()) {
2030b9c1b51eSKate Stone         error.SetErrorString(
2031b9c1b51eSKate Stone             "'\\' character was not followed by another character");
2032554f68d3SGreg Clayton         return error;
2033554f68d3SGreg Clayton       }
2034554f68d3SGreg Clayton 
2035554f68d3SGreg Clayton       const char desens_char = format[0];
2036554f68d3SGreg Clayton       format = format.drop_front(); // Skip the desensitized char character
2037b9c1b51eSKate Stone       switch (desens_char) {
2038b9c1b51eSKate Stone       case 'a':
2039b9c1b51eSKate Stone         parent_entry.AppendChar('\a');
2040b9c1b51eSKate Stone         break;
2041b9c1b51eSKate Stone       case 'b':
2042b9c1b51eSKate Stone         parent_entry.AppendChar('\b');
2043b9c1b51eSKate Stone         break;
2044b9c1b51eSKate Stone       case 'f':
2045b9c1b51eSKate Stone         parent_entry.AppendChar('\f');
2046b9c1b51eSKate Stone         break;
2047b9c1b51eSKate Stone       case 'n':
2048b9c1b51eSKate Stone         parent_entry.AppendChar('\n');
2049b9c1b51eSKate Stone         break;
2050b9c1b51eSKate Stone       case 'r':
2051b9c1b51eSKate Stone         parent_entry.AppendChar('\r');
2052b9c1b51eSKate Stone         break;
2053b9c1b51eSKate Stone       case 't':
2054b9c1b51eSKate Stone         parent_entry.AppendChar('\t');
2055b9c1b51eSKate Stone         break;
2056b9c1b51eSKate Stone       case 'v':
2057b9c1b51eSKate Stone         parent_entry.AppendChar('\v');
2058b9c1b51eSKate Stone         break;
2059b9c1b51eSKate Stone       case '\'':
2060b9c1b51eSKate Stone         parent_entry.AppendChar('\'');
2061b9c1b51eSKate Stone         break;
2062b9c1b51eSKate Stone       case '\\':
2063b9c1b51eSKate Stone         parent_entry.AppendChar('\\');
2064b9c1b51eSKate Stone         break;
2065554f68d3SGreg Clayton       case '0':
2066554f68d3SGreg Clayton         // 1 to 3 octal chars
2067554f68d3SGreg Clayton         {
2068554f68d3SGreg Clayton           // Make a string that can hold onto the initial zero char,
2069554f68d3SGreg Clayton           // up to 3 octal digits, and a terminating NULL.
2070554f68d3SGreg Clayton           char oct_str[5] = {0, 0, 0, 0, 0};
2071554f68d3SGreg Clayton 
2072554f68d3SGreg Clayton           int i;
2073554f68d3SGreg Clayton           for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2074554f68d3SGreg Clayton             oct_str[i] = format[i];
2075554f68d3SGreg Clayton 
2076554f68d3SGreg Clayton           // We don't want to consume the last octal character since
2077554f68d3SGreg Clayton           // the main for loop will do this for us, so we advance p by
2078554f68d3SGreg Clayton           // one less than i (even if i is zero)
2079554f68d3SGreg Clayton           format = format.drop_front(i);
2080a74f37a5SEugene Zelenko           unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2081b9c1b51eSKate Stone           if (octal_value <= UINT8_MAX) {
2082554f68d3SGreg Clayton             parent_entry.AppendChar((char)octal_value);
2083b9c1b51eSKate Stone           } else {
2084554f68d3SGreg Clayton             error.SetErrorString("octal number is larger than a single byte");
2085554f68d3SGreg Clayton             return error;
2086554f68d3SGreg Clayton           }
2087554f68d3SGreg Clayton         }
2088554f68d3SGreg Clayton         break;
2089554f68d3SGreg Clayton 
2090554f68d3SGreg Clayton       case 'x':
2091554f68d3SGreg Clayton         // hex number in the format
2092b9c1b51eSKate Stone         if (isxdigit(format[0])) {
2093554f68d3SGreg Clayton           // Make a string that can hold onto two hex chars plus a
2094554f68d3SGreg Clayton           // NULL terminator
2095554f68d3SGreg Clayton           char hex_str[3] = {0, 0, 0};
2096554f68d3SGreg Clayton           hex_str[0] = format[0];
2097554f68d3SGreg Clayton 
2098554f68d3SGreg Clayton           format = format.drop_front();
2099554f68d3SGreg Clayton 
2100b9c1b51eSKate Stone           if (isxdigit(format[0])) {
2101554f68d3SGreg Clayton             hex_str[1] = format[0];
2102554f68d3SGreg Clayton             format = format.drop_front();
2103554f68d3SGreg Clayton           }
2104554f68d3SGreg Clayton 
2105a74f37a5SEugene Zelenko           unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2106b9c1b51eSKate Stone           if (hex_value <= UINT8_MAX) {
2107554f68d3SGreg Clayton             parent_entry.AppendChar((char)hex_value);
2108b9c1b51eSKate Stone           } else {
2109554f68d3SGreg Clayton             error.SetErrorString("hex number is larger than a single byte");
2110554f68d3SGreg Clayton             return error;
2111554f68d3SGreg Clayton           }
2112b9c1b51eSKate Stone         } else {
2113554f68d3SGreg Clayton           parent_entry.AppendChar(desens_char);
2114554f68d3SGreg Clayton         }
2115554f68d3SGreg Clayton         break;
2116554f68d3SGreg Clayton 
2117554f68d3SGreg Clayton       default:
2118554f68d3SGreg Clayton         // Just desensitize any other character by just printing what
2119554f68d3SGreg Clayton         // came after the '\'
2120554f68d3SGreg Clayton         parent_entry.AppendChar(desens_char);
2121554f68d3SGreg Clayton         break;
2122554f68d3SGreg Clayton       }
2123b9c1b51eSKate Stone     } break;
2124554f68d3SGreg Clayton 
2125554f68d3SGreg Clayton     case '$':
2126b9c1b51eSKate Stone       if (format.size() == 1) {
2127554f68d3SGreg Clayton         // '$' at the end of a format string, just print the '$'
2128554f68d3SGreg Clayton         parent_entry.AppendText("$");
2129b9c1b51eSKate Stone       } else {
2130554f68d3SGreg Clayton         format = format.drop_front(); // Skip the '$'
2131554f68d3SGreg Clayton 
2132b9c1b51eSKate Stone         if (format[0] == '{') {
2133554f68d3SGreg Clayton           format = format.drop_front(); // Skip the '{'
2134554f68d3SGreg Clayton 
2135554f68d3SGreg Clayton           llvm::StringRef variable, variable_format;
2136b9c1b51eSKate Stone           error = FormatEntity::ExtractVariableInfo(format, variable,
2137b9c1b51eSKate Stone                                                     variable_format);
2138554f68d3SGreg Clayton           if (error.Fail())
2139554f68d3SGreg Clayton             return error;
2140554f68d3SGreg Clayton           bool verify_is_thread_id = false;
2141554f68d3SGreg Clayton           Entry entry;
2142b9c1b51eSKate Stone           if (!variable_format.empty()) {
21433a29f8b9SPavel Labath             entry.printf_format = variable_format.str();
2144554f68d3SGreg Clayton 
2145554f68d3SGreg Clayton             // If the format contains a '%' we are going to assume this is
2146554f68d3SGreg Clayton             // a printf style format. So if you want to format your thread ID
2147554f68d3SGreg Clayton             // using "0x%llx" you can use:
2148554f68d3SGreg Clayton             // ${thread.id%0x%llx}
2149554f68d3SGreg Clayton             //
2150554f68d3SGreg Clayton             // If there is no '%' in the format, then it is assumed to be a
2151554f68d3SGreg Clayton             // LLDB format name, or one of the extended formats specified in
2152554f68d3SGreg Clayton             // the switch statement below.
2153554f68d3SGreg Clayton 
2154b9c1b51eSKate Stone             if (entry.printf_format.find('%') == std::string::npos) {
2155554f68d3SGreg Clayton               bool clear_printf = false;
2156554f68d3SGreg Clayton 
2157b9c1b51eSKate Stone               if (FormatManager::GetFormatFromCString(
2158b9c1b51eSKate Stone                       entry.printf_format.c_str(), false, entry.fmt)) {
2159554f68d3SGreg Clayton                 // We have an LLDB format, so clear the printf format
2160554f68d3SGreg Clayton                 clear_printf = true;
2161b9c1b51eSKate Stone               } else if (entry.printf_format.size() == 1) {
2162b9c1b51eSKate Stone                 switch (entry.printf_format[0]) {
2163554f68d3SGreg Clayton                 case '@': // if this is an @ sign, print ObjC description
2164b9c1b51eSKate Stone                   entry.number = ValueObject::
2165b9c1b51eSKate Stone                       eValueObjectRepresentationStyleLanguageSpecific;
2166554f68d3SGreg Clayton                   clear_printf = true;
2167554f68d3SGreg Clayton                   break;
2168b9c1b51eSKate Stone                 case 'V': // if this is a V, print the value using the default
2169b9c1b51eSKate Stone                           // format
2170b9c1b51eSKate Stone                   entry.number =
2171b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleValue;
2172554f68d3SGreg Clayton                   clear_printf = true;
2173554f68d3SGreg Clayton                   break;
2174554f68d3SGreg Clayton                 case 'L': // if this is an L, print the location of the value
2175b9c1b51eSKate Stone                   entry.number =
2176b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleLocation;
2177554f68d3SGreg Clayton                   clear_printf = true;
2178554f68d3SGreg Clayton                   break;
2179554f68d3SGreg Clayton                 case 'S': // if this is an S, print the summary after all
2180b9c1b51eSKate Stone                   entry.number =
2181b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleSummary;
2182554f68d3SGreg Clayton                   clear_printf = true;
2183554f68d3SGreg Clayton                   break;
2184554f68d3SGreg Clayton                 case '#': // if this is a '#', print the number of children
2185b9c1b51eSKate Stone                   entry.number =
2186b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleChildrenCount;
2187554f68d3SGreg Clayton                   clear_printf = true;
2188554f68d3SGreg Clayton                   break;
2189554f68d3SGreg Clayton                 case 'T': // if this is a 'T', print the type
2190b9c1b51eSKate Stone                   entry.number =
2191b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleType;
2192554f68d3SGreg Clayton                   clear_printf = true;
2193554f68d3SGreg Clayton                   break;
2194554f68d3SGreg Clayton                 case 'N': // if this is a 'N', print the name
2195b9c1b51eSKate Stone                   entry.number =
2196b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleName;
2197554f68d3SGreg Clayton                   clear_printf = true;
2198554f68d3SGreg Clayton                   break;
2199281b65bcSGreg Clayton                 case '>': // if this is a '>', print the expression path
2200b9c1b51eSKate Stone                   entry.number = ValueObject::
2201b9c1b51eSKate Stone                       eValueObjectRepresentationStyleExpressionPath;
2202554f68d3SGreg Clayton                   clear_printf = true;
2203554f68d3SGreg Clayton                   break;
2204554f68d3SGreg Clayton                 default:
2205b9c1b51eSKate Stone                   error.SetErrorStringWithFormat("invalid format: '%s'",
2206b9c1b51eSKate Stone                                                  entry.printf_format.c_str());
2207554f68d3SGreg Clayton                   return error;
2208554f68d3SGreg Clayton                 }
2209b9c1b51eSKate Stone               } else if (FormatManager::GetFormatFromCString(
2210b9c1b51eSKate Stone                              entry.printf_format.c_str(), true, entry.fmt)) {
2211554f68d3SGreg Clayton                 clear_printf = true;
2212b9c1b51eSKate Stone               } else if (entry.printf_format == "tid") {
2213554f68d3SGreg Clayton                 verify_is_thread_id = true;
2214b9c1b51eSKate Stone               } else {
2215b9c1b51eSKate Stone                 error.SetErrorStringWithFormat("invalid format: '%s'",
2216b9c1b51eSKate Stone                                                entry.printf_format.c_str());
2217554f68d3SGreg Clayton                 return error;
2218554f68d3SGreg Clayton               }
2219554f68d3SGreg Clayton 
2220554f68d3SGreg Clayton               // Our format string turned out to not be a printf style format
2221554f68d3SGreg Clayton               // so lets clear the string
2222554f68d3SGreg Clayton               if (clear_printf)
2223554f68d3SGreg Clayton                 entry.printf_format.clear();
2224554f68d3SGreg Clayton             }
2225554f68d3SGreg Clayton           }
2226554f68d3SGreg Clayton 
2227554f68d3SGreg Clayton           // Check for dereferences
2228b9c1b51eSKate Stone           if (variable[0] == '*') {
2229554f68d3SGreg Clayton             entry.deref = true;
2230554f68d3SGreg Clayton             variable = variable.drop_front();
2231554f68d3SGreg Clayton           }
2232554f68d3SGreg Clayton 
2233554f68d3SGreg Clayton           error = ParseEntry(variable, &g_root, entry);
2234554f68d3SGreg Clayton           if (error.Fail())
2235554f68d3SGreg Clayton             return error;
2236554f68d3SGreg Clayton 
2237b9c1b51eSKate Stone           if (verify_is_thread_id) {
2238554f68d3SGreg Clayton             if (entry.type != Entry::Type::ThreadID &&
2239b9c1b51eSKate Stone                 entry.type != Entry::Type::ThreadProtocolID) {
2240b9c1b51eSKate Stone               error.SetErrorString("the 'tid' format can only be used on "
2241b9c1b51eSKate Stone                                    "${thread.id} and ${thread.protocol_id}");
2242554f68d3SGreg Clayton             }
2243554f68d3SGreg Clayton           }
2244554f68d3SGreg Clayton 
2245b9c1b51eSKate Stone           switch (entry.type) {
2246554f68d3SGreg Clayton           case Entry::Type::Variable:
2247554f68d3SGreg Clayton           case Entry::Type::VariableSynthetic:
2248b9c1b51eSKate Stone             if (entry.number == 0) {
2249554f68d3SGreg Clayton               if (entry.string.empty())
2250b9c1b51eSKate Stone                 entry.number =
2251b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleValue;
2252554f68d3SGreg Clayton               else
2253b9c1b51eSKate Stone                 entry.number =
2254b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleSummary;
2255554f68d3SGreg Clayton             }
2256554f68d3SGreg Clayton             break;
2257554f68d3SGreg Clayton           default:
2258b9c1b51eSKate Stone             // Make sure someone didn't try to dereference anything but ${var}
2259b9c1b51eSKate Stone             // or ${svar}
2260b9c1b51eSKate Stone             if (entry.deref) {
2261b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
2262b9c1b51eSKate Stone                   "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2263b9c1b51eSKate Stone                   variable.str().c_str());
2264554f68d3SGreg Clayton               return error;
2265554f68d3SGreg Clayton             }
2266554f68d3SGreg Clayton           }
2267554f68d3SGreg Clayton           // Check if this entry just wants to insert a constant string
2268554f68d3SGreg Clayton           // value into the parent_entry, if so, insert the string with
2269554f68d3SGreg Clayton           // AppendText, else append the entry to the parent_entry.
2270554f68d3SGreg Clayton           if (entry.type == Entry::Type::InsertString)
2271554f68d3SGreg Clayton             parent_entry.AppendText(entry.string.c_str());
2272554f68d3SGreg Clayton           else
2273554f68d3SGreg Clayton             parent_entry.AppendEntry(std::move(entry));
2274554f68d3SGreg Clayton         }
2275554f68d3SGreg Clayton       }
2276554f68d3SGreg Clayton       break;
2277554f68d3SGreg Clayton     }
2278554f68d3SGreg Clayton   }
2279554f68d3SGreg Clayton   return error;
2280554f68d3SGreg Clayton }
2281554f68d3SGreg Clayton 
2282b9c1b51eSKate Stone Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2283b9c1b51eSKate Stone                                         llvm::StringRef &variable_name,
2284b9c1b51eSKate Stone                                         llvm::StringRef &variable_format) {
2285554f68d3SGreg Clayton   Error error;
2286554f68d3SGreg Clayton   variable_name = llvm::StringRef();
2287554f68d3SGreg Clayton   variable_format = llvm::StringRef();
2288554f68d3SGreg Clayton 
2289e8433cc1SBruce Mitchener   const size_t paren_pos = format_str.find('}');
2290b9c1b51eSKate Stone   if (paren_pos != llvm::StringRef::npos) {
2291e8433cc1SBruce Mitchener     const size_t percent_pos = format_str.find('%');
2292b9c1b51eSKate Stone     if (percent_pos < paren_pos) {
2293b9c1b51eSKate Stone       if (percent_pos > 0) {
2294554f68d3SGreg Clayton         if (percent_pos > 1)
2295554f68d3SGreg Clayton           variable_name = format_str.substr(0, percent_pos);
2296b9c1b51eSKate Stone         variable_format =
2297b9c1b51eSKate Stone             format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2298554f68d3SGreg Clayton       }
2299b9c1b51eSKate Stone     } else {
2300554f68d3SGreg Clayton       variable_name = format_str.substr(0, paren_pos);
2301554f68d3SGreg Clayton     }
2302554f68d3SGreg Clayton     // Strip off elements and the formatting and the trailing '}'
2303554f68d3SGreg Clayton     format_str = format_str.substr(paren_pos + 1);
2304b9c1b51eSKate Stone   } else {
2305b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
2306b9c1b51eSKate Stone         "missing terminating '}' character for '${%s'",
2307b9c1b51eSKate Stone         format_str.str().c_str());
2308554f68d3SGreg Clayton   }
2309554f68d3SGreg Clayton   return error;
2310554f68d3SGreg Clayton }
2311554f68d3SGreg Clayton 
2312b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
2313b9c1b51eSKate Stone                                   llvm::StringRef variable_name,
2314b9c1b51eSKate Stone                                   llvm::StringRef variable_format) {
2315b9c1b51eSKate Stone   if (variable_name.empty() || variable_name.equals(".fullpath")) {
2316554f68d3SGreg Clayton     file_spec.Dump(&s);
2317554f68d3SGreg Clayton     return true;
2318b9c1b51eSKate Stone   } else if (variable_name.equals(".basename")) {
2319554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2320554f68d3SGreg Clayton     return true;
2321b9c1b51eSKate Stone   } else if (variable_name.equals(".dirname")) {
2322554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2323554f68d3SGreg Clayton     return true;
2324554f68d3SGreg Clayton   }
2325554f68d3SGreg Clayton   return false;
2326554f68d3SGreg Clayton }
2327554f68d3SGreg Clayton 
2328b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix,
2329b9c1b51eSKate Stone                              const char *suffix) {
2330554f68d3SGreg Clayton   std::string match(prefix.str());
2331554f68d3SGreg Clayton   match.append(suffix);
23323a29f8b9SPavel Labath   return match;
2333554f68d3SGreg Clayton }
2334554f68d3SGreg Clayton 
2335b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def,
2336554f68d3SGreg Clayton                        const llvm::StringRef &prefix,
2337554f68d3SGreg Clayton                        const llvm::StringRef &match_prefix,
2338b9c1b51eSKate Stone                        StringList &matches) {
2339554f68d3SGreg Clayton   const size_t n = def->num_children;
2340b9c1b51eSKate Stone   if (n > 0) {
2341b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
23423a29f8b9SPavel Labath       std::string match = prefix.str();
2343554f68d3SGreg Clayton       if (match_prefix.empty())
2344554f68d3SGreg Clayton         matches.AppendString(MakeMatch(prefix, def->children[i].name));
2345b9c1b51eSKate Stone       else if (strncmp(def->children[i].name, match_prefix.data(),
2346b9c1b51eSKate Stone                        match_prefix.size()) == 0)
2347b9c1b51eSKate Stone         matches.AppendString(
2348b9c1b51eSKate Stone             MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2349554f68d3SGreg Clayton     }
2350554f68d3SGreg Clayton   }
2351554f68d3SGreg Clayton }
2352a74f37a5SEugene Zelenko 
23534aa8753cSZachary Turner size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point,
2354b9c1b51eSKate Stone                                   int max_return_elements, bool &word_complete,
2355b9c1b51eSKate Stone                                   StringList &matches) {
2356554f68d3SGreg Clayton   word_complete = false;
23574aa8753cSZachary Turner   str = str.drop_front(match_start_point);
2358554f68d3SGreg Clayton   matches.Clear();
2359554f68d3SGreg Clayton 
2360554f68d3SGreg Clayton   const size_t dollar_pos = str.rfind('$');
23614aa8753cSZachary Turner   if (dollar_pos == llvm::StringRef::npos)
23624aa8753cSZachary Turner     return 0;
23634aa8753cSZachary Turner 
2364554f68d3SGreg Clayton   // Hitting TAB after $ at the end of the string add a "{"
2365b9c1b51eSKate Stone   if (dollar_pos == str.size() - 1) {
23663a29f8b9SPavel Labath     std::string match = str.str();
2367554f68d3SGreg Clayton     match.append("{");
23684aa8753cSZachary Turner     matches.AppendString(match);
23694aa8753cSZachary Turner     return 1;
23704aa8753cSZachary Turner   }
23714aa8753cSZachary Turner 
23724aa8753cSZachary Turner   if (str[dollar_pos + 1] != '{')
23734aa8753cSZachary Turner     return 0;
23744aa8753cSZachary Turner 
2375554f68d3SGreg Clayton   const size_t close_pos = str.find('}', dollar_pos + 2);
23764aa8753cSZachary Turner   if (close_pos != llvm::StringRef::npos)
23774aa8753cSZachary Turner     return 0;
23784aa8753cSZachary Turner 
2379554f68d3SGreg Clayton   const size_t format_pos = str.find('%', dollar_pos + 2);
23804aa8753cSZachary Turner   if (format_pos != llvm::StringRef::npos)
23814aa8753cSZachary Turner     return 0;
23824aa8753cSZachary Turner 
2383554f68d3SGreg Clayton   llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2384b9c1b51eSKate Stone   if (partial_variable.empty()) {
2385554f68d3SGreg Clayton     // Suggest all top level entites as we are just past "${"
2386554f68d3SGreg Clayton     AddMatches(&g_root, str, llvm::StringRef(), matches);
23874aa8753cSZachary Turner     return matches.GetSize();
23884aa8753cSZachary Turner   }
23894aa8753cSZachary Turner 
2390554f68d3SGreg Clayton   // We have a partially specified variable, find it
2391554f68d3SGreg Clayton   llvm::StringRef remainder;
2392b9c1b51eSKate Stone   const FormatEntity::Entry::Definition *entry_def =
2393b9c1b51eSKate Stone       FindEntry(partial_variable, &g_root, remainder);
23944aa8753cSZachary Turner   if (!entry_def)
23954aa8753cSZachary Turner     return 0;
23964aa8753cSZachary Turner 
2397554f68d3SGreg Clayton   const size_t n = entry_def->num_children;
2398554f68d3SGreg Clayton 
2399b9c1b51eSKate Stone   if (remainder.empty()) {
2400554f68d3SGreg Clayton     // Exact match
2401b9c1b51eSKate Stone     if (n > 0) {
2402554f68d3SGreg Clayton       // "${thread.info" <TAB>
24033a29f8b9SPavel Labath       matches.AppendString(MakeMatch(str, "."));
2404b9c1b51eSKate Stone     } else {
2405554f68d3SGreg Clayton       // "${thread.id" <TAB>
24063a29f8b9SPavel Labath       matches.AppendString(MakeMatch(str, "}"));
2407554f68d3SGreg Clayton       word_complete = true;
2408554f68d3SGreg Clayton     }
2409b9c1b51eSKate Stone   } else if (remainder.equals(".")) {
2410554f68d3SGreg Clayton     // "${thread." <TAB>
2411554f68d3SGreg Clayton     AddMatches(entry_def, str, llvm::StringRef(), matches);
2412b9c1b51eSKate Stone   } else {
2413554f68d3SGreg Clayton     // We have a partial match
2414554f68d3SGreg Clayton     // "${thre" <TAB>
2415554f68d3SGreg Clayton     AddMatches(entry_def, str, remainder, matches);
2416554f68d3SGreg Clayton   }
2417554f68d3SGreg Clayton   return matches.GetSize();
2418554f68d3SGreg Clayton }
2419