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 
12a74f37a5SEugene Zelenko // C Includes
13a74f37a5SEugene Zelenko // C++ Includes
14a74f37a5SEugene Zelenko // Other libraries and framework includes
15d717cc9fSEnrico Granata #include "llvm/ADT/STLExtras.h"
16d717cc9fSEnrico Granata #include "llvm/ADT/StringRef.h"
17d717cc9fSEnrico Granata 
18a74f37a5SEugene Zelenko // Project includes
19554f68d3SGreg Clayton #include "lldb/Core/Address.h"
20554f68d3SGreg Clayton #include "lldb/Core/Debugger.h"
21554f68d3SGreg Clayton #include "lldb/Core/Module.h"
22554f68d3SGreg Clayton #include "lldb/Core/Stream.h"
23554f68d3SGreg Clayton #include "lldb/Core/StreamString.h"
24554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h"
25554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h"
26554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h"
27554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h"
28ad91c7ceSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h"
29937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h"
30554f68d3SGreg Clayton #include "lldb/Host/FileSpec.h"
31554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
32554f68d3SGreg Clayton #include "lldb/Symbol/Block.h"
33554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
34554f68d3SGreg Clayton #include "lldb/Symbol/Function.h"
35554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h"
36554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h"
37554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h"
38554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h"
390e0984eeSJim Ingham #include "lldb/Target/Language.h"
40554f68d3SGreg Clayton #include "lldb/Target/Process.h"
41554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h"
42554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h"
43554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h"
44554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h"
45554f68d3SGreg Clayton #include "lldb/Target/Target.h"
46554f68d3SGreg Clayton #include "lldb/Target/Thread.h"
47554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
48554f68d3SGreg Clayton 
49554f68d3SGreg Clayton using namespace lldb;
50554f68d3SGreg Clayton using namespace lldb_private;
51554f68d3SGreg Clayton 
52b9c1b51eSKate Stone enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
53554f68d3SGreg Clayton 
54b9c1b51eSKate Stone #define ENTRY(n, t, f)                                                         \
55b9c1b51eSKate Stone   {                                                                            \
56b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
57b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false               \
58b9c1b51eSKate Stone   }
59b9c1b51eSKate Stone #define ENTRY_VALUE(n, t, f, v)                                                \
60b9c1b51eSKate Stone   {                                                                            \
61b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
62b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, v, 0, nullptr, false               \
63b9c1b51eSKate Stone   }
64b9c1b51eSKate Stone #define ENTRY_CHILDREN(n, t, f, c)                                             \
65b9c1b51eSKate Stone   {                                                                            \
66b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
67b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c,     \
68b9c1b51eSKate Stone         false                                                                  \
69b9c1b51eSKate Stone   }
70b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c)                                    \
71b9c1b51eSKate Stone   {                                                                            \
72b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
73b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c,     \
74b9c1b51eSKate Stone         true                                                                   \
75b9c1b51eSKate Stone   }
76b9c1b51eSKate Stone #define ENTRY_STRING(n, s)                                                     \
77b9c1b51eSKate Stone   {                                                                            \
78b9c1b51eSKate Stone     n, s, FormatEntity::Entry::Type::InsertString,                             \
79b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false            \
80b9c1b51eSKate Stone   }
81b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_string_entry[] = {
82b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
83554f68d3SGreg Clayton 
84b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_addr_entries[] = {
85b9c1b51eSKate Stone     ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64),
86554f68d3SGreg Clayton     ENTRY("load", AddressLoadOrFile, UInt64),
87554f68d3SGreg Clayton };
88554f68d3SGreg Clayton 
89b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_file_child_entries[] = {
90554f68d3SGreg Clayton     ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename),
91554f68d3SGreg Clayton     ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname),
92b9c1b51eSKate Stone     ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)};
93554f68d3SGreg Clayton 
94b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_frame_child_entries[] = {
95554f68d3SGreg Clayton     ENTRY("index", FrameIndex, UInt32),
96554f68d3SGreg Clayton     ENTRY("pc", FrameRegisterPC, UInt64),
97554f68d3SGreg Clayton     ENTRY("fp", FrameRegisterFP, UInt64),
98554f68d3SGreg Clayton     ENTRY("sp", FrameRegisterSP, UInt64),
99554f68d3SGreg Clayton     ENTRY("flags", FrameRegisterFlags, UInt64),
100554f68d3SGreg Clayton     ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry),
101554f68d3SGreg Clayton };
102554f68d3SGreg Clayton 
103b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = {
104b9c1b51eSKate Stone     ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString),
105554f68d3SGreg Clayton     ENTRY("name-without-args", FunctionNameNoArgs, CString),
106554f68d3SGreg Clayton     ENTRY("name-with-args", FunctionNameWithArgs, CString),
107554f68d3SGreg Clayton     ENTRY("addr-offset", FunctionAddrOffset, UInt64),
108b9c1b51eSKate Stone     ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete,
109b9c1b51eSKate Stone           UInt64),
110554f68d3SGreg Clayton     ENTRY("line-offset", FunctionLineOffset, UInt64),
111c980fa92SJason Molenda     ENTRY("pc-offset", FunctionPCOffset, UInt64),
112c980fa92SJason Molenda     ENTRY("initial-function", FunctionInitial, None),
1136ab659a9SJason Molenda     ENTRY("changed", FunctionChanged, None),
114b9c1b51eSKate Stone     ENTRY("is-optimized", FunctionIsOptimized, None)};
115554f68d3SGreg Clayton 
116b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = {
117554f68d3SGreg Clayton     ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries),
118554f68d3SGreg Clayton     ENTRY("number", LineEntryLineNumber, UInt32),
119554f68d3SGreg Clayton     ENTRY("start-addr", LineEntryStartAddress, UInt64),
120554f68d3SGreg Clayton     ENTRY("end-addr", LineEntryEndAddress, UInt64),
121554f68d3SGreg Clayton };
122554f68d3SGreg Clayton 
123b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = {
124554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
125554f68d3SGreg Clayton };
126554f68d3SGreg Clayton 
127b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = {
128554f68d3SGreg Clayton     ENTRY("id", ProcessID, UInt64),
129554f68d3SGreg Clayton     ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename),
130554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries),
131554f68d3SGreg Clayton };
132554f68d3SGreg Clayton 
133b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = {
134b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
135554f68d3SGreg Clayton 
136b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = {
137b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
138554f68d3SGreg Clayton 
139b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = {
140554f68d3SGreg Clayton     ENTRY("id", ThreadID, UInt64),
141554f68d3SGreg Clayton     ENTRY("protocol_id", ThreadProtocolID, UInt64),
142554f68d3SGreg Clayton     ENTRY("index", ThreadIndexID, UInt32),
143554f68d3SGreg Clayton     ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry),
144554f68d3SGreg Clayton     ENTRY("queue", ThreadQueue, CString),
145554f68d3SGreg Clayton     ENTRY("name", ThreadName, CString),
146554f68d3SGreg Clayton     ENTRY("stop-reason", ThreadStopReason, CString),
147554f68d3SGreg Clayton     ENTRY("return-value", ThreadReturnValue, CString),
148554f68d3SGreg Clayton     ENTRY("completed-expression", ThreadCompletedExpression, CString),
149554f68d3SGreg Clayton };
150554f68d3SGreg Clayton 
151b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = {
152554f68d3SGreg Clayton     ENTRY("arch", TargetArch, CString),
153554f68d3SGreg Clayton };
154554f68d3SGreg Clayton 
155554f68d3SGreg Clayton #define _TO_STR2(_val) #_val
156554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val)
157554f68d3SGreg Clayton 
158b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
159b9c1b51eSKate Stone     ENTRY_STRING("black",
160b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
161554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
162b9c1b51eSKate Stone     ENTRY_STRING("green",
163b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
164b9c1b51eSKate Stone     ENTRY_STRING("yellow",
165b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
166b9c1b51eSKate Stone     ENTRY_STRING("blue",
167b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
168b9c1b51eSKate Stone     ENTRY_STRING("purple",
169b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
170b9c1b51eSKate Stone     ENTRY_STRING("cyan",
171b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
172b9c1b51eSKate Stone     ENTRY_STRING("white",
173b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
174554f68d3SGreg Clayton };
175554f68d3SGreg Clayton 
176b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
177b9c1b51eSKate Stone     ENTRY_STRING("black",
178b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
179554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
180b9c1b51eSKate Stone     ENTRY_STRING("green",
181b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
182b9c1b51eSKate Stone     ENTRY_STRING("yellow",
183b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
184b9c1b51eSKate Stone     ENTRY_STRING("blue",
185b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
186b9c1b51eSKate Stone     ENTRY_STRING("purple",
187b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
188b9c1b51eSKate Stone     ENTRY_STRING("cyan",
189b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
190b9c1b51eSKate Stone     ENTRY_STRING("white",
191b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
192554f68d3SGreg Clayton };
193554f68d3SGreg Clayton 
194b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = {
195554f68d3SGreg Clayton     ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries),
196554f68d3SGreg Clayton     ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries),
197b9c1b51eSKate Stone     ENTRY_STRING("normal",
198b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
199554f68d3SGreg Clayton     ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
200554f68d3SGreg Clayton     ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
201b9c1b51eSKate Stone     ENTRY_STRING("italic",
202b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
203b9c1b51eSKate Stone     ENTRY_STRING("underline",
204b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
205b9c1b51eSKate Stone     ENTRY_STRING("slow-blink",
206b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
207b9c1b51eSKate Stone     ENTRY_STRING("fast-blink",
208b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
209b9c1b51eSKate Stone     ENTRY_STRING("negative",
210b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
211b9c1b51eSKate Stone     ENTRY_STRING("conceal",
212b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
213b9c1b51eSKate Stone     ENTRY_STRING("crossed-out",
214b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
215554f68d3SGreg Clayton };
216554f68d3SGreg Clayton 
217b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = {
218554f68d3SGreg Clayton     ENTRY("frame", ScriptFrame, None),
219554f68d3SGreg Clayton     ENTRY("process", ScriptProcess, None),
220554f68d3SGreg Clayton     ENTRY("target", ScriptTarget, None),
221554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
222554f68d3SGreg Clayton     ENTRY("var", ScriptVariable, None),
223554f68d3SGreg Clayton     ENTRY("svar", ScriptVariableSynthetic, None),
224554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
225554f68d3SGreg Clayton };
226554f68d3SGreg Clayton 
227b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = {
228554f68d3SGreg Clayton     ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries),
229554f68d3SGreg Clayton     ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64),
230554f68d3SGreg Clayton     ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries),
231554f68d3SGreg Clayton     ENTRY("current-pc-arrow", CurrentPCArrow, CString),
232554f68d3SGreg Clayton     ENTRY_CHILDREN("file", File, CString, g_file_child_entries),
233dc975670SDawn Perchik     ENTRY("language", Lang, CString),
234554f68d3SGreg Clayton     ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries),
235554f68d3SGreg Clayton     ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries),
236554f68d3SGreg Clayton     ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries),
237554f68d3SGreg Clayton     ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries),
238554f68d3SGreg Clayton     ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries),
239554f68d3SGreg Clayton     ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries),
240b9c1b51eSKate Stone     ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None,
241b9c1b51eSKate Stone                             g_svar_child_entries),
242554f68d3SGreg Clayton     ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries),
243554f68d3SGreg Clayton     ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries),
244554f68d3SGreg Clayton     ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries),
245554f68d3SGreg Clayton };
246554f68d3SGreg Clayton 
247b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root =
248b9c1b51eSKate Stone     ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries);
249554f68d3SGreg Clayton 
250b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s)
251b9c1b51eSKate Stone     : string(s.data(), s.size()), printf_format(), children(),
252b9c1b51eSKate Stone       definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
253b9c1b51eSKate Stone       number(0), deref(false) {}
254554f68d3SGreg Clayton 
255b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch)
256b9c1b51eSKate Stone     : string(1, ch), printf_format(), children(), definition(nullptr),
257b9c1b51eSKate Stone       type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
258554f68d3SGreg Clayton 
259b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) {
260554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
261554f68d3SGreg Clayton     children.push_back(Entry(ch));
262554f68d3SGreg Clayton   else
263554f68d3SGreg Clayton     children.back().string.append(1, ch);
264554f68d3SGreg Clayton }
265554f68d3SGreg Clayton 
266b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
267554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
268554f68d3SGreg Clayton     children.push_back(Entry(s));
269554f68d3SGreg Clayton   else
270554f68d3SGreg Clayton     children.back().string.append(s.data(), s.size());
271554f68d3SGreg Clayton }
272554f68d3SGreg Clayton 
273b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) {
274554f68d3SGreg Clayton   return AppendText(llvm::StringRef(cstr));
275554f68d3SGreg Clayton }
276554f68d3SGreg Clayton 
277b9c1b51eSKate Stone Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
278554f68d3SGreg Clayton   entry.Clear();
279554f68d3SGreg Clayton   entry.type = Entry::Type::Root;
280554f68d3SGreg Clayton   llvm::StringRef modifiable_format(format_str);
281554f68d3SGreg Clayton   return ParseInternal(modifiable_format, entry, 0);
282554f68d3SGreg Clayton }
283554f68d3SGreg Clayton 
284b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee)                                                      \
285b9c1b51eSKate Stone   case FormatEntity::Entry::Type::eee:                                         \
286b9c1b51eSKate Stone     return #eee
287554f68d3SGreg Clayton 
288b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) {
289b9c1b51eSKate Stone   switch (t) {
290554f68d3SGreg Clayton     ENUM_TO_CSTR(Invalid);
291554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentNumber);
292554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentString);
293554f68d3SGreg Clayton     ENUM_TO_CSTR(InsertString);
294554f68d3SGreg Clayton     ENUM_TO_CSTR(Root);
295554f68d3SGreg Clayton     ENUM_TO_CSTR(String);
296554f68d3SGreg Clayton     ENUM_TO_CSTR(Scope);
297554f68d3SGreg Clayton     ENUM_TO_CSTR(Variable);
298554f68d3SGreg Clayton     ENUM_TO_CSTR(VariableSynthetic);
299554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariable);
300554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariableSynthetic);
301554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoad);
302554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressFile);
303554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoadOrFile);
304554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessID);
305554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessFile);
306554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptProcess);
307554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadID);
308554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadProtocolID);
309554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadIndexID);
310554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadName);
311554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadQueue);
312554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadStopReason);
313554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadReturnValue);
314554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadCompletedExpression);
315554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptThread);
316554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadInfo);
317554f68d3SGreg Clayton     ENUM_TO_CSTR(TargetArch);
318554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptTarget);
319554f68d3SGreg Clayton     ENUM_TO_CSTR(ModuleFile);
320554f68d3SGreg Clayton     ENUM_TO_CSTR(File);
321dc975670SDawn Perchik     ENUM_TO_CSTR(Lang);
322554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameIndex);
323554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterPC);
324554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterSP);
325554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFP);
326554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFlags);
327554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterByName);
328554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptFrame);
329554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionID);
330554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionDidChange);
331554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionInitialFunction);
332554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionName);
333554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameWithArgs);
334554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameNoArgs);
335554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffset);
336554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
337554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionLineOffset);
338554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionPCOffset);
339c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionInitial);
340c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionChanged);
3416ab659a9SJason Molenda     ENUM_TO_CSTR(FunctionIsOptimized);
342554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryFile);
343554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryLineNumber);
344554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryStartAddress);
345554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryEndAddress);
346554f68d3SGreg Clayton     ENUM_TO_CSTR(CurrentPCArrow);
347554f68d3SGreg Clayton   }
348554f68d3SGreg Clayton   return "???";
349554f68d3SGreg Clayton }
350554f68d3SGreg Clayton 
351554f68d3SGreg Clayton #undef ENUM_TO_CSTR
352554f68d3SGreg Clayton 
353b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const {
354554f68d3SGreg Clayton   s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
355554f68d3SGreg Clayton   if (fmt != eFormatDefault)
356554f68d3SGreg Clayton     s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
357554f68d3SGreg Clayton   if (!string.empty())
358554f68d3SGreg Clayton     s.Printf("string = \"%s\"", string.c_str());
359554f68d3SGreg Clayton   if (!printf_format.empty())
360554f68d3SGreg Clayton     s.Printf("printf_format = \"%s\"", printf_format.c_str());
361554f68d3SGreg Clayton   if (number != 0)
362554f68d3SGreg Clayton     s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
363554f68d3SGreg Clayton   if (deref)
364554f68d3SGreg Clayton     s.Printf("deref = true, ");
365554f68d3SGreg Clayton   s.EOL();
366b9c1b51eSKate Stone   for (const auto &child : children) {
367554f68d3SGreg Clayton     child.Dump(s, depth + 1);
368554f68d3SGreg Clayton   }
369554f68d3SGreg Clayton }
370554f68d3SGreg Clayton 
371554f68d3SGreg Clayton template <typename T>
372b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
373b9c1b51eSKate Stone                                    const ExecutionContext *exe_ctx, T t,
374b9c1b51eSKate Stone                                    const char *script_function_name) {
375554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
376554f68d3SGreg Clayton 
377b9c1b51eSKate Stone   if (target) {
378b9c1b51eSKate Stone     ScriptInterpreter *script_interpreter =
379b9c1b51eSKate Stone         target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
380b9c1b51eSKate Stone     if (script_interpreter) {
381554f68d3SGreg Clayton       Error error;
382554f68d3SGreg Clayton       std::string script_output;
383554f68d3SGreg Clayton 
384b9c1b51eSKate Stone       if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
385b9c1b51eSKate Stone                                                      script_output, error) &&
386b9c1b51eSKate Stone           error.Success()) {
387554f68d3SGreg Clayton         s.Printf("%s", script_output.c_str());
388554f68d3SGreg Clayton         return true;
389b9c1b51eSKate Stone       } else {
390554f68d3SGreg Clayton         s.Printf("<error: %s>", error.AsCString());
391554f68d3SGreg Clayton       }
392554f68d3SGreg Clayton     }
393554f68d3SGreg Clayton   }
394554f68d3SGreg Clayton   return false;
395554f68d3SGreg Clayton }
396554f68d3SGreg Clayton 
397b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc,
398b9c1b51eSKate Stone                         const ExecutionContext *exe_ctx, const Address &addr,
399b9c1b51eSKate Stone                         bool print_file_addr_or_load_addr) {
400554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
401554f68d3SGreg Clayton   addr_t vaddr = LLDB_INVALID_ADDRESS;
402554f68d3SGreg Clayton   if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
403554f68d3SGreg Clayton     vaddr = addr.GetLoadAddress(target);
404554f68d3SGreg Clayton   if (vaddr == LLDB_INVALID_ADDRESS)
405554f68d3SGreg Clayton     vaddr = addr.GetFileAddress();
406554f68d3SGreg Clayton 
407b9c1b51eSKate Stone   if (vaddr != LLDB_INVALID_ADDRESS) {
408554f68d3SGreg Clayton     int addr_width = 0;
409b9c1b51eSKate Stone     if (exe_ctx && target) {
410554f68d3SGreg Clayton       addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
411554f68d3SGreg Clayton     }
412554f68d3SGreg Clayton     if (addr_width == 0)
413554f68d3SGreg Clayton       addr_width = 16;
414b9c1b51eSKate Stone     if (print_file_addr_or_load_addr) {
415a74f37a5SEugene Zelenko       ExecutionContextScope *exe_scope = nullptr;
416554f68d3SGreg Clayton       if (exe_ctx)
417554f68d3SGreg Clayton         exe_scope = exe_ctx->GetBestExecutionContextScope();
418b9c1b51eSKate Stone       addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
419b9c1b51eSKate Stone                 Address::DumpStyleModuleWithFileAddress, 0);
420b9c1b51eSKate Stone     } else {
421554f68d3SGreg Clayton       s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
422554f68d3SGreg Clayton     }
423554f68d3SGreg Clayton     return true;
424554f68d3SGreg Clayton   }
425554f68d3SGreg Clayton   return false;
426554f68d3SGreg Clayton }
427554f68d3SGreg Clayton 
428b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
429554f68d3SGreg Clayton                                           const ExecutionContext *exe_ctx,
430554f68d3SGreg Clayton                                           const Address &format_addr,
431b9c1b51eSKate Stone                                           bool concrete_only, bool no_padding,
432b9c1b51eSKate Stone                                           bool print_zero_offsets) {
433b9c1b51eSKate Stone   if (format_addr.IsValid()) {
434554f68d3SGreg Clayton     Address func_addr;
435554f68d3SGreg Clayton 
436b9c1b51eSKate Stone     if (sc) {
437b9c1b51eSKate Stone       if (sc->function) {
438554f68d3SGreg Clayton         func_addr = sc->function->GetAddressRange().GetBaseAddress();
439b9c1b51eSKate Stone         if (sc->block && !concrete_only) {
440554f68d3SGreg Clayton           // Check to make sure we aren't in an inline
441554f68d3SGreg Clayton           // function. If we are, use the inline block
442554f68d3SGreg Clayton           // range that contains "format_addr" since
443554f68d3SGreg Clayton           // blocks can be discontiguous.
444554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
445554f68d3SGreg Clayton           AddressRange inline_range;
446b9c1b51eSKate Stone           if (inline_block &&
447b9c1b51eSKate Stone               inline_block->GetRangeContainingAddress(format_addr,
448b9c1b51eSKate Stone                                                       inline_range))
449554f68d3SGreg Clayton             func_addr = inline_range.GetBaseAddress();
450554f68d3SGreg Clayton         }
451b9c1b51eSKate Stone       } else if (sc->symbol && sc->symbol->ValueIsAddress())
452358cf1eaSGreg Clayton         func_addr = sc->symbol->GetAddressRef();
453554f68d3SGreg Clayton     }
454554f68d3SGreg Clayton 
455b9c1b51eSKate Stone     if (func_addr.IsValid()) {
456554f68d3SGreg Clayton       const char *addr_offset_padding = no_padding ? "" : " ";
457554f68d3SGreg Clayton 
458b9c1b51eSKate Stone       if (func_addr.GetSection() == format_addr.GetSection()) {
459554f68d3SGreg Clayton         addr_t func_file_addr = func_addr.GetFileAddress();
460554f68d3SGreg Clayton         addr_t addr_file_addr = format_addr.GetFileAddress();
461b9c1b51eSKate Stone         if (addr_file_addr > func_file_addr ||
462b9c1b51eSKate Stone             (addr_file_addr == func_file_addr && print_zero_offsets)) {
463b9c1b51eSKate Stone           s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
464b9c1b51eSKate Stone                    addr_file_addr - func_file_addr);
465b9c1b51eSKate Stone         } else if (addr_file_addr < func_file_addr) {
466b9c1b51eSKate Stone           s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
467b9c1b51eSKate Stone                    func_file_addr - addr_file_addr);
468c980fa92SJason Molenda         }
469554f68d3SGreg Clayton         return true;
470b9c1b51eSKate Stone       } else {
471554f68d3SGreg Clayton         Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
472b9c1b51eSKate Stone         if (target) {
473554f68d3SGreg Clayton           addr_t func_load_addr = func_addr.GetLoadAddress(target);
474554f68d3SGreg Clayton           addr_t addr_load_addr = format_addr.GetLoadAddress(target);
475b9c1b51eSKate Stone           if (addr_load_addr > func_load_addr ||
476b9c1b51eSKate Stone               (addr_load_addr == func_load_addr && print_zero_offsets)) {
477b9c1b51eSKate Stone             s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
478b9c1b51eSKate Stone                      addr_load_addr - func_load_addr);
479b9c1b51eSKate Stone           } else if (addr_load_addr < func_load_addr) {
480b9c1b51eSKate Stone             s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
481b9c1b51eSKate Stone                      func_load_addr - addr_load_addr);
482c980fa92SJason Molenda           }
483554f68d3SGreg Clayton           return true;
484554f68d3SGreg Clayton         }
485554f68d3SGreg Clayton       }
486554f68d3SGreg Clayton     }
487554f68d3SGreg Clayton   }
488554f68d3SGreg Clayton   return false;
489554f68d3SGreg Clayton }
490554f68d3SGreg Clayton 
491b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath,
492554f68d3SGreg Clayton                                size_t &close_bracket_index,
493554f68d3SGreg Clayton                                const char *&var_name_final_if_array_range,
494b9c1b51eSKate Stone                                int64_t &index_lower, int64_t &index_higher) {
4954edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
496554f68d3SGreg Clayton   close_bracket_index = llvm::StringRef::npos;
497554f68d3SGreg Clayton   const size_t open_bracket_index = subpath.find('[');
498b9c1b51eSKate Stone   if (open_bracket_index == llvm::StringRef::npos) {
499554f68d3SGreg Clayton     if (log)
500554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
501554f68d3SGreg Clayton     return false;
502554f68d3SGreg Clayton   }
503554f68d3SGreg Clayton 
504554f68d3SGreg Clayton   close_bracket_index = subpath.find(']', open_bracket_index + 1);
505554f68d3SGreg Clayton 
506b9c1b51eSKate Stone   if (close_bracket_index == llvm::StringRef::npos) {
507554f68d3SGreg Clayton     if (log)
508554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
509554f68d3SGreg Clayton     return false;
510b9c1b51eSKate Stone   } else {
511554f68d3SGreg Clayton     var_name_final_if_array_range = subpath.data() + open_bracket_index;
512554f68d3SGreg Clayton 
513b9c1b51eSKate Stone     if (close_bracket_index - open_bracket_index == 1) {
514554f68d3SGreg Clayton       if (log)
515b9c1b51eSKate Stone         log->Printf(
516b9c1b51eSKate Stone             "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
517554f68d3SGreg Clayton       index_lower = 0;
518b9c1b51eSKate Stone     } else {
519554f68d3SGreg Clayton       const size_t separator_index = subpath.find('-', open_bracket_index + 1);
520554f68d3SGreg Clayton 
521b9c1b51eSKate Stone       if (separator_index == llvm::StringRef::npos) {
522554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
523a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
524554f68d3SGreg Clayton         index_higher = index_lower;
525554f68d3SGreg Clayton         if (log)
526b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64
527b9c1b51eSKate Stone                       "] detected, high index is same",
528b9c1b51eSKate Stone                       index_lower);
529b9c1b51eSKate Stone       } else {
530554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
531554f68d3SGreg Clayton         const char *index_higher_cstr = subpath.data() + separator_index + 1;
532a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
533a74f37a5SEugene Zelenko         index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
534554f68d3SGreg Clayton         if (log)
535b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
536b9c1b51eSKate Stone                       index_lower, index_higher);
537554f68d3SGreg Clayton       }
538b9c1b51eSKate Stone       if (index_lower > index_higher && index_higher > 0) {
539554f68d3SGreg Clayton         if (log)
540554f68d3SGreg Clayton           log->Printf("[ScanBracketedRange] swapping indices");
541554f68d3SGreg Clayton         const int64_t temp = index_lower;
542554f68d3SGreg Clayton         index_lower = index_higher;
543554f68d3SGreg Clayton         index_higher = temp;
544554f68d3SGreg Clayton       }
545554f68d3SGreg Clayton     }
546554f68d3SGreg Clayton   }
547554f68d3SGreg Clayton   return true;
548554f68d3SGreg Clayton }
549554f68d3SGreg Clayton 
550b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
551b9c1b51eSKate Stone   switch (file_kind) {
552554f68d3SGreg Clayton   case FileKind::FileError:
553554f68d3SGreg Clayton     break;
554554f68d3SGreg Clayton 
555554f68d3SGreg Clayton   case FileKind::Basename:
556b9c1b51eSKate Stone     if (file.GetFilename()) {
557554f68d3SGreg Clayton       s << file.GetFilename();
558554f68d3SGreg Clayton       return true;
559554f68d3SGreg Clayton     }
560554f68d3SGreg Clayton     break;
561554f68d3SGreg Clayton 
562554f68d3SGreg Clayton   case FileKind::Dirname:
563b9c1b51eSKate Stone     if (file.GetDirectory()) {
564554f68d3SGreg Clayton       s << file.GetDirectory();
565554f68d3SGreg Clayton       return true;
566554f68d3SGreg Clayton     }
567554f68d3SGreg Clayton     break;
568554f68d3SGreg Clayton 
569554f68d3SGreg Clayton   case FileKind::Fullpath:
570b9c1b51eSKate Stone     if (file) {
571554f68d3SGreg Clayton       s << file;
572554f68d3SGreg Clayton       return true;
573554f68d3SGreg Clayton     }
574554f68d3SGreg Clayton     break;
575554f68d3SGreg Clayton   }
576554f68d3SGreg Clayton   return false;
577554f68d3SGreg Clayton }
578554f68d3SGreg Clayton 
579b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
580b9c1b51eSKate Stone                          uint32_t reg_num, Format format)
581554f68d3SGreg Clayton 
582554f68d3SGreg Clayton {
583b9c1b51eSKate Stone   if (frame) {
584554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
585554f68d3SGreg Clayton 
586b9c1b51eSKate Stone     if (reg_ctx) {
587b9c1b51eSKate Stone       const uint32_t lldb_reg_num =
588b9c1b51eSKate Stone           reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
589b9c1b51eSKate Stone       if (lldb_reg_num != LLDB_INVALID_REGNUM) {
590b9c1b51eSKate Stone         const RegisterInfo *reg_info =
591b9c1b51eSKate Stone             reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
592b9c1b51eSKate Stone         if (reg_info) {
593554f68d3SGreg Clayton           RegisterValue reg_value;
594b9c1b51eSKate Stone           if (reg_ctx->ReadRegister(reg_info, reg_value)) {
595554f68d3SGreg Clayton             reg_value.Dump(&s, reg_info, false, false, format);
596554f68d3SGreg Clayton             return true;
597554f68d3SGreg Clayton           }
598554f68d3SGreg Clayton         }
599554f68d3SGreg Clayton       }
600554f68d3SGreg Clayton     }
601554f68d3SGreg Clayton   }
602554f68d3SGreg Clayton   return false;
603554f68d3SGreg Clayton }
604554f68d3SGreg Clayton 
605b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
606554f68d3SGreg Clayton                                              StackFrame *frame,
607b9c1b51eSKate Stone                                              bool deref_pointer) {
6084edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
609554f68d3SGreg Clayton   const char *ptr_deref_format = "[%d]";
610554f68d3SGreg Clayton   std::string ptr_deref_buffer(10, 0);
611554f68d3SGreg Clayton   ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
612554f68d3SGreg Clayton   if (log)
613b9c1b51eSKate Stone     log->Printf("[ExpandIndexedExpression] name to deref: %s",
614b9c1b51eSKate Stone                 ptr_deref_buffer.c_str());
615554f68d3SGreg Clayton   const char *first_unparsed;
616554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
617554f68d3SGreg Clayton   ValueObject::ExpressionPathEndResultType final_value_type;
618554f68d3SGreg Clayton   ValueObject::ExpressionPathScanEndReason reason_to_stop;
619b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
620b9c1b51eSKate Stone       (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
621b9c1b51eSKate Stone                      : ValueObject::eExpressionPathAftermathNothing);
622b9c1b51eSKate Stone   ValueObjectSP item = valobj->GetValueForExpressionPath(
623b9c1b51eSKate Stone       ptr_deref_buffer.c_str(), &first_unparsed, &reason_to_stop,
624b9c1b51eSKate Stone       &final_value_type, options, &what_next);
625b9c1b51eSKate Stone   if (!item) {
626554f68d3SGreg Clayton     if (log)
627b9c1b51eSKate Stone       log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why "
628b9c1b51eSKate Stone                   "stopping = %d,"
629554f68d3SGreg Clayton                   " final_value_type %d",
630554f68d3SGreg Clayton                   first_unparsed, reason_to_stop, final_value_type);
631b9c1b51eSKate Stone   } else {
632554f68d3SGreg Clayton     if (log)
633b9c1b51eSKate Stone       log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, "
634b9c1b51eSKate Stone                   "why stopping = %d,"
635554f68d3SGreg Clayton                   " final_value_type %d",
636554f68d3SGreg Clayton                   first_unparsed, reason_to_stop, final_value_type);
637554f68d3SGreg Clayton   }
638554f68d3SGreg Clayton   return item;
639554f68d3SGreg Clayton }
640554f68d3SGreg Clayton 
641b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar(
642b9c1b51eSKate Stone     ValueObject::ValueObjectRepresentationStyle style) {
643b9c1b51eSKate Stone   switch (style) {
644b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
645b9c1b51eSKate Stone     return '@';
646b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleValue:
647b9c1b51eSKate Stone     return 'V';
648b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLocation:
649b9c1b51eSKate Stone     return 'L';
650b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleSummary:
651b9c1b51eSKate Stone     return 'S';
652b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleChildrenCount:
653b9c1b51eSKate Stone     return '#';
654b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleType:
655b9c1b51eSKate Stone     return 'T';
656b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleName:
657b9c1b51eSKate Stone     return 'N';
658b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleExpressionPath:
659b9c1b51eSKate Stone     return '>';
660554f68d3SGreg Clayton   }
661554f68d3SGreg Clayton   return '\0';
662554f68d3SGreg Clayton }
663554f68d3SGreg Clayton 
664b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc,
665554f68d3SGreg Clayton                       const ExecutionContext *exe_ctx,
666b9c1b51eSKate Stone                       const FormatEntity::Entry &entry, ValueObject *valobj) {
667a74f37a5SEugene Zelenko   if (valobj == nullptr)
668554f68d3SGreg Clayton     return false;
669554f68d3SGreg Clayton 
6704edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
671554f68d3SGreg Clayton   Format custom_format = eFormatInvalid;
672b9c1b51eSKate Stone   ValueObject::ValueObjectRepresentationStyle val_obj_display =
673b9c1b51eSKate Stone       entry.string.empty()
674b9c1b51eSKate Stone           ? ValueObject::eValueObjectRepresentationStyleValue
675b9c1b51eSKate Stone           : ValueObject::eValueObjectRepresentationStyleSummary;
676554f68d3SGreg Clayton 
677554f68d3SGreg Clayton   bool do_deref_pointer = entry.deref;
678554f68d3SGreg Clayton   bool is_script = false;
679b9c1b51eSKate Stone   switch (entry.type) {
680554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariable:
681554f68d3SGreg Clayton     is_script = true;
682554f68d3SGreg Clayton     break;
683554f68d3SGreg Clayton 
684554f68d3SGreg Clayton   case FormatEntity::Entry::Type::Variable:
685554f68d3SGreg Clayton     custom_format = entry.fmt;
686554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
687554f68d3SGreg Clayton     break;
688554f68d3SGreg Clayton 
689554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariableSynthetic:
690554f68d3SGreg Clayton     is_script = true;
69162e0681aSJason Molenda     LLVM_FALLTHROUGH;
692554f68d3SGreg Clayton   case FormatEntity::Entry::Type::VariableSynthetic:
693554f68d3SGreg Clayton     custom_format = entry.fmt;
694554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
695b9c1b51eSKate Stone     if (!valobj->IsSynthetic()) {
696554f68d3SGreg Clayton       valobj = valobj->GetSyntheticValue().get();
697554f68d3SGreg Clayton       if (valobj == nullptr)
698554f68d3SGreg Clayton         return false;
699554f68d3SGreg Clayton     }
700554f68d3SGreg Clayton     break;
701554f68d3SGreg Clayton 
702554f68d3SGreg Clayton   default:
703554f68d3SGreg Clayton     return false;
704554f68d3SGreg Clayton   }
705554f68d3SGreg Clayton 
706a74f37a5SEugene Zelenko   if (valobj == nullptr)
707554f68d3SGreg Clayton     return false;
708554f68d3SGreg Clayton 
709b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
710b9c1b51eSKate Stone       (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
711b9c1b51eSKate Stone                         : ValueObject::eExpressionPathAftermathNothing);
712554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
713b9c1b51eSKate Stone   options.DontCheckDotVsArrowSyntax()
714b9c1b51eSKate Stone       .DoAllowBitfieldSyntax()
715b9c1b51eSKate Stone       .DoAllowFragileIVar()
716b9c1b51eSKate Stone       .SetSyntheticChildrenTraversal(
717b9c1b51eSKate Stone           ValueObject::GetValueForExpressionPathOptions::
718b9c1b51eSKate Stone               SyntheticChildrenTraversal::Both);
719a74f37a5SEugene Zelenko   ValueObject *target = nullptr;
720a74f37a5SEugene Zelenko   const char *var_name_final_if_array_range = nullptr;
721554f68d3SGreg Clayton   size_t close_bracket_index = llvm::StringRef::npos;
722554f68d3SGreg Clayton   int64_t index_lower = -1;
723554f68d3SGreg Clayton   int64_t index_higher = -1;
724554f68d3SGreg Clayton   bool is_array_range = false;
725554f68d3SGreg Clayton   const char *first_unparsed;
726554f68d3SGreg Clayton   bool was_plain_var = false;
727554f68d3SGreg Clayton   bool was_var_format = false;
728554f68d3SGreg Clayton   bool was_var_indexed = false;
729b9c1b51eSKate Stone   ValueObject::ExpressionPathScanEndReason reason_to_stop =
730b9c1b51eSKate Stone       ValueObject::eExpressionPathScanEndReasonEndOfString;
731b9c1b51eSKate Stone   ValueObject::ExpressionPathEndResultType final_value_type =
732b9c1b51eSKate Stone       ValueObject::eExpressionPathEndResultTypePlain;
733554f68d3SGreg Clayton 
734b9c1b51eSKate Stone   if (is_script) {
735554f68d3SGreg Clayton     return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
736554f68d3SGreg Clayton   }
737554f68d3SGreg Clayton 
738554f68d3SGreg Clayton   llvm::StringRef subpath(entry.string);
739554f68d3SGreg Clayton   // simplest case ${var}, just print valobj's value
740b9c1b51eSKate Stone   if (entry.string.empty()) {
741b9c1b51eSKate Stone     if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
742b9c1b51eSKate Stone         entry.number == ValueObject::eValueObjectRepresentationStyleValue)
743554f68d3SGreg Clayton       was_plain_var = true;
744554f68d3SGreg Clayton     else
745554f68d3SGreg Clayton       was_var_format = true;
746554f68d3SGreg Clayton     target = valobj;
747b9c1b51eSKate Stone   } else // this is ${var.something} or multiple .something nested
748554f68d3SGreg Clayton   {
749554f68d3SGreg Clayton     if (entry.string[0] == '[')
750554f68d3SGreg Clayton       was_var_indexed = true;
751b9c1b51eSKate Stone     ScanBracketedRange(subpath, close_bracket_index,
752b9c1b51eSKate Stone                        var_name_final_if_array_range, index_lower,
753554f68d3SGreg Clayton                        index_higher);
754554f68d3SGreg Clayton 
755554f68d3SGreg Clayton     Error error;
756554f68d3SGreg Clayton 
757554f68d3SGreg Clayton     const std::string &expr_path = entry.string;
758554f68d3SGreg Clayton 
759554f68d3SGreg Clayton     if (log)
760b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",
761b9c1b51eSKate Stone                   expr_path.c_str());
762554f68d3SGreg Clayton 
763b9c1b51eSKate Stone     target = valobj
764b9c1b51eSKate Stone                  ->GetValueForExpressionPath(expr_path.c_str(), &first_unparsed,
765b9c1b51eSKate Stone                                              &reason_to_stop, &final_value_type,
766b9c1b51eSKate Stone                                              options, &what_next)
767b9c1b51eSKate Stone                  .get();
768554f68d3SGreg Clayton 
769b9c1b51eSKate Stone     if (!target) {
770554f68d3SGreg Clayton       if (log)
771b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, "
772b9c1b51eSKate Stone                     "why stopping = %d,"
773554f68d3SGreg Clayton                     " final_value_type %d",
774554f68d3SGreg Clayton                     first_unparsed, reason_to_stop, final_value_type);
775554f68d3SGreg Clayton       return false;
776b9c1b51eSKate Stone     } else {
777554f68d3SGreg Clayton       if (log)
778b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = "
779b9c1b51eSKate Stone                     "%s, why stopping = %d,"
780554f68d3SGreg Clayton                     " final_value_type %d",
781554f68d3SGreg Clayton                     first_unparsed, reason_to_stop, final_value_type);
782b9c1b51eSKate Stone       target = target
783b9c1b51eSKate Stone                    ->GetQualifiedRepresentationIfAvailable(
784b9c1b51eSKate Stone                        target->GetDynamicValueType(), true)
785b9c1b51eSKate Stone                    .get();
786554f68d3SGreg Clayton     }
787554f68d3SGreg Clayton   }
788554f68d3SGreg Clayton 
789b9c1b51eSKate Stone   is_array_range =
790b9c1b51eSKate Stone       (final_value_type ==
791b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeBoundedRange ||
792b9c1b51eSKate Stone        final_value_type ==
793b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeUnboundedRange);
794554f68d3SGreg Clayton 
795b9c1b51eSKate Stone   do_deref_pointer =
796b9c1b51eSKate Stone       (what_next == ValueObject::eExpressionPathAftermathDereference);
797554f68d3SGreg Clayton 
798b9c1b51eSKate Stone   if (do_deref_pointer && !is_array_range) {
799554f68d3SGreg Clayton     // I have not deref-ed yet, let's do it
800b9c1b51eSKate Stone     // this happens when we are not going through
801b9c1b51eSKate Stone     // GetValueForVariableExpressionPath
802554f68d3SGreg Clayton     // to get to the target ValueObject
803554f68d3SGreg Clayton     Error error;
804554f68d3SGreg Clayton     target = target->Dereference(error).get();
805b9c1b51eSKate Stone     if (error.Fail()) {
806554f68d3SGreg Clayton       if (log)
807b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] ERROR: %s\n",
808b9c1b51eSKate Stone                     error.AsCString("unknown"));
809554f68d3SGreg Clayton       return false;
810554f68d3SGreg Clayton     }
811554f68d3SGreg Clayton     do_deref_pointer = false;
812554f68d3SGreg Clayton   }
813554f68d3SGreg Clayton 
814b9c1b51eSKate Stone   if (!target) {
815554f68d3SGreg Clayton     if (log)
816b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] could not calculate target for "
817b9c1b51eSKate Stone                   "prompt expression");
818554f68d3SGreg Clayton     return false;
819554f68d3SGreg Clayton   }
820554f68d3SGreg Clayton 
821554f68d3SGreg Clayton   // we do not want to use the summary for a bitfield of type T:n
822554f68d3SGreg Clayton   // if we were originally dealing with just a T - that would get
823554f68d3SGreg Clayton   // us into an endless recursion
824b9c1b51eSKate Stone   if (target->IsBitfield() && was_var_indexed) {
825554f68d3SGreg Clayton     // TODO: check for a (T:n)-specific summary - we should still obey that
826554f68d3SGreg Clayton     StreamString bitfield_name;
827b9c1b51eSKate Stone     bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
828b9c1b51eSKate Stone                          target->GetBitfieldBitSize());
829b9c1b51eSKate Stone     lldb::TypeNameSpecifierImplSP type_sp(
830b9c1b51eSKate Stone         new TypeNameSpecifierImpl(bitfield_name.GetData(), false));
831b9c1b51eSKate Stone     if (val_obj_display ==
832b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleSummary &&
833b9c1b51eSKate Stone         !DataVisualization::GetSummaryForType(type_sp))
834554f68d3SGreg Clayton       val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
835554f68d3SGreg Clayton   }
836554f68d3SGreg Clayton 
837554f68d3SGreg Clayton   // TODO use flags for these
838b9c1b51eSKate Stone   const uint32_t type_info_flags =
839b9c1b51eSKate Stone       target->GetCompilerType().GetTypeInfo(nullptr);
840554f68d3SGreg Clayton   bool is_array = (type_info_flags & eTypeIsArray) != 0;
841554f68d3SGreg Clayton   bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
84299558cc4SGreg Clayton   bool is_aggregate = target->GetCompilerType().IsAggregateType();
843554f68d3SGreg Clayton 
844b9c1b51eSKate Stone   if ((is_array || is_pointer) && (!is_array_range) &&
845b9c1b51eSKate Stone       val_obj_display ==
846b9c1b51eSKate Stone           ValueObject::eValueObjectRepresentationStyleValue) // this should be
847b9c1b51eSKate Stone                                                              // wrong, but there
848b9c1b51eSKate Stone                                                              // are some
849b9c1b51eSKate Stone                                                              // exceptions
850554f68d3SGreg Clayton   {
851554f68d3SGreg Clayton     StreamString str_temp;
852554f68d3SGreg Clayton     if (log)
853b9c1b51eSKate Stone       log->Printf(
854b9c1b51eSKate Stone           "[Debugger::FormatPrompt] I am into array || pointer && !range");
855554f68d3SGreg Clayton 
856b9c1b51eSKate Stone     if (target->HasSpecialPrintableRepresentation(val_obj_display,
857b9c1b51eSKate Stone                                                   custom_format)) {
858554f68d3SGreg Clayton       // try to use the special cases
859b9c1b51eSKate Stone       bool success = target->DumpPrintableRepresentation(
860b9c1b51eSKate Stone           str_temp, val_obj_display, custom_format);
861554f68d3SGreg Clayton       if (log)
862b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] special cases did%s match",
863b9c1b51eSKate Stone                     success ? "" : "n't");
864554f68d3SGreg Clayton 
865554f68d3SGreg Clayton       // should not happen
866554f68d3SGreg Clayton       if (success)
867554f68d3SGreg Clayton         s << str_temp.GetData();
868554f68d3SGreg Clayton       return true;
869b9c1b51eSKate Stone     } else {
870554f68d3SGreg Clayton       if (was_plain_var) // if ${var}
871554f68d3SGreg Clayton       {
872554f68d3SGreg Clayton         s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
873b9c1b51eSKate Stone       } else if (is_pointer) // if pointer, value is the address stored
874554f68d3SGreg Clayton       {
875b9c1b51eSKate Stone         target->DumpPrintableRepresentation(
876b9c1b51eSKate Stone             s, val_obj_display, custom_format,
877*65d86e4fSEnrico Granata             ValueObject::PrintableRepresentationSpecialCases::eDisable);
878554f68d3SGreg Clayton       }
879554f68d3SGreg Clayton       return true;
880554f68d3SGreg Clayton     }
881554f68d3SGreg Clayton   }
882554f68d3SGreg Clayton 
883b9c1b51eSKate Stone   // if directly trying to print ${var}, and this is an aggregate, display a
884b9c1b51eSKate Stone   // nice
885554f68d3SGreg Clayton   // type @ location message
886b9c1b51eSKate Stone   if (is_aggregate && was_plain_var) {
887554f68d3SGreg Clayton     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
888554f68d3SGreg Clayton     return true;
889554f68d3SGreg Clayton   }
890554f68d3SGreg Clayton 
891b9c1b51eSKate Stone   // if directly trying to print ${var%V}, and this is an aggregate, do not let
892b9c1b51eSKate Stone   // the user do it
893b9c1b51eSKate Stone   if (is_aggregate &&
894b9c1b51eSKate Stone       ((was_var_format &&
895b9c1b51eSKate Stone         val_obj_display ==
896b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleValue))) {
897554f68d3SGreg Clayton     s << "<invalid use of aggregate type>";
898554f68d3SGreg Clayton     return true;
899554f68d3SGreg Clayton   }
900554f68d3SGreg Clayton 
901b9c1b51eSKate Stone   if (!is_array_range) {
902554f68d3SGreg Clayton     if (log)
903554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
904b9c1b51eSKate Stone     return target->DumpPrintableRepresentation(s, val_obj_display,
905b9c1b51eSKate Stone                                                custom_format);
906b9c1b51eSKate Stone   } else {
907554f68d3SGreg Clayton     if (log)
908554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
909554f68d3SGreg Clayton     if (!is_array && !is_pointer)
910554f68d3SGreg Clayton       return false;
911554f68d3SGreg Clayton     if (log)
912554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] handle as array");
913e8376261SVince Harron     StreamString special_directions_stream;
914554f68d3SGreg Clayton     llvm::StringRef special_directions;
915b9c1b51eSKate Stone     if (close_bracket_index != llvm::StringRef::npos &&
916b9c1b51eSKate Stone         subpath.size() > close_bracket_index) {
917554f68d3SGreg Clayton       ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
918b9c1b51eSKate Stone       special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
919554f68d3SGreg Clayton                                        additional_data.GetCString());
920554f68d3SGreg Clayton 
921b9c1b51eSKate Stone       if (entry.fmt != eFormatDefault) {
922b9c1b51eSKate Stone         const char format_char =
923b9c1b51eSKate Stone             FormatManager::GetFormatAsFormatChar(entry.fmt);
924554f68d3SGreg Clayton         if (format_char != '\0')
925554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", format_char);
926b9c1b51eSKate Stone         else {
927b9c1b51eSKate Stone           const char *format_cstr =
928b9c1b51eSKate Stone               FormatManager::GetFormatAsCString(entry.fmt);
929554f68d3SGreg Clayton           special_directions_stream.Printf("%%%s", format_cstr);
930554f68d3SGreg Clayton         }
931b9c1b51eSKate Stone       } else if (entry.number != 0) {
932b9c1b51eSKate Stone         const char style_char = ConvertValueObjectStyleToChar(
933b9c1b51eSKate Stone             (ValueObject::ValueObjectRepresentationStyle)entry.number);
934554f68d3SGreg Clayton         if (style_char)
935554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", style_char);
936554f68d3SGreg Clayton       }
937554f68d3SGreg Clayton       special_directions_stream.PutChar('}');
938b9c1b51eSKate Stone       special_directions =
939b9c1b51eSKate Stone           llvm::StringRef(special_directions_stream.GetString());
940554f68d3SGreg Clayton     }
941554f68d3SGreg Clayton 
942554f68d3SGreg Clayton     // let us display items index_lower thru index_higher of this array
943554f68d3SGreg Clayton     s.PutChar('[');
944554f68d3SGreg Clayton 
945554f68d3SGreg Clayton     if (index_higher < 0)
946554f68d3SGreg Clayton       index_higher = valobj->GetNumChildren() - 1;
947554f68d3SGreg Clayton 
948b9c1b51eSKate Stone     uint32_t max_num_children =
949b9c1b51eSKate Stone         target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
950554f68d3SGreg Clayton 
951554f68d3SGreg Clayton     bool success = true;
952b9c1b51eSKate Stone     for (int64_t index = index_lower; index <= index_higher; ++index) {
953b9c1b51eSKate Stone       ValueObject *item =
954b9c1b51eSKate Stone           ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
955b9c1b51eSKate Stone               .get();
956554f68d3SGreg Clayton 
957b9c1b51eSKate Stone       if (!item) {
958554f68d3SGreg Clayton         if (log)
959b9c1b51eSKate Stone           log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at "
960b9c1b51eSKate Stone                       "index %" PRId64,
961b9c1b51eSKate Stone                       index);
962b9c1b51eSKate Stone       } else {
963554f68d3SGreg Clayton         if (log)
964b9c1b51eSKate Stone           log->Printf(
965b9c1b51eSKate Stone               "[Debugger::FormatPrompt] special_directions for child item: %s",
966b9c1b51eSKate Stone               special_directions.data() ? special_directions.data() : "");
967554f68d3SGreg Clayton       }
968554f68d3SGreg Clayton 
969b9c1b51eSKate Stone       if (special_directions.empty()) {
970b9c1b51eSKate Stone         success &= item->DumpPrintableRepresentation(s, val_obj_display,
971b9c1b51eSKate Stone                                                      custom_format);
972b9c1b51eSKate Stone       } else {
973b9c1b51eSKate Stone         success &= FormatEntity::FormatStringRef(
974b9c1b51eSKate Stone             special_directions, s, sc, exe_ctx, nullptr, item, false, false);
975554f68d3SGreg Clayton       }
976554f68d3SGreg Clayton 
977b9c1b51eSKate Stone       if (--max_num_children == 0) {
978554f68d3SGreg Clayton         s.PutCString(", ...");
979554f68d3SGreg Clayton         break;
980554f68d3SGreg Clayton       }
981554f68d3SGreg Clayton 
982554f68d3SGreg Clayton       if (index < index_higher)
983554f68d3SGreg Clayton         s.PutChar(',');
984554f68d3SGreg Clayton     }
985554f68d3SGreg Clayton     s.PutChar(']');
986554f68d3SGreg Clayton     return success;
987554f68d3SGreg Clayton   }
988554f68d3SGreg Clayton }
989554f68d3SGreg Clayton 
990b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
991b9c1b51eSKate Stone                          Format format) {
992b9c1b51eSKate Stone   if (frame) {
993554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
994554f68d3SGreg Clayton 
995b9c1b51eSKate Stone     if (reg_ctx) {
996554f68d3SGreg Clayton       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
997b9c1b51eSKate Stone       if (reg_info) {
998554f68d3SGreg Clayton         RegisterValue reg_value;
999b9c1b51eSKate Stone         if (reg_ctx->ReadRegister(reg_info, reg_value)) {
1000554f68d3SGreg Clayton           reg_value.Dump(&s, reg_info, false, false, format);
1001554f68d3SGreg Clayton           return true;
1002554f68d3SGreg Clayton         }
1003554f68d3SGreg Clayton       }
1004554f68d3SGreg Clayton     }
1005554f68d3SGreg Clayton   }
1006554f68d3SGreg Clayton   return false;
1007554f68d3SGreg Clayton }
1008554f68d3SGreg Clayton 
1009b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse(
1010b9c1b51eSKate Stone     const FormatEntity::Entry &entry,
1011554f68d3SGreg Clayton     const StructuredData::ObjectSP &thread_info_dictionary,
1012b9c1b51eSKate Stone     const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
1013554f68d3SGreg Clayton   llvm::StringRef path(entry.string);
1014554f68d3SGreg Clayton 
1015b9c1b51eSKate Stone   StructuredData::ObjectSP value =
1016b9c1b51eSKate Stone       thread_info_dictionary->GetObjectForDotSeparatedPath(path);
1017554f68d3SGreg Clayton 
1018b9c1b51eSKate Stone   if (value) {
1019b9c1b51eSKate Stone     if (value->GetType() == StructuredData::Type::eTypeInteger) {
1020554f68d3SGreg Clayton       const char *token_format = "0x%4.4" PRIx64;
1021554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1022554f68d3SGreg Clayton         token_format = entry.printf_format.c_str();
1023554f68d3SGreg Clayton       s.Printf(token_format, value->GetAsInteger()->GetValue());
1024554f68d3SGreg Clayton       return true;
1025b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeFloat) {
1026554f68d3SGreg Clayton       s.Printf("%f", value->GetAsFloat()->GetValue());
1027554f68d3SGreg Clayton       return true;
1028b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeString) {
1029554f68d3SGreg Clayton       s.Printf("%s", value->GetAsString()->GetValue().c_str());
1030554f68d3SGreg Clayton       return true;
1031b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeArray) {
1032b9c1b51eSKate Stone       if (value->GetAsArray()->GetSize() > 0) {
1033554f68d3SGreg Clayton         s.Printf("%zu", value->GetAsArray()->GetSize());
1034554f68d3SGreg Clayton         return true;
1035554f68d3SGreg Clayton       }
1036b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeDictionary) {
1037b9c1b51eSKate Stone       s.Printf("%zu",
1038b9c1b51eSKate Stone                value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1039554f68d3SGreg Clayton       return true;
1040554f68d3SGreg Clayton     }
1041554f68d3SGreg Clayton   }
1042554f68d3SGreg Clayton 
1043554f68d3SGreg Clayton   return false;
1044554f68d3SGreg Clayton }
1045554f68d3SGreg Clayton 
1046b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) {
1047554f68d3SGreg Clayton   return (::strncmp(var_name_begin, var, strlen(var)) == 0);
1048554f68d3SGreg Clayton }
1049554f68d3SGreg Clayton 
1050b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
1051554f68d3SGreg Clayton                                    const SymbolContext *sc,
1052554f68d3SGreg Clayton                                    const ExecutionContext *exe_ctx,
1053b9c1b51eSKate Stone                                    const Address *addr, ValueObject *valobj,
1054554f68d3SGreg Clayton                                    bool function_changed,
1055b9c1b51eSKate Stone                                    bool initial_function) {
1056b9c1b51eSKate Stone   if (!format_str.empty()) {
1057554f68d3SGreg Clayton     FormatEntity::Entry root;
1058554f68d3SGreg Clayton     Error error = FormatEntity::Parse(format_str, root);
1059b9c1b51eSKate Stone     if (error.Success()) {
1060b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1061b9c1b51eSKate Stone                                   function_changed, initial_function);
1062554f68d3SGreg Clayton     }
1063554f68d3SGreg Clayton   }
1064554f68d3SGreg Clayton   return false;
1065554f68d3SGreg Clayton }
1066a74f37a5SEugene Zelenko 
1067b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s,
1068554f68d3SGreg Clayton                                  const SymbolContext *sc,
1069554f68d3SGreg Clayton                                  const ExecutionContext *exe_ctx,
1070b9c1b51eSKate Stone                                  const Address *addr, ValueObject *valobj,
1071b9c1b51eSKate Stone                                  bool function_changed, bool initial_function) {
1072b9c1b51eSKate Stone   if (format && format[0]) {
1073554f68d3SGreg Clayton     FormatEntity::Entry root;
1074554f68d3SGreg Clayton     llvm::StringRef format_str(format);
1075554f68d3SGreg Clayton     Error error = FormatEntity::Parse(format_str, root);
1076b9c1b51eSKate Stone     if (error.Success()) {
1077b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1078b9c1b51eSKate Stone                                   function_changed, initial_function);
1079554f68d3SGreg Clayton     }
1080554f68d3SGreg Clayton   }
1081554f68d3SGreg Clayton   return false;
1082554f68d3SGreg Clayton }
1083554f68d3SGreg Clayton 
1084b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s,
1085554f68d3SGreg Clayton                           const SymbolContext *sc,
1086b9c1b51eSKate Stone                           const ExecutionContext *exe_ctx, const Address *addr,
1087b9c1b51eSKate Stone                           ValueObject *valobj, bool function_changed,
1088b9c1b51eSKate Stone                           bool initial_function) {
1089b9c1b51eSKate Stone   switch (entry.type) {
1090554f68d3SGreg Clayton   case Entry::Type::Invalid:
1091b9c1b51eSKate Stone   case Entry::Type::ParentNumber: // Only used for
1092b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1093b9c1b51eSKate Stone   case Entry::Type::ParentString: // Only used for
1094b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1095b9c1b51eSKate Stone   case Entry::Type::InsertString: // Only used for
1096b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1097554f68d3SGreg Clayton     return false;
1098554f68d3SGreg Clayton 
1099554f68d3SGreg Clayton   case Entry::Type::Root:
1100b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1101b9c1b51eSKate Stone       if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
1102b9c1b51eSKate Stone                   initial_function)) {
1103554f68d3SGreg Clayton         return false; // If any item of root fails, then the formatting fails
1104554f68d3SGreg Clayton       }
1105554f68d3SGreg Clayton     }
1106554f68d3SGreg Clayton     return true; // Only return true if all items succeeded
1107554f68d3SGreg Clayton 
1108554f68d3SGreg Clayton   case Entry::Type::String:
1109771ef6d4SMalcolm Parsons     s.PutCString(entry.string);
1110554f68d3SGreg Clayton     return true;
1111554f68d3SGreg Clayton 
1112b9c1b51eSKate Stone   case Entry::Type::Scope: {
1113554f68d3SGreg Clayton     StreamString scope_stream;
1114554f68d3SGreg Clayton     bool success = false;
1115b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1116b9c1b51eSKate Stone       success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
1117b9c1b51eSKate Stone                        function_changed, initial_function);
1118554f68d3SGreg Clayton       if (!success)
1119554f68d3SGreg Clayton         break;
1120554f68d3SGreg Clayton     }
1121554f68d3SGreg Clayton     // Only if all items in a scope succeed, then do we
1122554f68d3SGreg Clayton     // print the output into the main stream
1123554f68d3SGreg Clayton     if (success)
1124554f68d3SGreg Clayton       s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
1125554f68d3SGreg Clayton   }
1126554f68d3SGreg Clayton     return true; // Scopes always successfully print themselves
1127554f68d3SGreg Clayton 
1128554f68d3SGreg Clayton   case Entry::Type::Variable:
1129554f68d3SGreg Clayton   case Entry::Type::VariableSynthetic:
1130554f68d3SGreg Clayton   case Entry::Type::ScriptVariable:
1131554f68d3SGreg Clayton   case Entry::Type::ScriptVariableSynthetic:
1132a74f37a5SEugene Zelenko     return DumpValue(s, sc, exe_ctx, entry, valobj);
1133554f68d3SGreg Clayton 
1134554f68d3SGreg Clayton   case Entry::Type::AddressFile:
1135554f68d3SGreg Clayton   case Entry::Type::AddressLoad:
1136554f68d3SGreg Clayton   case Entry::Type::AddressLoadOrFile:
1137a74f37a5SEugene Zelenko     return (addr != nullptr && addr->IsValid() &&
1138b9c1b51eSKate Stone             DumpAddress(s, sc, exe_ctx, *addr,
1139b9c1b51eSKate Stone                         entry.type == Entry::Type::AddressLoadOrFile));
1140554f68d3SGreg Clayton 
1141554f68d3SGreg Clayton   case Entry::Type::ProcessID:
1142b9c1b51eSKate Stone     if (exe_ctx) {
1143554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1144b9c1b51eSKate Stone       if (process) {
1145554f68d3SGreg Clayton         const char *format = "%" PRIu64;
1146554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1147554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1148554f68d3SGreg Clayton         s.Printf(format, process->GetID());
1149554f68d3SGreg Clayton         return true;
1150554f68d3SGreg Clayton       }
1151554f68d3SGreg Clayton     }
1152554f68d3SGreg Clayton     return false;
1153554f68d3SGreg Clayton 
1154554f68d3SGreg Clayton   case Entry::Type::ProcessFile:
1155b9c1b51eSKate Stone     if (exe_ctx) {
1156554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1157b9c1b51eSKate Stone       if (process) {
1158554f68d3SGreg Clayton         Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1159b9c1b51eSKate Stone         if (exe_module) {
1160554f68d3SGreg Clayton           if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1161554f68d3SGreg Clayton             return true;
1162554f68d3SGreg Clayton         }
1163554f68d3SGreg Clayton       }
1164554f68d3SGreg Clayton     }
1165554f68d3SGreg Clayton     return false;
1166554f68d3SGreg Clayton 
1167554f68d3SGreg Clayton   case Entry::Type::ScriptProcess:
1168b9c1b51eSKate Stone     if (exe_ctx) {
1169554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1170554f68d3SGreg Clayton       if (process)
1171b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, process,
1172b9c1b51eSKate Stone                                       entry.string.c_str());
1173554f68d3SGreg Clayton     }
1174554f68d3SGreg Clayton     return false;
1175554f68d3SGreg Clayton 
1176554f68d3SGreg Clayton   case Entry::Type::ThreadID:
1177b9c1b51eSKate Stone     if (exe_ctx) {
1178554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1179b9c1b51eSKate Stone       if (thread) {
1180554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1181b9c1b51eSKate Stone         if (!entry.printf_format.empty()) {
1182554f68d3SGreg Clayton           // Watch for the special "tid" format...
1183b9c1b51eSKate Stone           if (entry.printf_format == "tid") {
1184b9c1b51eSKate Stone             // TODO(zturner): Rather than hardcoding this to be platform
1185b9c1b51eSKate Stone             // specific, it should be controlled by a
1186b9c1b51eSKate Stone             // setting and the default value of the setting can be different
1187b9c1b51eSKate Stone             // depending on the platform.
1188554f68d3SGreg Clayton             Target &target = thread->GetProcess()->GetTarget();
1189554f68d3SGreg Clayton             ArchSpec arch(target.GetArchitecture());
1190b9c1b51eSKate Stone             llvm::Triple::OSType ostype = arch.IsValid()
1191b9c1b51eSKate Stone                                               ? arch.GetTriple().getOS()
1192b9c1b51eSKate Stone                                               : llvm::Triple::UnknownOS;
1193b9c1b51eSKate Stone             if ((ostype == llvm::Triple::FreeBSD) ||
1194b9c1b51eSKate Stone                 (ostype == llvm::Triple::Linux)) {
1195554f68d3SGreg Clayton               format = "%" PRIu64;
1196554f68d3SGreg Clayton             }
1197b9c1b51eSKate Stone           } else {
1198554f68d3SGreg Clayton             format = entry.printf_format.c_str();
1199554f68d3SGreg Clayton           }
1200554f68d3SGreg Clayton         }
1201554f68d3SGreg Clayton         s.Printf(format, thread->GetID());
1202554f68d3SGreg Clayton         return true;
1203554f68d3SGreg Clayton       }
1204554f68d3SGreg Clayton     }
1205554f68d3SGreg Clayton     return false;
1206554f68d3SGreg Clayton 
1207554f68d3SGreg Clayton   case Entry::Type::ThreadProtocolID:
1208b9c1b51eSKate Stone     if (exe_ctx) {
1209554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1210b9c1b51eSKate Stone       if (thread) {
1211554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1212554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1213554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1214554f68d3SGreg Clayton         s.Printf(format, thread->GetProtocolID());
1215554f68d3SGreg Clayton         return true;
1216554f68d3SGreg Clayton       }
1217554f68d3SGreg Clayton     }
1218554f68d3SGreg Clayton     return false;
1219554f68d3SGreg Clayton 
1220554f68d3SGreg Clayton   case Entry::Type::ThreadIndexID:
1221b9c1b51eSKate Stone     if (exe_ctx) {
1222554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1223b9c1b51eSKate Stone       if (thread) {
1224554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1225554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1226554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1227554f68d3SGreg Clayton         s.Printf(format, thread->GetIndexID());
1228554f68d3SGreg Clayton         return true;
1229554f68d3SGreg Clayton       }
1230554f68d3SGreg Clayton     }
1231554f68d3SGreg Clayton     return false;
1232554f68d3SGreg Clayton 
1233554f68d3SGreg Clayton   case Entry::Type::ThreadName:
1234b9c1b51eSKate Stone     if (exe_ctx) {
1235554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1236b9c1b51eSKate Stone       if (thread) {
1237554f68d3SGreg Clayton         const char *cstr = thread->GetName();
1238b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1239554f68d3SGreg Clayton           s.PutCString(cstr);
1240554f68d3SGreg Clayton           return true;
1241554f68d3SGreg Clayton         }
1242554f68d3SGreg Clayton       }
1243554f68d3SGreg Clayton     }
1244554f68d3SGreg Clayton     return false;
1245554f68d3SGreg Clayton 
1246554f68d3SGreg Clayton   case Entry::Type::ThreadQueue:
1247b9c1b51eSKate Stone     if (exe_ctx) {
1248554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1249b9c1b51eSKate Stone       if (thread) {
1250554f68d3SGreg Clayton         const char *cstr = thread->GetQueueName();
1251b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1252554f68d3SGreg Clayton           s.PutCString(cstr);
1253554f68d3SGreg Clayton           return true;
1254554f68d3SGreg Clayton         }
1255554f68d3SGreg Clayton       }
1256554f68d3SGreg Clayton     }
1257554f68d3SGreg Clayton     return false;
1258554f68d3SGreg Clayton 
1259554f68d3SGreg Clayton   case Entry::Type::ThreadStopReason:
1260b9c1b51eSKate Stone     if (exe_ctx) {
1261554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1262b9c1b51eSKate Stone       if (thread) {
1263554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1264b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1265554f68d3SGreg Clayton           const char *cstr = stop_info_sp->GetDescription();
1266b9c1b51eSKate Stone           if (cstr && cstr[0]) {
1267554f68d3SGreg Clayton             s.PutCString(cstr);
1268554f68d3SGreg Clayton             return true;
1269554f68d3SGreg Clayton           }
1270554f68d3SGreg Clayton         }
1271554f68d3SGreg Clayton       }
1272554f68d3SGreg Clayton     }
1273554f68d3SGreg Clayton     return false;
1274554f68d3SGreg Clayton 
1275554f68d3SGreg Clayton   case Entry::Type::ThreadReturnValue:
1276b9c1b51eSKate Stone     if (exe_ctx) {
1277554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1278b9c1b51eSKate Stone       if (thread) {
1279554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1280b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1281b9c1b51eSKate Stone           ValueObjectSP return_valobj_sp =
1282b9c1b51eSKate Stone               StopInfo::GetReturnValueObject(stop_info_sp);
1283b9c1b51eSKate Stone           if (return_valobj_sp) {
1284554f68d3SGreg Clayton             return_valobj_sp->Dump(s);
1285554f68d3SGreg Clayton             return true;
1286554f68d3SGreg Clayton           }
1287554f68d3SGreg Clayton         }
1288554f68d3SGreg Clayton       }
1289554f68d3SGreg Clayton     }
1290554f68d3SGreg Clayton     return false;
1291554f68d3SGreg Clayton 
1292554f68d3SGreg Clayton   case Entry::Type::ThreadCompletedExpression:
1293b9c1b51eSKate Stone     if (exe_ctx) {
1294554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1295b9c1b51eSKate Stone       if (thread) {
1296554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1297b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1298b9c1b51eSKate Stone           ExpressionVariableSP expression_var_sp =
1299b9c1b51eSKate Stone               StopInfo::GetExpressionVariable(stop_info_sp);
1300b9c1b51eSKate Stone           if (expression_var_sp && expression_var_sp->GetValueObject()) {
1301554f68d3SGreg Clayton             expression_var_sp->GetValueObject()->Dump(s);
1302554f68d3SGreg Clayton             return true;
1303554f68d3SGreg Clayton           }
1304554f68d3SGreg Clayton         }
1305554f68d3SGreg Clayton       }
1306554f68d3SGreg Clayton     }
1307554f68d3SGreg Clayton     return false;
1308554f68d3SGreg Clayton 
1309554f68d3SGreg Clayton   case Entry::Type::ScriptThread:
1310b9c1b51eSKate Stone     if (exe_ctx) {
1311554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1312554f68d3SGreg Clayton       if (thread)
1313b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
1314b9c1b51eSKate Stone                                       entry.string.c_str());
1315554f68d3SGreg Clayton     }
1316554f68d3SGreg Clayton     return false;
1317554f68d3SGreg Clayton 
1318554f68d3SGreg Clayton   case Entry::Type::ThreadInfo:
1319b9c1b51eSKate Stone     if (exe_ctx) {
1320554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1321b9c1b51eSKate Stone       if (thread) {
1322554f68d3SGreg Clayton         StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1323b9c1b51eSKate Stone         if (object_sp &&
1324b9c1b51eSKate Stone             object_sp->GetType() == StructuredData::Type::eTypeDictionary) {
1325554f68d3SGreg Clayton           if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
1326554f68d3SGreg Clayton             return true;
1327554f68d3SGreg Clayton         }
1328554f68d3SGreg Clayton       }
1329554f68d3SGreg Clayton     }
1330554f68d3SGreg Clayton     return false;
1331554f68d3SGreg Clayton 
1332554f68d3SGreg Clayton   case Entry::Type::TargetArch:
1333b9c1b51eSKate Stone     if (exe_ctx) {
1334554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1335b9c1b51eSKate Stone       if (target) {
1336554f68d3SGreg Clayton         const ArchSpec &arch = target->GetArchitecture();
1337b9c1b51eSKate Stone         if (arch.IsValid()) {
1338554f68d3SGreg Clayton           s.PutCString(arch.GetArchitectureName());
1339554f68d3SGreg Clayton           return true;
1340554f68d3SGreg Clayton         }
1341554f68d3SGreg Clayton       }
1342554f68d3SGreg Clayton     }
1343554f68d3SGreg Clayton     return false;
1344554f68d3SGreg Clayton 
1345554f68d3SGreg Clayton   case Entry::Type::ScriptTarget:
1346b9c1b51eSKate Stone     if (exe_ctx) {
1347554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1348554f68d3SGreg Clayton       if (target)
1349b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, target,
1350b9c1b51eSKate Stone                                       entry.string.c_str());
1351554f68d3SGreg Clayton     }
1352554f68d3SGreg Clayton     return false;
1353554f68d3SGreg Clayton 
1354554f68d3SGreg Clayton   case Entry::Type::ModuleFile:
1355b9c1b51eSKate Stone     if (sc) {
1356554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1357b9c1b51eSKate Stone       if (module) {
1358554f68d3SGreg Clayton         if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1359554f68d3SGreg Clayton           return true;
1360554f68d3SGreg Clayton       }
1361554f68d3SGreg Clayton     }
1362554f68d3SGreg Clayton     return false;
1363554f68d3SGreg Clayton 
1364554f68d3SGreg Clayton   case Entry::Type::File:
1365b9c1b51eSKate Stone     if (sc) {
1366554f68d3SGreg Clayton       CompileUnit *cu = sc->comp_unit;
1367b9c1b51eSKate Stone       if (cu) {
1368554f68d3SGreg Clayton         // CompileUnit is a FileSpec
1369554f68d3SGreg Clayton         if (DumpFile(s, *cu, (FileKind)entry.number))
1370554f68d3SGreg Clayton           return true;
1371554f68d3SGreg Clayton       }
1372554f68d3SGreg Clayton     }
1373554f68d3SGreg Clayton     return false;
1374554f68d3SGreg Clayton 
1375dc975670SDawn Perchik   case Entry::Type::Lang:
1376b9c1b51eSKate Stone     if (sc) {
1377dc975670SDawn Perchik       CompileUnit *cu = sc->comp_unit;
1378b9c1b51eSKate Stone       if (cu) {
1379b9c1b51eSKate Stone         const char *lang_name =
1380b9c1b51eSKate Stone             Language::GetNameForLanguageType(cu->GetLanguage());
1381b9c1b51eSKate Stone         if (lang_name) {
1382dc975670SDawn Perchik           s.PutCString(lang_name);
1383dc975670SDawn Perchik           return true;
1384dc975670SDawn Perchik         }
1385dc975670SDawn Perchik       }
1386dc975670SDawn Perchik     }
1387dc975670SDawn Perchik     return false;
1388dc975670SDawn Perchik 
1389554f68d3SGreg Clayton   case Entry::Type::FrameIndex:
1390b9c1b51eSKate Stone     if (exe_ctx) {
1391554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1392b9c1b51eSKate Stone       if (frame) {
1393554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1394554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1395554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1396554f68d3SGreg Clayton         s.Printf(format, frame->GetFrameIndex());
1397554f68d3SGreg Clayton         return true;
1398554f68d3SGreg Clayton       }
1399554f68d3SGreg Clayton     }
1400554f68d3SGreg Clayton     return false;
1401554f68d3SGreg Clayton 
1402554f68d3SGreg Clayton   case Entry::Type::FrameRegisterPC:
1403b9c1b51eSKate Stone     if (exe_ctx) {
1404554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1405b9c1b51eSKate Stone       if (frame) {
1406554f68d3SGreg Clayton         const Address &pc_addr = frame->GetFrameCodeAddress();
1407b9c1b51eSKate Stone         if (pc_addr.IsValid()) {
1408554f68d3SGreg Clayton           if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
1409554f68d3SGreg Clayton             return true;
1410554f68d3SGreg Clayton         }
1411554f68d3SGreg Clayton       }
1412554f68d3SGreg Clayton     }
1413554f68d3SGreg Clayton     return false;
1414554f68d3SGreg Clayton 
1415554f68d3SGreg Clayton   case Entry::Type::FrameRegisterSP:
1416b9c1b51eSKate Stone     if (exe_ctx) {
1417554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1418b9c1b51eSKate Stone       if (frame) {
1419b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
1420b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1421554f68d3SGreg Clayton           return true;
1422554f68d3SGreg Clayton       }
1423554f68d3SGreg Clayton     }
1424554f68d3SGreg Clayton     return false;
1425554f68d3SGreg Clayton 
1426554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFP:
1427b9c1b51eSKate Stone     if (exe_ctx) {
1428554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1429b9c1b51eSKate Stone       if (frame) {
1430b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
1431b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1432554f68d3SGreg Clayton           return true;
1433554f68d3SGreg Clayton       }
1434554f68d3SGreg Clayton     }
1435554f68d3SGreg Clayton     return false;
1436554f68d3SGreg Clayton 
1437554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFlags:
1438b9c1b51eSKate Stone     if (exe_ctx) {
1439554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1440b9c1b51eSKate Stone       if (frame) {
1441b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric,
1442b9c1b51eSKate Stone                          LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
1443554f68d3SGreg Clayton           return true;
1444554f68d3SGreg Clayton       }
1445554f68d3SGreg Clayton     }
1446554f68d3SGreg Clayton     return false;
1447554f68d3SGreg Clayton 
1448554f68d3SGreg Clayton   case Entry::Type::FrameRegisterByName:
1449b9c1b51eSKate Stone     if (exe_ctx) {
1450554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1451b9c1b51eSKate Stone       if (frame) {
1452b9c1b51eSKate Stone         if (DumpRegister(s, frame, entry.string.c_str(),
1453b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1454554f68d3SGreg Clayton           return true;
1455554f68d3SGreg Clayton       }
1456554f68d3SGreg Clayton     }
1457554f68d3SGreg Clayton     return false;
1458554f68d3SGreg Clayton 
1459554f68d3SGreg Clayton   case Entry::Type::ScriptFrame:
1460b9c1b51eSKate Stone     if (exe_ctx) {
1461554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1462554f68d3SGreg Clayton       if (frame)
1463b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
1464b9c1b51eSKate Stone                                       entry.string.c_str());
1465554f68d3SGreg Clayton     }
1466554f68d3SGreg Clayton     return false;
1467554f68d3SGreg Clayton 
1468554f68d3SGreg Clayton   case Entry::Type::FunctionID:
1469b9c1b51eSKate Stone     if (sc) {
1470b9c1b51eSKate Stone       if (sc->function) {
1471554f68d3SGreg Clayton         s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
1472554f68d3SGreg Clayton         return true;
1473b9c1b51eSKate Stone       } else if (sc->symbol) {
1474554f68d3SGreg Clayton         s.Printf("symbol[%u]", sc->symbol->GetID());
1475554f68d3SGreg Clayton         return true;
1476554f68d3SGreg Clayton       }
1477554f68d3SGreg Clayton     }
1478554f68d3SGreg Clayton     return false;
1479554f68d3SGreg Clayton 
1480554f68d3SGreg Clayton   case Entry::Type::FunctionDidChange:
1481554f68d3SGreg Clayton     return function_changed;
1482554f68d3SGreg Clayton 
1483554f68d3SGreg Clayton   case Entry::Type::FunctionInitialFunction:
1484554f68d3SGreg Clayton     return initial_function;
1485554f68d3SGreg Clayton 
1486b9c1b51eSKate Stone   case Entry::Type::FunctionName: {
1487d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1488d4129b47SEnrico Granata     bool language_plugin_handled = false;
1489d4129b47SEnrico Granata     StreamString ss;
1490d4129b47SEnrico Granata     if (sc->function)
1491d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1492d4129b47SEnrico Granata     else if (sc->symbol)
1493d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1494b9c1b51eSKate Stone     if (language_plugin) {
1495b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1496b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1497d4129b47SEnrico Granata     }
1498b9c1b51eSKate Stone     if (language_plugin_handled) {
1499d4129b47SEnrico Granata       s.PutCString(ss.GetData());
1500d4129b47SEnrico Granata       return true;
1501b9c1b51eSKate Stone     } else {
1502a74f37a5SEugene Zelenko       const char *name = nullptr;
1503554f68d3SGreg Clayton       if (sc->function)
1504a74f37a5SEugene Zelenko         name = sc->function->GetName().AsCString(nullptr);
1505554f68d3SGreg Clayton       else if (sc->symbol)
1506a74f37a5SEugene Zelenko         name = sc->symbol->GetName().AsCString(nullptr);
1507b9c1b51eSKate Stone       if (name) {
1508554f68d3SGreg Clayton         s.PutCString(name);
1509554f68d3SGreg Clayton 
1510b9c1b51eSKate Stone         if (sc->block) {
1511554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
1512b9c1b51eSKate Stone           if (inline_block) {
1513b9c1b51eSKate Stone             const InlineFunctionInfo *inline_info =
1514b9c1b51eSKate Stone                 sc->block->GetInlinedFunctionInfo();
1515b9c1b51eSKate Stone             if (inline_info) {
1516554f68d3SGreg Clayton               s.PutCString(" [inlined] ");
1517ddaf6a72SGreg Clayton               inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
1518554f68d3SGreg Clayton             }
1519554f68d3SGreg Clayton           }
1520554f68d3SGreg Clayton         }
1521554f68d3SGreg Clayton         return true;
1522554f68d3SGreg Clayton       }
1523554f68d3SGreg Clayton     }
1524d4129b47SEnrico Granata   }
1525554f68d3SGreg Clayton     return false;
1526554f68d3SGreg Clayton 
1527b9c1b51eSKate Stone   case Entry::Type::FunctionNameNoArgs: {
1528d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1529d4129b47SEnrico Granata     bool language_plugin_handled = false;
1530d4129b47SEnrico Granata     StreamString ss;
1531d4129b47SEnrico Granata     if (sc->function)
1532d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1533d4129b47SEnrico Granata     else if (sc->symbol)
1534d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1535b9c1b51eSKate Stone     if (language_plugin) {
1536b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1537b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1538d4129b47SEnrico Granata           ss);
1539d4129b47SEnrico Granata     }
1540b9c1b51eSKate Stone     if (language_plugin_handled) {
1541d4129b47SEnrico Granata       s.PutCString(ss.GetData());
1542d4129b47SEnrico Granata       return true;
1543b9c1b51eSKate Stone     } else {
1544554f68d3SGreg Clayton       ConstString name;
1545554f68d3SGreg Clayton       if (sc->function)
1546ddaf6a72SGreg Clayton         name = sc->function->GetNameNoArguments();
1547554f68d3SGreg Clayton       else if (sc->symbol)
1548ddaf6a72SGreg Clayton         name = sc->symbol->GetNameNoArguments();
1549b9c1b51eSKate Stone       if (name) {
1550554f68d3SGreg Clayton         s.PutCString(name.GetCString());
1551554f68d3SGreg Clayton         return true;
1552554f68d3SGreg Clayton       }
1553554f68d3SGreg Clayton     }
1554d4129b47SEnrico Granata   }
1555554f68d3SGreg Clayton     return false;
1556554f68d3SGreg Clayton 
1557b9c1b51eSKate Stone   case Entry::Type::FunctionNameWithArgs: {
1558d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1559d4129b47SEnrico Granata     bool language_plugin_handled = false;
1560d4129b47SEnrico Granata     StreamString ss;
1561d4129b47SEnrico Granata     if (sc->function)
1562d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1563d4129b47SEnrico Granata     else if (sc->symbol)
1564d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1565b9c1b51eSKate Stone     if (language_plugin) {
1566b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1567b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1568d4129b47SEnrico Granata     }
1569b9c1b51eSKate Stone     if (language_plugin_handled) {
1570d4129b47SEnrico Granata       s.PutCString(ss.GetData());
1571d4129b47SEnrico Granata       return true;
1572b9c1b51eSKate Stone     } else {
1573554f68d3SGreg Clayton       // Print the function name with arguments in it
1574b9c1b51eSKate Stone       if (sc->function) {
1575b9c1b51eSKate Stone         ExecutionContextScope *exe_scope =
1576b9c1b51eSKate Stone             exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1577a74f37a5SEugene Zelenko         const char *cstr = sc->function->GetName().AsCString(nullptr);
1578b9c1b51eSKate Stone         if (cstr) {
1579a74f37a5SEugene Zelenko           const InlineFunctionInfo *inline_info = nullptr;
1580554f68d3SGreg Clayton           VariableListSP variable_list_sp;
1581554f68d3SGreg Clayton           bool get_function_vars = true;
1582b9c1b51eSKate Stone           if (sc->block) {
1583554f68d3SGreg Clayton             Block *inline_block = sc->block->GetContainingInlinedBlock();
1584554f68d3SGreg Clayton 
1585b9c1b51eSKate Stone             if (inline_block) {
1586554f68d3SGreg Clayton               get_function_vars = false;
1587554f68d3SGreg Clayton               inline_info = sc->block->GetInlinedFunctionInfo();
1588554f68d3SGreg Clayton               if (inline_info)
1589554f68d3SGreg Clayton                 variable_list_sp = inline_block->GetBlockVariableList(true);
1590554f68d3SGreg Clayton             }
1591554f68d3SGreg Clayton           }
1592554f68d3SGreg Clayton 
1593b9c1b51eSKate Stone           if (get_function_vars) {
1594b9c1b51eSKate Stone             variable_list_sp =
1595b9c1b51eSKate Stone                 sc->function->GetBlock(true).GetBlockVariableList(true);
1596554f68d3SGreg Clayton           }
1597554f68d3SGreg Clayton 
1598b9c1b51eSKate Stone           if (inline_info) {
1599554f68d3SGreg Clayton             s.PutCString(cstr);
1600554f68d3SGreg Clayton             s.PutCString(" [inlined] ");
1601b9c1b51eSKate Stone             cstr =
1602b9c1b51eSKate Stone                 inline_info->GetName(sc->function->GetLanguage()).GetCString();
1603554f68d3SGreg Clayton           }
1604554f68d3SGreg Clayton 
1605554f68d3SGreg Clayton           VariableList args;
1606554f68d3SGreg Clayton           if (variable_list_sp)
1607b9c1b51eSKate Stone             variable_list_sp->AppendVariablesWithScope(
1608b9c1b51eSKate Stone                 eValueTypeVariableArgument, args);
1609b9c1b51eSKate Stone           if (args.GetSize() > 0) {
1610554f68d3SGreg Clayton             const char *open_paren = strchr(cstr, '(');
1611554f68d3SGreg Clayton             const char *close_paren = nullptr;
1612554f68d3SGreg Clayton             const char *generic = strchr(cstr, '<');
1613554f68d3SGreg Clayton             // if before the arguments list begins there is a template sign
1614554f68d3SGreg Clayton             // then scan to the end of the generic args before you try to find
1615554f68d3SGreg Clayton             // the arguments list
1616b9c1b51eSKate Stone             if (generic && open_paren && generic < open_paren) {
1617554f68d3SGreg Clayton               int generic_depth = 1;
1618554f68d3SGreg Clayton               ++generic;
1619b9c1b51eSKate Stone               for (; *generic && generic_depth > 0; generic++) {
1620554f68d3SGreg Clayton                 if (*generic == '<')
1621554f68d3SGreg Clayton                   generic_depth++;
1622554f68d3SGreg Clayton                 if (*generic == '>')
1623554f68d3SGreg Clayton                   generic_depth--;
1624554f68d3SGreg Clayton               }
1625554f68d3SGreg Clayton               if (*generic)
1626554f68d3SGreg Clayton                 open_paren = strchr(generic, '(');
1627554f68d3SGreg Clayton               else
1628554f68d3SGreg Clayton                 open_paren = nullptr;
1629554f68d3SGreg Clayton             }
1630b9c1b51eSKate Stone             if (open_paren) {
1631b9c1b51eSKate Stone               if (IsToken(open_paren, "(anonymous namespace)")) {
1632b9c1b51eSKate Stone                 open_paren =
1633b9c1b51eSKate Stone                     strchr(open_paren + strlen("(anonymous namespace)"), '(');
1634554f68d3SGreg Clayton                 if (open_paren)
1635554f68d3SGreg Clayton                   close_paren = strchr(open_paren, ')');
1636b9c1b51eSKate Stone               } else
1637554f68d3SGreg Clayton                 close_paren = strchr(open_paren, ')');
1638554f68d3SGreg Clayton             }
1639554f68d3SGreg Clayton 
1640554f68d3SGreg Clayton             if (open_paren)
1641554f68d3SGreg Clayton               s.Write(cstr, open_paren - cstr + 1);
1642b9c1b51eSKate Stone             else {
1643554f68d3SGreg Clayton               s.PutCString(cstr);
1644554f68d3SGreg Clayton               s.PutChar('(');
1645554f68d3SGreg Clayton             }
1646554f68d3SGreg Clayton             const size_t num_args = args.GetSize();
1647b9c1b51eSKate Stone             for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1648554f68d3SGreg Clayton               std::string buffer;
1649554f68d3SGreg Clayton 
1650554f68d3SGreg Clayton               VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1651b9c1b51eSKate Stone               ValueObjectSP var_value_sp(
1652b9c1b51eSKate Stone                   ValueObjectVariable::Create(exe_scope, var_sp));
1653ad91c7ceSEnrico Granata               StreamString ss;
1654554f68d3SGreg Clayton               const char *var_representation = nullptr;
1655554f68d3SGreg Clayton               const char *var_name = var_value_sp->GetName().GetCString();
1656b9c1b51eSKate Stone               if (var_value_sp->GetCompilerType().IsValid()) {
1657ad91c7ceSEnrico Granata                 if (var_value_sp && exe_scope->CalculateTarget())
1658b9c1b51eSKate Stone                   var_value_sp =
1659b9c1b51eSKate Stone                       var_value_sp->GetQualifiedRepresentationIfAvailable(
1660b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1661b9c1b51eSKate Stone                               ->TargetProperties::GetPreferDynamicValue(),
1662b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1663b9c1b51eSKate Stone                               ->TargetProperties::GetEnableSyntheticValue());
166499558cc4SGreg Clayton                 if (var_value_sp->GetCompilerType().IsAggregateType() &&
1665b9c1b51eSKate Stone                     DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
1666b9c1b51eSKate Stone                   static StringSummaryFormat format(
1667b9c1b51eSKate Stone                       TypeSummaryImpl::Flags()
1668554f68d3SGreg Clayton                           .SetHideItemNames(false)
1669554f68d3SGreg Clayton                           .SetShowMembersOneLiner(true),
1670554f68d3SGreg Clayton                       "");
1671b9c1b51eSKate Stone                   format.FormatObject(var_value_sp.get(), buffer,
1672b9c1b51eSKate Stone                                       TypeSummaryOptions());
1673554f68d3SGreg Clayton                   var_representation = buffer.c_str();
1674b9c1b51eSKate Stone                 } else
1675b9c1b51eSKate Stone                   var_value_sp->DumpPrintableRepresentation(
1676b9c1b51eSKate Stone                       ss, ValueObject::ValueObjectRepresentationStyle::
1677b9c1b51eSKate Stone                               eValueObjectRepresentationStyleSummary,
1678ad91c7ceSEnrico Granata                       eFormatDefault,
1679*65d86e4fSEnrico Granata                       ValueObject::PrintableRepresentationSpecialCases::eAllow,
1680ad91c7ceSEnrico Granata                       false);
1681ad91c7ceSEnrico Granata               }
1682ad91c7ceSEnrico Granata 
1683ad91c7ceSEnrico Granata               if (ss.GetData() && ss.GetSize())
1684ad91c7ceSEnrico Granata                 var_representation = ss.GetData();
1685554f68d3SGreg Clayton               if (arg_idx > 0)
1686554f68d3SGreg Clayton                 s.PutCString(", ");
1687b9c1b51eSKate Stone               if (var_value_sp->GetError().Success()) {
1688554f68d3SGreg Clayton                 if (var_representation)
1689554f68d3SGreg Clayton                   s.Printf("%s=%s", var_name, var_representation);
1690554f68d3SGreg Clayton                 else
1691b9c1b51eSKate Stone                   s.Printf("%s=%s at %s", var_name,
1692b9c1b51eSKate Stone                            var_value_sp->GetTypeName().GetCString(),
1693b9c1b51eSKate Stone                            var_value_sp->GetLocationAsCString());
1694b9c1b51eSKate Stone               } else
1695554f68d3SGreg Clayton                 s.Printf("%s=<unavailable>", var_name);
1696554f68d3SGreg Clayton             }
1697554f68d3SGreg Clayton 
1698554f68d3SGreg Clayton             if (close_paren)
1699554f68d3SGreg Clayton               s.PutCString(close_paren);
1700554f68d3SGreg Clayton             else
1701554f68d3SGreg Clayton               s.PutChar(')');
1702554f68d3SGreg Clayton 
1703b9c1b51eSKate Stone           } else {
1704554f68d3SGreg Clayton             s.PutCString(cstr);
1705554f68d3SGreg Clayton           }
1706554f68d3SGreg Clayton           return true;
1707554f68d3SGreg Clayton         }
1708b9c1b51eSKate Stone       } else if (sc->symbol) {
1709a74f37a5SEugene Zelenko         const char *cstr = sc->symbol->GetName().AsCString(nullptr);
1710b9c1b51eSKate Stone         if (cstr) {
1711554f68d3SGreg Clayton           s.PutCString(cstr);
1712554f68d3SGreg Clayton           return true;
1713554f68d3SGreg Clayton         }
1714554f68d3SGreg Clayton       }
1715554f68d3SGreg Clayton     }
1716d4129b47SEnrico Granata   }
1717554f68d3SGreg Clayton     return false;
1718554f68d3SGreg Clayton 
1719554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffset:
1720b9c1b51eSKate Stone     if (addr) {
1721b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
1722b9c1b51eSKate Stone                                         false))
1723554f68d3SGreg Clayton         return true;
1724554f68d3SGreg Clayton     }
1725554f68d3SGreg Clayton     return false;
1726554f68d3SGreg Clayton 
1727554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffsetConcrete:
1728b9c1b51eSKate Stone     if (addr) {
1729b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
1730b9c1b51eSKate Stone                                         true))
1731554f68d3SGreg Clayton         return true;
1732554f68d3SGreg Clayton     }
1733554f68d3SGreg Clayton     return false;
1734554f68d3SGreg Clayton 
1735554f68d3SGreg Clayton   case Entry::Type::FunctionLineOffset:
1736b9c1b51eSKate Stone     return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1737b9c1b51eSKate Stone                                           sc->line_entry.range.GetBaseAddress(),
1738b9c1b51eSKate Stone                                           false, false, false));
1739554f68d3SGreg Clayton 
1740554f68d3SGreg Clayton   case Entry::Type::FunctionPCOffset:
1741b9c1b51eSKate Stone     if (exe_ctx) {
1742554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1743b9c1b51eSKate Stone       if (frame) {
1744b9c1b51eSKate Stone         if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1745b9c1b51eSKate Stone                                           frame->GetFrameCodeAddress(), false,
1746b9c1b51eSKate Stone                                           false, false))
1747554f68d3SGreg Clayton           return true;
1748554f68d3SGreg Clayton       }
1749554f68d3SGreg Clayton     }
1750554f68d3SGreg Clayton     return false;
1751554f68d3SGreg Clayton 
1752c980fa92SJason Molenda   case Entry::Type::FunctionChanged:
1753a74f37a5SEugene Zelenko     return function_changed;
1754c980fa92SJason Molenda 
1755b9c1b51eSKate Stone   case Entry::Type::FunctionIsOptimized: {
17566ab659a9SJason Molenda     bool is_optimized = false;
1757b9c1b51eSKate Stone     if (sc->function && sc->function->GetIsOptimized()) {
17586ab659a9SJason Molenda       is_optimized = true;
17596ab659a9SJason Molenda     }
17606ab659a9SJason Molenda     return is_optimized;
17616ab659a9SJason Molenda   }
17626ab659a9SJason Molenda 
1763c980fa92SJason Molenda   case Entry::Type::FunctionInitial:
1764a74f37a5SEugene Zelenko     return initial_function;
1765c980fa92SJason Molenda 
1766554f68d3SGreg Clayton   case Entry::Type::LineEntryFile:
1767b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1768554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1769b9c1b51eSKate Stone       if (module) {
1770554f68d3SGreg Clayton         if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
1771554f68d3SGreg Clayton           return true;
1772554f68d3SGreg Clayton       }
1773554f68d3SGreg Clayton     }
1774554f68d3SGreg Clayton     return false;
1775554f68d3SGreg Clayton 
1776554f68d3SGreg Clayton   case Entry::Type::LineEntryLineNumber:
1777b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1778554f68d3SGreg Clayton       const char *format = "%" PRIu32;
1779554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1780554f68d3SGreg Clayton         format = entry.printf_format.c_str();
1781554f68d3SGreg Clayton       s.Printf(format, sc->line_entry.line);
1782554f68d3SGreg Clayton       return true;
1783554f68d3SGreg Clayton     }
1784554f68d3SGreg Clayton     return false;
1785554f68d3SGreg Clayton 
1786554f68d3SGreg Clayton   case Entry::Type::LineEntryStartAddress:
1787554f68d3SGreg Clayton   case Entry::Type::LineEntryEndAddress:
1788b9c1b51eSKate Stone     if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
1789554f68d3SGreg Clayton       Address addr = sc->line_entry.range.GetBaseAddress();
1790554f68d3SGreg Clayton 
1791554f68d3SGreg Clayton       if (entry.type == Entry::Type::LineEntryEndAddress)
1792554f68d3SGreg Clayton         addr.Slide(sc->line_entry.range.GetByteSize());
1793554f68d3SGreg Clayton       if (DumpAddress(s, sc, exe_ctx, addr, false))
1794554f68d3SGreg Clayton         return true;
1795554f68d3SGreg Clayton     }
1796554f68d3SGreg Clayton     return false;
1797554f68d3SGreg Clayton 
1798554f68d3SGreg Clayton   case Entry::Type::CurrentPCArrow:
1799b9c1b51eSKate Stone     if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
1800b9c1b51eSKate Stone       RegisterContextSP reg_ctx =
1801b9c1b51eSKate Stone           exe_ctx->GetFramePtr()->GetRegisterContextSP();
1802b9c1b51eSKate Stone       if (reg_ctx) {
1803554f68d3SGreg Clayton         addr_t pc_loadaddr = reg_ctx->GetPC();
1804b9c1b51eSKate Stone         if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
1805554f68d3SGreg Clayton           Address pc;
1806554f68d3SGreg Clayton           pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
1807b9c1b51eSKate Stone           if (pc == *addr) {
1808554f68d3SGreg Clayton             s.Printf("-> ");
1809554f68d3SGreg Clayton             return true;
1810554f68d3SGreg Clayton           }
1811554f68d3SGreg Clayton         }
1812554f68d3SGreg Clayton       }
1813554f68d3SGreg Clayton       s.Printf("   ");
1814554f68d3SGreg Clayton       return true;
1815554f68d3SGreg Clayton     }
1816554f68d3SGreg Clayton     return false;
1817554f68d3SGreg Clayton   }
1818554f68d3SGreg Clayton   return false;
1819554f68d3SGreg Clayton }
1820554f68d3SGreg Clayton 
1821b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames(
1822b9c1b51eSKate Stone     Stream &s, const FormatEntity::Entry::Definition *parent) {
1823b9c1b51eSKate Stone   if (parent->children) {
1824554f68d3SGreg Clayton     const size_t n = parent->num_children;
1825b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
1826554f68d3SGreg Clayton       if (i > 0)
1827554f68d3SGreg Clayton         s.PutCString(", ");
1828554f68d3SGreg Clayton       s.Printf("\"%s\"", parent->children[i].name);
1829554f68d3SGreg Clayton     }
1830554f68d3SGreg Clayton     return true;
1831554f68d3SGreg Clayton   }
1832554f68d3SGreg Clayton   return false;
1833554f68d3SGreg Clayton }
1834554f68d3SGreg Clayton 
1835b9c1b51eSKate Stone static Error ParseEntry(const llvm::StringRef &format_str,
1836554f68d3SGreg Clayton                         const FormatEntity::Entry::Definition *parent,
1837b9c1b51eSKate Stone                         FormatEntity::Entry &entry) {
1838554f68d3SGreg Clayton   Error error;
1839554f68d3SGreg Clayton 
1840554f68d3SGreg Clayton   const size_t sep_pos = format_str.find_first_of(".[:");
1841b9c1b51eSKate Stone   const char sep_char =
1842b9c1b51eSKate Stone       (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
1843554f68d3SGreg Clayton   llvm::StringRef key = format_str.substr(0, sep_pos);
1844554f68d3SGreg Clayton 
1845554f68d3SGreg Clayton   const size_t n = parent->num_children;
1846b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1847554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1848b9c1b51eSKate Stone     if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
1849554f68d3SGreg Clayton       llvm::StringRef value;
1850554f68d3SGreg Clayton       if (sep_char)
1851b9c1b51eSKate Stone         value =
1852b9c1b51eSKate Stone             format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
1853b9c1b51eSKate Stone       switch (entry_def->type) {
1854554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentString:
18553a29f8b9SPavel Labath         entry.string = format_str.str();
1856554f68d3SGreg Clayton         return error; // Success
1857554f68d3SGreg Clayton 
1858554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentNumber:
1859554f68d3SGreg Clayton         entry.number = entry_def->data;
1860554f68d3SGreg Clayton         return error; // Success
1861554f68d3SGreg Clayton 
1862554f68d3SGreg Clayton       case FormatEntity::Entry::Type::InsertString:
1863554f68d3SGreg Clayton         entry.type = entry_def->type;
1864554f68d3SGreg Clayton         entry.string = entry_def->string;
1865554f68d3SGreg Clayton         return error; // Success
1866554f68d3SGreg Clayton 
1867554f68d3SGreg Clayton       default:
1868554f68d3SGreg Clayton         entry.type = entry_def->type;
1869554f68d3SGreg Clayton         break;
1870554f68d3SGreg Clayton       }
1871554f68d3SGreg Clayton 
1872b9c1b51eSKate Stone       if (value.empty()) {
1873b9c1b51eSKate Stone         if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
1874b9c1b51eSKate Stone           if (entry_def->children) {
1875554f68d3SGreg Clayton             StreamString error_strm;
1876b9c1b51eSKate Stone             error_strm.Printf("'%s' can't be specified on its own, you must "
1877b9c1b51eSKate Stone                               "access one of its children: ",
1878b9c1b51eSKate Stone                               entry_def->name);
1879554f68d3SGreg Clayton             DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
1880b9c1b51eSKate Stone             error.SetErrorStringWithFormat("%s",
1881b9c1b51eSKate Stone                                            error_strm.GetString().c_str());
1882b9c1b51eSKate Stone           } else if (sep_char == ':') {
1883b9c1b51eSKate Stone             // Any value whose separator is a with a ':' means this value has a
1884b9c1b51eSKate Stone             // string argument
1885554f68d3SGreg Clayton             // that needs to be stored in the entry (like "${script.var:}").
1886554f68d3SGreg Clayton             // In this case the string value is the empty string which is ok.
1887b9c1b51eSKate Stone           } else {
1888554f68d3SGreg Clayton             error.SetErrorStringWithFormat("%s", "invalid entry definitions");
1889554f68d3SGreg Clayton           }
1890554f68d3SGreg Clayton         }
1891b9c1b51eSKate Stone       } else {
1892b9c1b51eSKate Stone         if (entry_def->children) {
1893554f68d3SGreg Clayton           error = ParseEntry(value, entry_def, entry);
1894b9c1b51eSKate Stone         } else if (sep_char == ':') {
1895b9c1b51eSKate Stone           // Any value whose separator is a with a ':' means this value has a
1896b9c1b51eSKate Stone           // string argument
1897b9c1b51eSKate Stone           // that needs to be stored in the entry (like
1898b9c1b51eSKate Stone           // "${script.var:modulename.function}")
18993a29f8b9SPavel Labath           entry.string = value.str();
1900b9c1b51eSKate Stone         } else {
1901b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1902b9c1b51eSKate Stone               "'%s' followed by '%s' but it has no children", key.str().c_str(),
1903554f68d3SGreg Clayton               value.str().c_str());
1904554f68d3SGreg Clayton         }
1905554f68d3SGreg Clayton       }
1906554f68d3SGreg Clayton       return error;
1907554f68d3SGreg Clayton     }
1908554f68d3SGreg Clayton   }
1909554f68d3SGreg Clayton   StreamString error_strm;
1910554f68d3SGreg Clayton   if (parent->type == FormatEntity::Entry::Type::Root)
1911b9c1b51eSKate Stone     error_strm.Printf(
1912b9c1b51eSKate Stone         "invalid top level item '%s'. Valid top level items are: ",
1913b9c1b51eSKate Stone         key.str().c_str());
1914554f68d3SGreg Clayton   else
1915b9c1b51eSKate Stone     error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
1916b9c1b51eSKate Stone                       key.str().c_str(), parent->name);
1917554f68d3SGreg Clayton   DumpCommaSeparatedChildEntryNames(error_strm, parent);
1918554f68d3SGreg Clayton   error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
1919554f68d3SGreg Clayton   return error;
1920554f68d3SGreg Clayton }
1921554f68d3SGreg Clayton 
1922554f68d3SGreg Clayton static const FormatEntity::Entry::Definition *
1923b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str,
1924b9c1b51eSKate Stone           const FormatEntity::Entry::Definition *parent,
1925b9c1b51eSKate Stone           llvm::StringRef &remainder) {
1926554f68d3SGreg Clayton   Error error;
1927554f68d3SGreg Clayton 
1928554f68d3SGreg Clayton   std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
1929554f68d3SGreg Clayton   const size_t n = parent->num_children;
1930b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1931554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1932b9c1b51eSKate Stone     if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
1933b9c1b51eSKate Stone       if (p.second.empty()) {
1934554f68d3SGreg Clayton         if (format_str.back() == '.')
1935554f68d3SGreg Clayton           remainder = format_str.drop_front(format_str.size() - 1);
1936554f68d3SGreg Clayton         else
1937554f68d3SGreg Clayton           remainder = llvm::StringRef(); // Exact match
1938554f68d3SGreg Clayton         return entry_def;
1939b9c1b51eSKate Stone       } else {
1940b9c1b51eSKate Stone         if (entry_def->children) {
1941554f68d3SGreg Clayton           return FindEntry(p.second, entry_def, remainder);
1942b9c1b51eSKate Stone         } else {
1943554f68d3SGreg Clayton           remainder = p.second;
1944554f68d3SGreg Clayton           return entry_def;
1945554f68d3SGreg Clayton         }
1946554f68d3SGreg Clayton       }
1947554f68d3SGreg Clayton     }
1948554f68d3SGreg Clayton   }
1949554f68d3SGreg Clayton   remainder = format_str;
1950554f68d3SGreg Clayton   return parent;
1951554f68d3SGreg Clayton }
1952554f68d3SGreg Clayton 
1953b9c1b51eSKate Stone Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
1954b9c1b51eSKate Stone                                   uint32_t depth) {
1955554f68d3SGreg Clayton   Error error;
1956b9c1b51eSKate Stone   while (!format.empty() && error.Success()) {
1957554f68d3SGreg Clayton     const size_t non_special_chars = format.find_first_of("${}\\");
1958554f68d3SGreg Clayton 
1959b9c1b51eSKate Stone     if (non_special_chars == llvm::StringRef::npos) {
1960554f68d3SGreg Clayton       // No special characters, just string bytes so add them and we are done
1961554f68d3SGreg Clayton       parent_entry.AppendText(format);
1962554f68d3SGreg Clayton       return error;
1963554f68d3SGreg Clayton     }
1964554f68d3SGreg Clayton 
1965b9c1b51eSKate Stone     if (non_special_chars > 0) {
1966b9c1b51eSKate Stone       // We have a special character, so add all characters before these as a
1967b9c1b51eSKate Stone       // plain string
1968554f68d3SGreg Clayton       parent_entry.AppendText(format.substr(0, non_special_chars));
1969554f68d3SGreg Clayton       format = format.drop_front(non_special_chars);
1970554f68d3SGreg Clayton     }
1971554f68d3SGreg Clayton 
1972b9c1b51eSKate Stone     switch (format[0]) {
1973554f68d3SGreg Clayton     case '\0':
1974554f68d3SGreg Clayton       return error;
1975554f68d3SGreg Clayton 
1976b9c1b51eSKate Stone     case '{': {
1977554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '{'
1978554f68d3SGreg Clayton       Entry scope_entry(Entry::Type::Scope);
1979554f68d3SGreg Clayton       error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
1980554f68d3SGreg Clayton       if (error.Fail())
1981554f68d3SGreg Clayton         return error;
1982554f68d3SGreg Clayton       parent_entry.AppendEntry(std::move(scope_entry));
1983b9c1b51eSKate Stone     } break;
1984554f68d3SGreg Clayton 
1985554f68d3SGreg Clayton     case '}':
1986554f68d3SGreg Clayton       if (depth == 0)
1987554f68d3SGreg Clayton         error.SetErrorString("unmatched '}' character");
1988554f68d3SGreg Clayton       else
1989b9c1b51eSKate Stone         format =
1990b9c1b51eSKate Stone             format
1991b9c1b51eSKate Stone                 .drop_front(); // Skip the '}' as we are at the end of the scope
1992554f68d3SGreg Clayton       return error;
1993554f68d3SGreg Clayton 
1994b9c1b51eSKate Stone     case '\\': {
1995554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '\' character
1996b9c1b51eSKate Stone       if (format.empty()) {
1997b9c1b51eSKate Stone         error.SetErrorString(
1998b9c1b51eSKate Stone             "'\\' character was not followed by another character");
1999554f68d3SGreg Clayton         return error;
2000554f68d3SGreg Clayton       }
2001554f68d3SGreg Clayton 
2002554f68d3SGreg Clayton       const char desens_char = format[0];
2003554f68d3SGreg Clayton       format = format.drop_front(); // Skip the desensitized char character
2004b9c1b51eSKate Stone       switch (desens_char) {
2005b9c1b51eSKate Stone       case 'a':
2006b9c1b51eSKate Stone         parent_entry.AppendChar('\a');
2007b9c1b51eSKate Stone         break;
2008b9c1b51eSKate Stone       case 'b':
2009b9c1b51eSKate Stone         parent_entry.AppendChar('\b');
2010b9c1b51eSKate Stone         break;
2011b9c1b51eSKate Stone       case 'f':
2012b9c1b51eSKate Stone         parent_entry.AppendChar('\f');
2013b9c1b51eSKate Stone         break;
2014b9c1b51eSKate Stone       case 'n':
2015b9c1b51eSKate Stone         parent_entry.AppendChar('\n');
2016b9c1b51eSKate Stone         break;
2017b9c1b51eSKate Stone       case 'r':
2018b9c1b51eSKate Stone         parent_entry.AppendChar('\r');
2019b9c1b51eSKate Stone         break;
2020b9c1b51eSKate Stone       case 't':
2021b9c1b51eSKate Stone         parent_entry.AppendChar('\t');
2022b9c1b51eSKate Stone         break;
2023b9c1b51eSKate Stone       case 'v':
2024b9c1b51eSKate Stone         parent_entry.AppendChar('\v');
2025b9c1b51eSKate Stone         break;
2026b9c1b51eSKate Stone       case '\'':
2027b9c1b51eSKate Stone         parent_entry.AppendChar('\'');
2028b9c1b51eSKate Stone         break;
2029b9c1b51eSKate Stone       case '\\':
2030b9c1b51eSKate Stone         parent_entry.AppendChar('\\');
2031b9c1b51eSKate Stone         break;
2032554f68d3SGreg Clayton       case '0':
2033554f68d3SGreg Clayton         // 1 to 3 octal chars
2034554f68d3SGreg Clayton         {
2035554f68d3SGreg Clayton           // Make a string that can hold onto the initial zero char,
2036554f68d3SGreg Clayton           // up to 3 octal digits, and a terminating NULL.
2037554f68d3SGreg Clayton           char oct_str[5] = {0, 0, 0, 0, 0};
2038554f68d3SGreg Clayton 
2039554f68d3SGreg Clayton           int i;
2040554f68d3SGreg Clayton           for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2041554f68d3SGreg Clayton             oct_str[i] = format[i];
2042554f68d3SGreg Clayton 
2043554f68d3SGreg Clayton           // We don't want to consume the last octal character since
2044554f68d3SGreg Clayton           // the main for loop will do this for us, so we advance p by
2045554f68d3SGreg Clayton           // one less than i (even if i is zero)
2046554f68d3SGreg Clayton           format = format.drop_front(i);
2047a74f37a5SEugene Zelenko           unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2048b9c1b51eSKate Stone           if (octal_value <= UINT8_MAX) {
2049554f68d3SGreg Clayton             parent_entry.AppendChar((char)octal_value);
2050b9c1b51eSKate Stone           } else {
2051554f68d3SGreg Clayton             error.SetErrorString("octal number is larger than a single byte");
2052554f68d3SGreg Clayton             return error;
2053554f68d3SGreg Clayton           }
2054554f68d3SGreg Clayton         }
2055554f68d3SGreg Clayton         break;
2056554f68d3SGreg Clayton 
2057554f68d3SGreg Clayton       case 'x':
2058554f68d3SGreg Clayton         // hex number in the format
2059b9c1b51eSKate Stone         if (isxdigit(format[0])) {
2060554f68d3SGreg Clayton           // Make a string that can hold onto two hex chars plus a
2061554f68d3SGreg Clayton           // NULL terminator
2062554f68d3SGreg Clayton           char hex_str[3] = {0, 0, 0};
2063554f68d3SGreg Clayton           hex_str[0] = format[0];
2064554f68d3SGreg Clayton 
2065554f68d3SGreg Clayton           format = format.drop_front();
2066554f68d3SGreg Clayton 
2067b9c1b51eSKate Stone           if (isxdigit(format[0])) {
2068554f68d3SGreg Clayton             hex_str[1] = format[0];
2069554f68d3SGreg Clayton             format = format.drop_front();
2070554f68d3SGreg Clayton           }
2071554f68d3SGreg Clayton 
2072a74f37a5SEugene Zelenko           unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2073b9c1b51eSKate Stone           if (hex_value <= UINT8_MAX) {
2074554f68d3SGreg Clayton             parent_entry.AppendChar((char)hex_value);
2075b9c1b51eSKate Stone           } else {
2076554f68d3SGreg Clayton             error.SetErrorString("hex number is larger than a single byte");
2077554f68d3SGreg Clayton             return error;
2078554f68d3SGreg Clayton           }
2079b9c1b51eSKate Stone         } else {
2080554f68d3SGreg Clayton           parent_entry.AppendChar(desens_char);
2081554f68d3SGreg Clayton         }
2082554f68d3SGreg Clayton         break;
2083554f68d3SGreg Clayton 
2084554f68d3SGreg Clayton       default:
2085554f68d3SGreg Clayton         // Just desensitize any other character by just printing what
2086554f68d3SGreg Clayton         // came after the '\'
2087554f68d3SGreg Clayton         parent_entry.AppendChar(desens_char);
2088554f68d3SGreg Clayton         break;
2089554f68d3SGreg Clayton       }
2090b9c1b51eSKate Stone     } break;
2091554f68d3SGreg Clayton 
2092554f68d3SGreg Clayton     case '$':
2093b9c1b51eSKate Stone       if (format.size() == 1) {
2094554f68d3SGreg Clayton         // '$' at the end of a format string, just print the '$'
2095554f68d3SGreg Clayton         parent_entry.AppendText("$");
2096b9c1b51eSKate Stone       } else {
2097554f68d3SGreg Clayton         format = format.drop_front(); // Skip the '$'
2098554f68d3SGreg Clayton 
2099b9c1b51eSKate Stone         if (format[0] == '{') {
2100554f68d3SGreg Clayton           format = format.drop_front(); // Skip the '{'
2101554f68d3SGreg Clayton 
2102554f68d3SGreg Clayton           llvm::StringRef variable, variable_format;
2103b9c1b51eSKate Stone           error = FormatEntity::ExtractVariableInfo(format, variable,
2104b9c1b51eSKate Stone                                                     variable_format);
2105554f68d3SGreg Clayton           if (error.Fail())
2106554f68d3SGreg Clayton             return error;
2107554f68d3SGreg Clayton           bool verify_is_thread_id = false;
2108554f68d3SGreg Clayton           Entry entry;
2109b9c1b51eSKate Stone           if (!variable_format.empty()) {
21103a29f8b9SPavel Labath             entry.printf_format = variable_format.str();
2111554f68d3SGreg Clayton 
2112554f68d3SGreg Clayton             // If the format contains a '%' we are going to assume this is
2113554f68d3SGreg Clayton             // a printf style format. So if you want to format your thread ID
2114554f68d3SGreg Clayton             // using "0x%llx" you can use:
2115554f68d3SGreg Clayton             // ${thread.id%0x%llx}
2116554f68d3SGreg Clayton             //
2117554f68d3SGreg Clayton             // If there is no '%' in the format, then it is assumed to be a
2118554f68d3SGreg Clayton             // LLDB format name, or one of the extended formats specified in
2119554f68d3SGreg Clayton             // the switch statement below.
2120554f68d3SGreg Clayton 
2121b9c1b51eSKate Stone             if (entry.printf_format.find('%') == std::string::npos) {
2122554f68d3SGreg Clayton               bool clear_printf = false;
2123554f68d3SGreg Clayton 
2124b9c1b51eSKate Stone               if (FormatManager::GetFormatFromCString(
2125b9c1b51eSKate Stone                       entry.printf_format.c_str(), false, entry.fmt)) {
2126554f68d3SGreg Clayton                 // We have an LLDB format, so clear the printf format
2127554f68d3SGreg Clayton                 clear_printf = true;
2128b9c1b51eSKate Stone               } else if (entry.printf_format.size() == 1) {
2129b9c1b51eSKate Stone                 switch (entry.printf_format[0]) {
2130554f68d3SGreg Clayton                 case '@': // if this is an @ sign, print ObjC description
2131b9c1b51eSKate Stone                   entry.number = ValueObject::
2132b9c1b51eSKate Stone                       eValueObjectRepresentationStyleLanguageSpecific;
2133554f68d3SGreg Clayton                   clear_printf = true;
2134554f68d3SGreg Clayton                   break;
2135b9c1b51eSKate Stone                 case 'V': // if this is a V, print the value using the default
2136b9c1b51eSKate Stone                           // format
2137b9c1b51eSKate Stone                   entry.number =
2138b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleValue;
2139554f68d3SGreg Clayton                   clear_printf = true;
2140554f68d3SGreg Clayton                   break;
2141554f68d3SGreg Clayton                 case 'L': // if this is an L, print the location of the value
2142b9c1b51eSKate Stone                   entry.number =
2143b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleLocation;
2144554f68d3SGreg Clayton                   clear_printf = true;
2145554f68d3SGreg Clayton                   break;
2146554f68d3SGreg Clayton                 case 'S': // if this is an S, print the summary after all
2147b9c1b51eSKate Stone                   entry.number =
2148b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleSummary;
2149554f68d3SGreg Clayton                   clear_printf = true;
2150554f68d3SGreg Clayton                   break;
2151554f68d3SGreg Clayton                 case '#': // if this is a '#', print the number of children
2152b9c1b51eSKate Stone                   entry.number =
2153b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleChildrenCount;
2154554f68d3SGreg Clayton                   clear_printf = true;
2155554f68d3SGreg Clayton                   break;
2156554f68d3SGreg Clayton                 case 'T': // if this is a 'T', print the type
2157b9c1b51eSKate Stone                   entry.number =
2158b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleType;
2159554f68d3SGreg Clayton                   clear_printf = true;
2160554f68d3SGreg Clayton                   break;
2161554f68d3SGreg Clayton                 case 'N': // if this is a 'N', print the name
2162b9c1b51eSKate Stone                   entry.number =
2163b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleName;
2164554f68d3SGreg Clayton                   clear_printf = true;
2165554f68d3SGreg Clayton                   break;
2166281b65bcSGreg Clayton                 case '>': // if this is a '>', print the expression path
2167b9c1b51eSKate Stone                   entry.number = ValueObject::
2168b9c1b51eSKate Stone                       eValueObjectRepresentationStyleExpressionPath;
2169554f68d3SGreg Clayton                   clear_printf = true;
2170554f68d3SGreg Clayton                   break;
2171554f68d3SGreg Clayton                 default:
2172b9c1b51eSKate Stone                   error.SetErrorStringWithFormat("invalid format: '%s'",
2173b9c1b51eSKate Stone                                                  entry.printf_format.c_str());
2174554f68d3SGreg Clayton                   return error;
2175554f68d3SGreg Clayton                 }
2176b9c1b51eSKate Stone               } else if (FormatManager::GetFormatFromCString(
2177b9c1b51eSKate Stone                              entry.printf_format.c_str(), true, entry.fmt)) {
2178554f68d3SGreg Clayton                 clear_printf = true;
2179b9c1b51eSKate Stone               } else if (entry.printf_format == "tid") {
2180554f68d3SGreg Clayton                 verify_is_thread_id = true;
2181b9c1b51eSKate Stone               } else {
2182b9c1b51eSKate Stone                 error.SetErrorStringWithFormat("invalid format: '%s'",
2183b9c1b51eSKate Stone                                                entry.printf_format.c_str());
2184554f68d3SGreg Clayton                 return error;
2185554f68d3SGreg Clayton               }
2186554f68d3SGreg Clayton 
2187554f68d3SGreg Clayton               // Our format string turned out to not be a printf style format
2188554f68d3SGreg Clayton               // so lets clear the string
2189554f68d3SGreg Clayton               if (clear_printf)
2190554f68d3SGreg Clayton                 entry.printf_format.clear();
2191554f68d3SGreg Clayton             }
2192554f68d3SGreg Clayton           }
2193554f68d3SGreg Clayton 
2194554f68d3SGreg Clayton           // Check for dereferences
2195b9c1b51eSKate Stone           if (variable[0] == '*') {
2196554f68d3SGreg Clayton             entry.deref = true;
2197554f68d3SGreg Clayton             variable = variable.drop_front();
2198554f68d3SGreg Clayton           }
2199554f68d3SGreg Clayton 
2200554f68d3SGreg Clayton           error = ParseEntry(variable, &g_root, entry);
2201554f68d3SGreg Clayton           if (error.Fail())
2202554f68d3SGreg Clayton             return error;
2203554f68d3SGreg Clayton 
2204b9c1b51eSKate Stone           if (verify_is_thread_id) {
2205554f68d3SGreg Clayton             if (entry.type != Entry::Type::ThreadID &&
2206b9c1b51eSKate Stone                 entry.type != Entry::Type::ThreadProtocolID) {
2207b9c1b51eSKate Stone               error.SetErrorString("the 'tid' format can only be used on "
2208b9c1b51eSKate Stone                                    "${thread.id} and ${thread.protocol_id}");
2209554f68d3SGreg Clayton             }
2210554f68d3SGreg Clayton           }
2211554f68d3SGreg Clayton 
2212b9c1b51eSKate Stone           switch (entry.type) {
2213554f68d3SGreg Clayton           case Entry::Type::Variable:
2214554f68d3SGreg Clayton           case Entry::Type::VariableSynthetic:
2215b9c1b51eSKate Stone             if (entry.number == 0) {
2216554f68d3SGreg Clayton               if (entry.string.empty())
2217b9c1b51eSKate Stone                 entry.number =
2218b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleValue;
2219554f68d3SGreg Clayton               else
2220b9c1b51eSKate Stone                 entry.number =
2221b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleSummary;
2222554f68d3SGreg Clayton             }
2223554f68d3SGreg Clayton             break;
2224554f68d3SGreg Clayton           default:
2225b9c1b51eSKate Stone             // Make sure someone didn't try to dereference anything but ${var}
2226b9c1b51eSKate Stone             // or ${svar}
2227b9c1b51eSKate Stone             if (entry.deref) {
2228b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
2229b9c1b51eSKate Stone                   "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2230b9c1b51eSKate Stone                   variable.str().c_str());
2231554f68d3SGreg Clayton               return error;
2232554f68d3SGreg Clayton             }
2233554f68d3SGreg Clayton           }
2234554f68d3SGreg Clayton           // Check if this entry just wants to insert a constant string
2235554f68d3SGreg Clayton           // value into the parent_entry, if so, insert the string with
2236554f68d3SGreg Clayton           // AppendText, else append the entry to the parent_entry.
2237554f68d3SGreg Clayton           if (entry.type == Entry::Type::InsertString)
2238554f68d3SGreg Clayton             parent_entry.AppendText(entry.string.c_str());
2239554f68d3SGreg Clayton           else
2240554f68d3SGreg Clayton             parent_entry.AppendEntry(std::move(entry));
2241554f68d3SGreg Clayton         }
2242554f68d3SGreg Clayton       }
2243554f68d3SGreg Clayton       break;
2244554f68d3SGreg Clayton     }
2245554f68d3SGreg Clayton   }
2246554f68d3SGreg Clayton   return error;
2247554f68d3SGreg Clayton }
2248554f68d3SGreg Clayton 
2249b9c1b51eSKate Stone Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2250b9c1b51eSKate Stone                                         llvm::StringRef &variable_name,
2251b9c1b51eSKate Stone                                         llvm::StringRef &variable_format) {
2252554f68d3SGreg Clayton   Error error;
2253554f68d3SGreg Clayton   variable_name = llvm::StringRef();
2254554f68d3SGreg Clayton   variable_format = llvm::StringRef();
2255554f68d3SGreg Clayton 
2256e8433cc1SBruce Mitchener   const size_t paren_pos = format_str.find('}');
2257b9c1b51eSKate Stone   if (paren_pos != llvm::StringRef::npos) {
2258e8433cc1SBruce Mitchener     const size_t percent_pos = format_str.find('%');
2259b9c1b51eSKate Stone     if (percent_pos < paren_pos) {
2260b9c1b51eSKate Stone       if (percent_pos > 0) {
2261554f68d3SGreg Clayton         if (percent_pos > 1)
2262554f68d3SGreg Clayton           variable_name = format_str.substr(0, percent_pos);
2263b9c1b51eSKate Stone         variable_format =
2264b9c1b51eSKate Stone             format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2265554f68d3SGreg Clayton       }
2266b9c1b51eSKate Stone     } else {
2267554f68d3SGreg Clayton       variable_name = format_str.substr(0, paren_pos);
2268554f68d3SGreg Clayton     }
2269554f68d3SGreg Clayton     // Strip off elements and the formatting and the trailing '}'
2270554f68d3SGreg Clayton     format_str = format_str.substr(paren_pos + 1);
2271b9c1b51eSKate Stone   } else {
2272b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
2273b9c1b51eSKate Stone         "missing terminating '}' character for '${%s'",
2274b9c1b51eSKate Stone         format_str.str().c_str());
2275554f68d3SGreg Clayton   }
2276554f68d3SGreg Clayton   return error;
2277554f68d3SGreg Clayton }
2278554f68d3SGreg Clayton 
2279b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
2280b9c1b51eSKate Stone                                   llvm::StringRef variable_name,
2281b9c1b51eSKate Stone                                   llvm::StringRef variable_format) {
2282b9c1b51eSKate Stone   if (variable_name.empty() || variable_name.equals(".fullpath")) {
2283554f68d3SGreg Clayton     file_spec.Dump(&s);
2284554f68d3SGreg Clayton     return true;
2285b9c1b51eSKate Stone   } else if (variable_name.equals(".basename")) {
2286554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2287554f68d3SGreg Clayton     return true;
2288b9c1b51eSKate Stone   } else if (variable_name.equals(".dirname")) {
2289554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2290554f68d3SGreg Clayton     return true;
2291554f68d3SGreg Clayton   }
2292554f68d3SGreg Clayton   return false;
2293554f68d3SGreg Clayton }
2294554f68d3SGreg Clayton 
2295b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix,
2296b9c1b51eSKate Stone                              const char *suffix) {
2297554f68d3SGreg Clayton   std::string match(prefix.str());
2298554f68d3SGreg Clayton   match.append(suffix);
22993a29f8b9SPavel Labath   return match;
2300554f68d3SGreg Clayton }
2301554f68d3SGreg Clayton 
2302b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def,
2303554f68d3SGreg Clayton                        const llvm::StringRef &prefix,
2304554f68d3SGreg Clayton                        const llvm::StringRef &match_prefix,
2305b9c1b51eSKate Stone                        StringList &matches) {
2306554f68d3SGreg Clayton   const size_t n = def->num_children;
2307b9c1b51eSKate Stone   if (n > 0) {
2308b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
23093a29f8b9SPavel Labath       std::string match = prefix.str();
2310554f68d3SGreg Clayton       if (match_prefix.empty())
2311554f68d3SGreg Clayton         matches.AppendString(MakeMatch(prefix, def->children[i].name));
2312b9c1b51eSKate Stone       else if (strncmp(def->children[i].name, match_prefix.data(),
2313b9c1b51eSKate Stone                        match_prefix.size()) == 0)
2314b9c1b51eSKate Stone         matches.AppendString(
2315b9c1b51eSKate Stone             MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2316554f68d3SGreg Clayton     }
2317554f68d3SGreg Clayton   }
2318554f68d3SGreg Clayton }
2319a74f37a5SEugene Zelenko 
2320b9c1b51eSKate Stone size_t FormatEntity::AutoComplete(const char *s, int match_start_point,
2321b9c1b51eSKate Stone                                   int max_return_elements, bool &word_complete,
2322b9c1b51eSKate Stone                                   StringList &matches) {
2323554f68d3SGreg Clayton   word_complete = false;
2324554f68d3SGreg Clayton   llvm::StringRef str(s + match_start_point);
2325554f68d3SGreg Clayton   matches.Clear();
2326554f68d3SGreg Clayton 
2327554f68d3SGreg Clayton   const size_t dollar_pos = str.rfind('$');
2328b9c1b51eSKate Stone   if (dollar_pos != llvm::StringRef::npos) {
2329554f68d3SGreg Clayton     // Hitting TAB after $ at the end of the string add a "{"
2330b9c1b51eSKate Stone     if (dollar_pos == str.size() - 1) {
23313a29f8b9SPavel Labath       std::string match = str.str();
2332554f68d3SGreg Clayton       match.append("{");
2333554f68d3SGreg Clayton       matches.AppendString(std::move(match));
2334b9c1b51eSKate Stone     } else if (str[dollar_pos + 1] == '{') {
2335554f68d3SGreg Clayton       const size_t close_pos = str.find('}', dollar_pos + 2);
2336b9c1b51eSKate Stone       if (close_pos == llvm::StringRef::npos) {
2337554f68d3SGreg Clayton         const size_t format_pos = str.find('%', dollar_pos + 2);
2338b9c1b51eSKate Stone         if (format_pos == llvm::StringRef::npos) {
2339554f68d3SGreg Clayton           llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2340b9c1b51eSKate Stone           if (partial_variable.empty()) {
2341554f68d3SGreg Clayton             // Suggest all top level entites as we are just past "${"
2342554f68d3SGreg Clayton             AddMatches(&g_root, str, llvm::StringRef(), matches);
2343b9c1b51eSKate Stone           } else {
2344554f68d3SGreg Clayton             // We have a partially specified variable, find it
2345554f68d3SGreg Clayton             llvm::StringRef remainder;
2346b9c1b51eSKate Stone             const FormatEntity::Entry::Definition *entry_def =
2347b9c1b51eSKate Stone                 FindEntry(partial_variable, &g_root, remainder);
2348b9c1b51eSKate Stone             if (entry_def) {
2349554f68d3SGreg Clayton               const size_t n = entry_def->num_children;
2350554f68d3SGreg Clayton 
2351b9c1b51eSKate Stone               if (remainder.empty()) {
2352554f68d3SGreg Clayton                 // Exact match
2353b9c1b51eSKate Stone                 if (n > 0) {
2354554f68d3SGreg Clayton                   // "${thread.info" <TAB>
23553a29f8b9SPavel Labath                   matches.AppendString(MakeMatch(str, "."));
2356b9c1b51eSKate Stone                 } else {
2357554f68d3SGreg Clayton                   // "${thread.id" <TAB>
23583a29f8b9SPavel Labath                   matches.AppendString(MakeMatch(str, "}"));
2359554f68d3SGreg Clayton                   word_complete = true;
2360554f68d3SGreg Clayton                 }
2361b9c1b51eSKate Stone               } else if (remainder.equals(".")) {
2362554f68d3SGreg Clayton                 // "${thread." <TAB>
2363554f68d3SGreg Clayton                 AddMatches(entry_def, str, llvm::StringRef(), matches);
2364b9c1b51eSKate Stone               } else {
2365554f68d3SGreg Clayton                 // We have a partial match
2366554f68d3SGreg Clayton                 // "${thre" <TAB>
2367554f68d3SGreg Clayton                 AddMatches(entry_def, str, remainder, matches);
2368554f68d3SGreg Clayton               }
2369554f68d3SGreg Clayton             }
2370554f68d3SGreg Clayton           }
2371554f68d3SGreg Clayton         }
2372554f68d3SGreg Clayton       }
2373554f68d3SGreg Clayton     }
2374554f68d3SGreg Clayton   }
2375554f68d3SGreg Clayton   return matches.GetSize();
2376554f68d3SGreg Clayton }
2377