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/ValueObject.h"
23554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h"
24554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h"
25554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h"
26ad91c7ceSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h"
27937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h"
28554f68d3SGreg Clayton #include "lldb/Host/FileSpec.h"
29554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
30554f68d3SGreg Clayton #include "lldb/Symbol/Block.h"
31554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
32554f68d3SGreg Clayton #include "lldb/Symbol/Function.h"
33554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h"
34554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h"
35554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h"
36554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h"
370e0984eeSJim Ingham #include "lldb/Target/Language.h"
38554f68d3SGreg Clayton #include "lldb/Target/Process.h"
39554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h"
40554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h"
41554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h"
42554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h"
43554f68d3SGreg Clayton #include "lldb/Target/Target.h"
44554f68d3SGreg Clayton #include "lldb/Target/Thread.h"
45554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
46bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
47bf9a7730SZachary Turner #include "lldb/Utility/StreamString.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,                                  \
67*e28558f0SZachary Turner         FormatEntity::Entry::FormatType::f, 0,                                 \
68*e28558f0SZachary Turner         static_cast<uint32_t>(llvm::array_lengthof(c)), c, false               \
69b9c1b51eSKate Stone   }
70b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c)                                    \
71b9c1b51eSKate Stone   {                                                                            \
72b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
73*e28558f0SZachary Turner         FormatEntity::Entry::FormatType::f, 0,                                 \
74*e28558f0SZachary Turner         static_cast<uint32_t>(llvm::array_lengthof(c)), c, 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),
1006a9767c7SJim Ingham     ENTRY("no-debug", FrameNoDebug, None),
101554f68d3SGreg Clayton     ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry),
102554f68d3SGreg Clayton };
103554f68d3SGreg Clayton 
104b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = {
105b9c1b51eSKate Stone     ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString),
106554f68d3SGreg Clayton     ENTRY("name-without-args", FunctionNameNoArgs, CString),
107554f68d3SGreg Clayton     ENTRY("name-with-args", FunctionNameWithArgs, CString),
108554f68d3SGreg Clayton     ENTRY("addr-offset", FunctionAddrOffset, UInt64),
109b9c1b51eSKate Stone     ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete,
110b9c1b51eSKate Stone           UInt64),
111554f68d3SGreg Clayton     ENTRY("line-offset", FunctionLineOffset, UInt64),
112c980fa92SJason Molenda     ENTRY("pc-offset", FunctionPCOffset, UInt64),
113c980fa92SJason Molenda     ENTRY("initial-function", FunctionInitial, None),
1146ab659a9SJason Molenda     ENTRY("changed", FunctionChanged, None),
115b9c1b51eSKate Stone     ENTRY("is-optimized", FunctionIsOptimized, None)};
116554f68d3SGreg Clayton 
117b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = {
118554f68d3SGreg Clayton     ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries),
119554f68d3SGreg Clayton     ENTRY("number", LineEntryLineNumber, UInt32),
120554f68d3SGreg Clayton     ENTRY("start-addr", LineEntryStartAddress, UInt64),
121554f68d3SGreg Clayton     ENTRY("end-addr", LineEntryEndAddress, UInt64),
122554f68d3SGreg Clayton };
123554f68d3SGreg Clayton 
124b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = {
125554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
126554f68d3SGreg Clayton };
127554f68d3SGreg Clayton 
128b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = {
129554f68d3SGreg Clayton     ENTRY("id", ProcessID, UInt64),
130554f68d3SGreg Clayton     ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename),
131554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries),
132554f68d3SGreg Clayton };
133554f68d3SGreg Clayton 
134b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = {
135b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
136554f68d3SGreg Clayton 
137b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = {
138b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
139554f68d3SGreg Clayton 
140b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = {
141554f68d3SGreg Clayton     ENTRY("id", ThreadID, UInt64),
142554f68d3SGreg Clayton     ENTRY("protocol_id", ThreadProtocolID, UInt64),
143554f68d3SGreg Clayton     ENTRY("index", ThreadIndexID, UInt32),
144554f68d3SGreg Clayton     ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry),
145554f68d3SGreg Clayton     ENTRY("queue", ThreadQueue, CString),
146554f68d3SGreg Clayton     ENTRY("name", ThreadName, CString),
147554f68d3SGreg Clayton     ENTRY("stop-reason", ThreadStopReason, CString),
148554f68d3SGreg Clayton     ENTRY("return-value", ThreadReturnValue, CString),
149554f68d3SGreg Clayton     ENTRY("completed-expression", ThreadCompletedExpression, CString),
150554f68d3SGreg Clayton };
151554f68d3SGreg Clayton 
152b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = {
153554f68d3SGreg Clayton     ENTRY("arch", TargetArch, CString),
154554f68d3SGreg Clayton };
155554f68d3SGreg Clayton 
156554f68d3SGreg Clayton #define _TO_STR2(_val) #_val
157554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val)
158554f68d3SGreg Clayton 
159b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
160b9c1b51eSKate Stone     ENTRY_STRING("black",
161b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
162554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
163b9c1b51eSKate Stone     ENTRY_STRING("green",
164b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
165b9c1b51eSKate Stone     ENTRY_STRING("yellow",
166b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
167b9c1b51eSKate Stone     ENTRY_STRING("blue",
168b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
169b9c1b51eSKate Stone     ENTRY_STRING("purple",
170b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
171b9c1b51eSKate Stone     ENTRY_STRING("cyan",
172b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
173b9c1b51eSKate Stone     ENTRY_STRING("white",
174b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
175554f68d3SGreg Clayton };
176554f68d3SGreg Clayton 
177b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
178b9c1b51eSKate Stone     ENTRY_STRING("black",
179b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
180554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
181b9c1b51eSKate Stone     ENTRY_STRING("green",
182b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
183b9c1b51eSKate Stone     ENTRY_STRING("yellow",
184b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
185b9c1b51eSKate Stone     ENTRY_STRING("blue",
186b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
187b9c1b51eSKate Stone     ENTRY_STRING("purple",
188b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
189b9c1b51eSKate Stone     ENTRY_STRING("cyan",
190b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
191b9c1b51eSKate Stone     ENTRY_STRING("white",
192b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
193554f68d3SGreg Clayton };
194554f68d3SGreg Clayton 
195b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = {
196554f68d3SGreg Clayton     ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries),
197554f68d3SGreg Clayton     ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries),
198b9c1b51eSKate Stone     ENTRY_STRING("normal",
199b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
200554f68d3SGreg Clayton     ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
201554f68d3SGreg Clayton     ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
202b9c1b51eSKate Stone     ENTRY_STRING("italic",
203b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
204b9c1b51eSKate Stone     ENTRY_STRING("underline",
205b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
206b9c1b51eSKate Stone     ENTRY_STRING("slow-blink",
207b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
208b9c1b51eSKate Stone     ENTRY_STRING("fast-blink",
209b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
210b9c1b51eSKate Stone     ENTRY_STRING("negative",
211b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
212b9c1b51eSKate Stone     ENTRY_STRING("conceal",
213b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
214b9c1b51eSKate Stone     ENTRY_STRING("crossed-out",
215b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
216554f68d3SGreg Clayton };
217554f68d3SGreg Clayton 
218b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = {
219554f68d3SGreg Clayton     ENTRY("frame", ScriptFrame, None),
220554f68d3SGreg Clayton     ENTRY("process", ScriptProcess, None),
221554f68d3SGreg Clayton     ENTRY("target", ScriptTarget, None),
222554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
223554f68d3SGreg Clayton     ENTRY("var", ScriptVariable, None),
224554f68d3SGreg Clayton     ENTRY("svar", ScriptVariableSynthetic, None),
225554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
226554f68d3SGreg Clayton };
227554f68d3SGreg Clayton 
228b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = {
229554f68d3SGreg Clayton     ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries),
230554f68d3SGreg Clayton     ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64),
231554f68d3SGreg Clayton     ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries),
232554f68d3SGreg Clayton     ENTRY("current-pc-arrow", CurrentPCArrow, CString),
233554f68d3SGreg Clayton     ENTRY_CHILDREN("file", File, CString, g_file_child_entries),
234dc975670SDawn Perchik     ENTRY("language", Lang, CString),
235554f68d3SGreg Clayton     ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries),
236554f68d3SGreg Clayton     ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries),
237554f68d3SGreg Clayton     ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries),
238554f68d3SGreg Clayton     ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries),
239554f68d3SGreg Clayton     ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries),
240554f68d3SGreg Clayton     ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries),
241b9c1b51eSKate Stone     ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None,
242b9c1b51eSKate Stone                             g_svar_child_entries),
243554f68d3SGreg Clayton     ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries),
244554f68d3SGreg Clayton     ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries),
245554f68d3SGreg Clayton     ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries),
246554f68d3SGreg Clayton };
247554f68d3SGreg Clayton 
248b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root =
249b9c1b51eSKate Stone     ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries);
250554f68d3SGreg Clayton 
251b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s)
252b9c1b51eSKate Stone     : string(s.data(), s.size()), printf_format(), children(),
253b9c1b51eSKate Stone       definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
254b9c1b51eSKate Stone       number(0), deref(false) {}
255554f68d3SGreg Clayton 
256b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch)
257b9c1b51eSKate Stone     : string(1, ch), printf_format(), children(), definition(nullptr),
258b9c1b51eSKate Stone       type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
259554f68d3SGreg Clayton 
260b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) {
261554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
262554f68d3SGreg Clayton     children.push_back(Entry(ch));
263554f68d3SGreg Clayton   else
264554f68d3SGreg Clayton     children.back().string.append(1, ch);
265554f68d3SGreg Clayton }
266554f68d3SGreg Clayton 
267b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
268554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
269554f68d3SGreg Clayton     children.push_back(Entry(s));
270554f68d3SGreg Clayton   else
271554f68d3SGreg Clayton     children.back().string.append(s.data(), s.size());
272554f68d3SGreg Clayton }
273554f68d3SGreg Clayton 
274b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) {
275554f68d3SGreg Clayton   return AppendText(llvm::StringRef(cstr));
276554f68d3SGreg Clayton }
277554f68d3SGreg Clayton 
278b9c1b51eSKate Stone Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
279554f68d3SGreg Clayton   entry.Clear();
280554f68d3SGreg Clayton   entry.type = Entry::Type::Root;
281554f68d3SGreg Clayton   llvm::StringRef modifiable_format(format_str);
282554f68d3SGreg Clayton   return ParseInternal(modifiable_format, entry, 0);
283554f68d3SGreg Clayton }
284554f68d3SGreg Clayton 
285b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee)                                                      \
286b9c1b51eSKate Stone   case FormatEntity::Entry::Type::eee:                                         \
287b9c1b51eSKate Stone     return #eee
288554f68d3SGreg Clayton 
289b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) {
290b9c1b51eSKate Stone   switch (t) {
291554f68d3SGreg Clayton     ENUM_TO_CSTR(Invalid);
292554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentNumber);
293554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentString);
294554f68d3SGreg Clayton     ENUM_TO_CSTR(InsertString);
295554f68d3SGreg Clayton     ENUM_TO_CSTR(Root);
296554f68d3SGreg Clayton     ENUM_TO_CSTR(String);
297554f68d3SGreg Clayton     ENUM_TO_CSTR(Scope);
298554f68d3SGreg Clayton     ENUM_TO_CSTR(Variable);
299554f68d3SGreg Clayton     ENUM_TO_CSTR(VariableSynthetic);
300554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariable);
301554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariableSynthetic);
302554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoad);
303554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressFile);
304554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoadOrFile);
305554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessID);
306554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessFile);
307554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptProcess);
308554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadID);
309554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadProtocolID);
310554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadIndexID);
311554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadName);
312554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadQueue);
313554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadStopReason);
314554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadReturnValue);
315554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadCompletedExpression);
316554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptThread);
317554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadInfo);
318554f68d3SGreg Clayton     ENUM_TO_CSTR(TargetArch);
319554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptTarget);
320554f68d3SGreg Clayton     ENUM_TO_CSTR(ModuleFile);
321554f68d3SGreg Clayton     ENUM_TO_CSTR(File);
322dc975670SDawn Perchik     ENUM_TO_CSTR(Lang);
323554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameIndex);
3246a9767c7SJim Ingham     ENUM_TO_CSTR(FrameNoDebug);
325554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterPC);
326554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterSP);
327554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFP);
328554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFlags);
329554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterByName);
330554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptFrame);
331554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionID);
332554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionDidChange);
333554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionInitialFunction);
334554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionName);
335554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameWithArgs);
336554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameNoArgs);
337554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffset);
338554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
339554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionLineOffset);
340554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionPCOffset);
341c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionInitial);
342c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionChanged);
3436ab659a9SJason Molenda     ENUM_TO_CSTR(FunctionIsOptimized);
344554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryFile);
345554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryLineNumber);
346554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryStartAddress);
347554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryEndAddress);
348554f68d3SGreg Clayton     ENUM_TO_CSTR(CurrentPCArrow);
349554f68d3SGreg Clayton   }
350554f68d3SGreg Clayton   return "???";
351554f68d3SGreg Clayton }
352554f68d3SGreg Clayton 
353554f68d3SGreg Clayton #undef ENUM_TO_CSTR
354554f68d3SGreg Clayton 
355b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const {
356554f68d3SGreg Clayton   s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
357554f68d3SGreg Clayton   if (fmt != eFormatDefault)
358554f68d3SGreg Clayton     s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
359554f68d3SGreg Clayton   if (!string.empty())
360554f68d3SGreg Clayton     s.Printf("string = \"%s\"", string.c_str());
361554f68d3SGreg Clayton   if (!printf_format.empty())
362554f68d3SGreg Clayton     s.Printf("printf_format = \"%s\"", printf_format.c_str());
363554f68d3SGreg Clayton   if (number != 0)
364554f68d3SGreg Clayton     s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
365554f68d3SGreg Clayton   if (deref)
366554f68d3SGreg Clayton     s.Printf("deref = true, ");
367554f68d3SGreg Clayton   s.EOL();
368b9c1b51eSKate Stone   for (const auto &child : children) {
369554f68d3SGreg Clayton     child.Dump(s, depth + 1);
370554f68d3SGreg Clayton   }
371554f68d3SGreg Clayton }
372554f68d3SGreg Clayton 
373554f68d3SGreg Clayton template <typename T>
374b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
375b9c1b51eSKate Stone                                    const ExecutionContext *exe_ctx, T t,
376b9c1b51eSKate Stone                                    const char *script_function_name) {
377554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
378554f68d3SGreg Clayton 
379b9c1b51eSKate Stone   if (target) {
380b9c1b51eSKate Stone     ScriptInterpreter *script_interpreter =
381b9c1b51eSKate Stone         target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
382b9c1b51eSKate Stone     if (script_interpreter) {
383554f68d3SGreg Clayton       Error error;
384554f68d3SGreg Clayton       std::string script_output;
385554f68d3SGreg Clayton 
386b9c1b51eSKate Stone       if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
387b9c1b51eSKate Stone                                                      script_output, error) &&
388b9c1b51eSKate Stone           error.Success()) {
389554f68d3SGreg Clayton         s.Printf("%s", script_output.c_str());
390554f68d3SGreg Clayton         return true;
391b9c1b51eSKate Stone       } else {
392554f68d3SGreg Clayton         s.Printf("<error: %s>", error.AsCString());
393554f68d3SGreg Clayton       }
394554f68d3SGreg Clayton     }
395554f68d3SGreg Clayton   }
396554f68d3SGreg Clayton   return false;
397554f68d3SGreg Clayton }
398554f68d3SGreg Clayton 
399b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc,
400b9c1b51eSKate Stone                         const ExecutionContext *exe_ctx, const Address &addr,
401b9c1b51eSKate Stone                         bool print_file_addr_or_load_addr) {
402554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
403554f68d3SGreg Clayton   addr_t vaddr = LLDB_INVALID_ADDRESS;
404554f68d3SGreg Clayton   if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
405554f68d3SGreg Clayton     vaddr = addr.GetLoadAddress(target);
406554f68d3SGreg Clayton   if (vaddr == LLDB_INVALID_ADDRESS)
407554f68d3SGreg Clayton     vaddr = addr.GetFileAddress();
408554f68d3SGreg Clayton 
409b9c1b51eSKate Stone   if (vaddr != LLDB_INVALID_ADDRESS) {
410554f68d3SGreg Clayton     int addr_width = 0;
411b9c1b51eSKate Stone     if (exe_ctx && target) {
412554f68d3SGreg Clayton       addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
413554f68d3SGreg Clayton     }
414554f68d3SGreg Clayton     if (addr_width == 0)
415554f68d3SGreg Clayton       addr_width = 16;
416b9c1b51eSKate Stone     if (print_file_addr_or_load_addr) {
417a74f37a5SEugene Zelenko       ExecutionContextScope *exe_scope = nullptr;
418554f68d3SGreg Clayton       if (exe_ctx)
419554f68d3SGreg Clayton         exe_scope = exe_ctx->GetBestExecutionContextScope();
420b9c1b51eSKate Stone       addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
421b9c1b51eSKate Stone                 Address::DumpStyleModuleWithFileAddress, 0);
422b9c1b51eSKate Stone     } else {
423554f68d3SGreg Clayton       s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
424554f68d3SGreg Clayton     }
425554f68d3SGreg Clayton     return true;
426554f68d3SGreg Clayton   }
427554f68d3SGreg Clayton   return false;
428554f68d3SGreg Clayton }
429554f68d3SGreg Clayton 
430b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
431554f68d3SGreg Clayton                                           const ExecutionContext *exe_ctx,
432554f68d3SGreg Clayton                                           const Address &format_addr,
433b9c1b51eSKate Stone                                           bool concrete_only, bool no_padding,
434b9c1b51eSKate Stone                                           bool print_zero_offsets) {
435b9c1b51eSKate Stone   if (format_addr.IsValid()) {
436554f68d3SGreg Clayton     Address func_addr;
437554f68d3SGreg Clayton 
438b9c1b51eSKate Stone     if (sc) {
439b9c1b51eSKate Stone       if (sc->function) {
440554f68d3SGreg Clayton         func_addr = sc->function->GetAddressRange().GetBaseAddress();
441b9c1b51eSKate Stone         if (sc->block && !concrete_only) {
442554f68d3SGreg Clayton           // Check to make sure we aren't in an inline
443554f68d3SGreg Clayton           // function. If we are, use the inline block
444554f68d3SGreg Clayton           // range that contains "format_addr" since
445554f68d3SGreg Clayton           // blocks can be discontiguous.
446554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
447554f68d3SGreg Clayton           AddressRange inline_range;
448b9c1b51eSKate Stone           if (inline_block &&
449b9c1b51eSKate Stone               inline_block->GetRangeContainingAddress(format_addr,
450b9c1b51eSKate Stone                                                       inline_range))
451554f68d3SGreg Clayton             func_addr = inline_range.GetBaseAddress();
452554f68d3SGreg Clayton         }
453b9c1b51eSKate Stone       } else if (sc->symbol && sc->symbol->ValueIsAddress())
454358cf1eaSGreg Clayton         func_addr = sc->symbol->GetAddressRef();
455554f68d3SGreg Clayton     }
456554f68d3SGreg Clayton 
457b9c1b51eSKate Stone     if (func_addr.IsValid()) {
458554f68d3SGreg Clayton       const char *addr_offset_padding = no_padding ? "" : " ";
459554f68d3SGreg Clayton 
460b9c1b51eSKate Stone       if (func_addr.GetSection() == format_addr.GetSection()) {
461554f68d3SGreg Clayton         addr_t func_file_addr = func_addr.GetFileAddress();
462554f68d3SGreg Clayton         addr_t addr_file_addr = format_addr.GetFileAddress();
463b9c1b51eSKate Stone         if (addr_file_addr > func_file_addr ||
464b9c1b51eSKate Stone             (addr_file_addr == func_file_addr && print_zero_offsets)) {
465b9c1b51eSKate Stone           s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
466b9c1b51eSKate Stone                    addr_file_addr - func_file_addr);
467b9c1b51eSKate Stone         } else if (addr_file_addr < func_file_addr) {
468b9c1b51eSKate Stone           s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
469b9c1b51eSKate Stone                    func_file_addr - addr_file_addr);
470c980fa92SJason Molenda         }
471554f68d3SGreg Clayton         return true;
472b9c1b51eSKate Stone       } else {
473554f68d3SGreg Clayton         Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
474b9c1b51eSKate Stone         if (target) {
475554f68d3SGreg Clayton           addr_t func_load_addr = func_addr.GetLoadAddress(target);
476554f68d3SGreg Clayton           addr_t addr_load_addr = format_addr.GetLoadAddress(target);
477b9c1b51eSKate Stone           if (addr_load_addr > func_load_addr ||
478b9c1b51eSKate Stone               (addr_load_addr == func_load_addr && print_zero_offsets)) {
479b9c1b51eSKate Stone             s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
480b9c1b51eSKate Stone                      addr_load_addr - func_load_addr);
481b9c1b51eSKate Stone           } else if (addr_load_addr < func_load_addr) {
482b9c1b51eSKate Stone             s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
483b9c1b51eSKate Stone                      func_load_addr - addr_load_addr);
484c980fa92SJason Molenda           }
485554f68d3SGreg Clayton           return true;
486554f68d3SGreg Clayton         }
487554f68d3SGreg Clayton       }
488554f68d3SGreg Clayton     }
489554f68d3SGreg Clayton   }
490554f68d3SGreg Clayton   return false;
491554f68d3SGreg Clayton }
492554f68d3SGreg Clayton 
493b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath,
494554f68d3SGreg Clayton                                size_t &close_bracket_index,
495554f68d3SGreg Clayton                                const char *&var_name_final_if_array_range,
496b9c1b51eSKate Stone                                int64_t &index_lower, int64_t &index_higher) {
4974edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
498554f68d3SGreg Clayton   close_bracket_index = llvm::StringRef::npos;
499554f68d3SGreg Clayton   const size_t open_bracket_index = subpath.find('[');
500b9c1b51eSKate Stone   if (open_bracket_index == llvm::StringRef::npos) {
501554f68d3SGreg Clayton     if (log)
502554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
503554f68d3SGreg Clayton     return false;
504554f68d3SGreg Clayton   }
505554f68d3SGreg Clayton 
506554f68d3SGreg Clayton   close_bracket_index = subpath.find(']', open_bracket_index + 1);
507554f68d3SGreg Clayton 
508b9c1b51eSKate Stone   if (close_bracket_index == llvm::StringRef::npos) {
509554f68d3SGreg Clayton     if (log)
510554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
511554f68d3SGreg Clayton     return false;
512b9c1b51eSKate Stone   } else {
513554f68d3SGreg Clayton     var_name_final_if_array_range = subpath.data() + open_bracket_index;
514554f68d3SGreg Clayton 
515b9c1b51eSKate Stone     if (close_bracket_index - open_bracket_index == 1) {
516554f68d3SGreg Clayton       if (log)
517b9c1b51eSKate Stone         log->Printf(
518b9c1b51eSKate Stone             "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
519554f68d3SGreg Clayton       index_lower = 0;
520b9c1b51eSKate Stone     } else {
521554f68d3SGreg Clayton       const size_t separator_index = subpath.find('-', open_bracket_index + 1);
522554f68d3SGreg Clayton 
523b9c1b51eSKate Stone       if (separator_index == llvm::StringRef::npos) {
524554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
525a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
526554f68d3SGreg Clayton         index_higher = index_lower;
527554f68d3SGreg Clayton         if (log)
528b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64
529b9c1b51eSKate Stone                       "] detected, high index is same",
530b9c1b51eSKate Stone                       index_lower);
531b9c1b51eSKate Stone       } else {
532554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
533554f68d3SGreg Clayton         const char *index_higher_cstr = subpath.data() + separator_index + 1;
534a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
535a74f37a5SEugene Zelenko         index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
536554f68d3SGreg Clayton         if (log)
537b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
538b9c1b51eSKate Stone                       index_lower, index_higher);
539554f68d3SGreg Clayton       }
540b9c1b51eSKate Stone       if (index_lower > index_higher && index_higher > 0) {
541554f68d3SGreg Clayton         if (log)
542554f68d3SGreg Clayton           log->Printf("[ScanBracketedRange] swapping indices");
543554f68d3SGreg Clayton         const int64_t temp = index_lower;
544554f68d3SGreg Clayton         index_lower = index_higher;
545554f68d3SGreg Clayton         index_higher = temp;
546554f68d3SGreg Clayton       }
547554f68d3SGreg Clayton     }
548554f68d3SGreg Clayton   }
549554f68d3SGreg Clayton   return true;
550554f68d3SGreg Clayton }
551554f68d3SGreg Clayton 
552b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
553b9c1b51eSKate Stone   switch (file_kind) {
554554f68d3SGreg Clayton   case FileKind::FileError:
555554f68d3SGreg Clayton     break;
556554f68d3SGreg Clayton 
557554f68d3SGreg Clayton   case FileKind::Basename:
558b9c1b51eSKate Stone     if (file.GetFilename()) {
559554f68d3SGreg Clayton       s << file.GetFilename();
560554f68d3SGreg Clayton       return true;
561554f68d3SGreg Clayton     }
562554f68d3SGreg Clayton     break;
563554f68d3SGreg Clayton 
564554f68d3SGreg Clayton   case FileKind::Dirname:
565b9c1b51eSKate Stone     if (file.GetDirectory()) {
566554f68d3SGreg Clayton       s << file.GetDirectory();
567554f68d3SGreg Clayton       return true;
568554f68d3SGreg Clayton     }
569554f68d3SGreg Clayton     break;
570554f68d3SGreg Clayton 
571554f68d3SGreg Clayton   case FileKind::Fullpath:
572b9c1b51eSKate Stone     if (file) {
573554f68d3SGreg Clayton       s << file;
574554f68d3SGreg Clayton       return true;
575554f68d3SGreg Clayton     }
576554f68d3SGreg Clayton     break;
577554f68d3SGreg Clayton   }
578554f68d3SGreg Clayton   return false;
579554f68d3SGreg Clayton }
580554f68d3SGreg Clayton 
581b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
582b9c1b51eSKate Stone                          uint32_t reg_num, Format format)
583554f68d3SGreg Clayton 
584554f68d3SGreg Clayton {
585b9c1b51eSKate Stone   if (frame) {
586554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
587554f68d3SGreg Clayton 
588b9c1b51eSKate Stone     if (reg_ctx) {
589b9c1b51eSKate Stone       const uint32_t lldb_reg_num =
590b9c1b51eSKate Stone           reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
591b9c1b51eSKate Stone       if (lldb_reg_num != LLDB_INVALID_REGNUM) {
592b9c1b51eSKate Stone         const RegisterInfo *reg_info =
593b9c1b51eSKate Stone             reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
594b9c1b51eSKate Stone         if (reg_info) {
595554f68d3SGreg Clayton           RegisterValue reg_value;
596b9c1b51eSKate Stone           if (reg_ctx->ReadRegister(reg_info, reg_value)) {
597554f68d3SGreg Clayton             reg_value.Dump(&s, reg_info, false, false, format);
598554f68d3SGreg Clayton             return true;
599554f68d3SGreg Clayton           }
600554f68d3SGreg Clayton         }
601554f68d3SGreg Clayton       }
602554f68d3SGreg Clayton     }
603554f68d3SGreg Clayton   }
604554f68d3SGreg Clayton   return false;
605554f68d3SGreg Clayton }
606554f68d3SGreg Clayton 
607b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
608554f68d3SGreg Clayton                                              StackFrame *frame,
609b9c1b51eSKate Stone                                              bool deref_pointer) {
6104edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
611554f68d3SGreg Clayton   const char *ptr_deref_format = "[%d]";
612554f68d3SGreg Clayton   std::string ptr_deref_buffer(10, 0);
613554f68d3SGreg Clayton   ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
614554f68d3SGreg Clayton   if (log)
615b9c1b51eSKate Stone     log->Printf("[ExpandIndexedExpression] name to deref: %s",
616b9c1b51eSKate Stone                 ptr_deref_buffer.c_str());
617554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
618554f68d3SGreg Clayton   ValueObject::ExpressionPathEndResultType final_value_type;
619554f68d3SGreg Clayton   ValueObject::ExpressionPathScanEndReason reason_to_stop;
620b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
621b9c1b51eSKate Stone       (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
622b9c1b51eSKate Stone                      : ValueObject::eExpressionPathAftermathNothing);
623b9c1b51eSKate Stone   ValueObjectSP item = valobj->GetValueForExpressionPath(
624d2daca77SZachary Turner       ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options,
625d2daca77SZachary Turner       &what_next);
626b9c1b51eSKate Stone   if (!item) {
627554f68d3SGreg Clayton     if (log)
628d2daca77SZachary Turner       log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d,"
629554f68d3SGreg Clayton                   " final_value_type %d",
630d2daca77SZachary Turner                   reason_to_stop, final_value_type);
631b9c1b51eSKate Stone   } else {
632554f68d3SGreg Clayton     if (log)
633d2daca77SZachary Turner       log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
634554f68d3SGreg Clayton                   " final_value_type %d",
635d2daca77SZachary Turner                   reason_to_stop, final_value_type);
636554f68d3SGreg Clayton   }
637554f68d3SGreg Clayton   return item;
638554f68d3SGreg Clayton }
639554f68d3SGreg Clayton 
640b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar(
641b9c1b51eSKate Stone     ValueObject::ValueObjectRepresentationStyle style) {
642b9c1b51eSKate Stone   switch (style) {
643b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
644b9c1b51eSKate Stone     return '@';
645b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleValue:
646b9c1b51eSKate Stone     return 'V';
647b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLocation:
648b9c1b51eSKate Stone     return 'L';
649b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleSummary:
650b9c1b51eSKate Stone     return 'S';
651b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleChildrenCount:
652b9c1b51eSKate Stone     return '#';
653b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleType:
654b9c1b51eSKate Stone     return 'T';
655b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleName:
656b9c1b51eSKate Stone     return 'N';
657b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleExpressionPath:
658b9c1b51eSKate Stone     return '>';
659554f68d3SGreg Clayton   }
660554f68d3SGreg Clayton   return '\0';
661554f68d3SGreg Clayton }
662554f68d3SGreg Clayton 
663b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc,
664554f68d3SGreg Clayton                       const ExecutionContext *exe_ctx,
665b9c1b51eSKate Stone                       const FormatEntity::Entry &entry, ValueObject *valobj) {
666a74f37a5SEugene Zelenko   if (valobj == nullptr)
667554f68d3SGreg Clayton     return false;
668554f68d3SGreg Clayton 
6694edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
670554f68d3SGreg Clayton   Format custom_format = eFormatInvalid;
671b9c1b51eSKate Stone   ValueObject::ValueObjectRepresentationStyle val_obj_display =
672b9c1b51eSKate Stone       entry.string.empty()
673b9c1b51eSKate Stone           ? ValueObject::eValueObjectRepresentationStyleValue
674b9c1b51eSKate Stone           : ValueObject::eValueObjectRepresentationStyleSummary;
675554f68d3SGreg Clayton 
676554f68d3SGreg Clayton   bool do_deref_pointer = entry.deref;
677554f68d3SGreg Clayton   bool is_script = false;
678b9c1b51eSKate Stone   switch (entry.type) {
679554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariable:
680554f68d3SGreg Clayton     is_script = true;
681554f68d3SGreg Clayton     break;
682554f68d3SGreg Clayton 
683554f68d3SGreg Clayton   case FormatEntity::Entry::Type::Variable:
684554f68d3SGreg Clayton     custom_format = entry.fmt;
685554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
686554f68d3SGreg Clayton     break;
687554f68d3SGreg Clayton 
688554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariableSynthetic:
689554f68d3SGreg Clayton     is_script = true;
69062e0681aSJason Molenda     LLVM_FALLTHROUGH;
691554f68d3SGreg Clayton   case FormatEntity::Entry::Type::VariableSynthetic:
692554f68d3SGreg Clayton     custom_format = entry.fmt;
693554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
694b9c1b51eSKate Stone     if (!valobj->IsSynthetic()) {
695554f68d3SGreg Clayton       valobj = valobj->GetSyntheticValue().get();
696554f68d3SGreg Clayton       if (valobj == nullptr)
697554f68d3SGreg Clayton         return false;
698554f68d3SGreg Clayton     }
699554f68d3SGreg Clayton     break;
700554f68d3SGreg Clayton 
701554f68d3SGreg Clayton   default:
702554f68d3SGreg Clayton     return false;
703554f68d3SGreg Clayton   }
704554f68d3SGreg Clayton 
705a74f37a5SEugene Zelenko   if (valobj == nullptr)
706554f68d3SGreg Clayton     return false;
707554f68d3SGreg Clayton 
708b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
709b9c1b51eSKate Stone       (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
710b9c1b51eSKate Stone                         : ValueObject::eExpressionPathAftermathNothing);
711554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
712b9c1b51eSKate Stone   options.DontCheckDotVsArrowSyntax()
713b9c1b51eSKate Stone       .DoAllowBitfieldSyntax()
714b9c1b51eSKate Stone       .DoAllowFragileIVar()
715b9c1b51eSKate Stone       .SetSyntheticChildrenTraversal(
716b9c1b51eSKate Stone           ValueObject::GetValueForExpressionPathOptions::
717b9c1b51eSKate Stone               SyntheticChildrenTraversal::Both);
718a74f37a5SEugene Zelenko   ValueObject *target = nullptr;
719a74f37a5SEugene Zelenko   const char *var_name_final_if_array_range = nullptr;
720554f68d3SGreg Clayton   size_t close_bracket_index = llvm::StringRef::npos;
721554f68d3SGreg Clayton   int64_t index_lower = -1;
722554f68d3SGreg Clayton   int64_t index_higher = -1;
723554f68d3SGreg Clayton   bool is_array_range = false;
724554f68d3SGreg Clayton   bool was_plain_var = false;
725554f68d3SGreg Clayton   bool was_var_format = false;
726554f68d3SGreg Clayton   bool was_var_indexed = false;
727b9c1b51eSKate Stone   ValueObject::ExpressionPathScanEndReason reason_to_stop =
728b9c1b51eSKate Stone       ValueObject::eExpressionPathScanEndReasonEndOfString;
729b9c1b51eSKate Stone   ValueObject::ExpressionPathEndResultType final_value_type =
730b9c1b51eSKate Stone       ValueObject::eExpressionPathEndResultTypePlain;
731554f68d3SGreg Clayton 
732b9c1b51eSKate Stone   if (is_script) {
733554f68d3SGreg Clayton     return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
734554f68d3SGreg Clayton   }
735554f68d3SGreg Clayton 
736554f68d3SGreg Clayton   llvm::StringRef subpath(entry.string);
737554f68d3SGreg Clayton   // simplest case ${var}, just print valobj's value
738b9c1b51eSKate Stone   if (entry.string.empty()) {
739b9c1b51eSKate Stone     if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
740b9c1b51eSKate Stone         entry.number == ValueObject::eValueObjectRepresentationStyleValue)
741554f68d3SGreg Clayton       was_plain_var = true;
742554f68d3SGreg Clayton     else
743554f68d3SGreg Clayton       was_var_format = true;
744554f68d3SGreg Clayton     target = valobj;
745b9c1b51eSKate Stone   } else // this is ${var.something} or multiple .something nested
746554f68d3SGreg Clayton   {
747554f68d3SGreg Clayton     if (entry.string[0] == '[')
748554f68d3SGreg Clayton       was_var_indexed = true;
749b9c1b51eSKate Stone     ScanBracketedRange(subpath, close_bracket_index,
750b9c1b51eSKate Stone                        var_name_final_if_array_range, index_lower,
751554f68d3SGreg Clayton                        index_higher);
752554f68d3SGreg Clayton 
753554f68d3SGreg Clayton     Error error;
754554f68d3SGreg Clayton 
755554f68d3SGreg Clayton     const std::string &expr_path = entry.string;
756554f68d3SGreg Clayton 
757554f68d3SGreg Clayton     if (log)
758b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",
759b9c1b51eSKate Stone                   expr_path.c_str());
760554f68d3SGreg Clayton 
761d2daca77SZachary Turner     target =
762d2daca77SZachary Turner         valobj
763d2daca77SZachary Turner             ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
764d2daca77SZachary Turner                                         &final_value_type, options, &what_next)
765b9c1b51eSKate Stone             .get();
766554f68d3SGreg Clayton 
767b9c1b51eSKate Stone     if (!target) {
768554f68d3SGreg Clayton       if (log)
769d2daca77SZachary Turner         log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d,"
770655c4525SZachary Turner                     " final_value_type %d",
771d2daca77SZachary Turner                     reason_to_stop, final_value_type);
772554f68d3SGreg Clayton       return false;
773b9c1b51eSKate Stone     } else {
774554f68d3SGreg Clayton       if (log)
775d2daca77SZachary Turner         log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
776655c4525SZachary Turner                     " final_value_type %d",
777d2daca77SZachary Turner                     reason_to_stop, final_value_type);
778b9c1b51eSKate Stone       target = target
779b9c1b51eSKate Stone                    ->GetQualifiedRepresentationIfAvailable(
780b9c1b51eSKate Stone                        target->GetDynamicValueType(), true)
781b9c1b51eSKate Stone                    .get();
782554f68d3SGreg Clayton     }
783554f68d3SGreg Clayton   }
784554f68d3SGreg Clayton 
785b9c1b51eSKate Stone   is_array_range =
786b9c1b51eSKate Stone       (final_value_type ==
787b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeBoundedRange ||
788b9c1b51eSKate Stone        final_value_type ==
789b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeUnboundedRange);
790554f68d3SGreg Clayton 
791b9c1b51eSKate Stone   do_deref_pointer =
792b9c1b51eSKate Stone       (what_next == ValueObject::eExpressionPathAftermathDereference);
793554f68d3SGreg Clayton 
794b9c1b51eSKate Stone   if (do_deref_pointer && !is_array_range) {
795554f68d3SGreg Clayton     // I have not deref-ed yet, let's do it
796b9c1b51eSKate Stone     // this happens when we are not going through
797b9c1b51eSKate Stone     // GetValueForVariableExpressionPath
798554f68d3SGreg Clayton     // to get to the target ValueObject
799554f68d3SGreg Clayton     Error error;
800554f68d3SGreg Clayton     target = target->Dereference(error).get();
801b9c1b51eSKate Stone     if (error.Fail()) {
802554f68d3SGreg Clayton       if (log)
803b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] ERROR: %s\n",
804b9c1b51eSKate Stone                     error.AsCString("unknown"));
805554f68d3SGreg Clayton       return false;
806554f68d3SGreg Clayton     }
807554f68d3SGreg Clayton     do_deref_pointer = false;
808554f68d3SGreg Clayton   }
809554f68d3SGreg Clayton 
810b9c1b51eSKate Stone   if (!target) {
811554f68d3SGreg Clayton     if (log)
812b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] could not calculate target for "
813b9c1b51eSKate Stone                   "prompt expression");
814554f68d3SGreg Clayton     return false;
815554f68d3SGreg Clayton   }
816554f68d3SGreg Clayton 
817554f68d3SGreg Clayton   // we do not want to use the summary for a bitfield of type T:n
818554f68d3SGreg Clayton   // if we were originally dealing with just a T - that would get
819554f68d3SGreg Clayton   // us into an endless recursion
820b9c1b51eSKate Stone   if (target->IsBitfield() && was_var_indexed) {
821554f68d3SGreg Clayton     // TODO: check for a (T:n)-specific summary - we should still obey that
822554f68d3SGreg Clayton     StreamString bitfield_name;
823b9c1b51eSKate Stone     bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
824b9c1b51eSKate Stone                          target->GetBitfieldBitSize());
825b9c1b51eSKate Stone     lldb::TypeNameSpecifierImplSP type_sp(
826c156427dSZachary Turner         new TypeNameSpecifierImpl(bitfield_name.GetString(), false));
827b9c1b51eSKate Stone     if (val_obj_display ==
828b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleSummary &&
829b9c1b51eSKate Stone         !DataVisualization::GetSummaryForType(type_sp))
830554f68d3SGreg Clayton       val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
831554f68d3SGreg Clayton   }
832554f68d3SGreg Clayton 
833554f68d3SGreg Clayton   // TODO use flags for these
834b9c1b51eSKate Stone   const uint32_t type_info_flags =
835b9c1b51eSKate Stone       target->GetCompilerType().GetTypeInfo(nullptr);
836554f68d3SGreg Clayton   bool is_array = (type_info_flags & eTypeIsArray) != 0;
837554f68d3SGreg Clayton   bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
83899558cc4SGreg Clayton   bool is_aggregate = target->GetCompilerType().IsAggregateType();
839554f68d3SGreg Clayton 
840b9c1b51eSKate Stone   if ((is_array || is_pointer) && (!is_array_range) &&
841b9c1b51eSKate Stone       val_obj_display ==
842b9c1b51eSKate Stone           ValueObject::eValueObjectRepresentationStyleValue) // this should be
843b9c1b51eSKate Stone                                                              // wrong, but there
844b9c1b51eSKate Stone                                                              // are some
845b9c1b51eSKate Stone                                                              // exceptions
846554f68d3SGreg Clayton   {
847554f68d3SGreg Clayton     StreamString str_temp;
848554f68d3SGreg Clayton     if (log)
849b9c1b51eSKate Stone       log->Printf(
850b9c1b51eSKate Stone           "[Debugger::FormatPrompt] I am into array || pointer && !range");
851554f68d3SGreg Clayton 
852b9c1b51eSKate Stone     if (target->HasSpecialPrintableRepresentation(val_obj_display,
853b9c1b51eSKate Stone                                                   custom_format)) {
854554f68d3SGreg Clayton       // try to use the special cases
855b9c1b51eSKate Stone       bool success = target->DumpPrintableRepresentation(
856b9c1b51eSKate Stone           str_temp, val_obj_display, custom_format);
857554f68d3SGreg Clayton       if (log)
858b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] special cases did%s match",
859b9c1b51eSKate Stone                     success ? "" : "n't");
860554f68d3SGreg Clayton 
861554f68d3SGreg Clayton       // should not happen
862554f68d3SGreg Clayton       if (success)
863c156427dSZachary Turner         s << str_temp.GetString();
864554f68d3SGreg Clayton       return true;
865b9c1b51eSKate Stone     } else {
866554f68d3SGreg Clayton       if (was_plain_var) // if ${var}
867554f68d3SGreg Clayton       {
868554f68d3SGreg Clayton         s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
869b9c1b51eSKate Stone       } else if (is_pointer) // if pointer, value is the address stored
870554f68d3SGreg Clayton       {
871b9c1b51eSKate Stone         target->DumpPrintableRepresentation(
872b9c1b51eSKate Stone             s, val_obj_display, custom_format,
87365d86e4fSEnrico Granata             ValueObject::PrintableRepresentationSpecialCases::eDisable);
874554f68d3SGreg Clayton       }
875554f68d3SGreg Clayton       return true;
876554f68d3SGreg Clayton     }
877554f68d3SGreg Clayton   }
878554f68d3SGreg Clayton 
879b9c1b51eSKate Stone   // if directly trying to print ${var}, and this is an aggregate, display a
880b9c1b51eSKate Stone   // nice
881554f68d3SGreg Clayton   // type @ location message
882b9c1b51eSKate Stone   if (is_aggregate && was_plain_var) {
883554f68d3SGreg Clayton     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
884554f68d3SGreg Clayton     return true;
885554f68d3SGreg Clayton   }
886554f68d3SGreg Clayton 
887b9c1b51eSKate Stone   // if directly trying to print ${var%V}, and this is an aggregate, do not let
888b9c1b51eSKate Stone   // the user do it
889b9c1b51eSKate Stone   if (is_aggregate &&
890b9c1b51eSKate Stone       ((was_var_format &&
891b9c1b51eSKate Stone         val_obj_display ==
892b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleValue))) {
893554f68d3SGreg Clayton     s << "<invalid use of aggregate type>";
894554f68d3SGreg Clayton     return true;
895554f68d3SGreg Clayton   }
896554f68d3SGreg Clayton 
897b9c1b51eSKate Stone   if (!is_array_range) {
898554f68d3SGreg Clayton     if (log)
899554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
900b9c1b51eSKate Stone     return target->DumpPrintableRepresentation(s, val_obj_display,
901b9c1b51eSKate Stone                                                custom_format);
902b9c1b51eSKate Stone   } else {
903554f68d3SGreg Clayton     if (log)
904554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
905554f68d3SGreg Clayton     if (!is_array && !is_pointer)
906554f68d3SGreg Clayton       return false;
907554f68d3SGreg Clayton     if (log)
908554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] handle as array");
909e8376261SVince Harron     StreamString special_directions_stream;
910554f68d3SGreg Clayton     llvm::StringRef special_directions;
911b9c1b51eSKate Stone     if (close_bracket_index != llvm::StringRef::npos &&
912b9c1b51eSKate Stone         subpath.size() > close_bracket_index) {
913554f68d3SGreg Clayton       ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
914b9c1b51eSKate Stone       special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
915554f68d3SGreg Clayton                                        additional_data.GetCString());
916554f68d3SGreg Clayton 
917b9c1b51eSKate Stone       if (entry.fmt != eFormatDefault) {
918b9c1b51eSKate Stone         const char format_char =
919b9c1b51eSKate Stone             FormatManager::GetFormatAsFormatChar(entry.fmt);
920554f68d3SGreg Clayton         if (format_char != '\0')
921554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", format_char);
922b9c1b51eSKate Stone         else {
923b9c1b51eSKate Stone           const char *format_cstr =
924b9c1b51eSKate Stone               FormatManager::GetFormatAsCString(entry.fmt);
925554f68d3SGreg Clayton           special_directions_stream.Printf("%%%s", format_cstr);
926554f68d3SGreg Clayton         }
927b9c1b51eSKate Stone       } else if (entry.number != 0) {
928b9c1b51eSKate Stone         const char style_char = ConvertValueObjectStyleToChar(
929b9c1b51eSKate Stone             (ValueObject::ValueObjectRepresentationStyle)entry.number);
930554f68d3SGreg Clayton         if (style_char)
931554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", style_char);
932554f68d3SGreg Clayton       }
933554f68d3SGreg Clayton       special_directions_stream.PutChar('}');
934b9c1b51eSKate Stone       special_directions =
935b9c1b51eSKate Stone           llvm::StringRef(special_directions_stream.GetString());
936554f68d3SGreg Clayton     }
937554f68d3SGreg Clayton 
938554f68d3SGreg Clayton     // let us display items index_lower thru index_higher of this array
939554f68d3SGreg Clayton     s.PutChar('[');
940554f68d3SGreg Clayton 
941554f68d3SGreg Clayton     if (index_higher < 0)
942554f68d3SGreg Clayton       index_higher = valobj->GetNumChildren() - 1;
943554f68d3SGreg Clayton 
944b9c1b51eSKate Stone     uint32_t max_num_children =
945b9c1b51eSKate Stone         target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
946554f68d3SGreg Clayton 
947554f68d3SGreg Clayton     bool success = true;
948b9c1b51eSKate Stone     for (int64_t index = index_lower; index <= index_higher; ++index) {
949b9c1b51eSKate Stone       ValueObject *item =
950b9c1b51eSKate Stone           ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
951b9c1b51eSKate Stone               .get();
952554f68d3SGreg Clayton 
953b9c1b51eSKate Stone       if (!item) {
954554f68d3SGreg Clayton         if (log)
955b9c1b51eSKate Stone           log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at "
956b9c1b51eSKate Stone                       "index %" PRId64,
957b9c1b51eSKate Stone                       index);
958b9c1b51eSKate Stone       } else {
959554f68d3SGreg Clayton         if (log)
960b9c1b51eSKate Stone           log->Printf(
961b9c1b51eSKate Stone               "[Debugger::FormatPrompt] special_directions for child item: %s",
962b9c1b51eSKate Stone               special_directions.data() ? special_directions.data() : "");
963554f68d3SGreg Clayton       }
964554f68d3SGreg Clayton 
965b9c1b51eSKate Stone       if (special_directions.empty()) {
966b9c1b51eSKate Stone         success &= item->DumpPrintableRepresentation(s, val_obj_display,
967b9c1b51eSKate Stone                                                      custom_format);
968b9c1b51eSKate Stone       } else {
969b9c1b51eSKate Stone         success &= FormatEntity::FormatStringRef(
970b9c1b51eSKate Stone             special_directions, s, sc, exe_ctx, nullptr, item, false, false);
971554f68d3SGreg Clayton       }
972554f68d3SGreg Clayton 
973b9c1b51eSKate Stone       if (--max_num_children == 0) {
974554f68d3SGreg Clayton         s.PutCString(", ...");
975554f68d3SGreg Clayton         break;
976554f68d3SGreg Clayton       }
977554f68d3SGreg Clayton 
978554f68d3SGreg Clayton       if (index < index_higher)
979554f68d3SGreg Clayton         s.PutChar(',');
980554f68d3SGreg Clayton     }
981554f68d3SGreg Clayton     s.PutChar(']');
982554f68d3SGreg Clayton     return success;
983554f68d3SGreg Clayton   }
984554f68d3SGreg Clayton }
985554f68d3SGreg Clayton 
986b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
987b9c1b51eSKate Stone                          Format format) {
988b9c1b51eSKate Stone   if (frame) {
989554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
990554f68d3SGreg Clayton 
991b9c1b51eSKate Stone     if (reg_ctx) {
992554f68d3SGreg Clayton       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
993b9c1b51eSKate Stone       if (reg_info) {
994554f68d3SGreg Clayton         RegisterValue reg_value;
995b9c1b51eSKate Stone         if (reg_ctx->ReadRegister(reg_info, reg_value)) {
996554f68d3SGreg Clayton           reg_value.Dump(&s, reg_info, false, false, format);
997554f68d3SGreg Clayton           return true;
998554f68d3SGreg Clayton         }
999554f68d3SGreg Clayton       }
1000554f68d3SGreg Clayton     }
1001554f68d3SGreg Clayton   }
1002554f68d3SGreg Clayton   return false;
1003554f68d3SGreg Clayton }
1004554f68d3SGreg Clayton 
1005b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse(
1006b9c1b51eSKate Stone     const FormatEntity::Entry &entry,
1007554f68d3SGreg Clayton     const StructuredData::ObjectSP &thread_info_dictionary,
1008b9c1b51eSKate Stone     const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
1009554f68d3SGreg Clayton   llvm::StringRef path(entry.string);
1010554f68d3SGreg Clayton 
1011b9c1b51eSKate Stone   StructuredData::ObjectSP value =
1012b9c1b51eSKate Stone       thread_info_dictionary->GetObjectForDotSeparatedPath(path);
1013554f68d3SGreg Clayton 
1014b9c1b51eSKate Stone   if (value) {
1015b9c1b51eSKate Stone     if (value->GetType() == StructuredData::Type::eTypeInteger) {
1016554f68d3SGreg Clayton       const char *token_format = "0x%4.4" PRIx64;
1017554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1018554f68d3SGreg Clayton         token_format = entry.printf_format.c_str();
1019554f68d3SGreg Clayton       s.Printf(token_format, value->GetAsInteger()->GetValue());
1020554f68d3SGreg Clayton       return true;
1021b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeFloat) {
1022554f68d3SGreg Clayton       s.Printf("%f", value->GetAsFloat()->GetValue());
1023554f68d3SGreg Clayton       return true;
1024b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeString) {
1025554f68d3SGreg Clayton       s.Printf("%s", value->GetAsString()->GetValue().c_str());
1026554f68d3SGreg Clayton       return true;
1027b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeArray) {
1028b9c1b51eSKate Stone       if (value->GetAsArray()->GetSize() > 0) {
1029554f68d3SGreg Clayton         s.Printf("%zu", value->GetAsArray()->GetSize());
1030554f68d3SGreg Clayton         return true;
1031554f68d3SGreg Clayton       }
1032b9c1b51eSKate Stone     } else if (value->GetType() == StructuredData::Type::eTypeDictionary) {
1033b9c1b51eSKate Stone       s.Printf("%zu",
1034b9c1b51eSKate Stone                value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1035554f68d3SGreg Clayton       return true;
1036554f68d3SGreg Clayton     }
1037554f68d3SGreg Clayton   }
1038554f68d3SGreg Clayton 
1039554f68d3SGreg Clayton   return false;
1040554f68d3SGreg Clayton }
1041554f68d3SGreg Clayton 
1042b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) {
1043554f68d3SGreg Clayton   return (::strncmp(var_name_begin, var, strlen(var)) == 0);
1044554f68d3SGreg Clayton }
1045554f68d3SGreg Clayton 
1046b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
1047554f68d3SGreg Clayton                                    const SymbolContext *sc,
1048554f68d3SGreg Clayton                                    const ExecutionContext *exe_ctx,
1049b9c1b51eSKate Stone                                    const Address *addr, ValueObject *valobj,
1050554f68d3SGreg Clayton                                    bool function_changed,
1051b9c1b51eSKate Stone                                    bool initial_function) {
1052b9c1b51eSKate Stone   if (!format_str.empty()) {
1053554f68d3SGreg Clayton     FormatEntity::Entry root;
1054554f68d3SGreg Clayton     Error error = FormatEntity::Parse(format_str, root);
1055b9c1b51eSKate Stone     if (error.Success()) {
1056b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1057b9c1b51eSKate Stone                                   function_changed, initial_function);
1058554f68d3SGreg Clayton     }
1059554f68d3SGreg Clayton   }
1060554f68d3SGreg Clayton   return false;
1061554f68d3SGreg Clayton }
1062a74f37a5SEugene Zelenko 
1063b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s,
1064554f68d3SGreg Clayton                                  const SymbolContext *sc,
1065554f68d3SGreg Clayton                                  const ExecutionContext *exe_ctx,
1066b9c1b51eSKate Stone                                  const Address *addr, ValueObject *valobj,
1067b9c1b51eSKate Stone                                  bool function_changed, bool initial_function) {
1068b9c1b51eSKate Stone   if (format && format[0]) {
1069554f68d3SGreg Clayton     FormatEntity::Entry root;
1070554f68d3SGreg Clayton     llvm::StringRef format_str(format);
1071554f68d3SGreg Clayton     Error error = FormatEntity::Parse(format_str, root);
1072b9c1b51eSKate Stone     if (error.Success()) {
1073b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1074b9c1b51eSKate Stone                                   function_changed, initial_function);
1075554f68d3SGreg Clayton     }
1076554f68d3SGreg Clayton   }
1077554f68d3SGreg Clayton   return false;
1078554f68d3SGreg Clayton }
1079554f68d3SGreg Clayton 
1080b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s,
1081554f68d3SGreg Clayton                           const SymbolContext *sc,
1082b9c1b51eSKate Stone                           const ExecutionContext *exe_ctx, const Address *addr,
1083b9c1b51eSKate Stone                           ValueObject *valobj, bool function_changed,
1084b9c1b51eSKate Stone                           bool initial_function) {
1085b9c1b51eSKate Stone   switch (entry.type) {
1086554f68d3SGreg Clayton   case Entry::Type::Invalid:
1087b9c1b51eSKate Stone   case Entry::Type::ParentNumber: // Only used for
1088b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1089b9c1b51eSKate Stone   case Entry::Type::ParentString: // Only used for
1090b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1091b9c1b51eSKate Stone   case Entry::Type::InsertString: // Only used for
1092b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1093554f68d3SGreg Clayton     return false;
1094554f68d3SGreg Clayton 
1095554f68d3SGreg Clayton   case Entry::Type::Root:
1096b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1097b9c1b51eSKate Stone       if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
1098b9c1b51eSKate Stone                   initial_function)) {
1099554f68d3SGreg Clayton         return false; // If any item of root fails, then the formatting fails
1100554f68d3SGreg Clayton       }
1101554f68d3SGreg Clayton     }
1102554f68d3SGreg Clayton     return true; // Only return true if all items succeeded
1103554f68d3SGreg Clayton 
1104554f68d3SGreg Clayton   case Entry::Type::String:
1105771ef6d4SMalcolm Parsons     s.PutCString(entry.string);
1106554f68d3SGreg Clayton     return true;
1107554f68d3SGreg Clayton 
1108b9c1b51eSKate Stone   case Entry::Type::Scope: {
1109554f68d3SGreg Clayton     StreamString scope_stream;
1110554f68d3SGreg Clayton     bool success = false;
1111b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1112b9c1b51eSKate Stone       success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
1113b9c1b51eSKate Stone                        function_changed, initial_function);
1114554f68d3SGreg Clayton       if (!success)
1115554f68d3SGreg Clayton         break;
1116554f68d3SGreg Clayton     }
1117554f68d3SGreg Clayton     // Only if all items in a scope succeed, then do we
1118554f68d3SGreg Clayton     // print the output into the main stream
1119554f68d3SGreg Clayton     if (success)
1120554f68d3SGreg Clayton       s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
1121554f68d3SGreg Clayton   }
1122554f68d3SGreg Clayton     return true; // Scopes always successfully print themselves
1123554f68d3SGreg Clayton 
1124554f68d3SGreg Clayton   case Entry::Type::Variable:
1125554f68d3SGreg Clayton   case Entry::Type::VariableSynthetic:
1126554f68d3SGreg Clayton   case Entry::Type::ScriptVariable:
1127554f68d3SGreg Clayton   case Entry::Type::ScriptVariableSynthetic:
1128a74f37a5SEugene Zelenko     return DumpValue(s, sc, exe_ctx, entry, valobj);
1129554f68d3SGreg Clayton 
1130554f68d3SGreg Clayton   case Entry::Type::AddressFile:
1131554f68d3SGreg Clayton   case Entry::Type::AddressLoad:
1132554f68d3SGreg Clayton   case Entry::Type::AddressLoadOrFile:
1133a74f37a5SEugene Zelenko     return (addr != nullptr && addr->IsValid() &&
1134b9c1b51eSKate Stone             DumpAddress(s, sc, exe_ctx, *addr,
1135b9c1b51eSKate Stone                         entry.type == Entry::Type::AddressLoadOrFile));
1136554f68d3SGreg Clayton 
1137554f68d3SGreg Clayton   case Entry::Type::ProcessID:
1138b9c1b51eSKate Stone     if (exe_ctx) {
1139554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1140b9c1b51eSKate Stone       if (process) {
1141554f68d3SGreg Clayton         const char *format = "%" PRIu64;
1142554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1143554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1144554f68d3SGreg Clayton         s.Printf(format, process->GetID());
1145554f68d3SGreg Clayton         return true;
1146554f68d3SGreg Clayton       }
1147554f68d3SGreg Clayton     }
1148554f68d3SGreg Clayton     return false;
1149554f68d3SGreg Clayton 
1150554f68d3SGreg Clayton   case Entry::Type::ProcessFile:
1151b9c1b51eSKate Stone     if (exe_ctx) {
1152554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1153b9c1b51eSKate Stone       if (process) {
1154554f68d3SGreg Clayton         Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1155b9c1b51eSKate Stone         if (exe_module) {
1156554f68d3SGreg Clayton           if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1157554f68d3SGreg Clayton             return true;
1158554f68d3SGreg Clayton         }
1159554f68d3SGreg Clayton       }
1160554f68d3SGreg Clayton     }
1161554f68d3SGreg Clayton     return false;
1162554f68d3SGreg Clayton 
1163554f68d3SGreg Clayton   case Entry::Type::ScriptProcess:
1164b9c1b51eSKate Stone     if (exe_ctx) {
1165554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1166554f68d3SGreg Clayton       if (process)
1167b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, process,
1168b9c1b51eSKate Stone                                       entry.string.c_str());
1169554f68d3SGreg Clayton     }
1170554f68d3SGreg Clayton     return false;
1171554f68d3SGreg Clayton 
1172554f68d3SGreg Clayton   case Entry::Type::ThreadID:
1173b9c1b51eSKate Stone     if (exe_ctx) {
1174554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1175b9c1b51eSKate Stone       if (thread) {
1176554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1177b9c1b51eSKate Stone         if (!entry.printf_format.empty()) {
1178554f68d3SGreg Clayton           // Watch for the special "tid" format...
1179b9c1b51eSKate Stone           if (entry.printf_format == "tid") {
1180b9c1b51eSKate Stone             // TODO(zturner): Rather than hardcoding this to be platform
1181b9c1b51eSKate Stone             // specific, it should be controlled by a
1182b9c1b51eSKate Stone             // setting and the default value of the setting can be different
1183b9c1b51eSKate Stone             // depending on the platform.
1184554f68d3SGreg Clayton             Target &target = thread->GetProcess()->GetTarget();
1185554f68d3SGreg Clayton             ArchSpec arch(target.GetArchitecture());
1186b9c1b51eSKate Stone             llvm::Triple::OSType ostype = arch.IsValid()
1187b9c1b51eSKate Stone                                               ? arch.GetTriple().getOS()
1188b9c1b51eSKate Stone                                               : llvm::Triple::UnknownOS;
1189b9c1b51eSKate Stone             if ((ostype == llvm::Triple::FreeBSD) ||
1190b9c1b51eSKate Stone                 (ostype == llvm::Triple::Linux)) {
1191554f68d3SGreg Clayton               format = "%" PRIu64;
1192554f68d3SGreg Clayton             }
1193b9c1b51eSKate Stone           } else {
1194554f68d3SGreg Clayton             format = entry.printf_format.c_str();
1195554f68d3SGreg Clayton           }
1196554f68d3SGreg Clayton         }
1197554f68d3SGreg Clayton         s.Printf(format, thread->GetID());
1198554f68d3SGreg Clayton         return true;
1199554f68d3SGreg Clayton       }
1200554f68d3SGreg Clayton     }
1201554f68d3SGreg Clayton     return false;
1202554f68d3SGreg Clayton 
1203554f68d3SGreg Clayton   case Entry::Type::ThreadProtocolID:
1204b9c1b51eSKate Stone     if (exe_ctx) {
1205554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1206b9c1b51eSKate Stone       if (thread) {
1207554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1208554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1209554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1210554f68d3SGreg Clayton         s.Printf(format, thread->GetProtocolID());
1211554f68d3SGreg Clayton         return true;
1212554f68d3SGreg Clayton       }
1213554f68d3SGreg Clayton     }
1214554f68d3SGreg Clayton     return false;
1215554f68d3SGreg Clayton 
1216554f68d3SGreg Clayton   case Entry::Type::ThreadIndexID:
1217b9c1b51eSKate Stone     if (exe_ctx) {
1218554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1219b9c1b51eSKate Stone       if (thread) {
1220554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1221554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1222554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1223554f68d3SGreg Clayton         s.Printf(format, thread->GetIndexID());
1224554f68d3SGreg Clayton         return true;
1225554f68d3SGreg Clayton       }
1226554f68d3SGreg Clayton     }
1227554f68d3SGreg Clayton     return false;
1228554f68d3SGreg Clayton 
1229554f68d3SGreg Clayton   case Entry::Type::ThreadName:
1230b9c1b51eSKate Stone     if (exe_ctx) {
1231554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1232b9c1b51eSKate Stone       if (thread) {
1233554f68d3SGreg Clayton         const char *cstr = thread->GetName();
1234b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1235554f68d3SGreg Clayton           s.PutCString(cstr);
1236554f68d3SGreg Clayton           return true;
1237554f68d3SGreg Clayton         }
1238554f68d3SGreg Clayton       }
1239554f68d3SGreg Clayton     }
1240554f68d3SGreg Clayton     return false;
1241554f68d3SGreg Clayton 
1242554f68d3SGreg Clayton   case Entry::Type::ThreadQueue:
1243b9c1b51eSKate Stone     if (exe_ctx) {
1244554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1245b9c1b51eSKate Stone       if (thread) {
1246554f68d3SGreg Clayton         const char *cstr = thread->GetQueueName();
1247b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1248554f68d3SGreg Clayton           s.PutCString(cstr);
1249554f68d3SGreg Clayton           return true;
1250554f68d3SGreg Clayton         }
1251554f68d3SGreg Clayton       }
1252554f68d3SGreg Clayton     }
1253554f68d3SGreg Clayton     return false;
1254554f68d3SGreg Clayton 
1255554f68d3SGreg Clayton   case Entry::Type::ThreadStopReason:
1256b9c1b51eSKate Stone     if (exe_ctx) {
1257554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1258b9c1b51eSKate Stone       if (thread) {
1259554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1260b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1261554f68d3SGreg Clayton           const char *cstr = stop_info_sp->GetDescription();
1262b9c1b51eSKate Stone           if (cstr && cstr[0]) {
1263554f68d3SGreg Clayton             s.PutCString(cstr);
1264554f68d3SGreg Clayton             return true;
1265554f68d3SGreg Clayton           }
1266554f68d3SGreg Clayton         }
1267554f68d3SGreg Clayton       }
1268554f68d3SGreg Clayton     }
1269554f68d3SGreg Clayton     return false;
1270554f68d3SGreg Clayton 
1271554f68d3SGreg Clayton   case Entry::Type::ThreadReturnValue:
1272b9c1b51eSKate Stone     if (exe_ctx) {
1273554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1274b9c1b51eSKate Stone       if (thread) {
1275554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1276b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1277b9c1b51eSKate Stone           ValueObjectSP return_valobj_sp =
1278b9c1b51eSKate Stone               StopInfo::GetReturnValueObject(stop_info_sp);
1279b9c1b51eSKate Stone           if (return_valobj_sp) {
1280554f68d3SGreg Clayton             return_valobj_sp->Dump(s);
1281554f68d3SGreg Clayton             return true;
1282554f68d3SGreg Clayton           }
1283554f68d3SGreg Clayton         }
1284554f68d3SGreg Clayton       }
1285554f68d3SGreg Clayton     }
1286554f68d3SGreg Clayton     return false;
1287554f68d3SGreg Clayton 
1288554f68d3SGreg Clayton   case Entry::Type::ThreadCompletedExpression:
1289b9c1b51eSKate Stone     if (exe_ctx) {
1290554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1291b9c1b51eSKate Stone       if (thread) {
1292554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1293b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1294b9c1b51eSKate Stone           ExpressionVariableSP expression_var_sp =
1295b9c1b51eSKate Stone               StopInfo::GetExpressionVariable(stop_info_sp);
1296b9c1b51eSKate Stone           if (expression_var_sp && expression_var_sp->GetValueObject()) {
1297554f68d3SGreg Clayton             expression_var_sp->GetValueObject()->Dump(s);
1298554f68d3SGreg Clayton             return true;
1299554f68d3SGreg Clayton           }
1300554f68d3SGreg Clayton         }
1301554f68d3SGreg Clayton       }
1302554f68d3SGreg Clayton     }
1303554f68d3SGreg Clayton     return false;
1304554f68d3SGreg Clayton 
1305554f68d3SGreg Clayton   case Entry::Type::ScriptThread:
1306b9c1b51eSKate Stone     if (exe_ctx) {
1307554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1308554f68d3SGreg Clayton       if (thread)
1309b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
1310b9c1b51eSKate Stone                                       entry.string.c_str());
1311554f68d3SGreg Clayton     }
1312554f68d3SGreg Clayton     return false;
1313554f68d3SGreg Clayton 
1314554f68d3SGreg Clayton   case Entry::Type::ThreadInfo:
1315b9c1b51eSKate Stone     if (exe_ctx) {
1316554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1317b9c1b51eSKate Stone       if (thread) {
1318554f68d3SGreg Clayton         StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1319b9c1b51eSKate Stone         if (object_sp &&
1320b9c1b51eSKate Stone             object_sp->GetType() == StructuredData::Type::eTypeDictionary) {
1321554f68d3SGreg Clayton           if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
1322554f68d3SGreg Clayton             return true;
1323554f68d3SGreg Clayton         }
1324554f68d3SGreg Clayton       }
1325554f68d3SGreg Clayton     }
1326554f68d3SGreg Clayton     return false;
1327554f68d3SGreg Clayton 
1328554f68d3SGreg Clayton   case Entry::Type::TargetArch:
1329b9c1b51eSKate Stone     if (exe_ctx) {
1330554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1331b9c1b51eSKate Stone       if (target) {
1332554f68d3SGreg Clayton         const ArchSpec &arch = target->GetArchitecture();
1333b9c1b51eSKate Stone         if (arch.IsValid()) {
1334554f68d3SGreg Clayton           s.PutCString(arch.GetArchitectureName());
1335554f68d3SGreg Clayton           return true;
1336554f68d3SGreg Clayton         }
1337554f68d3SGreg Clayton       }
1338554f68d3SGreg Clayton     }
1339554f68d3SGreg Clayton     return false;
1340554f68d3SGreg Clayton 
1341554f68d3SGreg Clayton   case Entry::Type::ScriptTarget:
1342b9c1b51eSKate Stone     if (exe_ctx) {
1343554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1344554f68d3SGreg Clayton       if (target)
1345b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, target,
1346b9c1b51eSKate Stone                                       entry.string.c_str());
1347554f68d3SGreg Clayton     }
1348554f68d3SGreg Clayton     return false;
1349554f68d3SGreg Clayton 
1350554f68d3SGreg Clayton   case Entry::Type::ModuleFile:
1351b9c1b51eSKate Stone     if (sc) {
1352554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1353b9c1b51eSKate Stone       if (module) {
1354554f68d3SGreg Clayton         if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1355554f68d3SGreg Clayton           return true;
1356554f68d3SGreg Clayton       }
1357554f68d3SGreg Clayton     }
1358554f68d3SGreg Clayton     return false;
1359554f68d3SGreg Clayton 
1360554f68d3SGreg Clayton   case Entry::Type::File:
1361b9c1b51eSKate Stone     if (sc) {
1362554f68d3SGreg Clayton       CompileUnit *cu = sc->comp_unit;
1363b9c1b51eSKate Stone       if (cu) {
1364554f68d3SGreg Clayton         // CompileUnit is a FileSpec
1365554f68d3SGreg Clayton         if (DumpFile(s, *cu, (FileKind)entry.number))
1366554f68d3SGreg Clayton           return true;
1367554f68d3SGreg Clayton       }
1368554f68d3SGreg Clayton     }
1369554f68d3SGreg Clayton     return false;
1370554f68d3SGreg Clayton 
1371dc975670SDawn Perchik   case Entry::Type::Lang:
1372b9c1b51eSKate Stone     if (sc) {
1373dc975670SDawn Perchik       CompileUnit *cu = sc->comp_unit;
1374b9c1b51eSKate Stone       if (cu) {
1375b9c1b51eSKate Stone         const char *lang_name =
1376b9c1b51eSKate Stone             Language::GetNameForLanguageType(cu->GetLanguage());
1377b9c1b51eSKate Stone         if (lang_name) {
1378dc975670SDawn Perchik           s.PutCString(lang_name);
1379dc975670SDawn Perchik           return true;
1380dc975670SDawn Perchik         }
1381dc975670SDawn Perchik       }
1382dc975670SDawn Perchik     }
1383dc975670SDawn Perchik     return false;
1384dc975670SDawn Perchik 
1385554f68d3SGreg Clayton   case Entry::Type::FrameIndex:
1386b9c1b51eSKate Stone     if (exe_ctx) {
1387554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1388b9c1b51eSKate Stone       if (frame) {
1389554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1390554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1391554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1392554f68d3SGreg Clayton         s.Printf(format, frame->GetFrameIndex());
1393554f68d3SGreg Clayton         return true;
1394554f68d3SGreg Clayton       }
1395554f68d3SGreg Clayton     }
1396554f68d3SGreg Clayton     return false;
1397554f68d3SGreg Clayton 
1398554f68d3SGreg Clayton   case Entry::Type::FrameRegisterPC:
1399b9c1b51eSKate Stone     if (exe_ctx) {
1400554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1401b9c1b51eSKate Stone       if (frame) {
1402554f68d3SGreg Clayton         const Address &pc_addr = frame->GetFrameCodeAddress();
1403b9c1b51eSKate Stone         if (pc_addr.IsValid()) {
1404554f68d3SGreg Clayton           if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
1405554f68d3SGreg Clayton             return true;
1406554f68d3SGreg Clayton         }
1407554f68d3SGreg Clayton       }
1408554f68d3SGreg Clayton     }
1409554f68d3SGreg Clayton     return false;
1410554f68d3SGreg Clayton 
1411554f68d3SGreg Clayton   case Entry::Type::FrameRegisterSP:
1412b9c1b51eSKate Stone     if (exe_ctx) {
1413554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1414b9c1b51eSKate Stone       if (frame) {
1415b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
1416b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1417554f68d3SGreg Clayton           return true;
1418554f68d3SGreg Clayton       }
1419554f68d3SGreg Clayton     }
1420554f68d3SGreg Clayton     return false;
1421554f68d3SGreg Clayton 
1422554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFP:
1423b9c1b51eSKate Stone     if (exe_ctx) {
1424554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1425b9c1b51eSKate Stone       if (frame) {
1426b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
1427b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1428554f68d3SGreg Clayton           return true;
1429554f68d3SGreg Clayton       }
1430554f68d3SGreg Clayton     }
1431554f68d3SGreg Clayton     return false;
1432554f68d3SGreg Clayton 
1433554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFlags:
1434b9c1b51eSKate Stone     if (exe_ctx) {
1435554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1436b9c1b51eSKate Stone       if (frame) {
1437b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric,
1438b9c1b51eSKate Stone                          LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
1439554f68d3SGreg Clayton           return true;
1440554f68d3SGreg Clayton       }
1441554f68d3SGreg Clayton     }
1442554f68d3SGreg Clayton     return false;
1443554f68d3SGreg Clayton 
14446a9767c7SJim Ingham   case Entry::Type::FrameNoDebug:
14456a9767c7SJim Ingham     if (exe_ctx) {
14466a9767c7SJim Ingham       StackFrame *frame = exe_ctx->GetFramePtr();
14476a9767c7SJim Ingham       if (frame) {
14486a9767c7SJim Ingham         return !frame->HasDebugInformation();
14496a9767c7SJim Ingham       }
14506a9767c7SJim Ingham     }
14516a9767c7SJim Ingham     return true;
14526a9767c7SJim Ingham 
1453554f68d3SGreg Clayton   case Entry::Type::FrameRegisterByName:
1454b9c1b51eSKate Stone     if (exe_ctx) {
1455554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1456b9c1b51eSKate Stone       if (frame) {
1457b9c1b51eSKate Stone         if (DumpRegister(s, frame, entry.string.c_str(),
1458b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1459554f68d3SGreg Clayton           return true;
1460554f68d3SGreg Clayton       }
1461554f68d3SGreg Clayton     }
1462554f68d3SGreg Clayton     return false;
1463554f68d3SGreg Clayton 
1464554f68d3SGreg Clayton   case Entry::Type::ScriptFrame:
1465b9c1b51eSKate Stone     if (exe_ctx) {
1466554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1467554f68d3SGreg Clayton       if (frame)
1468b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
1469b9c1b51eSKate Stone                                       entry.string.c_str());
1470554f68d3SGreg Clayton     }
1471554f68d3SGreg Clayton     return false;
1472554f68d3SGreg Clayton 
1473554f68d3SGreg Clayton   case Entry::Type::FunctionID:
1474b9c1b51eSKate Stone     if (sc) {
1475b9c1b51eSKate Stone       if (sc->function) {
1476554f68d3SGreg Clayton         s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
1477554f68d3SGreg Clayton         return true;
1478b9c1b51eSKate Stone       } else if (sc->symbol) {
1479554f68d3SGreg Clayton         s.Printf("symbol[%u]", sc->symbol->GetID());
1480554f68d3SGreg Clayton         return true;
1481554f68d3SGreg Clayton       }
1482554f68d3SGreg Clayton     }
1483554f68d3SGreg Clayton     return false;
1484554f68d3SGreg Clayton 
1485554f68d3SGreg Clayton   case Entry::Type::FunctionDidChange:
1486554f68d3SGreg Clayton     return function_changed;
1487554f68d3SGreg Clayton 
1488554f68d3SGreg Clayton   case Entry::Type::FunctionInitialFunction:
1489554f68d3SGreg Clayton     return initial_function;
1490554f68d3SGreg Clayton 
1491b9c1b51eSKate Stone   case Entry::Type::FunctionName: {
1492d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1493d4129b47SEnrico Granata     bool language_plugin_handled = false;
1494d4129b47SEnrico Granata     StreamString ss;
1495d4129b47SEnrico Granata     if (sc->function)
1496d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1497d4129b47SEnrico Granata     else if (sc->symbol)
1498d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1499b9c1b51eSKate Stone     if (language_plugin) {
1500b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1501b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1502d4129b47SEnrico Granata     }
1503b9c1b51eSKate Stone     if (language_plugin_handled) {
1504c156427dSZachary Turner       s << ss.GetString();
1505d4129b47SEnrico Granata       return true;
1506b9c1b51eSKate Stone     } else {
1507a74f37a5SEugene Zelenko       const char *name = nullptr;
1508554f68d3SGreg Clayton       if (sc->function)
1509a74f37a5SEugene Zelenko         name = sc->function->GetName().AsCString(nullptr);
1510554f68d3SGreg Clayton       else if (sc->symbol)
1511a74f37a5SEugene Zelenko         name = sc->symbol->GetName().AsCString(nullptr);
1512b9c1b51eSKate Stone       if (name) {
1513554f68d3SGreg Clayton         s.PutCString(name);
1514554f68d3SGreg Clayton 
1515b9c1b51eSKate Stone         if (sc->block) {
1516554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
1517b9c1b51eSKate Stone           if (inline_block) {
1518b9c1b51eSKate Stone             const InlineFunctionInfo *inline_info =
1519b9c1b51eSKate Stone                 sc->block->GetInlinedFunctionInfo();
1520b9c1b51eSKate Stone             if (inline_info) {
1521554f68d3SGreg Clayton               s.PutCString(" [inlined] ");
1522ddaf6a72SGreg Clayton               inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
1523554f68d3SGreg Clayton             }
1524554f68d3SGreg Clayton           }
1525554f68d3SGreg Clayton         }
1526554f68d3SGreg Clayton         return true;
1527554f68d3SGreg Clayton       }
1528554f68d3SGreg Clayton     }
1529d4129b47SEnrico Granata   }
1530554f68d3SGreg Clayton     return false;
1531554f68d3SGreg Clayton 
1532b9c1b51eSKate Stone   case Entry::Type::FunctionNameNoArgs: {
1533d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1534d4129b47SEnrico Granata     bool language_plugin_handled = false;
1535d4129b47SEnrico Granata     StreamString ss;
1536d4129b47SEnrico Granata     if (sc->function)
1537d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1538d4129b47SEnrico Granata     else if (sc->symbol)
1539d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1540b9c1b51eSKate Stone     if (language_plugin) {
1541b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1542b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1543d4129b47SEnrico Granata           ss);
1544d4129b47SEnrico Granata     }
1545b9c1b51eSKate Stone     if (language_plugin_handled) {
1546c156427dSZachary Turner       s << ss.GetString();
1547d4129b47SEnrico Granata       return true;
1548b9c1b51eSKate Stone     } else {
1549554f68d3SGreg Clayton       ConstString name;
1550554f68d3SGreg Clayton       if (sc->function)
1551ddaf6a72SGreg Clayton         name = sc->function->GetNameNoArguments();
1552554f68d3SGreg Clayton       else if (sc->symbol)
1553ddaf6a72SGreg Clayton         name = sc->symbol->GetNameNoArguments();
1554b9c1b51eSKate Stone       if (name) {
1555554f68d3SGreg Clayton         s.PutCString(name.GetCString());
1556554f68d3SGreg Clayton         return true;
1557554f68d3SGreg Clayton       }
1558554f68d3SGreg Clayton     }
1559d4129b47SEnrico Granata   }
1560554f68d3SGreg Clayton     return false;
1561554f68d3SGreg Clayton 
1562b9c1b51eSKate Stone   case Entry::Type::FunctionNameWithArgs: {
1563d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1564d4129b47SEnrico Granata     bool language_plugin_handled = false;
1565d4129b47SEnrico Granata     StreamString ss;
1566d4129b47SEnrico Granata     if (sc->function)
1567d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1568d4129b47SEnrico Granata     else if (sc->symbol)
1569d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1570b9c1b51eSKate Stone     if (language_plugin) {
1571b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1572b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1573d4129b47SEnrico Granata     }
1574b9c1b51eSKate Stone     if (language_plugin_handled) {
1575c156427dSZachary Turner       s << ss.GetString();
1576d4129b47SEnrico Granata       return true;
1577b9c1b51eSKate Stone     } else {
1578554f68d3SGreg Clayton       // Print the function name with arguments in it
1579b9c1b51eSKate Stone       if (sc->function) {
1580b9c1b51eSKate Stone         ExecutionContextScope *exe_scope =
1581b9c1b51eSKate Stone             exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1582a74f37a5SEugene Zelenko         const char *cstr = sc->function->GetName().AsCString(nullptr);
1583b9c1b51eSKate Stone         if (cstr) {
1584a74f37a5SEugene Zelenko           const InlineFunctionInfo *inline_info = nullptr;
1585554f68d3SGreg Clayton           VariableListSP variable_list_sp;
1586554f68d3SGreg Clayton           bool get_function_vars = true;
1587b9c1b51eSKate Stone           if (sc->block) {
1588554f68d3SGreg Clayton             Block *inline_block = sc->block->GetContainingInlinedBlock();
1589554f68d3SGreg Clayton 
1590b9c1b51eSKate Stone             if (inline_block) {
1591554f68d3SGreg Clayton               get_function_vars = false;
1592554f68d3SGreg Clayton               inline_info = sc->block->GetInlinedFunctionInfo();
1593554f68d3SGreg Clayton               if (inline_info)
1594554f68d3SGreg Clayton                 variable_list_sp = inline_block->GetBlockVariableList(true);
1595554f68d3SGreg Clayton             }
1596554f68d3SGreg Clayton           }
1597554f68d3SGreg Clayton 
1598b9c1b51eSKate Stone           if (get_function_vars) {
1599b9c1b51eSKate Stone             variable_list_sp =
1600b9c1b51eSKate Stone                 sc->function->GetBlock(true).GetBlockVariableList(true);
1601554f68d3SGreg Clayton           }
1602554f68d3SGreg Clayton 
1603b9c1b51eSKate Stone           if (inline_info) {
1604554f68d3SGreg Clayton             s.PutCString(cstr);
1605554f68d3SGreg Clayton             s.PutCString(" [inlined] ");
1606b9c1b51eSKate Stone             cstr =
1607b9c1b51eSKate Stone                 inline_info->GetName(sc->function->GetLanguage()).GetCString();
1608554f68d3SGreg Clayton           }
1609554f68d3SGreg Clayton 
1610554f68d3SGreg Clayton           VariableList args;
1611554f68d3SGreg Clayton           if (variable_list_sp)
1612b9c1b51eSKate Stone             variable_list_sp->AppendVariablesWithScope(
1613b9c1b51eSKate Stone                 eValueTypeVariableArgument, args);
1614b9c1b51eSKate Stone           if (args.GetSize() > 0) {
1615554f68d3SGreg Clayton             const char *open_paren = strchr(cstr, '(');
1616554f68d3SGreg Clayton             const char *close_paren = nullptr;
1617554f68d3SGreg Clayton             const char *generic = strchr(cstr, '<');
1618554f68d3SGreg Clayton             // if before the arguments list begins there is a template sign
1619554f68d3SGreg Clayton             // then scan to the end of the generic args before you try to find
1620554f68d3SGreg Clayton             // the arguments list
1621b9c1b51eSKate Stone             if (generic && open_paren && generic < open_paren) {
1622554f68d3SGreg Clayton               int generic_depth = 1;
1623554f68d3SGreg Clayton               ++generic;
1624b9c1b51eSKate Stone               for (; *generic && generic_depth > 0; generic++) {
1625554f68d3SGreg Clayton                 if (*generic == '<')
1626554f68d3SGreg Clayton                   generic_depth++;
1627554f68d3SGreg Clayton                 if (*generic == '>')
1628554f68d3SGreg Clayton                   generic_depth--;
1629554f68d3SGreg Clayton               }
1630554f68d3SGreg Clayton               if (*generic)
1631554f68d3SGreg Clayton                 open_paren = strchr(generic, '(');
1632554f68d3SGreg Clayton               else
1633554f68d3SGreg Clayton                 open_paren = nullptr;
1634554f68d3SGreg Clayton             }
1635b9c1b51eSKate Stone             if (open_paren) {
1636b9c1b51eSKate Stone               if (IsToken(open_paren, "(anonymous namespace)")) {
1637b9c1b51eSKate Stone                 open_paren =
1638b9c1b51eSKate Stone                     strchr(open_paren + strlen("(anonymous namespace)"), '(');
1639554f68d3SGreg Clayton                 if (open_paren)
1640554f68d3SGreg Clayton                   close_paren = strchr(open_paren, ')');
1641b9c1b51eSKate Stone               } else
1642554f68d3SGreg Clayton                 close_paren = strchr(open_paren, ')');
1643554f68d3SGreg Clayton             }
1644554f68d3SGreg Clayton 
1645554f68d3SGreg Clayton             if (open_paren)
1646554f68d3SGreg Clayton               s.Write(cstr, open_paren - cstr + 1);
1647b9c1b51eSKate Stone             else {
1648554f68d3SGreg Clayton               s.PutCString(cstr);
1649554f68d3SGreg Clayton               s.PutChar('(');
1650554f68d3SGreg Clayton             }
1651554f68d3SGreg Clayton             const size_t num_args = args.GetSize();
1652b9c1b51eSKate Stone             for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1653554f68d3SGreg Clayton               std::string buffer;
1654554f68d3SGreg Clayton 
1655554f68d3SGreg Clayton               VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1656b9c1b51eSKate Stone               ValueObjectSP var_value_sp(
1657b9c1b51eSKate Stone                   ValueObjectVariable::Create(exe_scope, var_sp));
1658ad91c7ceSEnrico Granata               StreamString ss;
1659c156427dSZachary Turner               llvm::StringRef var_representation;
1660554f68d3SGreg Clayton               const char *var_name = var_value_sp->GetName().GetCString();
1661b9c1b51eSKate Stone               if (var_value_sp->GetCompilerType().IsValid()) {
1662ad91c7ceSEnrico Granata                 if (var_value_sp && exe_scope->CalculateTarget())
1663b9c1b51eSKate Stone                   var_value_sp =
1664b9c1b51eSKate Stone                       var_value_sp->GetQualifiedRepresentationIfAvailable(
1665b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1666b9c1b51eSKate Stone                               ->TargetProperties::GetPreferDynamicValue(),
1667b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1668b9c1b51eSKate Stone                               ->TargetProperties::GetEnableSyntheticValue());
166999558cc4SGreg Clayton                 if (var_value_sp->GetCompilerType().IsAggregateType() &&
1670b9c1b51eSKate Stone                     DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
1671b9c1b51eSKate Stone                   static StringSummaryFormat format(
1672b9c1b51eSKate Stone                       TypeSummaryImpl::Flags()
1673554f68d3SGreg Clayton                           .SetHideItemNames(false)
1674554f68d3SGreg Clayton                           .SetShowMembersOneLiner(true),
1675554f68d3SGreg Clayton                       "");
1676b9c1b51eSKate Stone                   format.FormatObject(var_value_sp.get(), buffer,
1677b9c1b51eSKate Stone                                       TypeSummaryOptions());
1678c156427dSZachary Turner                   var_representation = buffer;
1679b9c1b51eSKate Stone                 } else
1680b9c1b51eSKate Stone                   var_value_sp->DumpPrintableRepresentation(
1681b9c1b51eSKate Stone                       ss, ValueObject::ValueObjectRepresentationStyle::
1682b9c1b51eSKate Stone                               eValueObjectRepresentationStyleSummary,
1683ad91c7ceSEnrico Granata                       eFormatDefault,
168465d86e4fSEnrico Granata                       ValueObject::PrintableRepresentationSpecialCases::eAllow,
1685ad91c7ceSEnrico Granata                       false);
1686ad91c7ceSEnrico Granata               }
1687ad91c7ceSEnrico Granata 
1688c156427dSZachary Turner               if (!ss.GetString().empty())
1689c156427dSZachary Turner                 var_representation = ss.GetString();
1690554f68d3SGreg Clayton               if (arg_idx > 0)
1691554f68d3SGreg Clayton                 s.PutCString(", ");
1692b9c1b51eSKate Stone               if (var_value_sp->GetError().Success()) {
1693c156427dSZachary Turner                 if (!var_representation.empty())
1694c156427dSZachary Turner                   s.Printf("%s=%s", var_name, var_representation.str().c_str());
1695554f68d3SGreg Clayton                 else
1696b9c1b51eSKate Stone                   s.Printf("%s=%s at %s", var_name,
1697b9c1b51eSKate Stone                            var_value_sp->GetTypeName().GetCString(),
1698b9c1b51eSKate Stone                            var_value_sp->GetLocationAsCString());
1699b9c1b51eSKate Stone               } else
1700554f68d3SGreg Clayton                 s.Printf("%s=<unavailable>", var_name);
1701554f68d3SGreg Clayton             }
1702554f68d3SGreg Clayton 
1703554f68d3SGreg Clayton             if (close_paren)
1704554f68d3SGreg Clayton               s.PutCString(close_paren);
1705554f68d3SGreg Clayton             else
1706554f68d3SGreg Clayton               s.PutChar(')');
1707554f68d3SGreg Clayton 
1708b9c1b51eSKate Stone           } else {
1709554f68d3SGreg Clayton             s.PutCString(cstr);
1710554f68d3SGreg Clayton           }
1711554f68d3SGreg Clayton           return true;
1712554f68d3SGreg Clayton         }
1713b9c1b51eSKate Stone       } else if (sc->symbol) {
1714a74f37a5SEugene Zelenko         const char *cstr = sc->symbol->GetName().AsCString(nullptr);
1715b9c1b51eSKate Stone         if (cstr) {
1716554f68d3SGreg Clayton           s.PutCString(cstr);
1717554f68d3SGreg Clayton           return true;
1718554f68d3SGreg Clayton         }
1719554f68d3SGreg Clayton       }
1720554f68d3SGreg Clayton     }
1721d4129b47SEnrico Granata   }
1722554f68d3SGreg Clayton     return false;
1723554f68d3SGreg Clayton 
1724554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffset:
1725b9c1b51eSKate Stone     if (addr) {
1726b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
1727b9c1b51eSKate Stone                                         false))
1728554f68d3SGreg Clayton         return true;
1729554f68d3SGreg Clayton     }
1730554f68d3SGreg Clayton     return false;
1731554f68d3SGreg Clayton 
1732554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffsetConcrete:
1733b9c1b51eSKate Stone     if (addr) {
1734b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
1735b9c1b51eSKate Stone                                         true))
1736554f68d3SGreg Clayton         return true;
1737554f68d3SGreg Clayton     }
1738554f68d3SGreg Clayton     return false;
1739554f68d3SGreg Clayton 
1740554f68d3SGreg Clayton   case Entry::Type::FunctionLineOffset:
1741b9c1b51eSKate Stone     return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1742b9c1b51eSKate Stone                                           sc->line_entry.range.GetBaseAddress(),
1743b9c1b51eSKate Stone                                           false, false, false));
1744554f68d3SGreg Clayton 
1745554f68d3SGreg Clayton   case Entry::Type::FunctionPCOffset:
1746b9c1b51eSKate Stone     if (exe_ctx) {
1747554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1748b9c1b51eSKate Stone       if (frame) {
1749b9c1b51eSKate Stone         if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1750b9c1b51eSKate Stone                                           frame->GetFrameCodeAddress(), false,
1751b9c1b51eSKate Stone                                           false, false))
1752554f68d3SGreg Clayton           return true;
1753554f68d3SGreg Clayton       }
1754554f68d3SGreg Clayton     }
1755554f68d3SGreg Clayton     return false;
1756554f68d3SGreg Clayton 
1757c980fa92SJason Molenda   case Entry::Type::FunctionChanged:
1758a74f37a5SEugene Zelenko     return function_changed;
1759c980fa92SJason Molenda 
1760b9c1b51eSKate Stone   case Entry::Type::FunctionIsOptimized: {
17616ab659a9SJason Molenda     bool is_optimized = false;
1762b9c1b51eSKate Stone     if (sc->function && sc->function->GetIsOptimized()) {
17636ab659a9SJason Molenda       is_optimized = true;
17646ab659a9SJason Molenda     }
17656ab659a9SJason Molenda     return is_optimized;
17666ab659a9SJason Molenda   }
17676ab659a9SJason Molenda 
1768c980fa92SJason Molenda   case Entry::Type::FunctionInitial:
1769a74f37a5SEugene Zelenko     return initial_function;
1770c980fa92SJason Molenda 
1771554f68d3SGreg Clayton   case Entry::Type::LineEntryFile:
1772b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1773554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1774b9c1b51eSKate Stone       if (module) {
1775554f68d3SGreg Clayton         if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
1776554f68d3SGreg Clayton           return true;
1777554f68d3SGreg Clayton       }
1778554f68d3SGreg Clayton     }
1779554f68d3SGreg Clayton     return false;
1780554f68d3SGreg Clayton 
1781554f68d3SGreg Clayton   case Entry::Type::LineEntryLineNumber:
1782b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1783554f68d3SGreg Clayton       const char *format = "%" PRIu32;
1784554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1785554f68d3SGreg Clayton         format = entry.printf_format.c_str();
1786554f68d3SGreg Clayton       s.Printf(format, sc->line_entry.line);
1787554f68d3SGreg Clayton       return true;
1788554f68d3SGreg Clayton     }
1789554f68d3SGreg Clayton     return false;
1790554f68d3SGreg Clayton 
1791554f68d3SGreg Clayton   case Entry::Type::LineEntryStartAddress:
1792554f68d3SGreg Clayton   case Entry::Type::LineEntryEndAddress:
1793b9c1b51eSKate Stone     if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
1794554f68d3SGreg Clayton       Address addr = sc->line_entry.range.GetBaseAddress();
1795554f68d3SGreg Clayton 
1796554f68d3SGreg Clayton       if (entry.type == Entry::Type::LineEntryEndAddress)
1797554f68d3SGreg Clayton         addr.Slide(sc->line_entry.range.GetByteSize());
1798554f68d3SGreg Clayton       if (DumpAddress(s, sc, exe_ctx, addr, false))
1799554f68d3SGreg Clayton         return true;
1800554f68d3SGreg Clayton     }
1801554f68d3SGreg Clayton     return false;
1802554f68d3SGreg Clayton 
1803554f68d3SGreg Clayton   case Entry::Type::CurrentPCArrow:
1804b9c1b51eSKate Stone     if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
1805b9c1b51eSKate Stone       RegisterContextSP reg_ctx =
1806b9c1b51eSKate Stone           exe_ctx->GetFramePtr()->GetRegisterContextSP();
1807b9c1b51eSKate Stone       if (reg_ctx) {
1808554f68d3SGreg Clayton         addr_t pc_loadaddr = reg_ctx->GetPC();
1809b9c1b51eSKate Stone         if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
1810554f68d3SGreg Clayton           Address pc;
1811554f68d3SGreg Clayton           pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
1812b9c1b51eSKate Stone           if (pc == *addr) {
1813554f68d3SGreg Clayton             s.Printf("-> ");
1814554f68d3SGreg Clayton             return true;
1815554f68d3SGreg Clayton           }
1816554f68d3SGreg Clayton         }
1817554f68d3SGreg Clayton       }
1818554f68d3SGreg Clayton       s.Printf("   ");
1819554f68d3SGreg Clayton       return true;
1820554f68d3SGreg Clayton     }
1821554f68d3SGreg Clayton     return false;
1822554f68d3SGreg Clayton   }
1823554f68d3SGreg Clayton   return false;
1824554f68d3SGreg Clayton }
1825554f68d3SGreg Clayton 
1826b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames(
1827b9c1b51eSKate Stone     Stream &s, const FormatEntity::Entry::Definition *parent) {
1828b9c1b51eSKate Stone   if (parent->children) {
1829554f68d3SGreg Clayton     const size_t n = parent->num_children;
1830b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
1831554f68d3SGreg Clayton       if (i > 0)
1832554f68d3SGreg Clayton         s.PutCString(", ");
1833554f68d3SGreg Clayton       s.Printf("\"%s\"", parent->children[i].name);
1834554f68d3SGreg Clayton     }
1835554f68d3SGreg Clayton     return true;
1836554f68d3SGreg Clayton   }
1837554f68d3SGreg Clayton   return false;
1838554f68d3SGreg Clayton }
1839554f68d3SGreg Clayton 
1840b9c1b51eSKate Stone static Error ParseEntry(const llvm::StringRef &format_str,
1841554f68d3SGreg Clayton                         const FormatEntity::Entry::Definition *parent,
1842b9c1b51eSKate Stone                         FormatEntity::Entry &entry) {
1843554f68d3SGreg Clayton   Error error;
1844554f68d3SGreg Clayton 
1845554f68d3SGreg Clayton   const size_t sep_pos = format_str.find_first_of(".[:");
1846b9c1b51eSKate Stone   const char sep_char =
1847b9c1b51eSKate Stone       (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
1848554f68d3SGreg Clayton   llvm::StringRef key = format_str.substr(0, sep_pos);
1849554f68d3SGreg Clayton 
1850554f68d3SGreg Clayton   const size_t n = parent->num_children;
1851b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1852554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1853b9c1b51eSKate Stone     if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
1854554f68d3SGreg Clayton       llvm::StringRef value;
1855554f68d3SGreg Clayton       if (sep_char)
1856b9c1b51eSKate Stone         value =
1857b9c1b51eSKate Stone             format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
1858b9c1b51eSKate Stone       switch (entry_def->type) {
1859554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentString:
18603a29f8b9SPavel Labath         entry.string = format_str.str();
1861554f68d3SGreg Clayton         return error; // Success
1862554f68d3SGreg Clayton 
1863554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentNumber:
1864554f68d3SGreg Clayton         entry.number = entry_def->data;
1865554f68d3SGreg Clayton         return error; // Success
1866554f68d3SGreg Clayton 
1867554f68d3SGreg Clayton       case FormatEntity::Entry::Type::InsertString:
1868554f68d3SGreg Clayton         entry.type = entry_def->type;
1869554f68d3SGreg Clayton         entry.string = entry_def->string;
1870554f68d3SGreg Clayton         return error; // Success
1871554f68d3SGreg Clayton 
1872554f68d3SGreg Clayton       default:
1873554f68d3SGreg Clayton         entry.type = entry_def->type;
1874554f68d3SGreg Clayton         break;
1875554f68d3SGreg Clayton       }
1876554f68d3SGreg Clayton 
1877b9c1b51eSKate Stone       if (value.empty()) {
1878b9c1b51eSKate Stone         if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
1879b9c1b51eSKate Stone           if (entry_def->children) {
1880554f68d3SGreg Clayton             StreamString error_strm;
1881b9c1b51eSKate Stone             error_strm.Printf("'%s' can't be specified on its own, you must "
1882b9c1b51eSKate Stone                               "access one of its children: ",
1883b9c1b51eSKate Stone                               entry_def->name);
1884554f68d3SGreg Clayton             DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
1885c156427dSZachary Turner             error.SetErrorStringWithFormat("%s", error_strm.GetData());
1886b9c1b51eSKate Stone           } else if (sep_char == ':') {
1887b9c1b51eSKate Stone             // Any value whose separator is a with a ':' means this value has a
1888b9c1b51eSKate Stone             // string argument
1889554f68d3SGreg Clayton             // that needs to be stored in the entry (like "${script.var:}").
1890554f68d3SGreg Clayton             // In this case the string value is the empty string which is ok.
1891b9c1b51eSKate Stone           } else {
1892554f68d3SGreg Clayton             error.SetErrorStringWithFormat("%s", "invalid entry definitions");
1893554f68d3SGreg Clayton           }
1894554f68d3SGreg Clayton         }
1895b9c1b51eSKate Stone       } else {
1896b9c1b51eSKate Stone         if (entry_def->children) {
1897554f68d3SGreg Clayton           error = ParseEntry(value, entry_def, entry);
1898b9c1b51eSKate Stone         } else if (sep_char == ':') {
1899b9c1b51eSKate Stone           // Any value whose separator is a with a ':' means this value has a
1900b9c1b51eSKate Stone           // string argument
1901b9c1b51eSKate Stone           // that needs to be stored in the entry (like
1902b9c1b51eSKate Stone           // "${script.var:modulename.function}")
19033a29f8b9SPavel Labath           entry.string = value.str();
1904b9c1b51eSKate Stone         } else {
1905b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1906b9c1b51eSKate Stone               "'%s' followed by '%s' but it has no children", key.str().c_str(),
1907554f68d3SGreg Clayton               value.str().c_str());
1908554f68d3SGreg Clayton         }
1909554f68d3SGreg Clayton       }
1910554f68d3SGreg Clayton       return error;
1911554f68d3SGreg Clayton     }
1912554f68d3SGreg Clayton   }
1913554f68d3SGreg Clayton   StreamString error_strm;
1914554f68d3SGreg Clayton   if (parent->type == FormatEntity::Entry::Type::Root)
1915b9c1b51eSKate Stone     error_strm.Printf(
1916b9c1b51eSKate Stone         "invalid top level item '%s'. Valid top level items are: ",
1917b9c1b51eSKate Stone         key.str().c_str());
1918554f68d3SGreg Clayton   else
1919b9c1b51eSKate Stone     error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
1920b9c1b51eSKate Stone                       key.str().c_str(), parent->name);
1921554f68d3SGreg Clayton   DumpCommaSeparatedChildEntryNames(error_strm, parent);
1922c156427dSZachary Turner   error.SetErrorStringWithFormat("%s", error_strm.GetData());
1923554f68d3SGreg Clayton   return error;
1924554f68d3SGreg Clayton }
1925554f68d3SGreg Clayton 
1926554f68d3SGreg Clayton static const FormatEntity::Entry::Definition *
1927b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str,
1928b9c1b51eSKate Stone           const FormatEntity::Entry::Definition *parent,
1929b9c1b51eSKate Stone           llvm::StringRef &remainder) {
1930554f68d3SGreg Clayton   Error error;
1931554f68d3SGreg Clayton 
1932554f68d3SGreg Clayton   std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
1933554f68d3SGreg Clayton   const size_t n = parent->num_children;
1934b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1935554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1936b9c1b51eSKate Stone     if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
1937b9c1b51eSKate Stone       if (p.second.empty()) {
1938554f68d3SGreg Clayton         if (format_str.back() == '.')
1939554f68d3SGreg Clayton           remainder = format_str.drop_front(format_str.size() - 1);
1940554f68d3SGreg Clayton         else
1941554f68d3SGreg Clayton           remainder = llvm::StringRef(); // Exact match
1942554f68d3SGreg Clayton         return entry_def;
1943b9c1b51eSKate Stone       } else {
1944b9c1b51eSKate Stone         if (entry_def->children) {
1945554f68d3SGreg Clayton           return FindEntry(p.second, entry_def, remainder);
1946b9c1b51eSKate Stone         } else {
1947554f68d3SGreg Clayton           remainder = p.second;
1948554f68d3SGreg Clayton           return entry_def;
1949554f68d3SGreg Clayton         }
1950554f68d3SGreg Clayton       }
1951554f68d3SGreg Clayton     }
1952554f68d3SGreg Clayton   }
1953554f68d3SGreg Clayton   remainder = format_str;
1954554f68d3SGreg Clayton   return parent;
1955554f68d3SGreg Clayton }
1956554f68d3SGreg Clayton 
1957b9c1b51eSKate Stone Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
1958b9c1b51eSKate Stone                                   uint32_t depth) {
1959554f68d3SGreg Clayton   Error error;
1960b9c1b51eSKate Stone   while (!format.empty() && error.Success()) {
1961554f68d3SGreg Clayton     const size_t non_special_chars = format.find_first_of("${}\\");
1962554f68d3SGreg Clayton 
1963b9c1b51eSKate Stone     if (non_special_chars == llvm::StringRef::npos) {
1964554f68d3SGreg Clayton       // No special characters, just string bytes so add them and we are done
1965554f68d3SGreg Clayton       parent_entry.AppendText(format);
1966554f68d3SGreg Clayton       return error;
1967554f68d3SGreg Clayton     }
1968554f68d3SGreg Clayton 
1969b9c1b51eSKate Stone     if (non_special_chars > 0) {
1970b9c1b51eSKate Stone       // We have a special character, so add all characters before these as a
1971b9c1b51eSKate Stone       // plain string
1972554f68d3SGreg Clayton       parent_entry.AppendText(format.substr(0, non_special_chars));
1973554f68d3SGreg Clayton       format = format.drop_front(non_special_chars);
1974554f68d3SGreg Clayton     }
1975554f68d3SGreg Clayton 
1976b9c1b51eSKate Stone     switch (format[0]) {
1977554f68d3SGreg Clayton     case '\0':
1978554f68d3SGreg Clayton       return error;
1979554f68d3SGreg Clayton 
1980b9c1b51eSKate Stone     case '{': {
1981554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '{'
1982554f68d3SGreg Clayton       Entry scope_entry(Entry::Type::Scope);
1983554f68d3SGreg Clayton       error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
1984554f68d3SGreg Clayton       if (error.Fail())
1985554f68d3SGreg Clayton         return error;
1986554f68d3SGreg Clayton       parent_entry.AppendEntry(std::move(scope_entry));
1987b9c1b51eSKate Stone     } break;
1988554f68d3SGreg Clayton 
1989554f68d3SGreg Clayton     case '}':
1990554f68d3SGreg Clayton       if (depth == 0)
1991554f68d3SGreg Clayton         error.SetErrorString("unmatched '}' character");
1992554f68d3SGreg Clayton       else
1993b9c1b51eSKate Stone         format =
1994b9c1b51eSKate Stone             format
1995b9c1b51eSKate Stone                 .drop_front(); // Skip the '}' as we are at the end of the scope
1996554f68d3SGreg Clayton       return error;
1997554f68d3SGreg Clayton 
1998b9c1b51eSKate Stone     case '\\': {
1999554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '\' character
2000b9c1b51eSKate Stone       if (format.empty()) {
2001b9c1b51eSKate Stone         error.SetErrorString(
2002b9c1b51eSKate Stone             "'\\' character was not followed by another character");
2003554f68d3SGreg Clayton         return error;
2004554f68d3SGreg Clayton       }
2005554f68d3SGreg Clayton 
2006554f68d3SGreg Clayton       const char desens_char = format[0];
2007554f68d3SGreg Clayton       format = format.drop_front(); // Skip the desensitized char character
2008b9c1b51eSKate Stone       switch (desens_char) {
2009b9c1b51eSKate Stone       case 'a':
2010b9c1b51eSKate Stone         parent_entry.AppendChar('\a');
2011b9c1b51eSKate Stone         break;
2012b9c1b51eSKate Stone       case 'b':
2013b9c1b51eSKate Stone         parent_entry.AppendChar('\b');
2014b9c1b51eSKate Stone         break;
2015b9c1b51eSKate Stone       case 'f':
2016b9c1b51eSKate Stone         parent_entry.AppendChar('\f');
2017b9c1b51eSKate Stone         break;
2018b9c1b51eSKate Stone       case 'n':
2019b9c1b51eSKate Stone         parent_entry.AppendChar('\n');
2020b9c1b51eSKate Stone         break;
2021b9c1b51eSKate Stone       case 'r':
2022b9c1b51eSKate Stone         parent_entry.AppendChar('\r');
2023b9c1b51eSKate Stone         break;
2024b9c1b51eSKate Stone       case 't':
2025b9c1b51eSKate Stone         parent_entry.AppendChar('\t');
2026b9c1b51eSKate Stone         break;
2027b9c1b51eSKate Stone       case 'v':
2028b9c1b51eSKate Stone         parent_entry.AppendChar('\v');
2029b9c1b51eSKate Stone         break;
2030b9c1b51eSKate Stone       case '\'':
2031b9c1b51eSKate Stone         parent_entry.AppendChar('\'');
2032b9c1b51eSKate Stone         break;
2033b9c1b51eSKate Stone       case '\\':
2034b9c1b51eSKate Stone         parent_entry.AppendChar('\\');
2035b9c1b51eSKate Stone         break;
2036554f68d3SGreg Clayton       case '0':
2037554f68d3SGreg Clayton         // 1 to 3 octal chars
2038554f68d3SGreg Clayton         {
2039554f68d3SGreg Clayton           // Make a string that can hold onto the initial zero char,
2040554f68d3SGreg Clayton           // up to 3 octal digits, and a terminating NULL.
2041554f68d3SGreg Clayton           char oct_str[5] = {0, 0, 0, 0, 0};
2042554f68d3SGreg Clayton 
2043554f68d3SGreg Clayton           int i;
2044554f68d3SGreg Clayton           for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2045554f68d3SGreg Clayton             oct_str[i] = format[i];
2046554f68d3SGreg Clayton 
2047554f68d3SGreg Clayton           // We don't want to consume the last octal character since
2048554f68d3SGreg Clayton           // the main for loop will do this for us, so we advance p by
2049554f68d3SGreg Clayton           // one less than i (even if i is zero)
2050554f68d3SGreg Clayton           format = format.drop_front(i);
2051a74f37a5SEugene Zelenko           unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2052b9c1b51eSKate Stone           if (octal_value <= UINT8_MAX) {
2053554f68d3SGreg Clayton             parent_entry.AppendChar((char)octal_value);
2054b9c1b51eSKate Stone           } else {
2055554f68d3SGreg Clayton             error.SetErrorString("octal number is larger than a single byte");
2056554f68d3SGreg Clayton             return error;
2057554f68d3SGreg Clayton           }
2058554f68d3SGreg Clayton         }
2059554f68d3SGreg Clayton         break;
2060554f68d3SGreg Clayton 
2061554f68d3SGreg Clayton       case 'x':
2062554f68d3SGreg Clayton         // hex number in the format
2063b9c1b51eSKate Stone         if (isxdigit(format[0])) {
2064554f68d3SGreg Clayton           // Make a string that can hold onto two hex chars plus a
2065554f68d3SGreg Clayton           // NULL terminator
2066554f68d3SGreg Clayton           char hex_str[3] = {0, 0, 0};
2067554f68d3SGreg Clayton           hex_str[0] = format[0];
2068554f68d3SGreg Clayton 
2069554f68d3SGreg Clayton           format = format.drop_front();
2070554f68d3SGreg Clayton 
2071b9c1b51eSKate Stone           if (isxdigit(format[0])) {
2072554f68d3SGreg Clayton             hex_str[1] = format[0];
2073554f68d3SGreg Clayton             format = format.drop_front();
2074554f68d3SGreg Clayton           }
2075554f68d3SGreg Clayton 
2076a74f37a5SEugene Zelenko           unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2077b9c1b51eSKate Stone           if (hex_value <= UINT8_MAX) {
2078554f68d3SGreg Clayton             parent_entry.AppendChar((char)hex_value);
2079b9c1b51eSKate Stone           } else {
2080554f68d3SGreg Clayton             error.SetErrorString("hex number is larger than a single byte");
2081554f68d3SGreg Clayton             return error;
2082554f68d3SGreg Clayton           }
2083b9c1b51eSKate Stone         } else {
2084554f68d3SGreg Clayton           parent_entry.AppendChar(desens_char);
2085554f68d3SGreg Clayton         }
2086554f68d3SGreg Clayton         break;
2087554f68d3SGreg Clayton 
2088554f68d3SGreg Clayton       default:
2089554f68d3SGreg Clayton         // Just desensitize any other character by just printing what
2090554f68d3SGreg Clayton         // came after the '\'
2091554f68d3SGreg Clayton         parent_entry.AppendChar(desens_char);
2092554f68d3SGreg Clayton         break;
2093554f68d3SGreg Clayton       }
2094b9c1b51eSKate Stone     } break;
2095554f68d3SGreg Clayton 
2096554f68d3SGreg Clayton     case '$':
2097b9c1b51eSKate Stone       if (format.size() == 1) {
2098554f68d3SGreg Clayton         // '$' at the end of a format string, just print the '$'
2099554f68d3SGreg Clayton         parent_entry.AppendText("$");
2100b9c1b51eSKate Stone       } else {
2101554f68d3SGreg Clayton         format = format.drop_front(); // Skip the '$'
2102554f68d3SGreg Clayton 
2103b9c1b51eSKate Stone         if (format[0] == '{') {
2104554f68d3SGreg Clayton           format = format.drop_front(); // Skip the '{'
2105554f68d3SGreg Clayton 
2106554f68d3SGreg Clayton           llvm::StringRef variable, variable_format;
2107b9c1b51eSKate Stone           error = FormatEntity::ExtractVariableInfo(format, variable,
2108b9c1b51eSKate Stone                                                     variable_format);
2109554f68d3SGreg Clayton           if (error.Fail())
2110554f68d3SGreg Clayton             return error;
2111554f68d3SGreg Clayton           bool verify_is_thread_id = false;
2112554f68d3SGreg Clayton           Entry entry;
2113b9c1b51eSKate Stone           if (!variable_format.empty()) {
21143a29f8b9SPavel Labath             entry.printf_format = variable_format.str();
2115554f68d3SGreg Clayton 
2116554f68d3SGreg Clayton             // If the format contains a '%' we are going to assume this is
2117554f68d3SGreg Clayton             // a printf style format. So if you want to format your thread ID
2118554f68d3SGreg Clayton             // using "0x%llx" you can use:
2119554f68d3SGreg Clayton             // ${thread.id%0x%llx}
2120554f68d3SGreg Clayton             //
2121554f68d3SGreg Clayton             // If there is no '%' in the format, then it is assumed to be a
2122554f68d3SGreg Clayton             // LLDB format name, or one of the extended formats specified in
2123554f68d3SGreg Clayton             // the switch statement below.
2124554f68d3SGreg Clayton 
2125b9c1b51eSKate Stone             if (entry.printf_format.find('%') == std::string::npos) {
2126554f68d3SGreg Clayton               bool clear_printf = false;
2127554f68d3SGreg Clayton 
2128b9c1b51eSKate Stone               if (FormatManager::GetFormatFromCString(
2129b9c1b51eSKate Stone                       entry.printf_format.c_str(), false, entry.fmt)) {
2130554f68d3SGreg Clayton                 // We have an LLDB format, so clear the printf format
2131554f68d3SGreg Clayton                 clear_printf = true;
2132b9c1b51eSKate Stone               } else if (entry.printf_format.size() == 1) {
2133b9c1b51eSKate Stone                 switch (entry.printf_format[0]) {
2134554f68d3SGreg Clayton                 case '@': // if this is an @ sign, print ObjC description
2135b9c1b51eSKate Stone                   entry.number = ValueObject::
2136b9c1b51eSKate Stone                       eValueObjectRepresentationStyleLanguageSpecific;
2137554f68d3SGreg Clayton                   clear_printf = true;
2138554f68d3SGreg Clayton                   break;
2139b9c1b51eSKate Stone                 case 'V': // if this is a V, print the value using the default
2140b9c1b51eSKate Stone                           // format
2141b9c1b51eSKate Stone                   entry.number =
2142b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleValue;
2143554f68d3SGreg Clayton                   clear_printf = true;
2144554f68d3SGreg Clayton                   break;
2145554f68d3SGreg Clayton                 case 'L': // if this is an L, print the location of the value
2146b9c1b51eSKate Stone                   entry.number =
2147b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleLocation;
2148554f68d3SGreg Clayton                   clear_printf = true;
2149554f68d3SGreg Clayton                   break;
2150554f68d3SGreg Clayton                 case 'S': // if this is an S, print the summary after all
2151b9c1b51eSKate Stone                   entry.number =
2152b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleSummary;
2153554f68d3SGreg Clayton                   clear_printf = true;
2154554f68d3SGreg Clayton                   break;
2155554f68d3SGreg Clayton                 case '#': // if this is a '#', print the number of children
2156b9c1b51eSKate Stone                   entry.number =
2157b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleChildrenCount;
2158554f68d3SGreg Clayton                   clear_printf = true;
2159554f68d3SGreg Clayton                   break;
2160554f68d3SGreg Clayton                 case 'T': // if this is a 'T', print the type
2161b9c1b51eSKate Stone                   entry.number =
2162b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleType;
2163554f68d3SGreg Clayton                   clear_printf = true;
2164554f68d3SGreg Clayton                   break;
2165554f68d3SGreg Clayton                 case 'N': // if this is a 'N', print the name
2166b9c1b51eSKate Stone                   entry.number =
2167b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleName;
2168554f68d3SGreg Clayton                   clear_printf = true;
2169554f68d3SGreg Clayton                   break;
2170281b65bcSGreg Clayton                 case '>': // if this is a '>', print the expression path
2171b9c1b51eSKate Stone                   entry.number = ValueObject::
2172b9c1b51eSKate Stone                       eValueObjectRepresentationStyleExpressionPath;
2173554f68d3SGreg Clayton                   clear_printf = true;
2174554f68d3SGreg Clayton                   break;
2175554f68d3SGreg Clayton                 default:
2176b9c1b51eSKate Stone                   error.SetErrorStringWithFormat("invalid format: '%s'",
2177b9c1b51eSKate Stone                                                  entry.printf_format.c_str());
2178554f68d3SGreg Clayton                   return error;
2179554f68d3SGreg Clayton                 }
2180b9c1b51eSKate Stone               } else if (FormatManager::GetFormatFromCString(
2181b9c1b51eSKate Stone                              entry.printf_format.c_str(), true, entry.fmt)) {
2182554f68d3SGreg Clayton                 clear_printf = true;
2183b9c1b51eSKate Stone               } else if (entry.printf_format == "tid") {
2184554f68d3SGreg Clayton                 verify_is_thread_id = true;
2185b9c1b51eSKate Stone               } else {
2186b9c1b51eSKate Stone                 error.SetErrorStringWithFormat("invalid format: '%s'",
2187b9c1b51eSKate Stone                                                entry.printf_format.c_str());
2188554f68d3SGreg Clayton                 return error;
2189554f68d3SGreg Clayton               }
2190554f68d3SGreg Clayton 
2191554f68d3SGreg Clayton               // Our format string turned out to not be a printf style format
2192554f68d3SGreg Clayton               // so lets clear the string
2193554f68d3SGreg Clayton               if (clear_printf)
2194554f68d3SGreg Clayton                 entry.printf_format.clear();
2195554f68d3SGreg Clayton             }
2196554f68d3SGreg Clayton           }
2197554f68d3SGreg Clayton 
2198554f68d3SGreg Clayton           // Check for dereferences
2199b9c1b51eSKate Stone           if (variable[0] == '*') {
2200554f68d3SGreg Clayton             entry.deref = true;
2201554f68d3SGreg Clayton             variable = variable.drop_front();
2202554f68d3SGreg Clayton           }
2203554f68d3SGreg Clayton 
2204554f68d3SGreg Clayton           error = ParseEntry(variable, &g_root, entry);
2205554f68d3SGreg Clayton           if (error.Fail())
2206554f68d3SGreg Clayton             return error;
2207554f68d3SGreg Clayton 
2208b9c1b51eSKate Stone           if (verify_is_thread_id) {
2209554f68d3SGreg Clayton             if (entry.type != Entry::Type::ThreadID &&
2210b9c1b51eSKate Stone                 entry.type != Entry::Type::ThreadProtocolID) {
2211b9c1b51eSKate Stone               error.SetErrorString("the 'tid' format can only be used on "
2212b9c1b51eSKate Stone                                    "${thread.id} and ${thread.protocol_id}");
2213554f68d3SGreg Clayton             }
2214554f68d3SGreg Clayton           }
2215554f68d3SGreg Clayton 
2216b9c1b51eSKate Stone           switch (entry.type) {
2217554f68d3SGreg Clayton           case Entry::Type::Variable:
2218554f68d3SGreg Clayton           case Entry::Type::VariableSynthetic:
2219b9c1b51eSKate Stone             if (entry.number == 0) {
2220554f68d3SGreg Clayton               if (entry.string.empty())
2221b9c1b51eSKate Stone                 entry.number =
2222b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleValue;
2223554f68d3SGreg Clayton               else
2224b9c1b51eSKate Stone                 entry.number =
2225b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleSummary;
2226554f68d3SGreg Clayton             }
2227554f68d3SGreg Clayton             break;
2228554f68d3SGreg Clayton           default:
2229b9c1b51eSKate Stone             // Make sure someone didn't try to dereference anything but ${var}
2230b9c1b51eSKate Stone             // or ${svar}
2231b9c1b51eSKate Stone             if (entry.deref) {
2232b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
2233b9c1b51eSKate Stone                   "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2234b9c1b51eSKate Stone                   variable.str().c_str());
2235554f68d3SGreg Clayton               return error;
2236554f68d3SGreg Clayton             }
2237554f68d3SGreg Clayton           }
2238554f68d3SGreg Clayton           // Check if this entry just wants to insert a constant string
2239554f68d3SGreg Clayton           // value into the parent_entry, if so, insert the string with
2240554f68d3SGreg Clayton           // AppendText, else append the entry to the parent_entry.
2241554f68d3SGreg Clayton           if (entry.type == Entry::Type::InsertString)
2242554f68d3SGreg Clayton             parent_entry.AppendText(entry.string.c_str());
2243554f68d3SGreg Clayton           else
2244554f68d3SGreg Clayton             parent_entry.AppendEntry(std::move(entry));
2245554f68d3SGreg Clayton         }
2246554f68d3SGreg Clayton       }
2247554f68d3SGreg Clayton       break;
2248554f68d3SGreg Clayton     }
2249554f68d3SGreg Clayton   }
2250554f68d3SGreg Clayton   return error;
2251554f68d3SGreg Clayton }
2252554f68d3SGreg Clayton 
2253b9c1b51eSKate Stone Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2254b9c1b51eSKate Stone                                         llvm::StringRef &variable_name,
2255b9c1b51eSKate Stone                                         llvm::StringRef &variable_format) {
2256554f68d3SGreg Clayton   Error error;
2257554f68d3SGreg Clayton   variable_name = llvm::StringRef();
2258554f68d3SGreg Clayton   variable_format = llvm::StringRef();
2259554f68d3SGreg Clayton 
2260e8433cc1SBruce Mitchener   const size_t paren_pos = format_str.find('}');
2261b9c1b51eSKate Stone   if (paren_pos != llvm::StringRef::npos) {
2262e8433cc1SBruce Mitchener     const size_t percent_pos = format_str.find('%');
2263b9c1b51eSKate Stone     if (percent_pos < paren_pos) {
2264b9c1b51eSKate Stone       if (percent_pos > 0) {
2265554f68d3SGreg Clayton         if (percent_pos > 1)
2266554f68d3SGreg Clayton           variable_name = format_str.substr(0, percent_pos);
2267b9c1b51eSKate Stone         variable_format =
2268b9c1b51eSKate Stone             format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2269554f68d3SGreg Clayton       }
2270b9c1b51eSKate Stone     } else {
2271554f68d3SGreg Clayton       variable_name = format_str.substr(0, paren_pos);
2272554f68d3SGreg Clayton     }
2273554f68d3SGreg Clayton     // Strip off elements and the formatting and the trailing '}'
2274554f68d3SGreg Clayton     format_str = format_str.substr(paren_pos + 1);
2275b9c1b51eSKate Stone   } else {
2276b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
2277b9c1b51eSKate Stone         "missing terminating '}' character for '${%s'",
2278b9c1b51eSKate Stone         format_str.str().c_str());
2279554f68d3SGreg Clayton   }
2280554f68d3SGreg Clayton   return error;
2281554f68d3SGreg Clayton }
2282554f68d3SGreg Clayton 
2283b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
2284b9c1b51eSKate Stone                                   llvm::StringRef variable_name,
2285b9c1b51eSKate Stone                                   llvm::StringRef variable_format) {
2286b9c1b51eSKate Stone   if (variable_name.empty() || variable_name.equals(".fullpath")) {
2287554f68d3SGreg Clayton     file_spec.Dump(&s);
2288554f68d3SGreg Clayton     return true;
2289b9c1b51eSKate Stone   } else if (variable_name.equals(".basename")) {
2290554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2291554f68d3SGreg Clayton     return true;
2292b9c1b51eSKate Stone   } else if (variable_name.equals(".dirname")) {
2293554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2294554f68d3SGreg Clayton     return true;
2295554f68d3SGreg Clayton   }
2296554f68d3SGreg Clayton   return false;
2297554f68d3SGreg Clayton }
2298554f68d3SGreg Clayton 
2299b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix,
2300b9c1b51eSKate Stone                              const char *suffix) {
2301554f68d3SGreg Clayton   std::string match(prefix.str());
2302554f68d3SGreg Clayton   match.append(suffix);
23033a29f8b9SPavel Labath   return match;
2304554f68d3SGreg Clayton }
2305554f68d3SGreg Clayton 
2306b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def,
2307554f68d3SGreg Clayton                        const llvm::StringRef &prefix,
2308554f68d3SGreg Clayton                        const llvm::StringRef &match_prefix,
2309b9c1b51eSKate Stone                        StringList &matches) {
2310554f68d3SGreg Clayton   const size_t n = def->num_children;
2311b9c1b51eSKate Stone   if (n > 0) {
2312b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
23133a29f8b9SPavel Labath       std::string match = prefix.str();
2314554f68d3SGreg Clayton       if (match_prefix.empty())
2315554f68d3SGreg Clayton         matches.AppendString(MakeMatch(prefix, def->children[i].name));
2316b9c1b51eSKate Stone       else if (strncmp(def->children[i].name, match_prefix.data(),
2317b9c1b51eSKate Stone                        match_prefix.size()) == 0)
2318b9c1b51eSKate Stone         matches.AppendString(
2319b9c1b51eSKate Stone             MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2320554f68d3SGreg Clayton     }
2321554f68d3SGreg Clayton   }
2322554f68d3SGreg Clayton }
2323a74f37a5SEugene Zelenko 
23244aa8753cSZachary Turner size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point,
2325b9c1b51eSKate Stone                                   int max_return_elements, bool &word_complete,
2326b9c1b51eSKate Stone                                   StringList &matches) {
2327554f68d3SGreg Clayton   word_complete = false;
23284aa8753cSZachary Turner   str = str.drop_front(match_start_point);
2329554f68d3SGreg Clayton   matches.Clear();
2330554f68d3SGreg Clayton 
2331554f68d3SGreg Clayton   const size_t dollar_pos = str.rfind('$');
23324aa8753cSZachary Turner   if (dollar_pos == llvm::StringRef::npos)
23334aa8753cSZachary Turner     return 0;
23344aa8753cSZachary Turner 
2335554f68d3SGreg Clayton   // Hitting TAB after $ at the end of the string add a "{"
2336b9c1b51eSKate Stone   if (dollar_pos == str.size() - 1) {
23373a29f8b9SPavel Labath     std::string match = str.str();
2338554f68d3SGreg Clayton     match.append("{");
23394aa8753cSZachary Turner     matches.AppendString(match);
23404aa8753cSZachary Turner     return 1;
23414aa8753cSZachary Turner   }
23424aa8753cSZachary Turner 
23434aa8753cSZachary Turner   if (str[dollar_pos + 1] != '{')
23444aa8753cSZachary Turner     return 0;
23454aa8753cSZachary Turner 
2346554f68d3SGreg Clayton   const size_t close_pos = str.find('}', dollar_pos + 2);
23474aa8753cSZachary Turner   if (close_pos != llvm::StringRef::npos)
23484aa8753cSZachary Turner     return 0;
23494aa8753cSZachary Turner 
2350554f68d3SGreg Clayton   const size_t format_pos = str.find('%', dollar_pos + 2);
23514aa8753cSZachary Turner   if (format_pos != llvm::StringRef::npos)
23524aa8753cSZachary Turner     return 0;
23534aa8753cSZachary Turner 
2354554f68d3SGreg Clayton   llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2355b9c1b51eSKate Stone   if (partial_variable.empty()) {
2356554f68d3SGreg Clayton     // Suggest all top level entites as we are just past "${"
2357554f68d3SGreg Clayton     AddMatches(&g_root, str, llvm::StringRef(), matches);
23584aa8753cSZachary Turner     return matches.GetSize();
23594aa8753cSZachary Turner   }
23604aa8753cSZachary Turner 
2361554f68d3SGreg Clayton   // We have a partially specified variable, find it
2362554f68d3SGreg Clayton   llvm::StringRef remainder;
2363b9c1b51eSKate Stone   const FormatEntity::Entry::Definition *entry_def =
2364b9c1b51eSKate Stone       FindEntry(partial_variable, &g_root, remainder);
23654aa8753cSZachary Turner   if (!entry_def)
23664aa8753cSZachary Turner     return 0;
23674aa8753cSZachary Turner 
2368554f68d3SGreg Clayton   const size_t n = entry_def->num_children;
2369554f68d3SGreg Clayton 
2370b9c1b51eSKate Stone   if (remainder.empty()) {
2371554f68d3SGreg Clayton     // Exact match
2372b9c1b51eSKate Stone     if (n > 0) {
2373554f68d3SGreg Clayton       // "${thread.info" <TAB>
23743a29f8b9SPavel Labath       matches.AppendString(MakeMatch(str, "."));
2375b9c1b51eSKate Stone     } else {
2376554f68d3SGreg Clayton       // "${thread.id" <TAB>
23773a29f8b9SPavel Labath       matches.AppendString(MakeMatch(str, "}"));
2378554f68d3SGreg Clayton       word_complete = true;
2379554f68d3SGreg Clayton     }
2380b9c1b51eSKate Stone   } else if (remainder.equals(".")) {
2381554f68d3SGreg Clayton     // "${thread." <TAB>
2382554f68d3SGreg Clayton     AddMatches(entry_def, str, llvm::StringRef(), matches);
2383b9c1b51eSKate Stone   } else {
2384554f68d3SGreg Clayton     // We have a partial match
2385554f68d3SGreg Clayton     // "${thre" <TAB>
2386554f68d3SGreg Clayton     AddMatches(entry_def, str, remainder, matches);
2387554f68d3SGreg Clayton   }
2388554f68d3SGreg Clayton   return matches.GetSize();
2389554f68d3SGreg Clayton }
2390