1554f68d3SGreg Clayton //===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===//
2554f68d3SGreg Clayton //
3554f68d3SGreg Clayton //                     The LLVM Compiler Infrastructure
4554f68d3SGreg Clayton //
5554f68d3SGreg Clayton // This file is distributed under the University of Illinois Open Source
6554f68d3SGreg Clayton // License. See LICENSE.TXT for details.
7554f68d3SGreg Clayton //
8554f68d3SGreg Clayton //===----------------------------------------------------------------------===//
9554f68d3SGreg Clayton 
10554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h"
11554f68d3SGreg Clayton 
12554f68d3SGreg Clayton #include "lldb/Core/Address.h"
132f3df613SZachary Turner #include "lldb/Core/AddressRange.h" // for AddressRange
14554f68d3SGreg Clayton #include "lldb/Core/Debugger.h"
15554f68d3SGreg Clayton #include "lldb/Core/Module.h"
162f3df613SZachary Turner #include "lldb/Core/RegisterValue.h" // for RegisterValue
17554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h"
18554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h"
19554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h"
202f3df613SZachary Turner #include "lldb/DataFormatters/FormatClasses.h" // for TypeNameSpecifier...
21554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h"
222f3df613SZachary Turner #include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryImpl::...
23937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h"
24554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
25554f68d3SGreg Clayton #include "lldb/Symbol/Block.h"
26554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
272f3df613SZachary Turner #include "lldb/Symbol/CompilerType.h" // for CompilerType
28554f68d3SGreg Clayton #include "lldb/Symbol/Function.h"
29554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h"
30554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h"
312f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext
32554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h"
33554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h"
342f3df613SZachary Turner #include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextS...
350e0984eeSJim Ingham #include "lldb/Target/Language.h"
36554f68d3SGreg Clayton #include "lldb/Target/Process.h"
37554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h"
38554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h"
39554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h"
40554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h"
41554f68d3SGreg Clayton #include "lldb/Target/Target.h"
42554f68d3SGreg Clayton #include "lldb/Target/Thread.h"
43554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
445f19b907SPavel Labath #include "lldb/Utility/ArchSpec.h"    // for ArchSpec
452f3df613SZachary Turner #include "lldb/Utility/ConstString.h" // for ConstString, oper...
465713a05bSZachary Turner #include "lldb/Utility/FileSpec.h"
472f3df613SZachary Turner #include "lldb/Utility/Log.h"        // for Log
482f3df613SZachary Turner #include "lldb/Utility/Logging.h"    // for GetLogIfAllCatego...
492f3df613SZachary Turner #include "lldb/Utility/SharingPtr.h" // for SharingPtr
50bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
51bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
522f3df613SZachary Turner #include "lldb/Utility/StringList.h"     // for StringList
53f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h" // for StructuredData::O...
542f3df613SZachary Turner #include "lldb/lldb-defines.h"           // for LLDB_INVALID_ADDRESS
552f3df613SZachary Turner #include "lldb/lldb-forward.h"           // for ValueObjectSP
562f3df613SZachary Turner #include "llvm/ADT/STLExtras.h"
572f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
582f3df613SZachary Turner #include "llvm/ADT/Triple.h"       // for Triple, Triple::O...
592f3df613SZachary Turner #include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
602f3df613SZachary Turner 
612f3df613SZachary Turner #include <ctype.h>     // for isxdigit
622f3df613SZachary Turner #include <inttypes.h>  // for PRIu64, PRIx64
632f3df613SZachary Turner #include <memory>      // for shared_ptr, opera...
642f3df613SZachary Turner #include <stdio.h>     // for sprintf
652f3df613SZachary Turner #include <stdlib.h>    // for strtoul
662f3df613SZachary Turner #include <string.h>    // for size_t, strchr
672f3df613SZachary Turner #include <type_traits> // for move
682f3df613SZachary Turner #include <utility>     // for pair
692f3df613SZachary Turner 
702f3df613SZachary Turner namespace lldb_private {
712f3df613SZachary Turner class ScriptInterpreter;
722f3df613SZachary Turner }
732f3df613SZachary Turner namespace lldb_private {
742f3df613SZachary Turner struct RegisterInfo;
752f3df613SZachary Turner }
76554f68d3SGreg Clayton 
77554f68d3SGreg Clayton using namespace lldb;
78554f68d3SGreg Clayton using namespace lldb_private;
79554f68d3SGreg Clayton 
80b9c1b51eSKate Stone enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
81554f68d3SGreg Clayton 
82b9c1b51eSKate Stone #define ENTRY(n, t, f)                                                         \
83b9c1b51eSKate Stone   {                                                                            \
84b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
85b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false               \
86b9c1b51eSKate Stone   }
87b9c1b51eSKate Stone #define ENTRY_VALUE(n, t, f, v)                                                \
88b9c1b51eSKate Stone   {                                                                            \
89b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
90b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::f, v, 0, nullptr, false               \
91b9c1b51eSKate Stone   }
92b9c1b51eSKate Stone #define ENTRY_CHILDREN(n, t, f, c)                                             \
93b9c1b51eSKate Stone   {                                                                            \
94b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
95e28558f0SZachary Turner         FormatEntity::Entry::FormatType::f, 0,                                 \
96e28558f0SZachary Turner         static_cast<uint32_t>(llvm::array_lengthof(c)), c, false               \
97b9c1b51eSKate Stone   }
98b9c1b51eSKate Stone #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c)                                    \
99b9c1b51eSKate Stone   {                                                                            \
100b9c1b51eSKate Stone     n, nullptr, FormatEntity::Entry::Type::t,                                  \
101e28558f0SZachary Turner         FormatEntity::Entry::FormatType::f, 0,                                 \
102e28558f0SZachary Turner         static_cast<uint32_t>(llvm::array_lengthof(c)), c, true                \
103b9c1b51eSKate Stone   }
104b9c1b51eSKate Stone #define ENTRY_STRING(n, s)                                                     \
105b9c1b51eSKate Stone   {                                                                            \
106b9c1b51eSKate Stone     n, s, FormatEntity::Entry::Type::InsertString,                             \
107b9c1b51eSKate Stone         FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false            \
108b9c1b51eSKate Stone   }
109b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_string_entry[] = {
110b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
111554f68d3SGreg Clayton 
112b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_addr_entries[] = {
113b9c1b51eSKate Stone     ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64),
114554f68d3SGreg Clayton     ENTRY("load", AddressLoadOrFile, UInt64),
115554f68d3SGreg Clayton };
116554f68d3SGreg Clayton 
117b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_file_child_entries[] = {
118554f68d3SGreg Clayton     ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename),
119554f68d3SGreg Clayton     ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname),
120b9c1b51eSKate Stone     ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)};
121554f68d3SGreg Clayton 
122b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_frame_child_entries[] = {
123554f68d3SGreg Clayton     ENTRY("index", FrameIndex, UInt32),
124554f68d3SGreg Clayton     ENTRY("pc", FrameRegisterPC, UInt64),
125554f68d3SGreg Clayton     ENTRY("fp", FrameRegisterFP, UInt64),
126554f68d3SGreg Clayton     ENTRY("sp", FrameRegisterSP, UInt64),
127554f68d3SGreg Clayton     ENTRY("flags", FrameRegisterFlags, UInt64),
1286a9767c7SJim Ingham     ENTRY("no-debug", FrameNoDebug, None),
129554f68d3SGreg Clayton     ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry),
130554f68d3SGreg Clayton };
131554f68d3SGreg Clayton 
132b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_function_child_entries[] = {
133b9c1b51eSKate Stone     ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString),
134554f68d3SGreg Clayton     ENTRY("name-without-args", FunctionNameNoArgs, CString),
135554f68d3SGreg Clayton     ENTRY("name-with-args", FunctionNameWithArgs, CString),
136554f68d3SGreg Clayton     ENTRY("addr-offset", FunctionAddrOffset, UInt64),
137b9c1b51eSKate Stone     ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete,
138b9c1b51eSKate Stone           UInt64),
139554f68d3SGreg Clayton     ENTRY("line-offset", FunctionLineOffset, UInt64),
140c980fa92SJason Molenda     ENTRY("pc-offset", FunctionPCOffset, UInt64),
141c980fa92SJason Molenda     ENTRY("initial-function", FunctionInitial, None),
1426ab659a9SJason Molenda     ENTRY("changed", FunctionChanged, None),
143b9c1b51eSKate Stone     ENTRY("is-optimized", FunctionIsOptimized, None)};
144554f68d3SGreg Clayton 
145b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_line_child_entries[] = {
146554f68d3SGreg Clayton     ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries),
147554f68d3SGreg Clayton     ENTRY("number", LineEntryLineNumber, UInt32),
148554f68d3SGreg Clayton     ENTRY("start-addr", LineEntryStartAddress, UInt64),
149554f68d3SGreg Clayton     ENTRY("end-addr", LineEntryEndAddress, UInt64),
150554f68d3SGreg Clayton };
151554f68d3SGreg Clayton 
152b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_module_child_entries[] = {
153554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
154554f68d3SGreg Clayton };
155554f68d3SGreg Clayton 
156b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_process_child_entries[] = {
157554f68d3SGreg Clayton     ENTRY("id", ProcessID, UInt64),
158554f68d3SGreg Clayton     ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename),
159554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries),
160554f68d3SGreg Clayton };
161554f68d3SGreg Clayton 
162b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_svar_child_entries[] = {
163b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
164554f68d3SGreg Clayton 
165b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_var_child_entries[] = {
166b9c1b51eSKate Stone     ENTRY("*", ParentString, None)};
167554f68d3SGreg Clayton 
168b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_thread_child_entries[] = {
169554f68d3SGreg Clayton     ENTRY("id", ThreadID, UInt64),
170554f68d3SGreg Clayton     ENTRY("protocol_id", ThreadProtocolID, UInt64),
171554f68d3SGreg Clayton     ENTRY("index", ThreadIndexID, UInt32),
172554f68d3SGreg Clayton     ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry),
173554f68d3SGreg Clayton     ENTRY("queue", ThreadQueue, CString),
174554f68d3SGreg Clayton     ENTRY("name", ThreadName, CString),
175554f68d3SGreg Clayton     ENTRY("stop-reason", ThreadStopReason, CString),
176554f68d3SGreg Clayton     ENTRY("return-value", ThreadReturnValue, CString),
177554f68d3SGreg Clayton     ENTRY("completed-expression", ThreadCompletedExpression, CString),
178554f68d3SGreg Clayton };
179554f68d3SGreg Clayton 
180b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_target_child_entries[] = {
181554f68d3SGreg Clayton     ENTRY("arch", TargetArch, CString),
182554f68d3SGreg Clayton };
183554f68d3SGreg Clayton 
184554f68d3SGreg Clayton #define _TO_STR2(_val) #_val
185554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val)
186554f68d3SGreg Clayton 
187b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
188b9c1b51eSKate Stone     ENTRY_STRING("black",
189b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
190554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
191b9c1b51eSKate Stone     ENTRY_STRING("green",
192b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
193b9c1b51eSKate Stone     ENTRY_STRING("yellow",
194b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
195b9c1b51eSKate Stone     ENTRY_STRING("blue",
196b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
197b9c1b51eSKate Stone     ENTRY_STRING("purple",
198b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
199b9c1b51eSKate Stone     ENTRY_STRING("cyan",
200b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
201b9c1b51eSKate Stone     ENTRY_STRING("white",
202b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
203554f68d3SGreg Clayton };
204554f68d3SGreg Clayton 
205b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
206b9c1b51eSKate Stone     ENTRY_STRING("black",
207b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
208554f68d3SGreg Clayton     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
209b9c1b51eSKate Stone     ENTRY_STRING("green",
210b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
211b9c1b51eSKate Stone     ENTRY_STRING("yellow",
212b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
213b9c1b51eSKate Stone     ENTRY_STRING("blue",
214b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
215b9c1b51eSKate Stone     ENTRY_STRING("purple",
216b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
217b9c1b51eSKate Stone     ENTRY_STRING("cyan",
218b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
219b9c1b51eSKate Stone     ENTRY_STRING("white",
220b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
221554f68d3SGreg Clayton };
222554f68d3SGreg Clayton 
223b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_ansi_entries[] = {
224554f68d3SGreg Clayton     ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries),
225554f68d3SGreg Clayton     ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries),
226b9c1b51eSKate Stone     ENTRY_STRING("normal",
227b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
228554f68d3SGreg Clayton     ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
229554f68d3SGreg Clayton     ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
230b9c1b51eSKate Stone     ENTRY_STRING("italic",
231b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
232b9c1b51eSKate Stone     ENTRY_STRING("underline",
233b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
234b9c1b51eSKate Stone     ENTRY_STRING("slow-blink",
235b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
236b9c1b51eSKate Stone     ENTRY_STRING("fast-blink",
237b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
238b9c1b51eSKate Stone     ENTRY_STRING("negative",
239b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
240b9c1b51eSKate Stone     ENTRY_STRING("conceal",
241b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
242b9c1b51eSKate Stone     ENTRY_STRING("crossed-out",
243b9c1b51eSKate Stone                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
244554f68d3SGreg Clayton };
245554f68d3SGreg Clayton 
246b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_script_child_entries[] = {
247554f68d3SGreg Clayton     ENTRY("frame", ScriptFrame, None),
248554f68d3SGreg Clayton     ENTRY("process", ScriptProcess, None),
249554f68d3SGreg Clayton     ENTRY("target", ScriptTarget, None),
250554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
251554f68d3SGreg Clayton     ENTRY("var", ScriptVariable, None),
252554f68d3SGreg Clayton     ENTRY("svar", ScriptVariableSynthetic, None),
253554f68d3SGreg Clayton     ENTRY("thread", ScriptThread, None),
254554f68d3SGreg Clayton };
255554f68d3SGreg Clayton 
256b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_top_level_entries[] = {
257554f68d3SGreg Clayton     ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries),
258554f68d3SGreg Clayton     ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64),
259554f68d3SGreg Clayton     ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries),
260554f68d3SGreg Clayton     ENTRY("current-pc-arrow", CurrentPCArrow, CString),
261554f68d3SGreg Clayton     ENTRY_CHILDREN("file", File, CString, g_file_child_entries),
262dc975670SDawn Perchik     ENTRY("language", Lang, CString),
263554f68d3SGreg Clayton     ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries),
264554f68d3SGreg Clayton     ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries),
265554f68d3SGreg Clayton     ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries),
266554f68d3SGreg Clayton     ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries),
267554f68d3SGreg Clayton     ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries),
268554f68d3SGreg Clayton     ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries),
269b9c1b51eSKate Stone     ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None,
270b9c1b51eSKate Stone                             g_svar_child_entries),
271554f68d3SGreg Clayton     ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries),
272554f68d3SGreg Clayton     ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries),
273554f68d3SGreg Clayton     ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries),
274554f68d3SGreg Clayton };
275554f68d3SGreg Clayton 
276b9c1b51eSKate Stone static FormatEntity::Entry::Definition g_root =
277b9c1b51eSKate Stone     ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries);
278554f68d3SGreg Clayton 
279b9c1b51eSKate Stone FormatEntity::Entry::Entry(llvm::StringRef s)
280b9c1b51eSKate Stone     : string(s.data(), s.size()), printf_format(), children(),
281b9c1b51eSKate Stone       definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
282b9c1b51eSKate Stone       number(0), deref(false) {}
283554f68d3SGreg Clayton 
284b9c1b51eSKate Stone FormatEntity::Entry::Entry(char ch)
285b9c1b51eSKate Stone     : string(1, ch), printf_format(), children(), definition(nullptr),
286b9c1b51eSKate Stone       type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
287554f68d3SGreg Clayton 
288b9c1b51eSKate Stone void FormatEntity::Entry::AppendChar(char ch) {
289554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
290554f68d3SGreg Clayton     children.push_back(Entry(ch));
291554f68d3SGreg Clayton   else
292554f68d3SGreg Clayton     children.back().string.append(1, ch);
293554f68d3SGreg Clayton }
294554f68d3SGreg Clayton 
295b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
296554f68d3SGreg Clayton   if (children.empty() || children.back().type != Entry::Type::String)
297554f68d3SGreg Clayton     children.push_back(Entry(s));
298554f68d3SGreg Clayton   else
299554f68d3SGreg Clayton     children.back().string.append(s.data(), s.size());
300554f68d3SGreg Clayton }
301554f68d3SGreg Clayton 
302b9c1b51eSKate Stone void FormatEntity::Entry::AppendText(const char *cstr) {
303554f68d3SGreg Clayton   return AppendText(llvm::StringRef(cstr));
304554f68d3SGreg Clayton }
305554f68d3SGreg Clayton 
30697206d57SZachary Turner Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
307554f68d3SGreg Clayton   entry.Clear();
308554f68d3SGreg Clayton   entry.type = Entry::Type::Root;
309554f68d3SGreg Clayton   llvm::StringRef modifiable_format(format_str);
310554f68d3SGreg Clayton   return ParseInternal(modifiable_format, entry, 0);
311554f68d3SGreg Clayton }
312554f68d3SGreg Clayton 
313b9c1b51eSKate Stone #define ENUM_TO_CSTR(eee)                                                      \
314b9c1b51eSKate Stone   case FormatEntity::Entry::Type::eee:                                         \
315b9c1b51eSKate Stone     return #eee
316554f68d3SGreg Clayton 
317b9c1b51eSKate Stone const char *FormatEntity::Entry::TypeToCString(Type t) {
318b9c1b51eSKate Stone   switch (t) {
319554f68d3SGreg Clayton     ENUM_TO_CSTR(Invalid);
320554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentNumber);
321554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentString);
322554f68d3SGreg Clayton     ENUM_TO_CSTR(InsertString);
323554f68d3SGreg Clayton     ENUM_TO_CSTR(Root);
324554f68d3SGreg Clayton     ENUM_TO_CSTR(String);
325554f68d3SGreg Clayton     ENUM_TO_CSTR(Scope);
326554f68d3SGreg Clayton     ENUM_TO_CSTR(Variable);
327554f68d3SGreg Clayton     ENUM_TO_CSTR(VariableSynthetic);
328554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariable);
329554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariableSynthetic);
330554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoad);
331554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressFile);
332554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoadOrFile);
333554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessID);
334554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessFile);
335554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptProcess);
336554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadID);
337554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadProtocolID);
338554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadIndexID);
339554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadName);
340554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadQueue);
341554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadStopReason);
342554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadReturnValue);
343554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadCompletedExpression);
344554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptThread);
345554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadInfo);
346554f68d3SGreg Clayton     ENUM_TO_CSTR(TargetArch);
347554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptTarget);
348554f68d3SGreg Clayton     ENUM_TO_CSTR(ModuleFile);
349554f68d3SGreg Clayton     ENUM_TO_CSTR(File);
350dc975670SDawn Perchik     ENUM_TO_CSTR(Lang);
351554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameIndex);
3526a9767c7SJim Ingham     ENUM_TO_CSTR(FrameNoDebug);
353554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterPC);
354554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterSP);
355554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFP);
356554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFlags);
357554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterByName);
358554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptFrame);
359554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionID);
360554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionDidChange);
361554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionInitialFunction);
362554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionName);
363554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameWithArgs);
364554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameNoArgs);
365554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffset);
366554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
367554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionLineOffset);
368554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionPCOffset);
369c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionInitial);
370c980fa92SJason Molenda     ENUM_TO_CSTR(FunctionChanged);
3716ab659a9SJason Molenda     ENUM_TO_CSTR(FunctionIsOptimized);
372554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryFile);
373554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryLineNumber);
374554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryStartAddress);
375554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryEndAddress);
376554f68d3SGreg Clayton     ENUM_TO_CSTR(CurrentPCArrow);
377554f68d3SGreg Clayton   }
378554f68d3SGreg Clayton   return "???";
379554f68d3SGreg Clayton }
380554f68d3SGreg Clayton 
381554f68d3SGreg Clayton #undef ENUM_TO_CSTR
382554f68d3SGreg Clayton 
383b9c1b51eSKate Stone void FormatEntity::Entry::Dump(Stream &s, int depth) const {
384554f68d3SGreg Clayton   s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
385554f68d3SGreg Clayton   if (fmt != eFormatDefault)
386554f68d3SGreg Clayton     s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
387554f68d3SGreg Clayton   if (!string.empty())
388554f68d3SGreg Clayton     s.Printf("string = \"%s\"", string.c_str());
389554f68d3SGreg Clayton   if (!printf_format.empty())
390554f68d3SGreg Clayton     s.Printf("printf_format = \"%s\"", printf_format.c_str());
391554f68d3SGreg Clayton   if (number != 0)
392554f68d3SGreg Clayton     s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
393554f68d3SGreg Clayton   if (deref)
394554f68d3SGreg Clayton     s.Printf("deref = true, ");
395554f68d3SGreg Clayton   s.EOL();
396b9c1b51eSKate Stone   for (const auto &child : children) {
397554f68d3SGreg Clayton     child.Dump(s, depth + 1);
398554f68d3SGreg Clayton   }
399554f68d3SGreg Clayton }
400554f68d3SGreg Clayton 
401554f68d3SGreg Clayton template <typename T>
402b9c1b51eSKate Stone static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
403b9c1b51eSKate Stone                                    const ExecutionContext *exe_ctx, T t,
404b9c1b51eSKate Stone                                    const char *script_function_name) {
405554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
406554f68d3SGreg Clayton 
407b9c1b51eSKate Stone   if (target) {
408b9c1b51eSKate Stone     ScriptInterpreter *script_interpreter =
409b9c1b51eSKate Stone         target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
410b9c1b51eSKate Stone     if (script_interpreter) {
41197206d57SZachary Turner       Status error;
412554f68d3SGreg Clayton       std::string script_output;
413554f68d3SGreg Clayton 
414b9c1b51eSKate Stone       if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
415b9c1b51eSKate Stone                                                      script_output, error) &&
416b9c1b51eSKate Stone           error.Success()) {
417554f68d3SGreg Clayton         s.Printf("%s", script_output.c_str());
418554f68d3SGreg Clayton         return true;
419b9c1b51eSKate Stone       } else {
420554f68d3SGreg Clayton         s.Printf("<error: %s>", error.AsCString());
421554f68d3SGreg Clayton       }
422554f68d3SGreg Clayton     }
423554f68d3SGreg Clayton   }
424554f68d3SGreg Clayton   return false;
425554f68d3SGreg Clayton }
426554f68d3SGreg Clayton 
427b9c1b51eSKate Stone static bool DumpAddress(Stream &s, const SymbolContext *sc,
428b9c1b51eSKate Stone                         const ExecutionContext *exe_ctx, const Address &addr,
429b9c1b51eSKate Stone                         bool print_file_addr_or_load_addr) {
430554f68d3SGreg Clayton   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
431554f68d3SGreg Clayton   addr_t vaddr = LLDB_INVALID_ADDRESS;
432554f68d3SGreg Clayton   if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
433554f68d3SGreg Clayton     vaddr = addr.GetLoadAddress(target);
434554f68d3SGreg Clayton   if (vaddr == LLDB_INVALID_ADDRESS)
435554f68d3SGreg Clayton     vaddr = addr.GetFileAddress();
436554f68d3SGreg Clayton 
437b9c1b51eSKate Stone   if (vaddr != LLDB_INVALID_ADDRESS) {
438554f68d3SGreg Clayton     int addr_width = 0;
439b9c1b51eSKate Stone     if (exe_ctx && target) {
440554f68d3SGreg Clayton       addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
441554f68d3SGreg Clayton     }
442554f68d3SGreg Clayton     if (addr_width == 0)
443554f68d3SGreg Clayton       addr_width = 16;
444b9c1b51eSKate Stone     if (print_file_addr_or_load_addr) {
445a74f37a5SEugene Zelenko       ExecutionContextScope *exe_scope = nullptr;
446554f68d3SGreg Clayton       if (exe_ctx)
447554f68d3SGreg Clayton         exe_scope = exe_ctx->GetBestExecutionContextScope();
448b9c1b51eSKate Stone       addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
449b9c1b51eSKate Stone                 Address::DumpStyleModuleWithFileAddress, 0);
450b9c1b51eSKate Stone     } else {
451554f68d3SGreg Clayton       s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
452554f68d3SGreg Clayton     }
453554f68d3SGreg Clayton     return true;
454554f68d3SGreg Clayton   }
455554f68d3SGreg Clayton   return false;
456554f68d3SGreg Clayton }
457554f68d3SGreg Clayton 
458b9c1b51eSKate Stone static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
459554f68d3SGreg Clayton                                           const ExecutionContext *exe_ctx,
460554f68d3SGreg Clayton                                           const Address &format_addr,
461b9c1b51eSKate Stone                                           bool concrete_only, bool no_padding,
462b9c1b51eSKate Stone                                           bool print_zero_offsets) {
463b9c1b51eSKate Stone   if (format_addr.IsValid()) {
464554f68d3SGreg Clayton     Address func_addr;
465554f68d3SGreg Clayton 
466b9c1b51eSKate Stone     if (sc) {
467b9c1b51eSKate Stone       if (sc->function) {
468554f68d3SGreg Clayton         func_addr = sc->function->GetAddressRange().GetBaseAddress();
469b9c1b51eSKate Stone         if (sc->block && !concrete_only) {
47005097246SAdrian Prantl           // Check to make sure we aren't in an inline function. If we are, use
47105097246SAdrian Prantl           // the inline block range that contains "format_addr" since blocks
47205097246SAdrian Prantl           // can be discontiguous.
473554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
474554f68d3SGreg Clayton           AddressRange inline_range;
475b9c1b51eSKate Stone           if (inline_block &&
476b9c1b51eSKate Stone               inline_block->GetRangeContainingAddress(format_addr,
477b9c1b51eSKate Stone                                                       inline_range))
478554f68d3SGreg Clayton             func_addr = inline_range.GetBaseAddress();
479554f68d3SGreg Clayton         }
480b9c1b51eSKate Stone       } else if (sc->symbol && sc->symbol->ValueIsAddress())
481358cf1eaSGreg Clayton         func_addr = sc->symbol->GetAddressRef();
482554f68d3SGreg Clayton     }
483554f68d3SGreg Clayton 
484b9c1b51eSKate Stone     if (func_addr.IsValid()) {
485554f68d3SGreg Clayton       const char *addr_offset_padding = no_padding ? "" : " ";
486554f68d3SGreg Clayton 
487b9c1b51eSKate Stone       if (func_addr.GetSection() == format_addr.GetSection()) {
488554f68d3SGreg Clayton         addr_t func_file_addr = func_addr.GetFileAddress();
489554f68d3SGreg Clayton         addr_t addr_file_addr = format_addr.GetFileAddress();
490b9c1b51eSKate Stone         if (addr_file_addr > func_file_addr ||
491b9c1b51eSKate Stone             (addr_file_addr == func_file_addr && print_zero_offsets)) {
492b9c1b51eSKate Stone           s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
493b9c1b51eSKate Stone                    addr_file_addr - func_file_addr);
494b9c1b51eSKate Stone         } else if (addr_file_addr < func_file_addr) {
495b9c1b51eSKate Stone           s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
496b9c1b51eSKate Stone                    func_file_addr - addr_file_addr);
497c980fa92SJason Molenda         }
498554f68d3SGreg Clayton         return true;
499b9c1b51eSKate Stone       } else {
500554f68d3SGreg Clayton         Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
501b9c1b51eSKate Stone         if (target) {
502554f68d3SGreg Clayton           addr_t func_load_addr = func_addr.GetLoadAddress(target);
503554f68d3SGreg Clayton           addr_t addr_load_addr = format_addr.GetLoadAddress(target);
504b9c1b51eSKate Stone           if (addr_load_addr > func_load_addr ||
505b9c1b51eSKate Stone               (addr_load_addr == func_load_addr && print_zero_offsets)) {
506b9c1b51eSKate Stone             s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
507b9c1b51eSKate Stone                      addr_load_addr - func_load_addr);
508b9c1b51eSKate Stone           } else if (addr_load_addr < func_load_addr) {
509b9c1b51eSKate Stone             s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
510b9c1b51eSKate Stone                      func_load_addr - addr_load_addr);
511c980fa92SJason Molenda           }
512554f68d3SGreg Clayton           return true;
513554f68d3SGreg Clayton         }
514554f68d3SGreg Clayton       }
515554f68d3SGreg Clayton     }
516554f68d3SGreg Clayton   }
517554f68d3SGreg Clayton   return false;
518554f68d3SGreg Clayton }
519554f68d3SGreg Clayton 
520b9c1b51eSKate Stone static bool ScanBracketedRange(llvm::StringRef subpath,
521554f68d3SGreg Clayton                                size_t &close_bracket_index,
522554f68d3SGreg Clayton                                const char *&var_name_final_if_array_range,
523b9c1b51eSKate Stone                                int64_t &index_lower, int64_t &index_higher) {
5244edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
525554f68d3SGreg Clayton   close_bracket_index = llvm::StringRef::npos;
526554f68d3SGreg Clayton   const size_t open_bracket_index = subpath.find('[');
527b9c1b51eSKate Stone   if (open_bracket_index == llvm::StringRef::npos) {
528554f68d3SGreg Clayton     if (log)
529554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
530554f68d3SGreg Clayton     return false;
531554f68d3SGreg Clayton   }
532554f68d3SGreg Clayton 
533554f68d3SGreg Clayton   close_bracket_index = subpath.find(']', open_bracket_index + 1);
534554f68d3SGreg Clayton 
535b9c1b51eSKate Stone   if (close_bracket_index == llvm::StringRef::npos) {
536554f68d3SGreg Clayton     if (log)
537554f68d3SGreg Clayton       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
538554f68d3SGreg Clayton     return false;
539b9c1b51eSKate Stone   } else {
540554f68d3SGreg Clayton     var_name_final_if_array_range = subpath.data() + open_bracket_index;
541554f68d3SGreg Clayton 
542b9c1b51eSKate Stone     if (close_bracket_index - open_bracket_index == 1) {
543554f68d3SGreg Clayton       if (log)
544b9c1b51eSKate Stone         log->Printf(
545b9c1b51eSKate Stone             "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
546554f68d3SGreg Clayton       index_lower = 0;
547b9c1b51eSKate Stone     } else {
548554f68d3SGreg Clayton       const size_t separator_index = subpath.find('-', open_bracket_index + 1);
549554f68d3SGreg Clayton 
550b9c1b51eSKate Stone       if (separator_index == llvm::StringRef::npos) {
551554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
552a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
553554f68d3SGreg Clayton         index_higher = index_lower;
554554f68d3SGreg Clayton         if (log)
555b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64
556b9c1b51eSKate Stone                       "] detected, high index is same",
557b9c1b51eSKate Stone                       index_lower);
558b9c1b51eSKate Stone       } else {
559554f68d3SGreg Clayton         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
560554f68d3SGreg Clayton         const char *index_higher_cstr = subpath.data() + separator_index + 1;
561a74f37a5SEugene Zelenko         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
562a74f37a5SEugene Zelenko         index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
563554f68d3SGreg Clayton         if (log)
564b9c1b51eSKate Stone           log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
565b9c1b51eSKate Stone                       index_lower, index_higher);
566554f68d3SGreg Clayton       }
567b9c1b51eSKate Stone       if (index_lower > index_higher && index_higher > 0) {
568554f68d3SGreg Clayton         if (log)
569554f68d3SGreg Clayton           log->Printf("[ScanBracketedRange] swapping indices");
570554f68d3SGreg Clayton         const int64_t temp = index_lower;
571554f68d3SGreg Clayton         index_lower = index_higher;
572554f68d3SGreg Clayton         index_higher = temp;
573554f68d3SGreg Clayton       }
574554f68d3SGreg Clayton     }
575554f68d3SGreg Clayton   }
576554f68d3SGreg Clayton   return true;
577554f68d3SGreg Clayton }
578554f68d3SGreg Clayton 
579b9c1b51eSKate Stone static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
580b9c1b51eSKate Stone   switch (file_kind) {
581554f68d3SGreg Clayton   case FileKind::FileError:
582554f68d3SGreg Clayton     break;
583554f68d3SGreg Clayton 
584554f68d3SGreg Clayton   case FileKind::Basename:
585b9c1b51eSKate Stone     if (file.GetFilename()) {
586554f68d3SGreg Clayton       s << file.GetFilename();
587554f68d3SGreg Clayton       return true;
588554f68d3SGreg Clayton     }
589554f68d3SGreg Clayton     break;
590554f68d3SGreg Clayton 
591554f68d3SGreg Clayton   case FileKind::Dirname:
592b9c1b51eSKate Stone     if (file.GetDirectory()) {
593554f68d3SGreg Clayton       s << file.GetDirectory();
594554f68d3SGreg Clayton       return true;
595554f68d3SGreg Clayton     }
596554f68d3SGreg Clayton     break;
597554f68d3SGreg Clayton 
598554f68d3SGreg Clayton   case FileKind::Fullpath:
599b9c1b51eSKate Stone     if (file) {
600554f68d3SGreg Clayton       s << file;
601554f68d3SGreg Clayton       return true;
602554f68d3SGreg Clayton     }
603554f68d3SGreg Clayton     break;
604554f68d3SGreg Clayton   }
605554f68d3SGreg Clayton   return false;
606554f68d3SGreg Clayton }
607554f68d3SGreg Clayton 
608b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
609b9c1b51eSKate Stone                          uint32_t reg_num, Format format)
610554f68d3SGreg Clayton 
611554f68d3SGreg Clayton {
612b9c1b51eSKate Stone   if (frame) {
613554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
614554f68d3SGreg Clayton 
615b9c1b51eSKate Stone     if (reg_ctx) {
616b9c1b51eSKate Stone       const uint32_t lldb_reg_num =
617b9c1b51eSKate Stone           reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
618b9c1b51eSKate Stone       if (lldb_reg_num != LLDB_INVALID_REGNUM) {
619b9c1b51eSKate Stone         const RegisterInfo *reg_info =
620b9c1b51eSKate Stone             reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
621b9c1b51eSKate Stone         if (reg_info) {
622554f68d3SGreg Clayton           RegisterValue reg_value;
623b9c1b51eSKate Stone           if (reg_ctx->ReadRegister(reg_info, reg_value)) {
624554f68d3SGreg Clayton             reg_value.Dump(&s, reg_info, false, false, format);
625554f68d3SGreg Clayton             return true;
626554f68d3SGreg Clayton           }
627554f68d3SGreg Clayton         }
628554f68d3SGreg Clayton       }
629554f68d3SGreg Clayton     }
630554f68d3SGreg Clayton   }
631554f68d3SGreg Clayton   return false;
632554f68d3SGreg Clayton }
633554f68d3SGreg Clayton 
634b9c1b51eSKate Stone static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
635554f68d3SGreg Clayton                                              StackFrame *frame,
636b9c1b51eSKate Stone                                              bool deref_pointer) {
6374edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
638554f68d3SGreg Clayton   const char *ptr_deref_format = "[%d]";
639554f68d3SGreg Clayton   std::string ptr_deref_buffer(10, 0);
640554f68d3SGreg Clayton   ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
641554f68d3SGreg Clayton   if (log)
642b9c1b51eSKate Stone     log->Printf("[ExpandIndexedExpression] name to deref: %s",
643b9c1b51eSKate Stone                 ptr_deref_buffer.c_str());
644554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
645554f68d3SGreg Clayton   ValueObject::ExpressionPathEndResultType final_value_type;
646554f68d3SGreg Clayton   ValueObject::ExpressionPathScanEndReason reason_to_stop;
647b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
648b9c1b51eSKate Stone       (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
649b9c1b51eSKate Stone                      : ValueObject::eExpressionPathAftermathNothing);
650b9c1b51eSKate Stone   ValueObjectSP item = valobj->GetValueForExpressionPath(
651d2daca77SZachary Turner       ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options,
652d2daca77SZachary Turner       &what_next);
653b9c1b51eSKate Stone   if (!item) {
654554f68d3SGreg Clayton     if (log)
655d2daca77SZachary Turner       log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d,"
656554f68d3SGreg Clayton                   " final_value_type %d",
657d2daca77SZachary Turner                   reason_to_stop, final_value_type);
658b9c1b51eSKate Stone   } else {
659554f68d3SGreg Clayton     if (log)
660d2daca77SZachary Turner       log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
661554f68d3SGreg Clayton                   " final_value_type %d",
662d2daca77SZachary Turner                   reason_to_stop, final_value_type);
663554f68d3SGreg Clayton   }
664554f68d3SGreg Clayton   return item;
665554f68d3SGreg Clayton }
666554f68d3SGreg Clayton 
667b9c1b51eSKate Stone static char ConvertValueObjectStyleToChar(
668b9c1b51eSKate Stone     ValueObject::ValueObjectRepresentationStyle style) {
669b9c1b51eSKate Stone   switch (style) {
670b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
671b9c1b51eSKate Stone     return '@';
672b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleValue:
673b9c1b51eSKate Stone     return 'V';
674b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleLocation:
675b9c1b51eSKate Stone     return 'L';
676b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleSummary:
677b9c1b51eSKate Stone     return 'S';
678b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleChildrenCount:
679b9c1b51eSKate Stone     return '#';
680b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleType:
681b9c1b51eSKate Stone     return 'T';
682b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleName:
683b9c1b51eSKate Stone     return 'N';
684b9c1b51eSKate Stone   case ValueObject::eValueObjectRepresentationStyleExpressionPath:
685b9c1b51eSKate Stone     return '>';
686554f68d3SGreg Clayton   }
687554f68d3SGreg Clayton   return '\0';
688554f68d3SGreg Clayton }
689554f68d3SGreg Clayton 
690b9c1b51eSKate Stone static bool DumpValue(Stream &s, const SymbolContext *sc,
691554f68d3SGreg Clayton                       const ExecutionContext *exe_ctx,
692b9c1b51eSKate Stone                       const FormatEntity::Entry &entry, ValueObject *valobj) {
693a74f37a5SEugene Zelenko   if (valobj == nullptr)
694554f68d3SGreg Clayton     return false;
695554f68d3SGreg Clayton 
6964edfef45SEnrico Granata   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
697554f68d3SGreg Clayton   Format custom_format = eFormatInvalid;
698b9c1b51eSKate Stone   ValueObject::ValueObjectRepresentationStyle val_obj_display =
699b9c1b51eSKate Stone       entry.string.empty()
700b9c1b51eSKate Stone           ? ValueObject::eValueObjectRepresentationStyleValue
701b9c1b51eSKate Stone           : ValueObject::eValueObjectRepresentationStyleSummary;
702554f68d3SGreg Clayton 
703554f68d3SGreg Clayton   bool do_deref_pointer = entry.deref;
704554f68d3SGreg Clayton   bool is_script = false;
705b9c1b51eSKate Stone   switch (entry.type) {
706554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariable:
707554f68d3SGreg Clayton     is_script = true;
708554f68d3SGreg Clayton     break;
709554f68d3SGreg Clayton 
710554f68d3SGreg Clayton   case FormatEntity::Entry::Type::Variable:
711554f68d3SGreg Clayton     custom_format = entry.fmt;
712554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
713554f68d3SGreg Clayton     break;
714554f68d3SGreg Clayton 
715554f68d3SGreg Clayton   case FormatEntity::Entry::Type::ScriptVariableSynthetic:
716554f68d3SGreg Clayton     is_script = true;
71762e0681aSJason Molenda     LLVM_FALLTHROUGH;
718554f68d3SGreg Clayton   case FormatEntity::Entry::Type::VariableSynthetic:
719554f68d3SGreg Clayton     custom_format = entry.fmt;
720554f68d3SGreg Clayton     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
721b9c1b51eSKate Stone     if (!valobj->IsSynthetic()) {
722554f68d3SGreg Clayton       valobj = valobj->GetSyntheticValue().get();
723554f68d3SGreg Clayton       if (valobj == nullptr)
724554f68d3SGreg Clayton         return false;
725554f68d3SGreg Clayton     }
726554f68d3SGreg Clayton     break;
727554f68d3SGreg Clayton 
728554f68d3SGreg Clayton   default:
729554f68d3SGreg Clayton     return false;
730554f68d3SGreg Clayton   }
731554f68d3SGreg Clayton 
732a74f37a5SEugene Zelenko   if (valobj == nullptr)
733554f68d3SGreg Clayton     return false;
734554f68d3SGreg Clayton 
735b9c1b51eSKate Stone   ValueObject::ExpressionPathAftermath what_next =
736b9c1b51eSKate Stone       (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
737b9c1b51eSKate Stone                         : ValueObject::eExpressionPathAftermathNothing);
738554f68d3SGreg Clayton   ValueObject::GetValueForExpressionPathOptions options;
739b9c1b51eSKate Stone   options.DontCheckDotVsArrowSyntax()
740b9c1b51eSKate Stone       .DoAllowBitfieldSyntax()
741b9c1b51eSKate Stone       .DoAllowFragileIVar()
742b9c1b51eSKate Stone       .SetSyntheticChildrenTraversal(
743b9c1b51eSKate Stone           ValueObject::GetValueForExpressionPathOptions::
744b9c1b51eSKate Stone               SyntheticChildrenTraversal::Both);
745a74f37a5SEugene Zelenko   ValueObject *target = nullptr;
746a74f37a5SEugene Zelenko   const char *var_name_final_if_array_range = nullptr;
747554f68d3SGreg Clayton   size_t close_bracket_index = llvm::StringRef::npos;
748554f68d3SGreg Clayton   int64_t index_lower = -1;
749554f68d3SGreg Clayton   int64_t index_higher = -1;
750554f68d3SGreg Clayton   bool is_array_range = false;
751554f68d3SGreg Clayton   bool was_plain_var = false;
752554f68d3SGreg Clayton   bool was_var_format = false;
753554f68d3SGreg Clayton   bool was_var_indexed = false;
754b9c1b51eSKate Stone   ValueObject::ExpressionPathScanEndReason reason_to_stop =
755b9c1b51eSKate Stone       ValueObject::eExpressionPathScanEndReasonEndOfString;
756b9c1b51eSKate Stone   ValueObject::ExpressionPathEndResultType final_value_type =
757b9c1b51eSKate Stone       ValueObject::eExpressionPathEndResultTypePlain;
758554f68d3SGreg Clayton 
759b9c1b51eSKate Stone   if (is_script) {
760554f68d3SGreg Clayton     return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
761554f68d3SGreg Clayton   }
762554f68d3SGreg Clayton 
763554f68d3SGreg Clayton   llvm::StringRef subpath(entry.string);
764554f68d3SGreg Clayton   // simplest case ${var}, just print valobj's value
765b9c1b51eSKate Stone   if (entry.string.empty()) {
766b9c1b51eSKate Stone     if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
767b9c1b51eSKate Stone         entry.number == ValueObject::eValueObjectRepresentationStyleValue)
768554f68d3SGreg Clayton       was_plain_var = true;
769554f68d3SGreg Clayton     else
770554f68d3SGreg Clayton       was_var_format = true;
771554f68d3SGreg Clayton     target = valobj;
772b9c1b51eSKate Stone   } else // this is ${var.something} or multiple .something nested
773554f68d3SGreg Clayton   {
774554f68d3SGreg Clayton     if (entry.string[0] == '[')
775554f68d3SGreg Clayton       was_var_indexed = true;
776b9c1b51eSKate Stone     ScanBracketedRange(subpath, close_bracket_index,
777b9c1b51eSKate Stone                        var_name_final_if_array_range, index_lower,
778554f68d3SGreg Clayton                        index_higher);
779554f68d3SGreg Clayton 
78097206d57SZachary Turner     Status error;
781554f68d3SGreg Clayton 
782554f68d3SGreg Clayton     const std::string &expr_path = entry.string;
783554f68d3SGreg Clayton 
784554f68d3SGreg Clayton     if (log)
785b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",
786b9c1b51eSKate Stone                   expr_path.c_str());
787554f68d3SGreg Clayton 
788d2daca77SZachary Turner     target =
789d2daca77SZachary Turner         valobj
790d2daca77SZachary Turner             ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
791d2daca77SZachary Turner                                         &final_value_type, options, &what_next)
792b9c1b51eSKate Stone             .get();
793554f68d3SGreg Clayton 
794b9c1b51eSKate Stone     if (!target) {
795554f68d3SGreg Clayton       if (log)
796d2daca77SZachary Turner         log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d,"
797655c4525SZachary Turner                     " final_value_type %d",
798d2daca77SZachary Turner                     reason_to_stop, final_value_type);
799554f68d3SGreg Clayton       return false;
800b9c1b51eSKate Stone     } else {
801554f68d3SGreg Clayton       if (log)
802d2daca77SZachary Turner         log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
803655c4525SZachary Turner                     " final_value_type %d",
804d2daca77SZachary Turner                     reason_to_stop, final_value_type);
805b9c1b51eSKate Stone       target = target
806b9c1b51eSKate Stone                    ->GetQualifiedRepresentationIfAvailable(
807b9c1b51eSKate Stone                        target->GetDynamicValueType(), true)
808b9c1b51eSKate Stone                    .get();
809554f68d3SGreg Clayton     }
810554f68d3SGreg Clayton   }
811554f68d3SGreg Clayton 
812b9c1b51eSKate Stone   is_array_range =
813b9c1b51eSKate Stone       (final_value_type ==
814b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeBoundedRange ||
815b9c1b51eSKate Stone        final_value_type ==
816b9c1b51eSKate Stone            ValueObject::eExpressionPathEndResultTypeUnboundedRange);
817554f68d3SGreg Clayton 
818b9c1b51eSKate Stone   do_deref_pointer =
819b9c1b51eSKate Stone       (what_next == ValueObject::eExpressionPathAftermathDereference);
820554f68d3SGreg Clayton 
821b9c1b51eSKate Stone   if (do_deref_pointer && !is_array_range) {
822554f68d3SGreg Clayton     // I have not deref-ed yet, let's do it
823b9c1b51eSKate Stone     // this happens when we are not going through
82405097246SAdrian Prantl     // GetValueForVariableExpressionPath to get to the target ValueObject
82597206d57SZachary Turner     Status error;
826554f68d3SGreg Clayton     target = target->Dereference(error).get();
827b9c1b51eSKate Stone     if (error.Fail()) {
828554f68d3SGreg Clayton       if (log)
829b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] ERROR: %s\n",
830b9c1b51eSKate Stone                     error.AsCString("unknown"));
831554f68d3SGreg Clayton       return false;
832554f68d3SGreg Clayton     }
833554f68d3SGreg Clayton     do_deref_pointer = false;
834554f68d3SGreg Clayton   }
835554f68d3SGreg Clayton 
836b9c1b51eSKate Stone   if (!target) {
837554f68d3SGreg Clayton     if (log)
838b9c1b51eSKate Stone       log->Printf("[Debugger::FormatPrompt] could not calculate target for "
839b9c1b51eSKate Stone                   "prompt expression");
840554f68d3SGreg Clayton     return false;
841554f68d3SGreg Clayton   }
842554f68d3SGreg Clayton 
84305097246SAdrian Prantl   // we do not want to use the summary for a bitfield of type T:n if we were
84405097246SAdrian Prantl   // originally dealing with just a T - that would get us into an endless
84505097246SAdrian Prantl   // recursion
846b9c1b51eSKate Stone   if (target->IsBitfield() && was_var_indexed) {
847554f68d3SGreg Clayton     // TODO: check for a (T:n)-specific summary - we should still obey that
848554f68d3SGreg Clayton     StreamString bitfield_name;
849b9c1b51eSKate Stone     bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
850b9c1b51eSKate Stone                          target->GetBitfieldBitSize());
8512f3df613SZachary Turner     auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
8522f3df613SZachary Turner         bitfield_name.GetString(), false);
853b9c1b51eSKate Stone     if (val_obj_display ==
854b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleSummary &&
855b9c1b51eSKate Stone         !DataVisualization::GetSummaryForType(type_sp))
856554f68d3SGreg Clayton       val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
857554f68d3SGreg Clayton   }
858554f68d3SGreg Clayton 
859554f68d3SGreg Clayton   // TODO use flags for these
860b9c1b51eSKate Stone   const uint32_t type_info_flags =
861b9c1b51eSKate Stone       target->GetCompilerType().GetTypeInfo(nullptr);
862554f68d3SGreg Clayton   bool is_array = (type_info_flags & eTypeIsArray) != 0;
863554f68d3SGreg Clayton   bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
86499558cc4SGreg Clayton   bool is_aggregate = target->GetCompilerType().IsAggregateType();
865554f68d3SGreg Clayton 
866b9c1b51eSKate Stone   if ((is_array || is_pointer) && (!is_array_range) &&
867b9c1b51eSKate Stone       val_obj_display ==
868b9c1b51eSKate Stone           ValueObject::eValueObjectRepresentationStyleValue) // this should be
869b9c1b51eSKate Stone                                                              // wrong, but there
870b9c1b51eSKate Stone                                                              // are some
871b9c1b51eSKate Stone                                                              // exceptions
872554f68d3SGreg Clayton   {
873554f68d3SGreg Clayton     StreamString str_temp;
874554f68d3SGreg Clayton     if (log)
875b9c1b51eSKate Stone       log->Printf(
876b9c1b51eSKate Stone           "[Debugger::FormatPrompt] I am into array || pointer && !range");
877554f68d3SGreg Clayton 
878b9c1b51eSKate Stone     if (target->HasSpecialPrintableRepresentation(val_obj_display,
879b9c1b51eSKate Stone                                                   custom_format)) {
880554f68d3SGreg Clayton       // try to use the special cases
881b9c1b51eSKate Stone       bool success = target->DumpPrintableRepresentation(
882b9c1b51eSKate Stone           str_temp, val_obj_display, custom_format);
883554f68d3SGreg Clayton       if (log)
884b9c1b51eSKate Stone         log->Printf("[Debugger::FormatPrompt] special cases did%s match",
885b9c1b51eSKate Stone                     success ? "" : "n't");
886554f68d3SGreg Clayton 
887554f68d3SGreg Clayton       // should not happen
888554f68d3SGreg Clayton       if (success)
889c156427dSZachary Turner         s << str_temp.GetString();
890554f68d3SGreg Clayton       return true;
891b9c1b51eSKate Stone     } else {
892554f68d3SGreg Clayton       if (was_plain_var) // if ${var}
893554f68d3SGreg Clayton       {
894554f68d3SGreg Clayton         s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
895b9c1b51eSKate Stone       } else if (is_pointer) // if pointer, value is the address stored
896554f68d3SGreg Clayton       {
897b9c1b51eSKate Stone         target->DumpPrintableRepresentation(
898b9c1b51eSKate Stone             s, val_obj_display, custom_format,
89965d86e4fSEnrico Granata             ValueObject::PrintableRepresentationSpecialCases::eDisable);
900554f68d3SGreg Clayton       }
901554f68d3SGreg Clayton       return true;
902554f68d3SGreg Clayton     }
903554f68d3SGreg Clayton   }
904554f68d3SGreg Clayton 
905b9c1b51eSKate Stone   // if directly trying to print ${var}, and this is an aggregate, display a
90605097246SAdrian Prantl   // nice type @ location message
907b9c1b51eSKate Stone   if (is_aggregate && was_plain_var) {
908554f68d3SGreg Clayton     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
909554f68d3SGreg Clayton     return true;
910554f68d3SGreg Clayton   }
911554f68d3SGreg Clayton 
912b9c1b51eSKate Stone   // if directly trying to print ${var%V}, and this is an aggregate, do not let
913b9c1b51eSKate Stone   // the user do it
914b9c1b51eSKate Stone   if (is_aggregate &&
915b9c1b51eSKate Stone       ((was_var_format &&
916b9c1b51eSKate Stone         val_obj_display ==
917b9c1b51eSKate Stone             ValueObject::eValueObjectRepresentationStyleValue))) {
918554f68d3SGreg Clayton     s << "<invalid use of aggregate type>";
919554f68d3SGreg Clayton     return true;
920554f68d3SGreg Clayton   }
921554f68d3SGreg Clayton 
922b9c1b51eSKate Stone   if (!is_array_range) {
923554f68d3SGreg Clayton     if (log)
924554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
925b9c1b51eSKate Stone     return target->DumpPrintableRepresentation(s, val_obj_display,
926b9c1b51eSKate Stone                                                custom_format);
927b9c1b51eSKate Stone   } else {
928554f68d3SGreg Clayton     if (log)
929554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
930554f68d3SGreg Clayton     if (!is_array && !is_pointer)
931554f68d3SGreg Clayton       return false;
932554f68d3SGreg Clayton     if (log)
933554f68d3SGreg Clayton       log->Printf("[Debugger::FormatPrompt] handle as array");
934e8376261SVince Harron     StreamString special_directions_stream;
935554f68d3SGreg Clayton     llvm::StringRef special_directions;
936b9c1b51eSKate Stone     if (close_bracket_index != llvm::StringRef::npos &&
937b9c1b51eSKate Stone         subpath.size() > close_bracket_index) {
938554f68d3SGreg Clayton       ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
939b9c1b51eSKate Stone       special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
940554f68d3SGreg Clayton                                        additional_data.GetCString());
941554f68d3SGreg Clayton 
942b9c1b51eSKate Stone       if (entry.fmt != eFormatDefault) {
943b9c1b51eSKate Stone         const char format_char =
944b9c1b51eSKate Stone             FormatManager::GetFormatAsFormatChar(entry.fmt);
945554f68d3SGreg Clayton         if (format_char != '\0')
946554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", format_char);
947b9c1b51eSKate Stone         else {
948b9c1b51eSKate Stone           const char *format_cstr =
949b9c1b51eSKate Stone               FormatManager::GetFormatAsCString(entry.fmt);
950554f68d3SGreg Clayton           special_directions_stream.Printf("%%%s", format_cstr);
951554f68d3SGreg Clayton         }
952b9c1b51eSKate Stone       } else if (entry.number != 0) {
953b9c1b51eSKate Stone         const char style_char = ConvertValueObjectStyleToChar(
954b9c1b51eSKate Stone             (ValueObject::ValueObjectRepresentationStyle)entry.number);
955554f68d3SGreg Clayton         if (style_char)
956554f68d3SGreg Clayton           special_directions_stream.Printf("%%%c", style_char);
957554f68d3SGreg Clayton       }
958554f68d3SGreg Clayton       special_directions_stream.PutChar('}');
959b9c1b51eSKate Stone       special_directions =
960b9c1b51eSKate Stone           llvm::StringRef(special_directions_stream.GetString());
961554f68d3SGreg Clayton     }
962554f68d3SGreg Clayton 
963554f68d3SGreg Clayton     // let us display items index_lower thru index_higher of this array
964554f68d3SGreg Clayton     s.PutChar('[');
965554f68d3SGreg Clayton 
966554f68d3SGreg Clayton     if (index_higher < 0)
967554f68d3SGreg Clayton       index_higher = valobj->GetNumChildren() - 1;
968554f68d3SGreg Clayton 
969b9c1b51eSKate Stone     uint32_t max_num_children =
970b9c1b51eSKate Stone         target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
971554f68d3SGreg Clayton 
972554f68d3SGreg Clayton     bool success = true;
973b9c1b51eSKate Stone     for (int64_t index = index_lower; index <= index_higher; ++index) {
974b9c1b51eSKate Stone       ValueObject *item =
975b9c1b51eSKate Stone           ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
976b9c1b51eSKate Stone               .get();
977554f68d3SGreg Clayton 
978b9c1b51eSKate Stone       if (!item) {
979554f68d3SGreg Clayton         if (log)
980b9c1b51eSKate Stone           log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at "
981b9c1b51eSKate Stone                       "index %" PRId64,
982b9c1b51eSKate Stone                       index);
983b9c1b51eSKate Stone       } else {
984554f68d3SGreg Clayton         if (log)
985b9c1b51eSKate Stone           log->Printf(
986b9c1b51eSKate Stone               "[Debugger::FormatPrompt] special_directions for child item: %s",
987b9c1b51eSKate Stone               special_directions.data() ? special_directions.data() : "");
988554f68d3SGreg Clayton       }
989554f68d3SGreg Clayton 
990b9c1b51eSKate Stone       if (special_directions.empty()) {
991b9c1b51eSKate Stone         success &= item->DumpPrintableRepresentation(s, val_obj_display,
992b9c1b51eSKate Stone                                                      custom_format);
993b9c1b51eSKate Stone       } else {
994b9c1b51eSKate Stone         success &= FormatEntity::FormatStringRef(
995b9c1b51eSKate Stone             special_directions, s, sc, exe_ctx, nullptr, item, false, false);
996554f68d3SGreg Clayton       }
997554f68d3SGreg Clayton 
998b9c1b51eSKate Stone       if (--max_num_children == 0) {
999554f68d3SGreg Clayton         s.PutCString(", ...");
1000554f68d3SGreg Clayton         break;
1001554f68d3SGreg Clayton       }
1002554f68d3SGreg Clayton 
1003554f68d3SGreg Clayton       if (index < index_higher)
1004554f68d3SGreg Clayton         s.PutChar(',');
1005554f68d3SGreg Clayton     }
1006554f68d3SGreg Clayton     s.PutChar(']');
1007554f68d3SGreg Clayton     return success;
1008554f68d3SGreg Clayton   }
1009554f68d3SGreg Clayton }
1010554f68d3SGreg Clayton 
1011b9c1b51eSKate Stone static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
1012b9c1b51eSKate Stone                          Format format) {
1013b9c1b51eSKate Stone   if (frame) {
1014554f68d3SGreg Clayton     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
1015554f68d3SGreg Clayton 
1016b9c1b51eSKate Stone     if (reg_ctx) {
1017554f68d3SGreg Clayton       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
1018b9c1b51eSKate Stone       if (reg_info) {
1019554f68d3SGreg Clayton         RegisterValue reg_value;
1020b9c1b51eSKate Stone         if (reg_ctx->ReadRegister(reg_info, reg_value)) {
1021554f68d3SGreg Clayton           reg_value.Dump(&s, reg_info, false, false, format);
1022554f68d3SGreg Clayton           return true;
1023554f68d3SGreg Clayton         }
1024554f68d3SGreg Clayton       }
1025554f68d3SGreg Clayton     }
1026554f68d3SGreg Clayton   }
1027554f68d3SGreg Clayton   return false;
1028554f68d3SGreg Clayton }
1029554f68d3SGreg Clayton 
1030b9c1b51eSKate Stone static bool FormatThreadExtendedInfoRecurse(
1031b9c1b51eSKate Stone     const FormatEntity::Entry &entry,
1032554f68d3SGreg Clayton     const StructuredData::ObjectSP &thread_info_dictionary,
1033b9c1b51eSKate Stone     const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
1034554f68d3SGreg Clayton   llvm::StringRef path(entry.string);
1035554f68d3SGreg Clayton 
1036b9c1b51eSKate Stone   StructuredData::ObjectSP value =
1037b9c1b51eSKate Stone       thread_info_dictionary->GetObjectForDotSeparatedPath(path);
1038554f68d3SGreg Clayton 
1039b9c1b51eSKate Stone   if (value) {
10405bfee5f1SAbhishek Aggarwal     if (value->GetType() == eStructuredDataTypeInteger) {
1041554f68d3SGreg Clayton       const char *token_format = "0x%4.4" PRIx64;
1042554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1043554f68d3SGreg Clayton         token_format = entry.printf_format.c_str();
1044554f68d3SGreg Clayton       s.Printf(token_format, value->GetAsInteger()->GetValue());
1045554f68d3SGreg Clayton       return true;
10465bfee5f1SAbhishek Aggarwal     } else if (value->GetType() == eStructuredDataTypeFloat) {
1047554f68d3SGreg Clayton       s.Printf("%f", value->GetAsFloat()->GetValue());
1048554f68d3SGreg Clayton       return true;
10495bfee5f1SAbhishek Aggarwal     } else if (value->GetType() == eStructuredDataTypeString) {
10502833321fSZachary Turner       s.Format("{0}", value->GetAsString()->GetValue());
1051554f68d3SGreg Clayton       return true;
10525bfee5f1SAbhishek Aggarwal     } else if (value->GetType() == eStructuredDataTypeArray) {
1053b9c1b51eSKate Stone       if (value->GetAsArray()->GetSize() > 0) {
1054554f68d3SGreg Clayton         s.Printf("%zu", value->GetAsArray()->GetSize());
1055554f68d3SGreg Clayton         return true;
1056554f68d3SGreg Clayton       }
10575bfee5f1SAbhishek Aggarwal     } else if (value->GetType() == eStructuredDataTypeDictionary) {
1058b9c1b51eSKate Stone       s.Printf("%zu",
1059b9c1b51eSKate Stone                value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1060554f68d3SGreg Clayton       return true;
1061554f68d3SGreg Clayton     }
1062554f68d3SGreg Clayton   }
1063554f68d3SGreg Clayton 
1064554f68d3SGreg Clayton   return false;
1065554f68d3SGreg Clayton }
1066554f68d3SGreg Clayton 
1067b9c1b51eSKate Stone static inline bool IsToken(const char *var_name_begin, const char *var) {
1068554f68d3SGreg Clayton   return (::strncmp(var_name_begin, var, strlen(var)) == 0);
1069554f68d3SGreg Clayton }
1070554f68d3SGreg Clayton 
1071b9c1b51eSKate Stone bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
1072554f68d3SGreg Clayton                                    const SymbolContext *sc,
1073554f68d3SGreg Clayton                                    const ExecutionContext *exe_ctx,
1074b9c1b51eSKate Stone                                    const Address *addr, ValueObject *valobj,
1075554f68d3SGreg Clayton                                    bool function_changed,
1076b9c1b51eSKate Stone                                    bool initial_function) {
1077b9c1b51eSKate Stone   if (!format_str.empty()) {
1078554f68d3SGreg Clayton     FormatEntity::Entry root;
107997206d57SZachary Turner     Status error = FormatEntity::Parse(format_str, root);
1080b9c1b51eSKate Stone     if (error.Success()) {
1081b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1082b9c1b51eSKate Stone                                   function_changed, initial_function);
1083554f68d3SGreg Clayton     }
1084554f68d3SGreg Clayton   }
1085554f68d3SGreg Clayton   return false;
1086554f68d3SGreg Clayton }
1087a74f37a5SEugene Zelenko 
1088b9c1b51eSKate Stone bool FormatEntity::FormatCString(const char *format, Stream &s,
1089554f68d3SGreg Clayton                                  const SymbolContext *sc,
1090554f68d3SGreg Clayton                                  const ExecutionContext *exe_ctx,
1091b9c1b51eSKate Stone                                  const Address *addr, ValueObject *valobj,
1092b9c1b51eSKate Stone                                  bool function_changed, bool initial_function) {
1093b9c1b51eSKate Stone   if (format && format[0]) {
1094554f68d3SGreg Clayton     FormatEntity::Entry root;
1095554f68d3SGreg Clayton     llvm::StringRef format_str(format);
109697206d57SZachary Turner     Status error = FormatEntity::Parse(format_str, root);
1097b9c1b51eSKate Stone     if (error.Success()) {
1098b9c1b51eSKate Stone       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1099b9c1b51eSKate Stone                                   function_changed, initial_function);
1100554f68d3SGreg Clayton     }
1101554f68d3SGreg Clayton   }
1102554f68d3SGreg Clayton   return false;
1103554f68d3SGreg Clayton }
1104554f68d3SGreg Clayton 
1105b9c1b51eSKate Stone bool FormatEntity::Format(const Entry &entry, Stream &s,
1106554f68d3SGreg Clayton                           const SymbolContext *sc,
1107b9c1b51eSKate Stone                           const ExecutionContext *exe_ctx, const Address *addr,
1108b9c1b51eSKate Stone                           ValueObject *valobj, bool function_changed,
1109b9c1b51eSKate Stone                           bool initial_function) {
1110b9c1b51eSKate Stone   switch (entry.type) {
1111554f68d3SGreg Clayton   case Entry::Type::Invalid:
1112b9c1b51eSKate Stone   case Entry::Type::ParentNumber: // Only used for
1113b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1114b9c1b51eSKate Stone   case Entry::Type::ParentString: // Only used for
1115b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1116b9c1b51eSKate Stone   case Entry::Type::InsertString: // Only used for
1117b9c1b51eSKate Stone                                   // FormatEntity::Entry::Definition encoding
1118554f68d3SGreg Clayton     return false;
1119554f68d3SGreg Clayton 
1120554f68d3SGreg Clayton   case Entry::Type::Root:
1121b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1122b9c1b51eSKate Stone       if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
1123b9c1b51eSKate Stone                   initial_function)) {
1124554f68d3SGreg Clayton         return false; // If any item of root fails, then the formatting fails
1125554f68d3SGreg Clayton       }
1126554f68d3SGreg Clayton     }
1127554f68d3SGreg Clayton     return true; // Only return true if all items succeeded
1128554f68d3SGreg Clayton 
1129554f68d3SGreg Clayton   case Entry::Type::String:
1130771ef6d4SMalcolm Parsons     s.PutCString(entry.string);
1131554f68d3SGreg Clayton     return true;
1132554f68d3SGreg Clayton 
1133b9c1b51eSKate Stone   case Entry::Type::Scope: {
1134554f68d3SGreg Clayton     StreamString scope_stream;
1135554f68d3SGreg Clayton     bool success = false;
1136b9c1b51eSKate Stone     for (const auto &child : entry.children) {
1137b9c1b51eSKate Stone       success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
1138b9c1b51eSKate Stone                        function_changed, initial_function);
1139554f68d3SGreg Clayton       if (!success)
1140554f68d3SGreg Clayton         break;
1141554f68d3SGreg Clayton     }
114205097246SAdrian Prantl     // Only if all items in a scope succeed, then do we print the output into
114305097246SAdrian Prantl     // the main stream
1144554f68d3SGreg Clayton     if (success)
1145554f68d3SGreg Clayton       s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
1146554f68d3SGreg Clayton   }
1147554f68d3SGreg Clayton     return true; // Scopes always successfully print themselves
1148554f68d3SGreg Clayton 
1149554f68d3SGreg Clayton   case Entry::Type::Variable:
1150554f68d3SGreg Clayton   case Entry::Type::VariableSynthetic:
1151554f68d3SGreg Clayton   case Entry::Type::ScriptVariable:
1152554f68d3SGreg Clayton   case Entry::Type::ScriptVariableSynthetic:
1153a74f37a5SEugene Zelenko     return DumpValue(s, sc, exe_ctx, entry, valobj);
1154554f68d3SGreg Clayton 
1155554f68d3SGreg Clayton   case Entry::Type::AddressFile:
1156554f68d3SGreg Clayton   case Entry::Type::AddressLoad:
1157554f68d3SGreg Clayton   case Entry::Type::AddressLoadOrFile:
1158a74f37a5SEugene Zelenko     return (addr != nullptr && addr->IsValid() &&
1159b9c1b51eSKate Stone             DumpAddress(s, sc, exe_ctx, *addr,
1160b9c1b51eSKate Stone                         entry.type == Entry::Type::AddressLoadOrFile));
1161554f68d3SGreg Clayton 
1162554f68d3SGreg Clayton   case Entry::Type::ProcessID:
1163b9c1b51eSKate Stone     if (exe_ctx) {
1164554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1165b9c1b51eSKate Stone       if (process) {
1166554f68d3SGreg Clayton         const char *format = "%" PRIu64;
1167554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1168554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1169554f68d3SGreg Clayton         s.Printf(format, process->GetID());
1170554f68d3SGreg Clayton         return true;
1171554f68d3SGreg Clayton       }
1172554f68d3SGreg Clayton     }
1173554f68d3SGreg Clayton     return false;
1174554f68d3SGreg Clayton 
1175554f68d3SGreg Clayton   case Entry::Type::ProcessFile:
1176b9c1b51eSKate Stone     if (exe_ctx) {
1177554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1178b9c1b51eSKate Stone       if (process) {
1179554f68d3SGreg Clayton         Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1180b9c1b51eSKate Stone         if (exe_module) {
1181554f68d3SGreg Clayton           if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1182554f68d3SGreg Clayton             return true;
1183554f68d3SGreg Clayton         }
1184554f68d3SGreg Clayton       }
1185554f68d3SGreg Clayton     }
1186554f68d3SGreg Clayton     return false;
1187554f68d3SGreg Clayton 
1188554f68d3SGreg Clayton   case Entry::Type::ScriptProcess:
1189b9c1b51eSKate Stone     if (exe_ctx) {
1190554f68d3SGreg Clayton       Process *process = exe_ctx->GetProcessPtr();
1191554f68d3SGreg Clayton       if (process)
1192b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, process,
1193b9c1b51eSKate Stone                                       entry.string.c_str());
1194554f68d3SGreg Clayton     }
1195554f68d3SGreg Clayton     return false;
1196554f68d3SGreg Clayton 
1197554f68d3SGreg Clayton   case Entry::Type::ThreadID:
1198b9c1b51eSKate Stone     if (exe_ctx) {
1199554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1200b9c1b51eSKate Stone       if (thread) {
1201554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1202b9c1b51eSKate Stone         if (!entry.printf_format.empty()) {
1203554f68d3SGreg Clayton           // Watch for the special "tid" format...
1204b9c1b51eSKate Stone           if (entry.printf_format == "tid") {
1205b9c1b51eSKate Stone             // TODO(zturner): Rather than hardcoding this to be platform
120605097246SAdrian Prantl             // specific, it should be controlled by a setting and the default
120705097246SAdrian Prantl             // value of the setting can be different depending on the platform.
1208554f68d3SGreg Clayton             Target &target = thread->GetProcess()->GetTarget();
1209554f68d3SGreg Clayton             ArchSpec arch(target.GetArchitecture());
1210b9c1b51eSKate Stone             llvm::Triple::OSType ostype = arch.IsValid()
1211b9c1b51eSKate Stone                                               ? arch.GetTriple().getOS()
1212b9c1b51eSKate Stone                                               : llvm::Triple::UnknownOS;
1213b9c1b51eSKate Stone             if ((ostype == llvm::Triple::FreeBSD) ||
1214750228a6SKamil Rytarowski                 (ostype == llvm::Triple::Linux) ||
1215750228a6SKamil Rytarowski                 (ostype == llvm::Triple::NetBSD)) {
1216554f68d3SGreg Clayton               format = "%" PRIu64;
1217554f68d3SGreg Clayton             }
1218b9c1b51eSKate Stone           } else {
1219554f68d3SGreg Clayton             format = entry.printf_format.c_str();
1220554f68d3SGreg Clayton           }
1221554f68d3SGreg Clayton         }
1222554f68d3SGreg Clayton         s.Printf(format, thread->GetID());
1223554f68d3SGreg Clayton         return true;
1224554f68d3SGreg Clayton       }
1225554f68d3SGreg Clayton     }
1226554f68d3SGreg Clayton     return false;
1227554f68d3SGreg Clayton 
1228554f68d3SGreg Clayton   case Entry::Type::ThreadProtocolID:
1229b9c1b51eSKate Stone     if (exe_ctx) {
1230554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1231b9c1b51eSKate Stone       if (thread) {
1232554f68d3SGreg Clayton         const char *format = "0x%4.4" PRIx64;
1233554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1234554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1235554f68d3SGreg Clayton         s.Printf(format, thread->GetProtocolID());
1236554f68d3SGreg Clayton         return true;
1237554f68d3SGreg Clayton       }
1238554f68d3SGreg Clayton     }
1239554f68d3SGreg Clayton     return false;
1240554f68d3SGreg Clayton 
1241554f68d3SGreg Clayton   case Entry::Type::ThreadIndexID:
1242b9c1b51eSKate Stone     if (exe_ctx) {
1243554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1244b9c1b51eSKate Stone       if (thread) {
1245554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1246554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1247554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1248554f68d3SGreg Clayton         s.Printf(format, thread->GetIndexID());
1249554f68d3SGreg Clayton         return true;
1250554f68d3SGreg Clayton       }
1251554f68d3SGreg Clayton     }
1252554f68d3SGreg Clayton     return false;
1253554f68d3SGreg Clayton 
1254554f68d3SGreg Clayton   case Entry::Type::ThreadName:
1255b9c1b51eSKate Stone     if (exe_ctx) {
1256554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1257b9c1b51eSKate Stone       if (thread) {
1258554f68d3SGreg Clayton         const char *cstr = thread->GetName();
1259b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1260554f68d3SGreg Clayton           s.PutCString(cstr);
1261554f68d3SGreg Clayton           return true;
1262554f68d3SGreg Clayton         }
1263554f68d3SGreg Clayton       }
1264554f68d3SGreg Clayton     }
1265554f68d3SGreg Clayton     return false;
1266554f68d3SGreg Clayton 
1267554f68d3SGreg Clayton   case Entry::Type::ThreadQueue:
1268b9c1b51eSKate Stone     if (exe_ctx) {
1269554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1270b9c1b51eSKate Stone       if (thread) {
1271554f68d3SGreg Clayton         const char *cstr = thread->GetQueueName();
1272b9c1b51eSKate Stone         if (cstr && cstr[0]) {
1273554f68d3SGreg Clayton           s.PutCString(cstr);
1274554f68d3SGreg Clayton           return true;
1275554f68d3SGreg Clayton         }
1276554f68d3SGreg Clayton       }
1277554f68d3SGreg Clayton     }
1278554f68d3SGreg Clayton     return false;
1279554f68d3SGreg Clayton 
1280554f68d3SGreg Clayton   case Entry::Type::ThreadStopReason:
1281b9c1b51eSKate Stone     if (exe_ctx) {
1282554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1283b9c1b51eSKate Stone       if (thread) {
1284554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1285b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1286554f68d3SGreg Clayton           const char *cstr = stop_info_sp->GetDescription();
1287b9c1b51eSKate Stone           if (cstr && cstr[0]) {
1288554f68d3SGreg Clayton             s.PutCString(cstr);
1289554f68d3SGreg Clayton             return true;
1290554f68d3SGreg Clayton           }
1291554f68d3SGreg Clayton         }
1292554f68d3SGreg Clayton       }
1293554f68d3SGreg Clayton     }
1294554f68d3SGreg Clayton     return false;
1295554f68d3SGreg Clayton 
1296554f68d3SGreg Clayton   case Entry::Type::ThreadReturnValue:
1297b9c1b51eSKate Stone     if (exe_ctx) {
1298554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1299b9c1b51eSKate Stone       if (thread) {
1300554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1301b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1302b9c1b51eSKate Stone           ValueObjectSP return_valobj_sp =
1303b9c1b51eSKate Stone               StopInfo::GetReturnValueObject(stop_info_sp);
1304b9c1b51eSKate Stone           if (return_valobj_sp) {
1305554f68d3SGreg Clayton             return_valobj_sp->Dump(s);
1306554f68d3SGreg Clayton             return true;
1307554f68d3SGreg Clayton           }
1308554f68d3SGreg Clayton         }
1309554f68d3SGreg Clayton       }
1310554f68d3SGreg Clayton     }
1311554f68d3SGreg Clayton     return false;
1312554f68d3SGreg Clayton 
1313554f68d3SGreg Clayton   case Entry::Type::ThreadCompletedExpression:
1314b9c1b51eSKate Stone     if (exe_ctx) {
1315554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1316b9c1b51eSKate Stone       if (thread) {
1317554f68d3SGreg Clayton         StopInfoSP stop_info_sp = thread->GetStopInfo();
1318b9c1b51eSKate Stone         if (stop_info_sp && stop_info_sp->IsValid()) {
1319b9c1b51eSKate Stone           ExpressionVariableSP expression_var_sp =
1320b9c1b51eSKate Stone               StopInfo::GetExpressionVariable(stop_info_sp);
1321b9c1b51eSKate Stone           if (expression_var_sp && expression_var_sp->GetValueObject()) {
1322554f68d3SGreg Clayton             expression_var_sp->GetValueObject()->Dump(s);
1323554f68d3SGreg Clayton             return true;
1324554f68d3SGreg Clayton           }
1325554f68d3SGreg Clayton         }
1326554f68d3SGreg Clayton       }
1327554f68d3SGreg Clayton     }
1328554f68d3SGreg Clayton     return false;
1329554f68d3SGreg Clayton 
1330554f68d3SGreg Clayton   case Entry::Type::ScriptThread:
1331b9c1b51eSKate Stone     if (exe_ctx) {
1332554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1333554f68d3SGreg Clayton       if (thread)
1334b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
1335b9c1b51eSKate Stone                                       entry.string.c_str());
1336554f68d3SGreg Clayton     }
1337554f68d3SGreg Clayton     return false;
1338554f68d3SGreg Clayton 
1339554f68d3SGreg Clayton   case Entry::Type::ThreadInfo:
1340b9c1b51eSKate Stone     if (exe_ctx) {
1341554f68d3SGreg Clayton       Thread *thread = exe_ctx->GetThreadPtr();
1342b9c1b51eSKate Stone       if (thread) {
1343554f68d3SGreg Clayton         StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1344b9c1b51eSKate Stone         if (object_sp &&
13455bfee5f1SAbhishek Aggarwal             object_sp->GetType() == eStructuredDataTypeDictionary) {
1346554f68d3SGreg Clayton           if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
1347554f68d3SGreg Clayton             return true;
1348554f68d3SGreg Clayton         }
1349554f68d3SGreg Clayton       }
1350554f68d3SGreg Clayton     }
1351554f68d3SGreg Clayton     return false;
1352554f68d3SGreg Clayton 
1353554f68d3SGreg Clayton   case Entry::Type::TargetArch:
1354b9c1b51eSKate Stone     if (exe_ctx) {
1355554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1356b9c1b51eSKate Stone       if (target) {
1357554f68d3SGreg Clayton         const ArchSpec &arch = target->GetArchitecture();
1358b9c1b51eSKate Stone         if (arch.IsValid()) {
1359554f68d3SGreg Clayton           s.PutCString(arch.GetArchitectureName());
1360554f68d3SGreg Clayton           return true;
1361554f68d3SGreg Clayton         }
1362554f68d3SGreg Clayton       }
1363554f68d3SGreg Clayton     }
1364554f68d3SGreg Clayton     return false;
1365554f68d3SGreg Clayton 
1366554f68d3SGreg Clayton   case Entry::Type::ScriptTarget:
1367b9c1b51eSKate Stone     if (exe_ctx) {
1368554f68d3SGreg Clayton       Target *target = exe_ctx->GetTargetPtr();
1369554f68d3SGreg Clayton       if (target)
1370b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, target,
1371b9c1b51eSKate Stone                                       entry.string.c_str());
1372554f68d3SGreg Clayton     }
1373554f68d3SGreg Clayton     return false;
1374554f68d3SGreg Clayton 
1375554f68d3SGreg Clayton   case Entry::Type::ModuleFile:
1376b9c1b51eSKate Stone     if (sc) {
1377554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1378b9c1b51eSKate Stone       if (module) {
1379554f68d3SGreg Clayton         if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1380554f68d3SGreg Clayton           return true;
1381554f68d3SGreg Clayton       }
1382554f68d3SGreg Clayton     }
1383554f68d3SGreg Clayton     return false;
1384554f68d3SGreg Clayton 
1385554f68d3SGreg Clayton   case Entry::Type::File:
1386b9c1b51eSKate Stone     if (sc) {
1387554f68d3SGreg Clayton       CompileUnit *cu = sc->comp_unit;
1388b9c1b51eSKate Stone       if (cu) {
1389554f68d3SGreg Clayton         // CompileUnit is a FileSpec
1390554f68d3SGreg Clayton         if (DumpFile(s, *cu, (FileKind)entry.number))
1391554f68d3SGreg Clayton           return true;
1392554f68d3SGreg Clayton       }
1393554f68d3SGreg Clayton     }
1394554f68d3SGreg Clayton     return false;
1395554f68d3SGreg Clayton 
1396dc975670SDawn Perchik   case Entry::Type::Lang:
1397b9c1b51eSKate Stone     if (sc) {
1398dc975670SDawn Perchik       CompileUnit *cu = sc->comp_unit;
1399b9c1b51eSKate Stone       if (cu) {
1400b9c1b51eSKate Stone         const char *lang_name =
1401b9c1b51eSKate Stone             Language::GetNameForLanguageType(cu->GetLanguage());
1402b9c1b51eSKate Stone         if (lang_name) {
1403dc975670SDawn Perchik           s.PutCString(lang_name);
1404dc975670SDawn Perchik           return true;
1405dc975670SDawn Perchik         }
1406dc975670SDawn Perchik       }
1407dc975670SDawn Perchik     }
1408dc975670SDawn Perchik     return false;
1409dc975670SDawn Perchik 
1410554f68d3SGreg Clayton   case Entry::Type::FrameIndex:
1411b9c1b51eSKate Stone     if (exe_ctx) {
1412554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1413b9c1b51eSKate Stone       if (frame) {
1414554f68d3SGreg Clayton         const char *format = "%" PRIu32;
1415554f68d3SGreg Clayton         if (!entry.printf_format.empty())
1416554f68d3SGreg Clayton           format = entry.printf_format.c_str();
1417554f68d3SGreg Clayton         s.Printf(format, frame->GetFrameIndex());
1418554f68d3SGreg Clayton         return true;
1419554f68d3SGreg Clayton       }
1420554f68d3SGreg Clayton     }
1421554f68d3SGreg Clayton     return false;
1422554f68d3SGreg Clayton 
1423554f68d3SGreg Clayton   case Entry::Type::FrameRegisterPC:
1424b9c1b51eSKate Stone     if (exe_ctx) {
1425554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1426b9c1b51eSKate Stone       if (frame) {
1427554f68d3SGreg Clayton         const Address &pc_addr = frame->GetFrameCodeAddress();
1428b9c1b51eSKate Stone         if (pc_addr.IsValid()) {
1429554f68d3SGreg Clayton           if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
1430554f68d3SGreg Clayton             return true;
1431554f68d3SGreg Clayton         }
1432554f68d3SGreg Clayton       }
1433554f68d3SGreg Clayton     }
1434554f68d3SGreg Clayton     return false;
1435554f68d3SGreg Clayton 
1436554f68d3SGreg Clayton   case Entry::Type::FrameRegisterSP:
1437b9c1b51eSKate Stone     if (exe_ctx) {
1438554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1439b9c1b51eSKate Stone       if (frame) {
1440b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
1441b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1442554f68d3SGreg Clayton           return true;
1443554f68d3SGreg Clayton       }
1444554f68d3SGreg Clayton     }
1445554f68d3SGreg Clayton     return false;
1446554f68d3SGreg Clayton 
1447554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFP:
1448b9c1b51eSKate Stone     if (exe_ctx) {
1449554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1450b9c1b51eSKate Stone       if (frame) {
1451b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
1452b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1453554f68d3SGreg Clayton           return true;
1454554f68d3SGreg Clayton       }
1455554f68d3SGreg Clayton     }
1456554f68d3SGreg Clayton     return false;
1457554f68d3SGreg Clayton 
1458554f68d3SGreg Clayton   case Entry::Type::FrameRegisterFlags:
1459b9c1b51eSKate Stone     if (exe_ctx) {
1460554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1461b9c1b51eSKate Stone       if (frame) {
1462b9c1b51eSKate Stone         if (DumpRegister(s, frame, eRegisterKindGeneric,
1463b9c1b51eSKate Stone                          LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
1464554f68d3SGreg Clayton           return true;
1465554f68d3SGreg Clayton       }
1466554f68d3SGreg Clayton     }
1467554f68d3SGreg Clayton     return false;
1468554f68d3SGreg Clayton 
14696a9767c7SJim Ingham   case Entry::Type::FrameNoDebug:
14706a9767c7SJim Ingham     if (exe_ctx) {
14716a9767c7SJim Ingham       StackFrame *frame = exe_ctx->GetFramePtr();
14726a9767c7SJim Ingham       if (frame) {
14736a9767c7SJim Ingham         return !frame->HasDebugInformation();
14746a9767c7SJim Ingham       }
14756a9767c7SJim Ingham     }
14766a9767c7SJim Ingham     return true;
14776a9767c7SJim Ingham 
1478554f68d3SGreg Clayton   case Entry::Type::FrameRegisterByName:
1479b9c1b51eSKate Stone     if (exe_ctx) {
1480554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1481b9c1b51eSKate Stone       if (frame) {
1482b9c1b51eSKate Stone         if (DumpRegister(s, frame, entry.string.c_str(),
1483b9c1b51eSKate Stone                          (lldb::Format)entry.number))
1484554f68d3SGreg Clayton           return true;
1485554f68d3SGreg Clayton       }
1486554f68d3SGreg Clayton     }
1487554f68d3SGreg Clayton     return false;
1488554f68d3SGreg Clayton 
1489554f68d3SGreg Clayton   case Entry::Type::ScriptFrame:
1490b9c1b51eSKate Stone     if (exe_ctx) {
1491554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1492554f68d3SGreg Clayton       if (frame)
1493b9c1b51eSKate Stone         return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
1494b9c1b51eSKate Stone                                       entry.string.c_str());
1495554f68d3SGreg Clayton     }
1496554f68d3SGreg Clayton     return false;
1497554f68d3SGreg Clayton 
1498554f68d3SGreg Clayton   case Entry::Type::FunctionID:
1499b9c1b51eSKate Stone     if (sc) {
1500b9c1b51eSKate Stone       if (sc->function) {
1501554f68d3SGreg Clayton         s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
1502554f68d3SGreg Clayton         return true;
1503b9c1b51eSKate Stone       } else if (sc->symbol) {
1504554f68d3SGreg Clayton         s.Printf("symbol[%u]", sc->symbol->GetID());
1505554f68d3SGreg Clayton         return true;
1506554f68d3SGreg Clayton       }
1507554f68d3SGreg Clayton     }
1508554f68d3SGreg Clayton     return false;
1509554f68d3SGreg Clayton 
1510554f68d3SGreg Clayton   case Entry::Type::FunctionDidChange:
1511554f68d3SGreg Clayton     return function_changed;
1512554f68d3SGreg Clayton 
1513554f68d3SGreg Clayton   case Entry::Type::FunctionInitialFunction:
1514554f68d3SGreg Clayton     return initial_function;
1515554f68d3SGreg Clayton 
1516b9c1b51eSKate Stone   case Entry::Type::FunctionName: {
1517d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1518d4129b47SEnrico Granata     bool language_plugin_handled = false;
1519d4129b47SEnrico Granata     StreamString ss;
1520d4129b47SEnrico Granata     if (sc->function)
1521d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1522d4129b47SEnrico Granata     else if (sc->symbol)
1523d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1524b9c1b51eSKate Stone     if (language_plugin) {
1525b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1526b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1527d4129b47SEnrico Granata     }
1528b9c1b51eSKate Stone     if (language_plugin_handled) {
1529c156427dSZachary Turner       s << ss.GetString();
1530d4129b47SEnrico Granata       return true;
1531b9c1b51eSKate Stone     } else {
1532a74f37a5SEugene Zelenko       const char *name = nullptr;
1533554f68d3SGreg Clayton       if (sc->function)
1534a74f37a5SEugene Zelenko         name = sc->function->GetName().AsCString(nullptr);
1535554f68d3SGreg Clayton       else if (sc->symbol)
1536a74f37a5SEugene Zelenko         name = sc->symbol->GetName().AsCString(nullptr);
1537b9c1b51eSKate Stone       if (name) {
1538554f68d3SGreg Clayton         s.PutCString(name);
1539554f68d3SGreg Clayton 
1540b9c1b51eSKate Stone         if (sc->block) {
1541554f68d3SGreg Clayton           Block *inline_block = sc->block->GetContainingInlinedBlock();
1542b9c1b51eSKate Stone           if (inline_block) {
1543b9c1b51eSKate Stone             const InlineFunctionInfo *inline_info =
1544b9c1b51eSKate Stone                 sc->block->GetInlinedFunctionInfo();
1545b9c1b51eSKate Stone             if (inline_info) {
1546554f68d3SGreg Clayton               s.PutCString(" [inlined] ");
1547ddaf6a72SGreg Clayton               inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
1548554f68d3SGreg Clayton             }
1549554f68d3SGreg Clayton           }
1550554f68d3SGreg Clayton         }
1551554f68d3SGreg Clayton         return true;
1552554f68d3SGreg Clayton       }
1553554f68d3SGreg Clayton     }
1554d4129b47SEnrico Granata   }
1555554f68d3SGreg Clayton     return false;
1556554f68d3SGreg Clayton 
1557b9c1b51eSKate Stone   case Entry::Type::FunctionNameNoArgs: {
1558d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1559d4129b47SEnrico Granata     bool language_plugin_handled = false;
1560d4129b47SEnrico Granata     StreamString ss;
1561d4129b47SEnrico Granata     if (sc->function)
1562d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1563d4129b47SEnrico Granata     else if (sc->symbol)
1564d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1565b9c1b51eSKate Stone     if (language_plugin) {
1566b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1567b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1568d4129b47SEnrico Granata           ss);
1569d4129b47SEnrico Granata     }
1570b9c1b51eSKate Stone     if (language_plugin_handled) {
1571c156427dSZachary Turner       s << ss.GetString();
1572d4129b47SEnrico Granata       return true;
1573b9c1b51eSKate Stone     } else {
1574554f68d3SGreg Clayton       ConstString name;
1575554f68d3SGreg Clayton       if (sc->function)
1576ddaf6a72SGreg Clayton         name = sc->function->GetNameNoArguments();
1577554f68d3SGreg Clayton       else if (sc->symbol)
1578ddaf6a72SGreg Clayton         name = sc->symbol->GetNameNoArguments();
1579b9c1b51eSKate Stone       if (name) {
1580554f68d3SGreg Clayton         s.PutCString(name.GetCString());
1581554f68d3SGreg Clayton         return true;
1582554f68d3SGreg Clayton       }
1583554f68d3SGreg Clayton     }
1584d4129b47SEnrico Granata   }
1585554f68d3SGreg Clayton     return false;
1586554f68d3SGreg Clayton 
1587b9c1b51eSKate Stone   case Entry::Type::FunctionNameWithArgs: {
1588d4129b47SEnrico Granata     Language *language_plugin = nullptr;
1589d4129b47SEnrico Granata     bool language_plugin_handled = false;
1590d4129b47SEnrico Granata     StreamString ss;
1591d4129b47SEnrico Granata     if (sc->function)
1592d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1593d4129b47SEnrico Granata     else if (sc->symbol)
1594d4129b47SEnrico Granata       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1595b9c1b51eSKate Stone     if (language_plugin) {
1596b9c1b51eSKate Stone       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1597b9c1b51eSKate Stone           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1598d4129b47SEnrico Granata     }
1599b9c1b51eSKate Stone     if (language_plugin_handled) {
1600c156427dSZachary Turner       s << ss.GetString();
1601d4129b47SEnrico Granata       return true;
1602b9c1b51eSKate Stone     } else {
1603554f68d3SGreg Clayton       // Print the function name with arguments in it
1604b9c1b51eSKate Stone       if (sc->function) {
1605b9c1b51eSKate Stone         ExecutionContextScope *exe_scope =
1606b9c1b51eSKate Stone             exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1607a74f37a5SEugene Zelenko         const char *cstr = sc->function->GetName().AsCString(nullptr);
1608b9c1b51eSKate Stone         if (cstr) {
1609a74f37a5SEugene Zelenko           const InlineFunctionInfo *inline_info = nullptr;
1610554f68d3SGreg Clayton           VariableListSP variable_list_sp;
1611554f68d3SGreg Clayton           bool get_function_vars = true;
1612b9c1b51eSKate Stone           if (sc->block) {
1613554f68d3SGreg Clayton             Block *inline_block = sc->block->GetContainingInlinedBlock();
1614554f68d3SGreg Clayton 
1615b9c1b51eSKate Stone             if (inline_block) {
1616554f68d3SGreg Clayton               get_function_vars = false;
1617554f68d3SGreg Clayton               inline_info = sc->block->GetInlinedFunctionInfo();
1618554f68d3SGreg Clayton               if (inline_info)
1619554f68d3SGreg Clayton                 variable_list_sp = inline_block->GetBlockVariableList(true);
1620554f68d3SGreg Clayton             }
1621554f68d3SGreg Clayton           }
1622554f68d3SGreg Clayton 
1623b9c1b51eSKate Stone           if (get_function_vars) {
1624b9c1b51eSKate Stone             variable_list_sp =
1625b9c1b51eSKate Stone                 sc->function->GetBlock(true).GetBlockVariableList(true);
1626554f68d3SGreg Clayton           }
1627554f68d3SGreg Clayton 
1628b9c1b51eSKate Stone           if (inline_info) {
1629554f68d3SGreg Clayton             s.PutCString(cstr);
1630554f68d3SGreg Clayton             s.PutCString(" [inlined] ");
1631b9c1b51eSKate Stone             cstr =
1632b9c1b51eSKate Stone                 inline_info->GetName(sc->function->GetLanguage()).GetCString();
1633554f68d3SGreg Clayton           }
1634554f68d3SGreg Clayton 
1635554f68d3SGreg Clayton           VariableList args;
1636554f68d3SGreg Clayton           if (variable_list_sp)
1637b9c1b51eSKate Stone             variable_list_sp->AppendVariablesWithScope(
1638b9c1b51eSKate Stone                 eValueTypeVariableArgument, args);
1639b9c1b51eSKate Stone           if (args.GetSize() > 0) {
1640554f68d3SGreg Clayton             const char *open_paren = strchr(cstr, '(');
1641554f68d3SGreg Clayton             const char *close_paren = nullptr;
1642554f68d3SGreg Clayton             const char *generic = strchr(cstr, '<');
1643554f68d3SGreg Clayton             // if before the arguments list begins there is a template sign
1644554f68d3SGreg Clayton             // then scan to the end of the generic args before you try to find
1645554f68d3SGreg Clayton             // the arguments list
1646b9c1b51eSKate Stone             if (generic && open_paren && generic < open_paren) {
1647554f68d3SGreg Clayton               int generic_depth = 1;
1648554f68d3SGreg Clayton               ++generic;
1649b9c1b51eSKate Stone               for (; *generic && generic_depth > 0; generic++) {
1650554f68d3SGreg Clayton                 if (*generic == '<')
1651554f68d3SGreg Clayton                   generic_depth++;
1652554f68d3SGreg Clayton                 if (*generic == '>')
1653554f68d3SGreg Clayton                   generic_depth--;
1654554f68d3SGreg Clayton               }
1655554f68d3SGreg Clayton               if (*generic)
1656554f68d3SGreg Clayton                 open_paren = strchr(generic, '(');
1657554f68d3SGreg Clayton               else
1658554f68d3SGreg Clayton                 open_paren = nullptr;
1659554f68d3SGreg Clayton             }
1660b9c1b51eSKate Stone             if (open_paren) {
1661b9c1b51eSKate Stone               if (IsToken(open_paren, "(anonymous namespace)")) {
1662b9c1b51eSKate Stone                 open_paren =
1663b9c1b51eSKate Stone                     strchr(open_paren + strlen("(anonymous namespace)"), '(');
1664554f68d3SGreg Clayton                 if (open_paren)
1665554f68d3SGreg Clayton                   close_paren = strchr(open_paren, ')');
1666b9c1b51eSKate Stone               } else
1667554f68d3SGreg Clayton                 close_paren = strchr(open_paren, ')');
1668554f68d3SGreg Clayton             }
1669554f68d3SGreg Clayton 
1670554f68d3SGreg Clayton             if (open_paren)
1671554f68d3SGreg Clayton               s.Write(cstr, open_paren - cstr + 1);
1672b9c1b51eSKate Stone             else {
1673554f68d3SGreg Clayton               s.PutCString(cstr);
1674554f68d3SGreg Clayton               s.PutChar('(');
1675554f68d3SGreg Clayton             }
1676554f68d3SGreg Clayton             const size_t num_args = args.GetSize();
1677b9c1b51eSKate Stone             for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1678554f68d3SGreg Clayton               std::string buffer;
1679554f68d3SGreg Clayton 
1680554f68d3SGreg Clayton               VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1681b9c1b51eSKate Stone               ValueObjectSP var_value_sp(
1682b9c1b51eSKate Stone                   ValueObjectVariable::Create(exe_scope, var_sp));
1683ad91c7ceSEnrico Granata               StreamString ss;
1684c156427dSZachary Turner               llvm::StringRef var_representation;
1685554f68d3SGreg Clayton               const char *var_name = var_value_sp->GetName().GetCString();
1686b9c1b51eSKate Stone               if (var_value_sp->GetCompilerType().IsValid()) {
1687ad91c7ceSEnrico Granata                 if (var_value_sp && exe_scope->CalculateTarget())
1688b9c1b51eSKate Stone                   var_value_sp =
1689b9c1b51eSKate Stone                       var_value_sp->GetQualifiedRepresentationIfAvailable(
1690b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1691b9c1b51eSKate Stone                               ->TargetProperties::GetPreferDynamicValue(),
1692b9c1b51eSKate Stone                           exe_scope->CalculateTarget()
1693b9c1b51eSKate Stone                               ->TargetProperties::GetEnableSyntheticValue());
169499558cc4SGreg Clayton                 if (var_value_sp->GetCompilerType().IsAggregateType() &&
1695b9c1b51eSKate Stone                     DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
1696b9c1b51eSKate Stone                   static StringSummaryFormat format(
1697b9c1b51eSKate Stone                       TypeSummaryImpl::Flags()
1698554f68d3SGreg Clayton                           .SetHideItemNames(false)
1699554f68d3SGreg Clayton                           .SetShowMembersOneLiner(true),
1700554f68d3SGreg Clayton                       "");
1701b9c1b51eSKate Stone                   format.FormatObject(var_value_sp.get(), buffer,
1702b9c1b51eSKate Stone                                       TypeSummaryOptions());
1703c156427dSZachary Turner                   var_representation = buffer;
1704b9c1b51eSKate Stone                 } else
1705b9c1b51eSKate Stone                   var_value_sp->DumpPrintableRepresentation(
1706b9c1b51eSKate Stone                       ss, ValueObject::ValueObjectRepresentationStyle::
1707b9c1b51eSKate Stone                               eValueObjectRepresentationStyleSummary,
1708ad91c7ceSEnrico Granata                       eFormatDefault,
170965d86e4fSEnrico Granata                       ValueObject::PrintableRepresentationSpecialCases::eAllow,
1710ad91c7ceSEnrico Granata                       false);
1711ad91c7ceSEnrico Granata               }
1712ad91c7ceSEnrico Granata 
1713c156427dSZachary Turner               if (!ss.GetString().empty())
1714c156427dSZachary Turner                 var_representation = ss.GetString();
1715554f68d3SGreg Clayton               if (arg_idx > 0)
1716554f68d3SGreg Clayton                 s.PutCString(", ");
1717b9c1b51eSKate Stone               if (var_value_sp->GetError().Success()) {
1718c156427dSZachary Turner                 if (!var_representation.empty())
1719c156427dSZachary Turner                   s.Printf("%s=%s", var_name, var_representation.str().c_str());
1720554f68d3SGreg Clayton                 else
1721b9c1b51eSKate Stone                   s.Printf("%s=%s at %s", var_name,
1722b9c1b51eSKate Stone                            var_value_sp->GetTypeName().GetCString(),
1723b9c1b51eSKate Stone                            var_value_sp->GetLocationAsCString());
1724b9c1b51eSKate Stone               } else
1725554f68d3SGreg Clayton                 s.Printf("%s=<unavailable>", var_name);
1726554f68d3SGreg Clayton             }
1727554f68d3SGreg Clayton 
1728554f68d3SGreg Clayton             if (close_paren)
1729554f68d3SGreg Clayton               s.PutCString(close_paren);
1730554f68d3SGreg Clayton             else
1731554f68d3SGreg Clayton               s.PutChar(')');
1732554f68d3SGreg Clayton 
1733b9c1b51eSKate Stone           } else {
1734554f68d3SGreg Clayton             s.PutCString(cstr);
1735554f68d3SGreg Clayton           }
1736554f68d3SGreg Clayton           return true;
1737554f68d3SGreg Clayton         }
1738b9c1b51eSKate Stone       } else if (sc->symbol) {
1739a74f37a5SEugene Zelenko         const char *cstr = sc->symbol->GetName().AsCString(nullptr);
1740b9c1b51eSKate Stone         if (cstr) {
1741554f68d3SGreg Clayton           s.PutCString(cstr);
1742554f68d3SGreg Clayton           return true;
1743554f68d3SGreg Clayton         }
1744554f68d3SGreg Clayton       }
1745554f68d3SGreg Clayton     }
1746d4129b47SEnrico Granata   }
1747554f68d3SGreg Clayton     return false;
1748554f68d3SGreg Clayton 
1749554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffset:
1750b9c1b51eSKate Stone     if (addr) {
1751b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
1752b9c1b51eSKate Stone                                         false))
1753554f68d3SGreg Clayton         return true;
1754554f68d3SGreg Clayton     }
1755554f68d3SGreg Clayton     return false;
1756554f68d3SGreg Clayton 
1757554f68d3SGreg Clayton   case Entry::Type::FunctionAddrOffsetConcrete:
1758b9c1b51eSKate Stone     if (addr) {
1759b9c1b51eSKate Stone       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
1760b9c1b51eSKate Stone                                         true))
1761554f68d3SGreg Clayton         return true;
1762554f68d3SGreg Clayton     }
1763554f68d3SGreg Clayton     return false;
1764554f68d3SGreg Clayton 
1765554f68d3SGreg Clayton   case Entry::Type::FunctionLineOffset:
1766b9c1b51eSKate Stone     return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1767b9c1b51eSKate Stone                                           sc->line_entry.range.GetBaseAddress(),
1768b9c1b51eSKate Stone                                           false, false, false));
1769554f68d3SGreg Clayton 
1770554f68d3SGreg Clayton   case Entry::Type::FunctionPCOffset:
1771b9c1b51eSKate Stone     if (exe_ctx) {
1772554f68d3SGreg Clayton       StackFrame *frame = exe_ctx->GetFramePtr();
1773b9c1b51eSKate Stone       if (frame) {
1774b9c1b51eSKate Stone         if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1775b9c1b51eSKate Stone                                           frame->GetFrameCodeAddress(), false,
1776b9c1b51eSKate Stone                                           false, false))
1777554f68d3SGreg Clayton           return true;
1778554f68d3SGreg Clayton       }
1779554f68d3SGreg Clayton     }
1780554f68d3SGreg Clayton     return false;
1781554f68d3SGreg Clayton 
1782c980fa92SJason Molenda   case Entry::Type::FunctionChanged:
1783a74f37a5SEugene Zelenko     return function_changed;
1784c980fa92SJason Molenda 
1785b9c1b51eSKate Stone   case Entry::Type::FunctionIsOptimized: {
17866ab659a9SJason Molenda     bool is_optimized = false;
1787b9c1b51eSKate Stone     if (sc->function && sc->function->GetIsOptimized()) {
17886ab659a9SJason Molenda       is_optimized = true;
17896ab659a9SJason Molenda     }
17906ab659a9SJason Molenda     return is_optimized;
17916ab659a9SJason Molenda   }
17926ab659a9SJason Molenda 
1793c980fa92SJason Molenda   case Entry::Type::FunctionInitial:
1794a74f37a5SEugene Zelenko     return initial_function;
1795c980fa92SJason Molenda 
1796554f68d3SGreg Clayton   case Entry::Type::LineEntryFile:
1797b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1798554f68d3SGreg Clayton       Module *module = sc->module_sp.get();
1799b9c1b51eSKate Stone       if (module) {
1800554f68d3SGreg Clayton         if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
1801554f68d3SGreg Clayton           return true;
1802554f68d3SGreg Clayton       }
1803554f68d3SGreg Clayton     }
1804554f68d3SGreg Clayton     return false;
1805554f68d3SGreg Clayton 
1806554f68d3SGreg Clayton   case Entry::Type::LineEntryLineNumber:
1807b9c1b51eSKate Stone     if (sc && sc->line_entry.IsValid()) {
1808554f68d3SGreg Clayton       const char *format = "%" PRIu32;
1809554f68d3SGreg Clayton       if (!entry.printf_format.empty())
1810554f68d3SGreg Clayton         format = entry.printf_format.c_str();
1811554f68d3SGreg Clayton       s.Printf(format, sc->line_entry.line);
1812554f68d3SGreg Clayton       return true;
1813554f68d3SGreg Clayton     }
1814554f68d3SGreg Clayton     return false;
1815554f68d3SGreg Clayton 
1816554f68d3SGreg Clayton   case Entry::Type::LineEntryStartAddress:
1817554f68d3SGreg Clayton   case Entry::Type::LineEntryEndAddress:
1818b9c1b51eSKate Stone     if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
1819554f68d3SGreg Clayton       Address addr = sc->line_entry.range.GetBaseAddress();
1820554f68d3SGreg Clayton 
1821554f68d3SGreg Clayton       if (entry.type == Entry::Type::LineEntryEndAddress)
1822554f68d3SGreg Clayton         addr.Slide(sc->line_entry.range.GetByteSize());
1823554f68d3SGreg Clayton       if (DumpAddress(s, sc, exe_ctx, addr, false))
1824554f68d3SGreg Clayton         return true;
1825554f68d3SGreg Clayton     }
1826554f68d3SGreg Clayton     return false;
1827554f68d3SGreg Clayton 
1828554f68d3SGreg Clayton   case Entry::Type::CurrentPCArrow:
1829b9c1b51eSKate Stone     if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
1830b9c1b51eSKate Stone       RegisterContextSP reg_ctx =
1831b9c1b51eSKate Stone           exe_ctx->GetFramePtr()->GetRegisterContextSP();
1832b9c1b51eSKate Stone       if (reg_ctx) {
1833554f68d3SGreg Clayton         addr_t pc_loadaddr = reg_ctx->GetPC();
1834b9c1b51eSKate Stone         if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
1835554f68d3SGreg Clayton           Address pc;
1836554f68d3SGreg Clayton           pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
1837b9c1b51eSKate Stone           if (pc == *addr) {
1838554f68d3SGreg Clayton             s.Printf("-> ");
1839554f68d3SGreg Clayton             return true;
1840554f68d3SGreg Clayton           }
1841554f68d3SGreg Clayton         }
1842554f68d3SGreg Clayton       }
1843554f68d3SGreg Clayton       s.Printf("   ");
1844554f68d3SGreg Clayton       return true;
1845554f68d3SGreg Clayton     }
1846554f68d3SGreg Clayton     return false;
1847554f68d3SGreg Clayton   }
1848554f68d3SGreg Clayton   return false;
1849554f68d3SGreg Clayton }
1850554f68d3SGreg Clayton 
1851b9c1b51eSKate Stone static bool DumpCommaSeparatedChildEntryNames(
1852b9c1b51eSKate Stone     Stream &s, const FormatEntity::Entry::Definition *parent) {
1853b9c1b51eSKate Stone   if (parent->children) {
1854554f68d3SGreg Clayton     const size_t n = parent->num_children;
1855b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
1856554f68d3SGreg Clayton       if (i > 0)
1857554f68d3SGreg Clayton         s.PutCString(", ");
1858554f68d3SGreg Clayton       s.Printf("\"%s\"", parent->children[i].name);
1859554f68d3SGreg Clayton     }
1860554f68d3SGreg Clayton     return true;
1861554f68d3SGreg Clayton   }
1862554f68d3SGreg Clayton   return false;
1863554f68d3SGreg Clayton }
1864554f68d3SGreg Clayton 
186597206d57SZachary Turner static Status ParseEntry(const llvm::StringRef &format_str,
1866554f68d3SGreg Clayton                          const FormatEntity::Entry::Definition *parent,
1867b9c1b51eSKate Stone                          FormatEntity::Entry &entry) {
186897206d57SZachary Turner   Status error;
1869554f68d3SGreg Clayton 
1870554f68d3SGreg Clayton   const size_t sep_pos = format_str.find_first_of(".[:");
1871b9c1b51eSKate Stone   const char sep_char =
1872b9c1b51eSKate Stone       (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
1873554f68d3SGreg Clayton   llvm::StringRef key = format_str.substr(0, sep_pos);
1874554f68d3SGreg Clayton 
1875554f68d3SGreg Clayton   const size_t n = parent->num_children;
1876b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1877554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1878b9c1b51eSKate Stone     if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
1879554f68d3SGreg Clayton       llvm::StringRef value;
1880554f68d3SGreg Clayton       if (sep_char)
1881b9c1b51eSKate Stone         value =
1882b9c1b51eSKate Stone             format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
1883b9c1b51eSKate Stone       switch (entry_def->type) {
1884554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentString:
18853a29f8b9SPavel Labath         entry.string = format_str.str();
1886554f68d3SGreg Clayton         return error; // Success
1887554f68d3SGreg Clayton 
1888554f68d3SGreg Clayton       case FormatEntity::Entry::Type::ParentNumber:
1889554f68d3SGreg Clayton         entry.number = entry_def->data;
1890554f68d3SGreg Clayton         return error; // Success
1891554f68d3SGreg Clayton 
1892554f68d3SGreg Clayton       case FormatEntity::Entry::Type::InsertString:
1893554f68d3SGreg Clayton         entry.type = entry_def->type;
1894554f68d3SGreg Clayton         entry.string = entry_def->string;
1895554f68d3SGreg Clayton         return error; // Success
1896554f68d3SGreg Clayton 
1897554f68d3SGreg Clayton       default:
1898554f68d3SGreg Clayton         entry.type = entry_def->type;
1899554f68d3SGreg Clayton         break;
1900554f68d3SGreg Clayton       }
1901554f68d3SGreg Clayton 
1902b9c1b51eSKate Stone       if (value.empty()) {
1903b9c1b51eSKate Stone         if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
1904b9c1b51eSKate Stone           if (entry_def->children) {
1905554f68d3SGreg Clayton             StreamString error_strm;
1906b9c1b51eSKate Stone             error_strm.Printf("'%s' can't be specified on its own, you must "
1907b9c1b51eSKate Stone                               "access one of its children: ",
1908b9c1b51eSKate Stone                               entry_def->name);
1909554f68d3SGreg Clayton             DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
1910c156427dSZachary Turner             error.SetErrorStringWithFormat("%s", error_strm.GetData());
1911b9c1b51eSKate Stone           } else if (sep_char == ':') {
1912b9c1b51eSKate Stone             // Any value whose separator is a with a ':' means this value has a
191305097246SAdrian Prantl             // string argument that needs to be stored in the entry (like
191405097246SAdrian Prantl             // "${script.var:}"). In this case the string value is the empty
191505097246SAdrian Prantl             // string which is ok.
1916b9c1b51eSKate Stone           } else {
1917554f68d3SGreg Clayton             error.SetErrorStringWithFormat("%s", "invalid entry definitions");
1918554f68d3SGreg Clayton           }
1919554f68d3SGreg Clayton         }
1920b9c1b51eSKate Stone       } else {
1921b9c1b51eSKate Stone         if (entry_def->children) {
1922554f68d3SGreg Clayton           error = ParseEntry(value, entry_def, entry);
1923b9c1b51eSKate Stone         } else if (sep_char == ':') {
1924b9c1b51eSKate Stone           // Any value whose separator is a with a ':' means this value has a
192505097246SAdrian Prantl           // string argument that needs to be stored in the entry (like
1926b9c1b51eSKate Stone           // "${script.var:modulename.function}")
19273a29f8b9SPavel Labath           entry.string = value.str();
1928b9c1b51eSKate Stone         } else {
1929b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1930b9c1b51eSKate Stone               "'%s' followed by '%s' but it has no children", key.str().c_str(),
1931554f68d3SGreg Clayton               value.str().c_str());
1932554f68d3SGreg Clayton         }
1933554f68d3SGreg Clayton       }
1934554f68d3SGreg Clayton       return error;
1935554f68d3SGreg Clayton     }
1936554f68d3SGreg Clayton   }
1937554f68d3SGreg Clayton   StreamString error_strm;
1938554f68d3SGreg Clayton   if (parent->type == FormatEntity::Entry::Type::Root)
1939b9c1b51eSKate Stone     error_strm.Printf(
1940b9c1b51eSKate Stone         "invalid top level item '%s'. Valid top level items are: ",
1941b9c1b51eSKate Stone         key.str().c_str());
1942554f68d3SGreg Clayton   else
1943b9c1b51eSKate Stone     error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
1944b9c1b51eSKate Stone                       key.str().c_str(), parent->name);
1945554f68d3SGreg Clayton   DumpCommaSeparatedChildEntryNames(error_strm, parent);
1946c156427dSZachary Turner   error.SetErrorStringWithFormat("%s", error_strm.GetData());
1947554f68d3SGreg Clayton   return error;
1948554f68d3SGreg Clayton }
1949554f68d3SGreg Clayton 
1950554f68d3SGreg Clayton static const FormatEntity::Entry::Definition *
1951b9c1b51eSKate Stone FindEntry(const llvm::StringRef &format_str,
1952b9c1b51eSKate Stone           const FormatEntity::Entry::Definition *parent,
1953b9c1b51eSKate Stone           llvm::StringRef &remainder) {
195497206d57SZachary Turner   Status error;
1955554f68d3SGreg Clayton 
1956554f68d3SGreg Clayton   std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
1957554f68d3SGreg Clayton   const size_t n = parent->num_children;
1958b9c1b51eSKate Stone   for (size_t i = 0; i < n; ++i) {
1959554f68d3SGreg Clayton     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1960b9c1b51eSKate Stone     if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
1961b9c1b51eSKate Stone       if (p.second.empty()) {
1962554f68d3SGreg Clayton         if (format_str.back() == '.')
1963554f68d3SGreg Clayton           remainder = format_str.drop_front(format_str.size() - 1);
1964554f68d3SGreg Clayton         else
1965554f68d3SGreg Clayton           remainder = llvm::StringRef(); // Exact match
1966554f68d3SGreg Clayton         return entry_def;
1967b9c1b51eSKate Stone       } else {
1968b9c1b51eSKate Stone         if (entry_def->children) {
1969554f68d3SGreg Clayton           return FindEntry(p.second, entry_def, remainder);
1970b9c1b51eSKate Stone         } else {
1971554f68d3SGreg Clayton           remainder = p.second;
1972554f68d3SGreg Clayton           return entry_def;
1973554f68d3SGreg Clayton         }
1974554f68d3SGreg Clayton       }
1975554f68d3SGreg Clayton     }
1976554f68d3SGreg Clayton   }
1977554f68d3SGreg Clayton   remainder = format_str;
1978554f68d3SGreg Clayton   return parent;
1979554f68d3SGreg Clayton }
1980554f68d3SGreg Clayton 
198197206d57SZachary Turner Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
1982b9c1b51eSKate Stone                                    uint32_t depth) {
198397206d57SZachary Turner   Status error;
1984b9c1b51eSKate Stone   while (!format.empty() && error.Success()) {
1985554f68d3SGreg Clayton     const size_t non_special_chars = format.find_first_of("${}\\");
1986554f68d3SGreg Clayton 
1987b9c1b51eSKate Stone     if (non_special_chars == llvm::StringRef::npos) {
1988554f68d3SGreg Clayton       // No special characters, just string bytes so add them and we are done
1989554f68d3SGreg Clayton       parent_entry.AppendText(format);
1990554f68d3SGreg Clayton       return error;
1991554f68d3SGreg Clayton     }
1992554f68d3SGreg Clayton 
1993b9c1b51eSKate Stone     if (non_special_chars > 0) {
1994b9c1b51eSKate Stone       // We have a special character, so add all characters before these as a
1995b9c1b51eSKate Stone       // plain string
1996554f68d3SGreg Clayton       parent_entry.AppendText(format.substr(0, non_special_chars));
1997554f68d3SGreg Clayton       format = format.drop_front(non_special_chars);
1998554f68d3SGreg Clayton     }
1999554f68d3SGreg Clayton 
2000b9c1b51eSKate Stone     switch (format[0]) {
2001554f68d3SGreg Clayton     case '\0':
2002554f68d3SGreg Clayton       return error;
2003554f68d3SGreg Clayton 
2004b9c1b51eSKate Stone     case '{': {
2005554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '{'
2006554f68d3SGreg Clayton       Entry scope_entry(Entry::Type::Scope);
2007554f68d3SGreg Clayton       error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
2008554f68d3SGreg Clayton       if (error.Fail())
2009554f68d3SGreg Clayton         return error;
2010554f68d3SGreg Clayton       parent_entry.AppendEntry(std::move(scope_entry));
2011b9c1b51eSKate Stone     } break;
2012554f68d3SGreg Clayton 
2013554f68d3SGreg Clayton     case '}':
2014554f68d3SGreg Clayton       if (depth == 0)
2015554f68d3SGreg Clayton         error.SetErrorString("unmatched '}' character");
2016554f68d3SGreg Clayton       else
2017b9c1b51eSKate Stone         format =
2018b9c1b51eSKate Stone             format
2019b9c1b51eSKate Stone                 .drop_front(); // Skip the '}' as we are at the end of the scope
2020554f68d3SGreg Clayton       return error;
2021554f68d3SGreg Clayton 
2022b9c1b51eSKate Stone     case '\\': {
2023554f68d3SGreg Clayton       format = format.drop_front(); // Skip the '\' character
2024b9c1b51eSKate Stone       if (format.empty()) {
2025b9c1b51eSKate Stone         error.SetErrorString(
2026b9c1b51eSKate Stone             "'\\' character was not followed by another character");
2027554f68d3SGreg Clayton         return error;
2028554f68d3SGreg Clayton       }
2029554f68d3SGreg Clayton 
2030554f68d3SGreg Clayton       const char desens_char = format[0];
2031554f68d3SGreg Clayton       format = format.drop_front(); // Skip the desensitized char character
2032b9c1b51eSKate Stone       switch (desens_char) {
2033b9c1b51eSKate Stone       case 'a':
2034b9c1b51eSKate Stone         parent_entry.AppendChar('\a');
2035b9c1b51eSKate Stone         break;
2036b9c1b51eSKate Stone       case 'b':
2037b9c1b51eSKate Stone         parent_entry.AppendChar('\b');
2038b9c1b51eSKate Stone         break;
2039b9c1b51eSKate Stone       case 'f':
2040b9c1b51eSKate Stone         parent_entry.AppendChar('\f');
2041b9c1b51eSKate Stone         break;
2042b9c1b51eSKate Stone       case 'n':
2043b9c1b51eSKate Stone         parent_entry.AppendChar('\n');
2044b9c1b51eSKate Stone         break;
2045b9c1b51eSKate Stone       case 'r':
2046b9c1b51eSKate Stone         parent_entry.AppendChar('\r');
2047b9c1b51eSKate Stone         break;
2048b9c1b51eSKate Stone       case 't':
2049b9c1b51eSKate Stone         parent_entry.AppendChar('\t');
2050b9c1b51eSKate Stone         break;
2051b9c1b51eSKate Stone       case 'v':
2052b9c1b51eSKate Stone         parent_entry.AppendChar('\v');
2053b9c1b51eSKate Stone         break;
2054b9c1b51eSKate Stone       case '\'':
2055b9c1b51eSKate Stone         parent_entry.AppendChar('\'');
2056b9c1b51eSKate Stone         break;
2057b9c1b51eSKate Stone       case '\\':
2058b9c1b51eSKate Stone         parent_entry.AppendChar('\\');
2059b9c1b51eSKate Stone         break;
2060554f68d3SGreg Clayton       case '0':
2061554f68d3SGreg Clayton         // 1 to 3 octal chars
2062554f68d3SGreg Clayton         {
206305097246SAdrian Prantl           // Make a string that can hold onto the initial zero char, up to 3
206405097246SAdrian Prantl           // octal digits, and a terminating NULL.
2065554f68d3SGreg Clayton           char oct_str[5] = {0, 0, 0, 0, 0};
2066554f68d3SGreg Clayton 
2067554f68d3SGreg Clayton           int i;
2068554f68d3SGreg Clayton           for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2069554f68d3SGreg Clayton             oct_str[i] = format[i];
2070554f68d3SGreg Clayton 
207105097246SAdrian Prantl           // We don't want to consume the last octal character since the main
207205097246SAdrian Prantl           // for loop will do this for us, so we advance p by one less than i
207305097246SAdrian Prantl           // (even if i is zero)
2074554f68d3SGreg Clayton           format = format.drop_front(i);
2075a74f37a5SEugene Zelenko           unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2076b9c1b51eSKate Stone           if (octal_value <= UINT8_MAX) {
2077554f68d3SGreg Clayton             parent_entry.AppendChar((char)octal_value);
2078b9c1b51eSKate Stone           } else {
2079554f68d3SGreg Clayton             error.SetErrorString("octal number is larger than a single byte");
2080554f68d3SGreg Clayton             return error;
2081554f68d3SGreg Clayton           }
2082554f68d3SGreg Clayton         }
2083554f68d3SGreg Clayton         break;
2084554f68d3SGreg Clayton 
2085554f68d3SGreg Clayton       case 'x':
2086554f68d3SGreg Clayton         // hex number in the format
2087b9c1b51eSKate Stone         if (isxdigit(format[0])) {
2088554f68d3SGreg Clayton           // Make a string that can hold onto two hex chars plus a
2089554f68d3SGreg Clayton           // NULL terminator
2090554f68d3SGreg Clayton           char hex_str[3] = {0, 0, 0};
2091554f68d3SGreg Clayton           hex_str[0] = format[0];
2092554f68d3SGreg Clayton 
2093554f68d3SGreg Clayton           format = format.drop_front();
2094554f68d3SGreg Clayton 
2095b9c1b51eSKate Stone           if (isxdigit(format[0])) {
2096554f68d3SGreg Clayton             hex_str[1] = format[0];
2097554f68d3SGreg Clayton             format = format.drop_front();
2098554f68d3SGreg Clayton           }
2099554f68d3SGreg Clayton 
2100a74f37a5SEugene Zelenko           unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2101b9c1b51eSKate Stone           if (hex_value <= UINT8_MAX) {
2102554f68d3SGreg Clayton             parent_entry.AppendChar((char)hex_value);
2103b9c1b51eSKate Stone           } else {
2104554f68d3SGreg Clayton             error.SetErrorString("hex number is larger than a single byte");
2105554f68d3SGreg Clayton             return error;
2106554f68d3SGreg Clayton           }
2107b9c1b51eSKate Stone         } else {
2108554f68d3SGreg Clayton           parent_entry.AppendChar(desens_char);
2109554f68d3SGreg Clayton         }
2110554f68d3SGreg Clayton         break;
2111554f68d3SGreg Clayton 
2112554f68d3SGreg Clayton       default:
211305097246SAdrian Prantl         // Just desensitize any other character by just printing what came
211405097246SAdrian Prantl         // after the '\'
2115554f68d3SGreg Clayton         parent_entry.AppendChar(desens_char);
2116554f68d3SGreg Clayton         break;
2117554f68d3SGreg Clayton       }
2118b9c1b51eSKate Stone     } break;
2119554f68d3SGreg Clayton 
2120554f68d3SGreg Clayton     case '$':
2121b9c1b51eSKate Stone       if (format.size() == 1) {
2122554f68d3SGreg Clayton         // '$' at the end of a format string, just print the '$'
2123554f68d3SGreg Clayton         parent_entry.AppendText("$");
2124b9c1b51eSKate Stone       } else {
2125554f68d3SGreg Clayton         format = format.drop_front(); // Skip the '$'
2126554f68d3SGreg Clayton 
2127b9c1b51eSKate Stone         if (format[0] == '{') {
2128554f68d3SGreg Clayton           format = format.drop_front(); // Skip the '{'
2129554f68d3SGreg Clayton 
2130554f68d3SGreg Clayton           llvm::StringRef variable, variable_format;
2131b9c1b51eSKate Stone           error = FormatEntity::ExtractVariableInfo(format, variable,
2132b9c1b51eSKate Stone                                                     variable_format);
2133554f68d3SGreg Clayton           if (error.Fail())
2134554f68d3SGreg Clayton             return error;
2135554f68d3SGreg Clayton           bool verify_is_thread_id = false;
2136554f68d3SGreg Clayton           Entry entry;
2137b9c1b51eSKate Stone           if (!variable_format.empty()) {
21383a29f8b9SPavel Labath             entry.printf_format = variable_format.str();
2139554f68d3SGreg Clayton 
214005097246SAdrian Prantl             // If the format contains a '%' we are going to assume this is a
214105097246SAdrian Prantl             // printf style format. So if you want to format your thread ID
214205097246SAdrian Prantl             // using "0x%llx" you can use: ${thread.id%0x%llx}
2143554f68d3SGreg Clayton             //
2144554f68d3SGreg Clayton             // If there is no '%' in the format, then it is assumed to be a
2145554f68d3SGreg Clayton             // LLDB format name, or one of the extended formats specified in
2146554f68d3SGreg Clayton             // the switch statement below.
2147554f68d3SGreg Clayton 
2148b9c1b51eSKate Stone             if (entry.printf_format.find('%') == std::string::npos) {
2149554f68d3SGreg Clayton               bool clear_printf = false;
2150554f68d3SGreg Clayton 
2151b9c1b51eSKate Stone               if (FormatManager::GetFormatFromCString(
2152b9c1b51eSKate Stone                       entry.printf_format.c_str(), false, entry.fmt)) {
2153554f68d3SGreg Clayton                 // We have an LLDB format, so clear the printf format
2154554f68d3SGreg Clayton                 clear_printf = true;
2155b9c1b51eSKate Stone               } else if (entry.printf_format.size() == 1) {
2156b9c1b51eSKate Stone                 switch (entry.printf_format[0]) {
2157554f68d3SGreg Clayton                 case '@': // if this is an @ sign, print ObjC description
2158b9c1b51eSKate Stone                   entry.number = ValueObject::
2159b9c1b51eSKate Stone                       eValueObjectRepresentationStyleLanguageSpecific;
2160554f68d3SGreg Clayton                   clear_printf = true;
2161554f68d3SGreg Clayton                   break;
2162b9c1b51eSKate Stone                 case 'V': // if this is a V, print the value using the default
2163b9c1b51eSKate Stone                           // format
2164b9c1b51eSKate Stone                   entry.number =
2165b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleValue;
2166554f68d3SGreg Clayton                   clear_printf = true;
2167554f68d3SGreg Clayton                   break;
2168554f68d3SGreg Clayton                 case 'L': // if this is an L, print the location of the value
2169b9c1b51eSKate Stone                   entry.number =
2170b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleLocation;
2171554f68d3SGreg Clayton                   clear_printf = true;
2172554f68d3SGreg Clayton                   break;
2173554f68d3SGreg Clayton                 case 'S': // if this is an S, print the summary after all
2174b9c1b51eSKate Stone                   entry.number =
2175b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleSummary;
2176554f68d3SGreg Clayton                   clear_printf = true;
2177554f68d3SGreg Clayton                   break;
2178554f68d3SGreg Clayton                 case '#': // if this is a '#', print the number of children
2179b9c1b51eSKate Stone                   entry.number =
2180b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleChildrenCount;
2181554f68d3SGreg Clayton                   clear_printf = true;
2182554f68d3SGreg Clayton                   break;
2183554f68d3SGreg Clayton                 case 'T': // if this is a 'T', print the type
2184b9c1b51eSKate Stone                   entry.number =
2185b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleType;
2186554f68d3SGreg Clayton                   clear_printf = true;
2187554f68d3SGreg Clayton                   break;
2188554f68d3SGreg Clayton                 case 'N': // if this is a 'N', print the name
2189b9c1b51eSKate Stone                   entry.number =
2190b9c1b51eSKate Stone                       ValueObject::eValueObjectRepresentationStyleName;
2191554f68d3SGreg Clayton                   clear_printf = true;
2192554f68d3SGreg Clayton                   break;
2193281b65bcSGreg Clayton                 case '>': // if this is a '>', print the expression path
2194b9c1b51eSKate Stone                   entry.number = ValueObject::
2195b9c1b51eSKate Stone                       eValueObjectRepresentationStyleExpressionPath;
2196554f68d3SGreg Clayton                   clear_printf = true;
2197554f68d3SGreg Clayton                   break;
2198554f68d3SGreg Clayton                 default:
2199b9c1b51eSKate Stone                   error.SetErrorStringWithFormat("invalid format: '%s'",
2200b9c1b51eSKate Stone                                                  entry.printf_format.c_str());
2201554f68d3SGreg Clayton                   return error;
2202554f68d3SGreg Clayton                 }
2203b9c1b51eSKate Stone               } else if (FormatManager::GetFormatFromCString(
2204b9c1b51eSKate Stone                              entry.printf_format.c_str(), true, entry.fmt)) {
2205554f68d3SGreg Clayton                 clear_printf = true;
2206b9c1b51eSKate Stone               } else if (entry.printf_format == "tid") {
2207554f68d3SGreg Clayton                 verify_is_thread_id = true;
2208b9c1b51eSKate Stone               } else {
2209b9c1b51eSKate Stone                 error.SetErrorStringWithFormat("invalid format: '%s'",
2210b9c1b51eSKate Stone                                                entry.printf_format.c_str());
2211554f68d3SGreg Clayton                 return error;
2212554f68d3SGreg Clayton               }
2213554f68d3SGreg Clayton 
2214554f68d3SGreg Clayton               // Our format string turned out to not be a printf style format
2215554f68d3SGreg Clayton               // so lets clear the string
2216554f68d3SGreg Clayton               if (clear_printf)
2217554f68d3SGreg Clayton                 entry.printf_format.clear();
2218554f68d3SGreg Clayton             }
2219554f68d3SGreg Clayton           }
2220554f68d3SGreg Clayton 
2221554f68d3SGreg Clayton           // Check for dereferences
2222b9c1b51eSKate Stone           if (variable[0] == '*') {
2223554f68d3SGreg Clayton             entry.deref = true;
2224554f68d3SGreg Clayton             variable = variable.drop_front();
2225554f68d3SGreg Clayton           }
2226554f68d3SGreg Clayton 
2227554f68d3SGreg Clayton           error = ParseEntry(variable, &g_root, entry);
2228554f68d3SGreg Clayton           if (error.Fail())
2229554f68d3SGreg Clayton             return error;
2230554f68d3SGreg Clayton 
2231b9c1b51eSKate Stone           if (verify_is_thread_id) {
2232554f68d3SGreg Clayton             if (entry.type != Entry::Type::ThreadID &&
2233b9c1b51eSKate Stone                 entry.type != Entry::Type::ThreadProtocolID) {
2234b9c1b51eSKate Stone               error.SetErrorString("the 'tid' format can only be used on "
2235b9c1b51eSKate Stone                                    "${thread.id} and ${thread.protocol_id}");
2236554f68d3SGreg Clayton             }
2237554f68d3SGreg Clayton           }
2238554f68d3SGreg Clayton 
2239b9c1b51eSKate Stone           switch (entry.type) {
2240554f68d3SGreg Clayton           case Entry::Type::Variable:
2241554f68d3SGreg Clayton           case Entry::Type::VariableSynthetic:
2242b9c1b51eSKate Stone             if (entry.number == 0) {
2243554f68d3SGreg Clayton               if (entry.string.empty())
2244b9c1b51eSKate Stone                 entry.number =
2245b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleValue;
2246554f68d3SGreg Clayton               else
2247b9c1b51eSKate Stone                 entry.number =
2248b9c1b51eSKate Stone                     ValueObject::eValueObjectRepresentationStyleSummary;
2249554f68d3SGreg Clayton             }
2250554f68d3SGreg Clayton             break;
2251554f68d3SGreg Clayton           default:
2252b9c1b51eSKate Stone             // Make sure someone didn't try to dereference anything but ${var}
2253b9c1b51eSKate Stone             // or ${svar}
2254b9c1b51eSKate Stone             if (entry.deref) {
2255b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
2256b9c1b51eSKate Stone                   "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2257b9c1b51eSKate Stone                   variable.str().c_str());
2258554f68d3SGreg Clayton               return error;
2259554f68d3SGreg Clayton             }
2260554f68d3SGreg Clayton           }
226105097246SAdrian Prantl           // Check if this entry just wants to insert a constant string value
226205097246SAdrian Prantl           // into the parent_entry, if so, insert the string with AppendText,
226305097246SAdrian Prantl           // else append the entry to the parent_entry.
2264554f68d3SGreg Clayton           if (entry.type == Entry::Type::InsertString)
2265554f68d3SGreg Clayton             parent_entry.AppendText(entry.string.c_str());
2266554f68d3SGreg Clayton           else
2267554f68d3SGreg Clayton             parent_entry.AppendEntry(std::move(entry));
2268554f68d3SGreg Clayton         }
2269554f68d3SGreg Clayton       }
2270554f68d3SGreg Clayton       break;
2271554f68d3SGreg Clayton     }
2272554f68d3SGreg Clayton   }
2273554f68d3SGreg Clayton   return error;
2274554f68d3SGreg Clayton }
2275554f68d3SGreg Clayton 
227697206d57SZachary Turner Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2277b9c1b51eSKate Stone                                          llvm::StringRef &variable_name,
2278b9c1b51eSKate Stone                                          llvm::StringRef &variable_format) {
227997206d57SZachary Turner   Status error;
2280554f68d3SGreg Clayton   variable_name = llvm::StringRef();
2281554f68d3SGreg Clayton   variable_format = llvm::StringRef();
2282554f68d3SGreg Clayton 
2283e8433cc1SBruce Mitchener   const size_t paren_pos = format_str.find('}');
2284b9c1b51eSKate Stone   if (paren_pos != llvm::StringRef::npos) {
2285e8433cc1SBruce Mitchener     const size_t percent_pos = format_str.find('%');
2286b9c1b51eSKate Stone     if (percent_pos < paren_pos) {
2287b9c1b51eSKate Stone       if (percent_pos > 0) {
2288554f68d3SGreg Clayton         if (percent_pos > 1)
2289554f68d3SGreg Clayton           variable_name = format_str.substr(0, percent_pos);
2290b9c1b51eSKate Stone         variable_format =
2291b9c1b51eSKate Stone             format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2292554f68d3SGreg Clayton       }
2293b9c1b51eSKate Stone     } else {
2294554f68d3SGreg Clayton       variable_name = format_str.substr(0, paren_pos);
2295554f68d3SGreg Clayton     }
2296554f68d3SGreg Clayton     // Strip off elements and the formatting and the trailing '}'
2297554f68d3SGreg Clayton     format_str = format_str.substr(paren_pos + 1);
2298b9c1b51eSKate Stone   } else {
2299b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
2300b9c1b51eSKate Stone         "missing terminating '}' character for '${%s'",
2301b9c1b51eSKate Stone         format_str.str().c_str());
2302554f68d3SGreg Clayton   }
2303554f68d3SGreg Clayton   return error;
2304554f68d3SGreg Clayton }
2305554f68d3SGreg Clayton 
2306b9c1b51eSKate Stone bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
2307b9c1b51eSKate Stone                                   llvm::StringRef variable_name,
2308b9c1b51eSKate Stone                                   llvm::StringRef variable_format) {
2309b9c1b51eSKate Stone   if (variable_name.empty() || variable_name.equals(".fullpath")) {
2310554f68d3SGreg Clayton     file_spec.Dump(&s);
2311554f68d3SGreg Clayton     return true;
2312b9c1b51eSKate Stone   } else if (variable_name.equals(".basename")) {
2313554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2314554f68d3SGreg Clayton     return true;
2315b9c1b51eSKate Stone   } else if (variable_name.equals(".dirname")) {
2316554f68d3SGreg Clayton     s.PutCString(file_spec.GetFilename().AsCString(""));
2317554f68d3SGreg Clayton     return true;
2318554f68d3SGreg Clayton   }
2319554f68d3SGreg Clayton   return false;
2320554f68d3SGreg Clayton }
2321554f68d3SGreg Clayton 
2322b9c1b51eSKate Stone static std::string MakeMatch(const llvm::StringRef &prefix,
2323b9c1b51eSKate Stone                              const char *suffix) {
2324554f68d3SGreg Clayton   std::string match(prefix.str());
2325554f68d3SGreg Clayton   match.append(suffix);
23263a29f8b9SPavel Labath   return match;
2327554f68d3SGreg Clayton }
2328554f68d3SGreg Clayton 
2329b9c1b51eSKate Stone static void AddMatches(const FormatEntity::Entry::Definition *def,
2330554f68d3SGreg Clayton                        const llvm::StringRef &prefix,
2331554f68d3SGreg Clayton                        const llvm::StringRef &match_prefix,
2332b9c1b51eSKate Stone                        StringList &matches) {
2333554f68d3SGreg Clayton   const size_t n = def->num_children;
2334b9c1b51eSKate Stone   if (n > 0) {
2335b9c1b51eSKate Stone     for (size_t i = 0; i < n; ++i) {
23363a29f8b9SPavel Labath       std::string match = prefix.str();
2337554f68d3SGreg Clayton       if (match_prefix.empty())
2338554f68d3SGreg Clayton         matches.AppendString(MakeMatch(prefix, def->children[i].name));
2339b9c1b51eSKate Stone       else if (strncmp(def->children[i].name, match_prefix.data(),
2340b9c1b51eSKate Stone                        match_prefix.size()) == 0)
2341b9c1b51eSKate Stone         matches.AppendString(
2342b9c1b51eSKate Stone             MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2343554f68d3SGreg Clayton     }
2344554f68d3SGreg Clayton   }
2345554f68d3SGreg Clayton }
2346a74f37a5SEugene Zelenko 
2347*a2e76c0bSRaphael Isemann size_t FormatEntity::AutoComplete(CompletionRequest &request) {
2348*a2e76c0bSRaphael Isemann   llvm::StringRef str = request.GetCursorArgumentPrefix().str();
2349*a2e76c0bSRaphael Isemann 
2350*a2e76c0bSRaphael Isemann   request.SetWordComplete(false);
2351*a2e76c0bSRaphael Isemann   str = str.drop_front(request.GetMatchStartPoint());
2352*a2e76c0bSRaphael Isemann   request.GetMatches().Clear();
2353554f68d3SGreg Clayton 
2354554f68d3SGreg Clayton   const size_t dollar_pos = str.rfind('$');
23554aa8753cSZachary Turner   if (dollar_pos == llvm::StringRef::npos)
23564aa8753cSZachary Turner     return 0;
23574aa8753cSZachary Turner 
2358554f68d3SGreg Clayton   // Hitting TAB after $ at the end of the string add a "{"
2359b9c1b51eSKate Stone   if (dollar_pos == str.size() - 1) {
23603a29f8b9SPavel Labath     std::string match = str.str();
2361554f68d3SGreg Clayton     match.append("{");
2362*a2e76c0bSRaphael Isemann     request.GetMatches().AppendString(match);
23634aa8753cSZachary Turner     return 1;
23644aa8753cSZachary Turner   }
23654aa8753cSZachary Turner 
23664aa8753cSZachary Turner   if (str[dollar_pos + 1] != '{')
23674aa8753cSZachary Turner     return 0;
23684aa8753cSZachary Turner 
2369554f68d3SGreg Clayton   const size_t close_pos = str.find('}', dollar_pos + 2);
23704aa8753cSZachary Turner   if (close_pos != llvm::StringRef::npos)
23714aa8753cSZachary Turner     return 0;
23724aa8753cSZachary Turner 
2373554f68d3SGreg Clayton   const size_t format_pos = str.find('%', dollar_pos + 2);
23744aa8753cSZachary Turner   if (format_pos != llvm::StringRef::npos)
23754aa8753cSZachary Turner     return 0;
23764aa8753cSZachary Turner 
2377554f68d3SGreg Clayton   llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2378b9c1b51eSKate Stone   if (partial_variable.empty()) {
2379554f68d3SGreg Clayton     // Suggest all top level entites as we are just past "${"
2380*a2e76c0bSRaphael Isemann     AddMatches(&g_root, str, llvm::StringRef(), request.GetMatches());
2381*a2e76c0bSRaphael Isemann     return request.GetMatches().GetSize();
23824aa8753cSZachary Turner   }
23834aa8753cSZachary Turner 
2384554f68d3SGreg Clayton   // We have a partially specified variable, find it
2385554f68d3SGreg Clayton   llvm::StringRef remainder;
2386b9c1b51eSKate Stone   const FormatEntity::Entry::Definition *entry_def =
2387b9c1b51eSKate Stone       FindEntry(partial_variable, &g_root, remainder);
23884aa8753cSZachary Turner   if (!entry_def)
23894aa8753cSZachary Turner     return 0;
23904aa8753cSZachary Turner 
2391554f68d3SGreg Clayton   const size_t n = entry_def->num_children;
2392554f68d3SGreg Clayton 
2393b9c1b51eSKate Stone   if (remainder.empty()) {
2394554f68d3SGreg Clayton     // Exact match
2395b9c1b51eSKate Stone     if (n > 0) {
2396554f68d3SGreg Clayton       // "${thread.info" <TAB>
2397*a2e76c0bSRaphael Isemann       request.GetMatches().AppendString(MakeMatch(str, "."));
2398b9c1b51eSKate Stone     } else {
2399554f68d3SGreg Clayton       // "${thread.id" <TAB>
2400*a2e76c0bSRaphael Isemann       request.GetMatches().AppendString(MakeMatch(str, "}"));
2401*a2e76c0bSRaphael Isemann       request.SetWordComplete(true);
2402554f68d3SGreg Clayton     }
2403b9c1b51eSKate Stone   } else if (remainder.equals(".")) {
2404554f68d3SGreg Clayton     // "${thread." <TAB>
2405*a2e76c0bSRaphael Isemann     AddMatches(entry_def, str, llvm::StringRef(), request.GetMatches());
2406b9c1b51eSKate Stone   } else {
2407554f68d3SGreg Clayton     // We have a partial match
2408554f68d3SGreg Clayton     // "${thre" <TAB>
2409*a2e76c0bSRaphael Isemann     AddMatches(entry_def, str, remainder, request.GetMatches());
2410554f68d3SGreg Clayton   }
2411*a2e76c0bSRaphael Isemann   return request.GetMatches().GetSize();
2412554f68d3SGreg Clayton }
2413