1 //===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/FormatEntity.h"
11 
12 #include "lldb/Core/Address.h"
13 #include "lldb/Core/AddressRange.h" // for AddressRange
14 #include "lldb/Core/Debugger.h"
15 #include "lldb/Core/DumpRegisterValue.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/Core/ValueObjectVariable.h"
19 #include "lldb/DataFormatters/DataVisualization.h"
20 #include "lldb/DataFormatters/FormatClasses.h" // for TypeNameSpecifier...
21 #include "lldb/DataFormatters/FormatManager.h"
22 #include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryImpl::...
23 #include "lldb/Expression/ExpressionVariable.h"
24 #include "lldb/Interpreter/CommandInterpreter.h"
25 #include "lldb/Symbol/Block.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/CompilerType.h" // for CompilerType
28 #include "lldb/Symbol/Function.h"
29 #include "lldb/Symbol/LineEntry.h"
30 #include "lldb/Symbol/Symbol.h"
31 #include "lldb/Symbol/SymbolContext.h" // for SymbolContext
32 #include "lldb/Symbol/VariableList.h"
33 #include "lldb/Target/ExecutionContext.h"
34 #include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextS...
35 #include "lldb/Target/Language.h"
36 #include "lldb/Target/Process.h"
37 #include "lldb/Target/RegisterContext.h"
38 #include "lldb/Target/SectionLoadList.h"
39 #include "lldb/Target/StackFrame.h"
40 #include "lldb/Target/StopInfo.h"
41 #include "lldb/Target/Target.h"
42 #include "lldb/Target/Thread.h"
43 #include "lldb/Utility/AnsiTerminal.h"
44 #include "lldb/Utility/ArchSpec.h"    // for ArchSpec
45 #include "lldb/Utility/ConstString.h" // for ConstString, oper...
46 #include "lldb/Utility/FileSpec.h"
47 #include "lldb/Utility/Log.h"           // for Log
48 #include "lldb/Utility/Logging.h"       // for GetLogIfAllCatego...
49 #include "lldb/Utility/RegisterValue.h" // for RegisterValue
50 #include "lldb/Utility/SharingPtr.h"    // for SharingPtr
51 #include "lldb/Utility/Stream.h"
52 #include "lldb/Utility/StreamString.h"
53 #include "lldb/Utility/StringList.h"     // for StringList
54 #include "lldb/Utility/StructuredData.h" // for StructuredData::O...
55 #include "lldb/lldb-defines.h"           // for LLDB_INVALID_ADDRESS
56 #include "lldb/lldb-forward.h"           // for ValueObjectSP
57 #include "llvm/ADT/STLExtras.h"
58 #include "llvm/ADT/StringRef.h"
59 #include "llvm/ADT/Triple.h"       // for Triple, Triple::O...
60 #include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
61 
62 #include <ctype.h>     // for isxdigit
63 #include <inttypes.h>  // for PRIu64, PRIx64
64 #include <memory>      // for shared_ptr, opera...
65 #include <stdio.h>     // for sprintf
66 #include <stdlib.h>    // for strtoul
67 #include <string.h>    // for size_t, strchr
68 #include <type_traits> // for move
69 #include <utility>     // for pair
70 
71 namespace lldb_private {
72 class ScriptInterpreter;
73 }
74 namespace lldb_private {
75 struct RegisterInfo;
76 }
77 
78 using namespace lldb;
79 using namespace lldb_private;
80 
81 enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
82 
83 #define ENTRY(n, t, f)                                                         \
84   {                                                                            \
85     n, nullptr, FormatEntity::Entry::Type::t,                                  \
86         FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false               \
87   }
88 #define ENTRY_VALUE(n, t, f, v)                                                \
89   {                                                                            \
90     n, nullptr, FormatEntity::Entry::Type::t,                                  \
91         FormatEntity::Entry::FormatType::f, v, 0, nullptr, false               \
92   }
93 #define ENTRY_CHILDREN(n, t, f, c)                                             \
94   {                                                                            \
95     n, nullptr, FormatEntity::Entry::Type::t,                                  \
96         FormatEntity::Entry::FormatType::f, 0,                                 \
97         static_cast<uint32_t>(llvm::array_lengthof(c)), c, false               \
98   }
99 #define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c)                                    \
100   {                                                                            \
101     n, nullptr, FormatEntity::Entry::Type::t,                                  \
102         FormatEntity::Entry::FormatType::f, 0,                                 \
103         static_cast<uint32_t>(llvm::array_lengthof(c)), c, true                \
104   }
105 #define ENTRY_STRING(n, s)                                                     \
106   {                                                                            \
107     n, s, FormatEntity::Entry::Type::InsertString,                             \
108         FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false            \
109   }
110 static FormatEntity::Entry::Definition g_string_entry[] = {
111     ENTRY("*", ParentString, None)};
112 
113 static FormatEntity::Entry::Definition g_addr_entries[] = {
114     ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64),
115     ENTRY("load", AddressLoadOrFile, UInt64),
116 };
117 
118 static FormatEntity::Entry::Definition g_file_child_entries[] = {
119     ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename),
120     ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname),
121     ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)};
122 
123 static FormatEntity::Entry::Definition g_frame_child_entries[] = {
124     ENTRY("index", FrameIndex, UInt32),
125     ENTRY("pc", FrameRegisterPC, UInt64),
126     ENTRY("fp", FrameRegisterFP, UInt64),
127     ENTRY("sp", FrameRegisterSP, UInt64),
128     ENTRY("flags", FrameRegisterFlags, UInt64),
129     ENTRY("no-debug", FrameNoDebug, None),
130     ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry),
131 };
132 
133 static FormatEntity::Entry::Definition g_function_child_entries[] = {
134     ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString),
135     ENTRY("name-without-args", FunctionNameNoArgs, CString),
136     ENTRY("name-with-args", FunctionNameWithArgs, CString),
137     ENTRY("addr-offset", FunctionAddrOffset, UInt64),
138     ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete,
139           UInt64),
140     ENTRY("line-offset", FunctionLineOffset, UInt64),
141     ENTRY("pc-offset", FunctionPCOffset, UInt64),
142     ENTRY("initial-function", FunctionInitial, None),
143     ENTRY("changed", FunctionChanged, None),
144     ENTRY("is-optimized", FunctionIsOptimized, None)};
145 
146 static FormatEntity::Entry::Definition g_line_child_entries[] = {
147     ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries),
148     ENTRY("number", LineEntryLineNumber, UInt32),
149     ENTRY("column", LineEntryColumn, UInt32),
150     ENTRY("start-addr", LineEntryStartAddress, UInt64),
151     ENTRY("end-addr", LineEntryEndAddress, UInt64),
152 };
153 
154 static FormatEntity::Entry::Definition g_module_child_entries[] = {
155     ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
156 };
157 
158 static FormatEntity::Entry::Definition g_process_child_entries[] = {
159     ENTRY("id", ProcessID, UInt64),
160     ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename),
161     ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries),
162 };
163 
164 static FormatEntity::Entry::Definition g_svar_child_entries[] = {
165     ENTRY("*", ParentString, None)};
166 
167 static FormatEntity::Entry::Definition g_var_child_entries[] = {
168     ENTRY("*", ParentString, None)};
169 
170 static FormatEntity::Entry::Definition g_thread_child_entries[] = {
171     ENTRY("id", ThreadID, UInt64),
172     ENTRY("protocol_id", ThreadProtocolID, UInt64),
173     ENTRY("index", ThreadIndexID, UInt32),
174     ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry),
175     ENTRY("queue", ThreadQueue, CString),
176     ENTRY("name", ThreadName, CString),
177     ENTRY("stop-reason", ThreadStopReason, CString),
178     ENTRY("return-value", ThreadReturnValue, CString),
179     ENTRY("completed-expression", ThreadCompletedExpression, CString),
180 };
181 
182 static FormatEntity::Entry::Definition g_target_child_entries[] = {
183     ENTRY("arch", TargetArch, CString),
184 };
185 
186 #define _TO_STR2(_val) #_val
187 #define _TO_STR(_val) _TO_STR2(_val)
188 
189 static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
190     ENTRY_STRING("black",
191                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
192     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
193     ENTRY_STRING("green",
194                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
195     ENTRY_STRING("yellow",
196                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
197     ENTRY_STRING("blue",
198                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
199     ENTRY_STRING("purple",
200                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
201     ENTRY_STRING("cyan",
202                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
203     ENTRY_STRING("white",
204                  ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
205 };
206 
207 static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
208     ENTRY_STRING("black",
209                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
210     ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
211     ENTRY_STRING("green",
212                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
213     ENTRY_STRING("yellow",
214                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
215     ENTRY_STRING("blue",
216                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
217     ENTRY_STRING("purple",
218                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
219     ENTRY_STRING("cyan",
220                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
221     ENTRY_STRING("white",
222                  ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
223 };
224 
225 static FormatEntity::Entry::Definition g_ansi_entries[] = {
226     ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries),
227     ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries),
228     ENTRY_STRING("normal",
229                  ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
230     ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
231     ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
232     ENTRY_STRING("italic",
233                  ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
234     ENTRY_STRING("underline",
235                  ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
236     ENTRY_STRING("slow-blink",
237                  ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
238     ENTRY_STRING("fast-blink",
239                  ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
240     ENTRY_STRING("negative",
241                  ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
242     ENTRY_STRING("conceal",
243                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
244     ENTRY_STRING("crossed-out",
245                  ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
246 };
247 
248 static FormatEntity::Entry::Definition g_script_child_entries[] = {
249     ENTRY("frame", ScriptFrame, None),
250     ENTRY("process", ScriptProcess, None),
251     ENTRY("target", ScriptTarget, None),
252     ENTRY("thread", ScriptThread, None),
253     ENTRY("var", ScriptVariable, None),
254     ENTRY("svar", ScriptVariableSynthetic, None),
255     ENTRY("thread", ScriptThread, None),
256 };
257 
258 static FormatEntity::Entry::Definition g_top_level_entries[] = {
259     ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries),
260     ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64),
261     ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries),
262     ENTRY("current-pc-arrow", CurrentPCArrow, CString),
263     ENTRY_CHILDREN("file", File, CString, g_file_child_entries),
264     ENTRY("language", Lang, CString),
265     ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries),
266     ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries),
267     ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries),
268     ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries),
269     ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries),
270     ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries),
271     ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None,
272                             g_svar_child_entries),
273     ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries),
274     ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries),
275     ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries),
276 };
277 
278 static FormatEntity::Entry::Definition g_root =
279     ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries);
280 
281 FormatEntity::Entry::Entry(llvm::StringRef s)
282     : string(s.data(), s.size()), printf_format(), children(),
283       definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
284       number(0), deref(false) {}
285 
286 FormatEntity::Entry::Entry(char ch)
287     : string(1, ch), printf_format(), children(), definition(nullptr),
288       type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
289 
290 void FormatEntity::Entry::AppendChar(char ch) {
291   if (children.empty() || children.back().type != Entry::Type::String)
292     children.push_back(Entry(ch));
293   else
294     children.back().string.append(1, ch);
295 }
296 
297 void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
298   if (children.empty() || children.back().type != Entry::Type::String)
299     children.push_back(Entry(s));
300   else
301     children.back().string.append(s.data(), s.size());
302 }
303 
304 void FormatEntity::Entry::AppendText(const char *cstr) {
305   return AppendText(llvm::StringRef(cstr));
306 }
307 
308 Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
309   entry.Clear();
310   entry.type = Entry::Type::Root;
311   llvm::StringRef modifiable_format(format_str);
312   return ParseInternal(modifiable_format, entry, 0);
313 }
314 
315 #define ENUM_TO_CSTR(eee)                                                      \
316   case FormatEntity::Entry::Type::eee:                                         \
317     return #eee
318 
319 const char *FormatEntity::Entry::TypeToCString(Type t) {
320   switch (t) {
321     ENUM_TO_CSTR(Invalid);
322     ENUM_TO_CSTR(ParentNumber);
323     ENUM_TO_CSTR(ParentString);
324     ENUM_TO_CSTR(InsertString);
325     ENUM_TO_CSTR(Root);
326     ENUM_TO_CSTR(String);
327     ENUM_TO_CSTR(Scope);
328     ENUM_TO_CSTR(Variable);
329     ENUM_TO_CSTR(VariableSynthetic);
330     ENUM_TO_CSTR(ScriptVariable);
331     ENUM_TO_CSTR(ScriptVariableSynthetic);
332     ENUM_TO_CSTR(AddressLoad);
333     ENUM_TO_CSTR(AddressFile);
334     ENUM_TO_CSTR(AddressLoadOrFile);
335     ENUM_TO_CSTR(ProcessID);
336     ENUM_TO_CSTR(ProcessFile);
337     ENUM_TO_CSTR(ScriptProcess);
338     ENUM_TO_CSTR(ThreadID);
339     ENUM_TO_CSTR(ThreadProtocolID);
340     ENUM_TO_CSTR(ThreadIndexID);
341     ENUM_TO_CSTR(ThreadName);
342     ENUM_TO_CSTR(ThreadQueue);
343     ENUM_TO_CSTR(ThreadStopReason);
344     ENUM_TO_CSTR(ThreadReturnValue);
345     ENUM_TO_CSTR(ThreadCompletedExpression);
346     ENUM_TO_CSTR(ScriptThread);
347     ENUM_TO_CSTR(ThreadInfo);
348     ENUM_TO_CSTR(TargetArch);
349     ENUM_TO_CSTR(ScriptTarget);
350     ENUM_TO_CSTR(ModuleFile);
351     ENUM_TO_CSTR(File);
352     ENUM_TO_CSTR(Lang);
353     ENUM_TO_CSTR(FrameIndex);
354     ENUM_TO_CSTR(FrameNoDebug);
355     ENUM_TO_CSTR(FrameRegisterPC);
356     ENUM_TO_CSTR(FrameRegisterSP);
357     ENUM_TO_CSTR(FrameRegisterFP);
358     ENUM_TO_CSTR(FrameRegisterFlags);
359     ENUM_TO_CSTR(FrameRegisterByName);
360     ENUM_TO_CSTR(ScriptFrame);
361     ENUM_TO_CSTR(FunctionID);
362     ENUM_TO_CSTR(FunctionDidChange);
363     ENUM_TO_CSTR(FunctionInitialFunction);
364     ENUM_TO_CSTR(FunctionName);
365     ENUM_TO_CSTR(FunctionNameWithArgs);
366     ENUM_TO_CSTR(FunctionNameNoArgs);
367     ENUM_TO_CSTR(FunctionAddrOffset);
368     ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
369     ENUM_TO_CSTR(FunctionLineOffset);
370     ENUM_TO_CSTR(FunctionPCOffset);
371     ENUM_TO_CSTR(FunctionInitial);
372     ENUM_TO_CSTR(FunctionChanged);
373     ENUM_TO_CSTR(FunctionIsOptimized);
374     ENUM_TO_CSTR(LineEntryFile);
375     ENUM_TO_CSTR(LineEntryLineNumber);
376     ENUM_TO_CSTR(LineEntryColumn);
377     ENUM_TO_CSTR(LineEntryStartAddress);
378     ENUM_TO_CSTR(LineEntryEndAddress);
379     ENUM_TO_CSTR(CurrentPCArrow);
380   }
381   return "???";
382 }
383 
384 #undef ENUM_TO_CSTR
385 
386 void FormatEntity::Entry::Dump(Stream &s, int depth) const {
387   s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
388   if (fmt != eFormatDefault)
389     s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
390   if (!string.empty())
391     s.Printf("string = \"%s\"", string.c_str());
392   if (!printf_format.empty())
393     s.Printf("printf_format = \"%s\"", printf_format.c_str());
394   if (number != 0)
395     s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
396   if (deref)
397     s.Printf("deref = true, ");
398   s.EOL();
399   for (const auto &child : children) {
400     child.Dump(s, depth + 1);
401   }
402 }
403 
404 template <typename T>
405 static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
406                                    const ExecutionContext *exe_ctx, T t,
407                                    const char *script_function_name) {
408   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
409 
410   if (target) {
411     ScriptInterpreter *script_interpreter =
412         target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
413     if (script_interpreter) {
414       Status error;
415       std::string script_output;
416 
417       if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
418                                                      script_output, error) &&
419           error.Success()) {
420         s.Printf("%s", script_output.c_str());
421         return true;
422       } else {
423         s.Printf("<error: %s>", error.AsCString());
424       }
425     }
426   }
427   return false;
428 }
429 
430 static bool DumpAddress(Stream &s, const SymbolContext *sc,
431                         const ExecutionContext *exe_ctx, const Address &addr,
432                         bool print_file_addr_or_load_addr) {
433   Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
434   addr_t vaddr = LLDB_INVALID_ADDRESS;
435   if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
436     vaddr = addr.GetLoadAddress(target);
437   if (vaddr == LLDB_INVALID_ADDRESS)
438     vaddr = addr.GetFileAddress();
439 
440   if (vaddr != LLDB_INVALID_ADDRESS) {
441     int addr_width = 0;
442     if (exe_ctx && target) {
443       addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
444     }
445     if (addr_width == 0)
446       addr_width = 16;
447     if (print_file_addr_or_load_addr) {
448       ExecutionContextScope *exe_scope = nullptr;
449       if (exe_ctx)
450         exe_scope = exe_ctx->GetBestExecutionContextScope();
451       addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
452                 Address::DumpStyleModuleWithFileAddress, 0);
453     } else {
454       s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
455     }
456     return true;
457   }
458   return false;
459 }
460 
461 static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
462                                           const ExecutionContext *exe_ctx,
463                                           const Address &format_addr,
464                                           bool concrete_only, bool no_padding,
465                                           bool print_zero_offsets) {
466   if (format_addr.IsValid()) {
467     Address func_addr;
468 
469     if (sc) {
470       if (sc->function) {
471         func_addr = sc->function->GetAddressRange().GetBaseAddress();
472         if (sc->block && !concrete_only) {
473           // Check to make sure we aren't in an inline function. If we are, use
474           // the inline block range that contains "format_addr" since blocks
475           // can be discontiguous.
476           Block *inline_block = sc->block->GetContainingInlinedBlock();
477           AddressRange inline_range;
478           if (inline_block &&
479               inline_block->GetRangeContainingAddress(format_addr,
480                                                       inline_range))
481             func_addr = inline_range.GetBaseAddress();
482         }
483       } else if (sc->symbol && sc->symbol->ValueIsAddress())
484         func_addr = sc->symbol->GetAddressRef();
485     }
486 
487     if (func_addr.IsValid()) {
488       const char *addr_offset_padding = no_padding ? "" : " ";
489 
490       if (func_addr.GetSection() == format_addr.GetSection()) {
491         addr_t func_file_addr = func_addr.GetFileAddress();
492         addr_t addr_file_addr = format_addr.GetFileAddress();
493         if (addr_file_addr > func_file_addr ||
494             (addr_file_addr == func_file_addr && print_zero_offsets)) {
495           s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
496                    addr_file_addr - func_file_addr);
497         } else if (addr_file_addr < func_file_addr) {
498           s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
499                    func_file_addr - addr_file_addr);
500         }
501         return true;
502       } else {
503         Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
504         if (target) {
505           addr_t func_load_addr = func_addr.GetLoadAddress(target);
506           addr_t addr_load_addr = format_addr.GetLoadAddress(target);
507           if (addr_load_addr > func_load_addr ||
508               (addr_load_addr == func_load_addr && print_zero_offsets)) {
509             s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
510                      addr_load_addr - func_load_addr);
511           } else if (addr_load_addr < func_load_addr) {
512             s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
513                      func_load_addr - addr_load_addr);
514           }
515           return true;
516         }
517       }
518     }
519   }
520   return false;
521 }
522 
523 static bool ScanBracketedRange(llvm::StringRef subpath,
524                                size_t &close_bracket_index,
525                                const char *&var_name_final_if_array_range,
526                                int64_t &index_lower, int64_t &index_higher) {
527   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
528   close_bracket_index = llvm::StringRef::npos;
529   const size_t open_bracket_index = subpath.find('[');
530   if (open_bracket_index == llvm::StringRef::npos) {
531     if (log)
532       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
533     return false;
534   }
535 
536   close_bracket_index = subpath.find(']', open_bracket_index + 1);
537 
538   if (close_bracket_index == llvm::StringRef::npos) {
539     if (log)
540       log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
541     return false;
542   } else {
543     var_name_final_if_array_range = subpath.data() + open_bracket_index;
544 
545     if (close_bracket_index - open_bracket_index == 1) {
546       if (log)
547         log->Printf(
548             "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
549       index_lower = 0;
550     } else {
551       const size_t separator_index = subpath.find('-', open_bracket_index + 1);
552 
553       if (separator_index == llvm::StringRef::npos) {
554         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
555         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
556         index_higher = index_lower;
557         if (log)
558           log->Printf("[ScanBracketedRange] [%" PRId64
559                       "] detected, high index is same",
560                       index_lower);
561       } else {
562         const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
563         const char *index_higher_cstr = subpath.data() + separator_index + 1;
564         index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
565         index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
566         if (log)
567           log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
568                       index_lower, index_higher);
569       }
570       if (index_lower > index_higher && index_higher > 0) {
571         if (log)
572           log->Printf("[ScanBracketedRange] swapping indices");
573         const int64_t temp = index_lower;
574         index_lower = index_higher;
575         index_higher = temp;
576       }
577     }
578   }
579   return true;
580 }
581 
582 static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
583   switch (file_kind) {
584   case FileKind::FileError:
585     break;
586 
587   case FileKind::Basename:
588     if (file.GetFilename()) {
589       s << file.GetFilename();
590       return true;
591     }
592     break;
593 
594   case FileKind::Dirname:
595     if (file.GetDirectory()) {
596       s << file.GetDirectory();
597       return true;
598     }
599     break;
600 
601   case FileKind::Fullpath:
602     if (file) {
603       s << file;
604       return true;
605     }
606     break;
607   }
608   return false;
609 }
610 
611 static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
612                          uint32_t reg_num, Format format)
613 
614 {
615   if (frame) {
616     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
617 
618     if (reg_ctx) {
619       const uint32_t lldb_reg_num =
620           reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
621       if (lldb_reg_num != LLDB_INVALID_REGNUM) {
622         const RegisterInfo *reg_info =
623             reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
624         if (reg_info) {
625           RegisterValue reg_value;
626           if (reg_ctx->ReadRegister(reg_info, reg_value)) {
627             DumpRegisterValue(reg_value, &s, reg_info, false, false, format);
628             return true;
629           }
630         }
631       }
632     }
633   }
634   return false;
635 }
636 
637 static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
638                                              StackFrame *frame,
639                                              bool deref_pointer) {
640   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
641   const char *ptr_deref_format = "[%d]";
642   std::string ptr_deref_buffer(10, 0);
643   ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
644   if (log)
645     log->Printf("[ExpandIndexedExpression] name to deref: %s",
646                 ptr_deref_buffer.c_str());
647   ValueObject::GetValueForExpressionPathOptions options;
648   ValueObject::ExpressionPathEndResultType final_value_type;
649   ValueObject::ExpressionPathScanEndReason reason_to_stop;
650   ValueObject::ExpressionPathAftermath what_next =
651       (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
652                      : ValueObject::eExpressionPathAftermathNothing);
653   ValueObjectSP item = valobj->GetValueForExpressionPath(
654       ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options,
655       &what_next);
656   if (!item) {
657     if (log)
658       log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d,"
659                   " final_value_type %d",
660                   reason_to_stop, final_value_type);
661   } else {
662     if (log)
663       log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
664                   " final_value_type %d",
665                   reason_to_stop, final_value_type);
666   }
667   return item;
668 }
669 
670 static char ConvertValueObjectStyleToChar(
671     ValueObject::ValueObjectRepresentationStyle style) {
672   switch (style) {
673   case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
674     return '@';
675   case ValueObject::eValueObjectRepresentationStyleValue:
676     return 'V';
677   case ValueObject::eValueObjectRepresentationStyleLocation:
678     return 'L';
679   case ValueObject::eValueObjectRepresentationStyleSummary:
680     return 'S';
681   case ValueObject::eValueObjectRepresentationStyleChildrenCount:
682     return '#';
683   case ValueObject::eValueObjectRepresentationStyleType:
684     return 'T';
685   case ValueObject::eValueObjectRepresentationStyleName:
686     return 'N';
687   case ValueObject::eValueObjectRepresentationStyleExpressionPath:
688     return '>';
689   }
690   return '\0';
691 }
692 
693 static bool DumpValue(Stream &s, const SymbolContext *sc,
694                       const ExecutionContext *exe_ctx,
695                       const FormatEntity::Entry &entry, ValueObject *valobj) {
696   if (valobj == nullptr)
697     return false;
698 
699   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
700   Format custom_format = eFormatInvalid;
701   ValueObject::ValueObjectRepresentationStyle val_obj_display =
702       entry.string.empty()
703           ? ValueObject::eValueObjectRepresentationStyleValue
704           : ValueObject::eValueObjectRepresentationStyleSummary;
705 
706   bool do_deref_pointer = entry.deref;
707   bool is_script = false;
708   switch (entry.type) {
709   case FormatEntity::Entry::Type::ScriptVariable:
710     is_script = true;
711     break;
712 
713   case FormatEntity::Entry::Type::Variable:
714     custom_format = entry.fmt;
715     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
716     break;
717 
718   case FormatEntity::Entry::Type::ScriptVariableSynthetic:
719     is_script = true;
720     LLVM_FALLTHROUGH;
721   case FormatEntity::Entry::Type::VariableSynthetic:
722     custom_format = entry.fmt;
723     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
724     if (!valobj->IsSynthetic()) {
725       valobj = valobj->GetSyntheticValue().get();
726       if (valobj == nullptr)
727         return false;
728     }
729     break;
730 
731   default:
732     return false;
733   }
734 
735   if (valobj == nullptr)
736     return false;
737 
738   ValueObject::ExpressionPathAftermath what_next =
739       (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
740                         : ValueObject::eExpressionPathAftermathNothing);
741   ValueObject::GetValueForExpressionPathOptions options;
742   options.DontCheckDotVsArrowSyntax()
743       .DoAllowBitfieldSyntax()
744       .DoAllowFragileIVar()
745       .SetSyntheticChildrenTraversal(
746           ValueObject::GetValueForExpressionPathOptions::
747               SyntheticChildrenTraversal::Both);
748   ValueObject *target = nullptr;
749   const char *var_name_final_if_array_range = nullptr;
750   size_t close_bracket_index = llvm::StringRef::npos;
751   int64_t index_lower = -1;
752   int64_t index_higher = -1;
753   bool is_array_range = false;
754   bool was_plain_var = false;
755   bool was_var_format = false;
756   bool was_var_indexed = false;
757   ValueObject::ExpressionPathScanEndReason reason_to_stop =
758       ValueObject::eExpressionPathScanEndReasonEndOfString;
759   ValueObject::ExpressionPathEndResultType final_value_type =
760       ValueObject::eExpressionPathEndResultTypePlain;
761 
762   if (is_script) {
763     return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
764   }
765 
766   llvm::StringRef subpath(entry.string);
767   // simplest case ${var}, just print valobj's value
768   if (entry.string.empty()) {
769     if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
770         entry.number == ValueObject::eValueObjectRepresentationStyleValue)
771       was_plain_var = true;
772     else
773       was_var_format = true;
774     target = valobj;
775   } else // this is ${var.something} or multiple .something nested
776   {
777     if (entry.string[0] == '[')
778       was_var_indexed = true;
779     ScanBracketedRange(subpath, close_bracket_index,
780                        var_name_final_if_array_range, index_lower,
781                        index_higher);
782 
783     Status error;
784 
785     const std::string &expr_path = entry.string;
786 
787     if (log)
788       log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",
789                   expr_path.c_str());
790 
791     target =
792         valobj
793             ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
794                                         &final_value_type, options, &what_next)
795             .get();
796 
797     if (!target) {
798       if (log)
799         log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d,"
800                     " final_value_type %d",
801                     reason_to_stop, final_value_type);
802       return false;
803     } else {
804       if (log)
805         log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
806                     " final_value_type %d",
807                     reason_to_stop, final_value_type);
808       target = target
809                    ->GetQualifiedRepresentationIfAvailable(
810                        target->GetDynamicValueType(), true)
811                    .get();
812     }
813   }
814 
815   is_array_range =
816       (final_value_type ==
817            ValueObject::eExpressionPathEndResultTypeBoundedRange ||
818        final_value_type ==
819            ValueObject::eExpressionPathEndResultTypeUnboundedRange);
820 
821   do_deref_pointer =
822       (what_next == ValueObject::eExpressionPathAftermathDereference);
823 
824   if (do_deref_pointer && !is_array_range) {
825     // I have not deref-ed yet, let's do it
826     // this happens when we are not going through
827     // GetValueForVariableExpressionPath to get to the target ValueObject
828     Status error;
829     target = target->Dereference(error).get();
830     if (error.Fail()) {
831       if (log)
832         log->Printf("[Debugger::FormatPrompt] ERROR: %s\n",
833                     error.AsCString("unknown"));
834       return false;
835     }
836     do_deref_pointer = false;
837   }
838 
839   if (!target) {
840     if (log)
841       log->Printf("[Debugger::FormatPrompt] could not calculate target for "
842                   "prompt expression");
843     return false;
844   }
845 
846   // we do not want to use the summary for a bitfield of type T:n if we were
847   // originally dealing with just a T - that would get us into an endless
848   // recursion
849   if (target->IsBitfield() && was_var_indexed) {
850     // TODO: check for a (T:n)-specific summary - we should still obey that
851     StreamString bitfield_name;
852     bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
853                          target->GetBitfieldBitSize());
854     auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
855         bitfield_name.GetString(), false);
856     if (val_obj_display ==
857             ValueObject::eValueObjectRepresentationStyleSummary &&
858         !DataVisualization::GetSummaryForType(type_sp))
859       val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
860   }
861 
862   // TODO use flags for these
863   const uint32_t type_info_flags =
864       target->GetCompilerType().GetTypeInfo(nullptr);
865   bool is_array = (type_info_flags & eTypeIsArray) != 0;
866   bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
867   bool is_aggregate = target->GetCompilerType().IsAggregateType();
868 
869   if ((is_array || is_pointer) && (!is_array_range) &&
870       val_obj_display ==
871           ValueObject::eValueObjectRepresentationStyleValue) // this should be
872                                                              // wrong, but there
873                                                              // are some
874                                                              // exceptions
875   {
876     StreamString str_temp;
877     if (log)
878       log->Printf(
879           "[Debugger::FormatPrompt] I am into array || pointer && !range");
880 
881     if (target->HasSpecialPrintableRepresentation(val_obj_display,
882                                                   custom_format)) {
883       // try to use the special cases
884       bool success = target->DumpPrintableRepresentation(
885           str_temp, val_obj_display, custom_format);
886       if (log)
887         log->Printf("[Debugger::FormatPrompt] special cases did%s match",
888                     success ? "" : "n't");
889 
890       // should not happen
891       if (success)
892         s << str_temp.GetString();
893       return true;
894     } else {
895       if (was_plain_var) // if ${var}
896       {
897         s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
898       } else if (is_pointer) // if pointer, value is the address stored
899       {
900         target->DumpPrintableRepresentation(
901             s, val_obj_display, custom_format,
902             ValueObject::PrintableRepresentationSpecialCases::eDisable);
903       }
904       return true;
905     }
906   }
907 
908   // if directly trying to print ${var}, and this is an aggregate, display a
909   // nice type @ location message
910   if (is_aggregate && was_plain_var) {
911     s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
912     return true;
913   }
914 
915   // if directly trying to print ${var%V}, and this is an aggregate, do not let
916   // the user do it
917   if (is_aggregate &&
918       ((was_var_format &&
919         val_obj_display ==
920             ValueObject::eValueObjectRepresentationStyleValue))) {
921     s << "<invalid use of aggregate type>";
922     return true;
923   }
924 
925   if (!is_array_range) {
926     if (log)
927       log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
928     return target->DumpPrintableRepresentation(s, val_obj_display,
929                                                custom_format);
930   } else {
931     if (log)
932       log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
933     if (!is_array && !is_pointer)
934       return false;
935     if (log)
936       log->Printf("[Debugger::FormatPrompt] handle as array");
937     StreamString special_directions_stream;
938     llvm::StringRef special_directions;
939     if (close_bracket_index != llvm::StringRef::npos &&
940         subpath.size() > close_bracket_index) {
941       ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
942       special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
943                                        additional_data.GetCString());
944 
945       if (entry.fmt != eFormatDefault) {
946         const char format_char =
947             FormatManager::GetFormatAsFormatChar(entry.fmt);
948         if (format_char != '\0')
949           special_directions_stream.Printf("%%%c", format_char);
950         else {
951           const char *format_cstr =
952               FormatManager::GetFormatAsCString(entry.fmt);
953           special_directions_stream.Printf("%%%s", format_cstr);
954         }
955       } else if (entry.number != 0) {
956         const char style_char = ConvertValueObjectStyleToChar(
957             (ValueObject::ValueObjectRepresentationStyle)entry.number);
958         if (style_char)
959           special_directions_stream.Printf("%%%c", style_char);
960       }
961       special_directions_stream.PutChar('}');
962       special_directions =
963           llvm::StringRef(special_directions_stream.GetString());
964     }
965 
966     // let us display items index_lower thru index_higher of this array
967     s.PutChar('[');
968 
969     if (index_higher < 0)
970       index_higher = valobj->GetNumChildren() - 1;
971 
972     uint32_t max_num_children =
973         target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
974 
975     bool success = true;
976     for (int64_t index = index_lower; index <= index_higher; ++index) {
977       ValueObject *item =
978           ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
979               .get();
980 
981       if (!item) {
982         if (log)
983           log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at "
984                       "index %" PRId64,
985                       index);
986       } else {
987         if (log)
988           log->Printf(
989               "[Debugger::FormatPrompt] special_directions for child item: %s",
990               special_directions.data() ? special_directions.data() : "");
991       }
992 
993       if (special_directions.empty()) {
994         success &= item->DumpPrintableRepresentation(s, val_obj_display,
995                                                      custom_format);
996       } else {
997         success &= FormatEntity::FormatStringRef(
998             special_directions, s, sc, exe_ctx, nullptr, item, false, false);
999       }
1000 
1001       if (--max_num_children == 0) {
1002         s.PutCString(", ...");
1003         break;
1004       }
1005 
1006       if (index < index_higher)
1007         s.PutChar(',');
1008     }
1009     s.PutChar(']');
1010     return success;
1011   }
1012 }
1013 
1014 static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
1015                          Format format) {
1016   if (frame) {
1017     RegisterContext *reg_ctx = frame->GetRegisterContext().get();
1018 
1019     if (reg_ctx) {
1020       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
1021       if (reg_info) {
1022         RegisterValue reg_value;
1023         if (reg_ctx->ReadRegister(reg_info, reg_value)) {
1024           DumpRegisterValue(reg_value, &s, reg_info, false, false, format);
1025           return true;
1026         }
1027       }
1028     }
1029   }
1030   return false;
1031 }
1032 
1033 static bool FormatThreadExtendedInfoRecurse(
1034     const FormatEntity::Entry &entry,
1035     const StructuredData::ObjectSP &thread_info_dictionary,
1036     const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
1037   llvm::StringRef path(entry.string);
1038 
1039   StructuredData::ObjectSP value =
1040       thread_info_dictionary->GetObjectForDotSeparatedPath(path);
1041 
1042   if (value) {
1043     if (value->GetType() == eStructuredDataTypeInteger) {
1044       const char *token_format = "0x%4.4" PRIx64;
1045       if (!entry.printf_format.empty())
1046         token_format = entry.printf_format.c_str();
1047       s.Printf(token_format, value->GetAsInteger()->GetValue());
1048       return true;
1049     } else if (value->GetType() == eStructuredDataTypeFloat) {
1050       s.Printf("%f", value->GetAsFloat()->GetValue());
1051       return true;
1052     } else if (value->GetType() == eStructuredDataTypeString) {
1053       s.Format("{0}", value->GetAsString()->GetValue());
1054       return true;
1055     } else if (value->GetType() == eStructuredDataTypeArray) {
1056       if (value->GetAsArray()->GetSize() > 0) {
1057         s.Printf("%zu", value->GetAsArray()->GetSize());
1058         return true;
1059       }
1060     } else if (value->GetType() == eStructuredDataTypeDictionary) {
1061       s.Printf("%zu",
1062                value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1063       return true;
1064     }
1065   }
1066 
1067   return false;
1068 }
1069 
1070 static inline bool IsToken(const char *var_name_begin, const char *var) {
1071   return (::strncmp(var_name_begin, var, strlen(var)) == 0);
1072 }
1073 
1074 bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
1075                                    const SymbolContext *sc,
1076                                    const ExecutionContext *exe_ctx,
1077                                    const Address *addr, ValueObject *valobj,
1078                                    bool function_changed,
1079                                    bool initial_function) {
1080   if (!format_str.empty()) {
1081     FormatEntity::Entry root;
1082     Status error = FormatEntity::Parse(format_str, root);
1083     if (error.Success()) {
1084       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1085                                   function_changed, initial_function);
1086     }
1087   }
1088   return false;
1089 }
1090 
1091 bool FormatEntity::FormatCString(const char *format, Stream &s,
1092                                  const SymbolContext *sc,
1093                                  const ExecutionContext *exe_ctx,
1094                                  const Address *addr, ValueObject *valobj,
1095                                  bool function_changed, bool initial_function) {
1096   if (format && format[0]) {
1097     FormatEntity::Entry root;
1098     llvm::StringRef format_str(format);
1099     Status error = FormatEntity::Parse(format_str, root);
1100     if (error.Success()) {
1101       return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1102                                   function_changed, initial_function);
1103     }
1104   }
1105   return false;
1106 }
1107 
1108 bool FormatEntity::Format(const Entry &entry, Stream &s,
1109                           const SymbolContext *sc,
1110                           const ExecutionContext *exe_ctx, const Address *addr,
1111                           ValueObject *valobj, bool function_changed,
1112                           bool initial_function) {
1113   switch (entry.type) {
1114   case Entry::Type::Invalid:
1115   case Entry::Type::ParentNumber: // Only used for
1116                                   // FormatEntity::Entry::Definition encoding
1117   case Entry::Type::ParentString: // Only used for
1118                                   // FormatEntity::Entry::Definition encoding
1119   case Entry::Type::InsertString: // Only used for
1120                                   // FormatEntity::Entry::Definition encoding
1121     return false;
1122 
1123   case Entry::Type::Root:
1124     for (const auto &child : entry.children) {
1125       if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
1126                   initial_function)) {
1127         return false; // If any item of root fails, then the formatting fails
1128       }
1129     }
1130     return true; // Only return true if all items succeeded
1131 
1132   case Entry::Type::String:
1133     s.PutCString(entry.string);
1134     return true;
1135 
1136   case Entry::Type::Scope: {
1137     StreamString scope_stream;
1138     bool success = false;
1139     for (const auto &child : entry.children) {
1140       success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
1141                        function_changed, initial_function);
1142       if (!success)
1143         break;
1144     }
1145     // Only if all items in a scope succeed, then do we print the output into
1146     // the main stream
1147     if (success)
1148       s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
1149   }
1150     return true; // Scopes always successfully print themselves
1151 
1152   case Entry::Type::Variable:
1153   case Entry::Type::VariableSynthetic:
1154   case Entry::Type::ScriptVariable:
1155   case Entry::Type::ScriptVariableSynthetic:
1156     return DumpValue(s, sc, exe_ctx, entry, valobj);
1157 
1158   case Entry::Type::AddressFile:
1159   case Entry::Type::AddressLoad:
1160   case Entry::Type::AddressLoadOrFile:
1161     return (addr != nullptr && addr->IsValid() &&
1162             DumpAddress(s, sc, exe_ctx, *addr,
1163                         entry.type == Entry::Type::AddressLoadOrFile));
1164 
1165   case Entry::Type::ProcessID:
1166     if (exe_ctx) {
1167       Process *process = exe_ctx->GetProcessPtr();
1168       if (process) {
1169         const char *format = "%" PRIu64;
1170         if (!entry.printf_format.empty())
1171           format = entry.printf_format.c_str();
1172         s.Printf(format, process->GetID());
1173         return true;
1174       }
1175     }
1176     return false;
1177 
1178   case Entry::Type::ProcessFile:
1179     if (exe_ctx) {
1180       Process *process = exe_ctx->GetProcessPtr();
1181       if (process) {
1182         Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1183         if (exe_module) {
1184           if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1185             return true;
1186         }
1187       }
1188     }
1189     return false;
1190 
1191   case Entry::Type::ScriptProcess:
1192     if (exe_ctx) {
1193       Process *process = exe_ctx->GetProcessPtr();
1194       if (process)
1195         return RunScriptFormatKeyword(s, sc, exe_ctx, process,
1196                                       entry.string.c_str());
1197     }
1198     return false;
1199 
1200   case Entry::Type::ThreadID:
1201     if (exe_ctx) {
1202       Thread *thread = exe_ctx->GetThreadPtr();
1203       if (thread) {
1204         const char *format = "0x%4.4" PRIx64;
1205         if (!entry.printf_format.empty()) {
1206           // Watch for the special "tid" format...
1207           if (entry.printf_format == "tid") {
1208             // TODO(zturner): Rather than hardcoding this to be platform
1209             // specific, it should be controlled by a setting and the default
1210             // value of the setting can be different depending on the platform.
1211             Target &target = thread->GetProcess()->GetTarget();
1212             ArchSpec arch(target.GetArchitecture());
1213             llvm::Triple::OSType ostype = arch.IsValid()
1214                                               ? arch.GetTriple().getOS()
1215                                               : llvm::Triple::UnknownOS;
1216             if ((ostype == llvm::Triple::FreeBSD) ||
1217                 (ostype == llvm::Triple::Linux) ||
1218                 (ostype == llvm::Triple::NetBSD)) {
1219               format = "%" PRIu64;
1220             }
1221           } else {
1222             format = entry.printf_format.c_str();
1223           }
1224         }
1225         s.Printf(format, thread->GetID());
1226         return true;
1227       }
1228     }
1229     return false;
1230 
1231   case Entry::Type::ThreadProtocolID:
1232     if (exe_ctx) {
1233       Thread *thread = exe_ctx->GetThreadPtr();
1234       if (thread) {
1235         const char *format = "0x%4.4" PRIx64;
1236         if (!entry.printf_format.empty())
1237           format = entry.printf_format.c_str();
1238         s.Printf(format, thread->GetProtocolID());
1239         return true;
1240       }
1241     }
1242     return false;
1243 
1244   case Entry::Type::ThreadIndexID:
1245     if (exe_ctx) {
1246       Thread *thread = exe_ctx->GetThreadPtr();
1247       if (thread) {
1248         const char *format = "%" PRIu32;
1249         if (!entry.printf_format.empty())
1250           format = entry.printf_format.c_str();
1251         s.Printf(format, thread->GetIndexID());
1252         return true;
1253       }
1254     }
1255     return false;
1256 
1257   case Entry::Type::ThreadName:
1258     if (exe_ctx) {
1259       Thread *thread = exe_ctx->GetThreadPtr();
1260       if (thread) {
1261         const char *cstr = thread->GetName();
1262         if (cstr && cstr[0]) {
1263           s.PutCString(cstr);
1264           return true;
1265         }
1266       }
1267     }
1268     return false;
1269 
1270   case Entry::Type::ThreadQueue:
1271     if (exe_ctx) {
1272       Thread *thread = exe_ctx->GetThreadPtr();
1273       if (thread) {
1274         const char *cstr = thread->GetQueueName();
1275         if (cstr && cstr[0]) {
1276           s.PutCString(cstr);
1277           return true;
1278         }
1279       }
1280     }
1281     return false;
1282 
1283   case Entry::Type::ThreadStopReason:
1284     if (exe_ctx) {
1285       Thread *thread = exe_ctx->GetThreadPtr();
1286       if (thread) {
1287         StopInfoSP stop_info_sp = thread->GetStopInfo();
1288         if (stop_info_sp && stop_info_sp->IsValid()) {
1289           const char *cstr = stop_info_sp->GetDescription();
1290           if (cstr && cstr[0]) {
1291             s.PutCString(cstr);
1292             return true;
1293           }
1294         }
1295       }
1296     }
1297     return false;
1298 
1299   case Entry::Type::ThreadReturnValue:
1300     if (exe_ctx) {
1301       Thread *thread = exe_ctx->GetThreadPtr();
1302       if (thread) {
1303         StopInfoSP stop_info_sp = thread->GetStopInfo();
1304         if (stop_info_sp && stop_info_sp->IsValid()) {
1305           ValueObjectSP return_valobj_sp =
1306               StopInfo::GetReturnValueObject(stop_info_sp);
1307           if (return_valobj_sp) {
1308             return_valobj_sp->Dump(s);
1309             return true;
1310           }
1311         }
1312       }
1313     }
1314     return false;
1315 
1316   case Entry::Type::ThreadCompletedExpression:
1317     if (exe_ctx) {
1318       Thread *thread = exe_ctx->GetThreadPtr();
1319       if (thread) {
1320         StopInfoSP stop_info_sp = thread->GetStopInfo();
1321         if (stop_info_sp && stop_info_sp->IsValid()) {
1322           ExpressionVariableSP expression_var_sp =
1323               StopInfo::GetExpressionVariable(stop_info_sp);
1324           if (expression_var_sp && expression_var_sp->GetValueObject()) {
1325             expression_var_sp->GetValueObject()->Dump(s);
1326             return true;
1327           }
1328         }
1329       }
1330     }
1331     return false;
1332 
1333   case Entry::Type::ScriptThread:
1334     if (exe_ctx) {
1335       Thread *thread = exe_ctx->GetThreadPtr();
1336       if (thread)
1337         return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
1338                                       entry.string.c_str());
1339     }
1340     return false;
1341 
1342   case Entry::Type::ThreadInfo:
1343     if (exe_ctx) {
1344       Thread *thread = exe_ctx->GetThreadPtr();
1345       if (thread) {
1346         StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1347         if (object_sp &&
1348             object_sp->GetType() == eStructuredDataTypeDictionary) {
1349           if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
1350             return true;
1351         }
1352       }
1353     }
1354     return false;
1355 
1356   case Entry::Type::TargetArch:
1357     if (exe_ctx) {
1358       Target *target = exe_ctx->GetTargetPtr();
1359       if (target) {
1360         const ArchSpec &arch = target->GetArchitecture();
1361         if (arch.IsValid()) {
1362           s.PutCString(arch.GetArchitectureName());
1363           return true;
1364         }
1365       }
1366     }
1367     return false;
1368 
1369   case Entry::Type::ScriptTarget:
1370     if (exe_ctx) {
1371       Target *target = exe_ctx->GetTargetPtr();
1372       if (target)
1373         return RunScriptFormatKeyword(s, sc, exe_ctx, target,
1374                                       entry.string.c_str());
1375     }
1376     return false;
1377 
1378   case Entry::Type::ModuleFile:
1379     if (sc) {
1380       Module *module = sc->module_sp.get();
1381       if (module) {
1382         if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1383           return true;
1384       }
1385     }
1386     return false;
1387 
1388   case Entry::Type::File:
1389     if (sc) {
1390       CompileUnit *cu = sc->comp_unit;
1391       if (cu) {
1392         // CompileUnit is a FileSpec
1393         if (DumpFile(s, *cu, (FileKind)entry.number))
1394           return true;
1395       }
1396     }
1397     return false;
1398 
1399   case Entry::Type::Lang:
1400     if (sc) {
1401       CompileUnit *cu = sc->comp_unit;
1402       if (cu) {
1403         const char *lang_name =
1404             Language::GetNameForLanguageType(cu->GetLanguage());
1405         if (lang_name) {
1406           s.PutCString(lang_name);
1407           return true;
1408         }
1409       }
1410     }
1411     return false;
1412 
1413   case Entry::Type::FrameIndex:
1414     if (exe_ctx) {
1415       StackFrame *frame = exe_ctx->GetFramePtr();
1416       if (frame) {
1417         const char *format = "%" PRIu32;
1418         if (!entry.printf_format.empty())
1419           format = entry.printf_format.c_str();
1420         s.Printf(format, frame->GetFrameIndex());
1421         return true;
1422       }
1423     }
1424     return false;
1425 
1426   case Entry::Type::FrameRegisterPC:
1427     if (exe_ctx) {
1428       StackFrame *frame = exe_ctx->GetFramePtr();
1429       if (frame) {
1430         const Address &pc_addr = frame->GetFrameCodeAddress();
1431         if (pc_addr.IsValid()) {
1432           if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
1433             return true;
1434         }
1435       }
1436     }
1437     return false;
1438 
1439   case Entry::Type::FrameRegisterSP:
1440     if (exe_ctx) {
1441       StackFrame *frame = exe_ctx->GetFramePtr();
1442       if (frame) {
1443         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
1444                          (lldb::Format)entry.number))
1445           return true;
1446       }
1447     }
1448     return false;
1449 
1450   case Entry::Type::FrameRegisterFP:
1451     if (exe_ctx) {
1452       StackFrame *frame = exe_ctx->GetFramePtr();
1453       if (frame) {
1454         if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
1455                          (lldb::Format)entry.number))
1456           return true;
1457       }
1458     }
1459     return false;
1460 
1461   case Entry::Type::FrameRegisterFlags:
1462     if (exe_ctx) {
1463       StackFrame *frame = exe_ctx->GetFramePtr();
1464       if (frame) {
1465         if (DumpRegister(s, frame, eRegisterKindGeneric,
1466                          LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
1467           return true;
1468       }
1469     }
1470     return false;
1471 
1472   case Entry::Type::FrameNoDebug:
1473     if (exe_ctx) {
1474       StackFrame *frame = exe_ctx->GetFramePtr();
1475       if (frame) {
1476         return !frame->HasDebugInformation();
1477       }
1478     }
1479     return true;
1480 
1481   case Entry::Type::FrameRegisterByName:
1482     if (exe_ctx) {
1483       StackFrame *frame = exe_ctx->GetFramePtr();
1484       if (frame) {
1485         if (DumpRegister(s, frame, entry.string.c_str(),
1486                          (lldb::Format)entry.number))
1487           return true;
1488       }
1489     }
1490     return false;
1491 
1492   case Entry::Type::ScriptFrame:
1493     if (exe_ctx) {
1494       StackFrame *frame = exe_ctx->GetFramePtr();
1495       if (frame)
1496         return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
1497                                       entry.string.c_str());
1498     }
1499     return false;
1500 
1501   case Entry::Type::FunctionID:
1502     if (sc) {
1503       if (sc->function) {
1504         s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
1505         return true;
1506       } else if (sc->symbol) {
1507         s.Printf("symbol[%u]", sc->symbol->GetID());
1508         return true;
1509       }
1510     }
1511     return false;
1512 
1513   case Entry::Type::FunctionDidChange:
1514     return function_changed;
1515 
1516   case Entry::Type::FunctionInitialFunction:
1517     return initial_function;
1518 
1519   case Entry::Type::FunctionName: {
1520     Language *language_plugin = nullptr;
1521     bool language_plugin_handled = false;
1522     StreamString ss;
1523     if (sc->function)
1524       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1525     else if (sc->symbol)
1526       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1527     if (language_plugin) {
1528       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1529           sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1530     }
1531     if (language_plugin_handled) {
1532       s << ss.GetString();
1533       return true;
1534     } else {
1535       const char *name = nullptr;
1536       if (sc->function)
1537         name = sc->function->GetName().AsCString(nullptr);
1538       else if (sc->symbol)
1539         name = sc->symbol->GetName().AsCString(nullptr);
1540       if (name) {
1541         s.PutCString(name);
1542 
1543         if (sc->block) {
1544           Block *inline_block = sc->block->GetContainingInlinedBlock();
1545           if (inline_block) {
1546             const InlineFunctionInfo *inline_info =
1547                 sc->block->GetInlinedFunctionInfo();
1548             if (inline_info) {
1549               s.PutCString(" [inlined] ");
1550               inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
1551             }
1552           }
1553         }
1554         return true;
1555       }
1556     }
1557   }
1558     return false;
1559 
1560   case Entry::Type::FunctionNameNoArgs: {
1561     Language *language_plugin = nullptr;
1562     bool language_plugin_handled = false;
1563     StreamString ss;
1564     if (sc->function)
1565       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1566     else if (sc->symbol)
1567       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1568     if (language_plugin) {
1569       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1570           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1571           ss);
1572     }
1573     if (language_plugin_handled) {
1574       s << ss.GetString();
1575       return true;
1576     } else {
1577       ConstString name;
1578       if (sc->function)
1579         name = sc->function->GetNameNoArguments();
1580       else if (sc->symbol)
1581         name = sc->symbol->GetNameNoArguments();
1582       if (name) {
1583         s.PutCString(name.GetCString());
1584         return true;
1585       }
1586     }
1587   }
1588     return false;
1589 
1590   case Entry::Type::FunctionNameWithArgs: {
1591     Language *language_plugin = nullptr;
1592     bool language_plugin_handled = false;
1593     StreamString ss;
1594     if (sc->function)
1595       language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1596     else if (sc->symbol)
1597       language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1598     if (language_plugin) {
1599       language_plugin_handled = language_plugin->GetFunctionDisplayName(
1600           sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1601     }
1602     if (language_plugin_handled) {
1603       s << ss.GetString();
1604       return true;
1605     } else {
1606       // Print the function name with arguments in it
1607       if (sc->function) {
1608         ExecutionContextScope *exe_scope =
1609             exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1610         const char *cstr = sc->function->GetName().AsCString(nullptr);
1611         if (cstr) {
1612           const InlineFunctionInfo *inline_info = nullptr;
1613           VariableListSP variable_list_sp;
1614           bool get_function_vars = true;
1615           if (sc->block) {
1616             Block *inline_block = sc->block->GetContainingInlinedBlock();
1617 
1618             if (inline_block) {
1619               get_function_vars = false;
1620               inline_info = sc->block->GetInlinedFunctionInfo();
1621               if (inline_info)
1622                 variable_list_sp = inline_block->GetBlockVariableList(true);
1623             }
1624           }
1625 
1626           if (get_function_vars) {
1627             variable_list_sp =
1628                 sc->function->GetBlock(true).GetBlockVariableList(true);
1629           }
1630 
1631           if (inline_info) {
1632             s.PutCString(cstr);
1633             s.PutCString(" [inlined] ");
1634             cstr =
1635                 inline_info->GetName(sc->function->GetLanguage()).GetCString();
1636           }
1637 
1638           VariableList args;
1639           if (variable_list_sp)
1640             variable_list_sp->AppendVariablesWithScope(
1641                 eValueTypeVariableArgument, args);
1642           if (args.GetSize() > 0) {
1643             const char *open_paren = strchr(cstr, '(');
1644             const char *close_paren = nullptr;
1645             const char *generic = strchr(cstr, '<');
1646             // if before the arguments list begins there is a template sign
1647             // then scan to the end of the generic args before you try to find
1648             // the arguments list
1649             if (generic && open_paren && generic < open_paren) {
1650               int generic_depth = 1;
1651               ++generic;
1652               for (; *generic && generic_depth > 0; generic++) {
1653                 if (*generic == '<')
1654                   generic_depth++;
1655                 if (*generic == '>')
1656                   generic_depth--;
1657               }
1658               if (*generic)
1659                 open_paren = strchr(generic, '(');
1660               else
1661                 open_paren = nullptr;
1662             }
1663             if (open_paren) {
1664               if (IsToken(open_paren, "(anonymous namespace)")) {
1665                 open_paren =
1666                     strchr(open_paren + strlen("(anonymous namespace)"), '(');
1667                 if (open_paren)
1668                   close_paren = strchr(open_paren, ')');
1669               } else
1670                 close_paren = strchr(open_paren, ')');
1671             }
1672 
1673             if (open_paren)
1674               s.Write(cstr, open_paren - cstr + 1);
1675             else {
1676               s.PutCString(cstr);
1677               s.PutChar('(');
1678             }
1679             const size_t num_args = args.GetSize();
1680             for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1681               std::string buffer;
1682 
1683               VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1684               ValueObjectSP var_value_sp(
1685                   ValueObjectVariable::Create(exe_scope, var_sp));
1686               StreamString ss;
1687               llvm::StringRef var_representation;
1688               const char *var_name = var_value_sp->GetName().GetCString();
1689               if (var_value_sp->GetCompilerType().IsValid()) {
1690                 if (var_value_sp && exe_scope->CalculateTarget())
1691                   var_value_sp =
1692                       var_value_sp->GetQualifiedRepresentationIfAvailable(
1693                           exe_scope->CalculateTarget()
1694                               ->TargetProperties::GetPreferDynamicValue(),
1695                           exe_scope->CalculateTarget()
1696                               ->TargetProperties::GetEnableSyntheticValue());
1697                 if (var_value_sp->GetCompilerType().IsAggregateType() &&
1698                     DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
1699                   static StringSummaryFormat format(
1700                       TypeSummaryImpl::Flags()
1701                           .SetHideItemNames(false)
1702                           .SetShowMembersOneLiner(true),
1703                       "");
1704                   format.FormatObject(var_value_sp.get(), buffer,
1705                                       TypeSummaryOptions());
1706                   var_representation = buffer;
1707                 } else
1708                   var_value_sp->DumpPrintableRepresentation(
1709                       ss, ValueObject::ValueObjectRepresentationStyle::
1710                               eValueObjectRepresentationStyleSummary,
1711                       eFormatDefault,
1712                       ValueObject::PrintableRepresentationSpecialCases::eAllow,
1713                       false);
1714               }
1715 
1716               if (!ss.GetString().empty())
1717                 var_representation = ss.GetString();
1718               if (arg_idx > 0)
1719                 s.PutCString(", ");
1720               if (var_value_sp->GetError().Success()) {
1721                 if (!var_representation.empty())
1722                   s.Printf("%s=%s", var_name, var_representation.str().c_str());
1723                 else
1724                   s.Printf("%s=%s at %s", var_name,
1725                            var_value_sp->GetTypeName().GetCString(),
1726                            var_value_sp->GetLocationAsCString());
1727               } else
1728                 s.Printf("%s=<unavailable>", var_name);
1729             }
1730 
1731             if (close_paren)
1732               s.PutCString(close_paren);
1733             else
1734               s.PutChar(')');
1735 
1736           } else {
1737             s.PutCString(cstr);
1738           }
1739           return true;
1740         }
1741       } else if (sc->symbol) {
1742         const char *cstr = sc->symbol->GetName().AsCString(nullptr);
1743         if (cstr) {
1744           s.PutCString(cstr);
1745           return true;
1746         }
1747       }
1748     }
1749   }
1750     return false;
1751 
1752   case Entry::Type::FunctionAddrOffset:
1753     if (addr) {
1754       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
1755                                         false))
1756         return true;
1757     }
1758     return false;
1759 
1760   case Entry::Type::FunctionAddrOffsetConcrete:
1761     if (addr) {
1762       if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
1763                                         true))
1764         return true;
1765     }
1766     return false;
1767 
1768   case Entry::Type::FunctionLineOffset:
1769     return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1770                                           sc->line_entry.range.GetBaseAddress(),
1771                                           false, false, false));
1772 
1773   case Entry::Type::FunctionPCOffset:
1774     if (exe_ctx) {
1775       StackFrame *frame = exe_ctx->GetFramePtr();
1776       if (frame) {
1777         if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1778                                           frame->GetFrameCodeAddress(), false,
1779                                           false, false))
1780           return true;
1781       }
1782     }
1783     return false;
1784 
1785   case Entry::Type::FunctionChanged:
1786     return function_changed;
1787 
1788   case Entry::Type::FunctionIsOptimized: {
1789     bool is_optimized = false;
1790     if (sc->function && sc->function->GetIsOptimized()) {
1791       is_optimized = true;
1792     }
1793     return is_optimized;
1794   }
1795 
1796   case Entry::Type::FunctionInitial:
1797     return initial_function;
1798 
1799   case Entry::Type::LineEntryFile:
1800     if (sc && sc->line_entry.IsValid()) {
1801       Module *module = sc->module_sp.get();
1802       if (module) {
1803         if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
1804           return true;
1805       }
1806     }
1807     return false;
1808 
1809   case Entry::Type::LineEntryLineNumber:
1810     if (sc && sc->line_entry.IsValid()) {
1811       const char *format = "%" PRIu32;
1812       if (!entry.printf_format.empty())
1813         format = entry.printf_format.c_str();
1814       s.Printf(format, sc->line_entry.line);
1815       return true;
1816     }
1817     return false;
1818 
1819   case Entry::Type::LineEntryColumn:
1820     if (sc && sc->line_entry.IsValid() && sc->line_entry.column) {
1821       const char *format = "%" PRIu32;
1822       if (!entry.printf_format.empty())
1823         format = entry.printf_format.c_str();
1824       s.Printf(format, sc->line_entry.column);
1825       return true;
1826     }
1827     return false;
1828 
1829   case Entry::Type::LineEntryStartAddress:
1830   case Entry::Type::LineEntryEndAddress:
1831     if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
1832       Address addr = sc->line_entry.range.GetBaseAddress();
1833 
1834       if (entry.type == Entry::Type::LineEntryEndAddress)
1835         addr.Slide(sc->line_entry.range.GetByteSize());
1836       if (DumpAddress(s, sc, exe_ctx, addr, false))
1837         return true;
1838     }
1839     return false;
1840 
1841   case Entry::Type::CurrentPCArrow:
1842     if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
1843       RegisterContextSP reg_ctx =
1844           exe_ctx->GetFramePtr()->GetRegisterContextSP();
1845       if (reg_ctx) {
1846         addr_t pc_loadaddr = reg_ctx->GetPC();
1847         if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
1848           Address pc;
1849           pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
1850           if (pc == *addr) {
1851             s.Printf("-> ");
1852             return true;
1853           }
1854         }
1855       }
1856       s.Printf("   ");
1857       return true;
1858     }
1859     return false;
1860   }
1861   return false;
1862 }
1863 
1864 static bool DumpCommaSeparatedChildEntryNames(
1865     Stream &s, const FormatEntity::Entry::Definition *parent) {
1866   if (parent->children) {
1867     const size_t n = parent->num_children;
1868     for (size_t i = 0; i < n; ++i) {
1869       if (i > 0)
1870         s.PutCString(", ");
1871       s.Printf("\"%s\"", parent->children[i].name);
1872     }
1873     return true;
1874   }
1875   return false;
1876 }
1877 
1878 static Status ParseEntry(const llvm::StringRef &format_str,
1879                          const FormatEntity::Entry::Definition *parent,
1880                          FormatEntity::Entry &entry) {
1881   Status error;
1882 
1883   const size_t sep_pos = format_str.find_first_of(".[:");
1884   const char sep_char =
1885       (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
1886   llvm::StringRef key = format_str.substr(0, sep_pos);
1887 
1888   const size_t n = parent->num_children;
1889   for (size_t i = 0; i < n; ++i) {
1890     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1891     if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
1892       llvm::StringRef value;
1893       if (sep_char)
1894         value =
1895             format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
1896       switch (entry_def->type) {
1897       case FormatEntity::Entry::Type::ParentString:
1898         entry.string = format_str.str();
1899         return error; // Success
1900 
1901       case FormatEntity::Entry::Type::ParentNumber:
1902         entry.number = entry_def->data;
1903         return error; // Success
1904 
1905       case FormatEntity::Entry::Type::InsertString:
1906         entry.type = entry_def->type;
1907         entry.string = entry_def->string;
1908         return error; // Success
1909 
1910       default:
1911         entry.type = entry_def->type;
1912         break;
1913       }
1914 
1915       if (value.empty()) {
1916         if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
1917           if (entry_def->children) {
1918             StreamString error_strm;
1919             error_strm.Printf("'%s' can't be specified on its own, you must "
1920                               "access one of its children: ",
1921                               entry_def->name);
1922             DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
1923             error.SetErrorStringWithFormat("%s", error_strm.GetData());
1924           } else if (sep_char == ':') {
1925             // Any value whose separator is a with a ':' means this value has a
1926             // string argument that needs to be stored in the entry (like
1927             // "${script.var:}"). In this case the string value is the empty
1928             // string which is ok.
1929           } else {
1930             error.SetErrorStringWithFormat("%s", "invalid entry definitions");
1931           }
1932         }
1933       } else {
1934         if (entry_def->children) {
1935           error = ParseEntry(value, entry_def, entry);
1936         } else if (sep_char == ':') {
1937           // Any value whose separator is a with a ':' means this value has a
1938           // string argument that needs to be stored in the entry (like
1939           // "${script.var:modulename.function}")
1940           entry.string = value.str();
1941         } else {
1942           error.SetErrorStringWithFormat(
1943               "'%s' followed by '%s' but it has no children", key.str().c_str(),
1944               value.str().c_str());
1945         }
1946       }
1947       return error;
1948     }
1949   }
1950   StreamString error_strm;
1951   if (parent->type == FormatEntity::Entry::Type::Root)
1952     error_strm.Printf(
1953         "invalid top level item '%s'. Valid top level items are: ",
1954         key.str().c_str());
1955   else
1956     error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
1957                       key.str().c_str(), parent->name);
1958   DumpCommaSeparatedChildEntryNames(error_strm, parent);
1959   error.SetErrorStringWithFormat("%s", error_strm.GetData());
1960   return error;
1961 }
1962 
1963 static const FormatEntity::Entry::Definition *
1964 FindEntry(const llvm::StringRef &format_str,
1965           const FormatEntity::Entry::Definition *parent,
1966           llvm::StringRef &remainder) {
1967   Status error;
1968 
1969   std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
1970   const size_t n = parent->num_children;
1971   for (size_t i = 0; i < n; ++i) {
1972     const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1973     if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
1974       if (p.second.empty()) {
1975         if (format_str.back() == '.')
1976           remainder = format_str.drop_front(format_str.size() - 1);
1977         else
1978           remainder = llvm::StringRef(); // Exact match
1979         return entry_def;
1980       } else {
1981         if (entry_def->children) {
1982           return FindEntry(p.second, entry_def, remainder);
1983         } else {
1984           remainder = p.second;
1985           return entry_def;
1986         }
1987       }
1988     }
1989   }
1990   remainder = format_str;
1991   return parent;
1992 }
1993 
1994 Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
1995                                    uint32_t depth) {
1996   Status error;
1997   while (!format.empty() && error.Success()) {
1998     const size_t non_special_chars = format.find_first_of("${}\\");
1999 
2000     if (non_special_chars == llvm::StringRef::npos) {
2001       // No special characters, just string bytes so add them and we are done
2002       parent_entry.AppendText(format);
2003       return error;
2004     }
2005 
2006     if (non_special_chars > 0) {
2007       // We have a special character, so add all characters before these as a
2008       // plain string
2009       parent_entry.AppendText(format.substr(0, non_special_chars));
2010       format = format.drop_front(non_special_chars);
2011     }
2012 
2013     switch (format[0]) {
2014     case '\0':
2015       return error;
2016 
2017     case '{': {
2018       format = format.drop_front(); // Skip the '{'
2019       Entry scope_entry(Entry::Type::Scope);
2020       error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
2021       if (error.Fail())
2022         return error;
2023       parent_entry.AppendEntry(std::move(scope_entry));
2024     } break;
2025 
2026     case '}':
2027       if (depth == 0)
2028         error.SetErrorString("unmatched '}' character");
2029       else
2030         format =
2031             format
2032                 .drop_front(); // Skip the '}' as we are at the end of the scope
2033       return error;
2034 
2035     case '\\': {
2036       format = format.drop_front(); // Skip the '\' character
2037       if (format.empty()) {
2038         error.SetErrorString(
2039             "'\\' character was not followed by another character");
2040         return error;
2041       }
2042 
2043       const char desens_char = format[0];
2044       format = format.drop_front(); // Skip the desensitized char character
2045       switch (desens_char) {
2046       case 'a':
2047         parent_entry.AppendChar('\a');
2048         break;
2049       case 'b':
2050         parent_entry.AppendChar('\b');
2051         break;
2052       case 'f':
2053         parent_entry.AppendChar('\f');
2054         break;
2055       case 'n':
2056         parent_entry.AppendChar('\n');
2057         break;
2058       case 'r':
2059         parent_entry.AppendChar('\r');
2060         break;
2061       case 't':
2062         parent_entry.AppendChar('\t');
2063         break;
2064       case 'v':
2065         parent_entry.AppendChar('\v');
2066         break;
2067       case '\'':
2068         parent_entry.AppendChar('\'');
2069         break;
2070       case '\\':
2071         parent_entry.AppendChar('\\');
2072         break;
2073       case '0':
2074         // 1 to 3 octal chars
2075         {
2076           // Make a string that can hold onto the initial zero char, up to 3
2077           // octal digits, and a terminating NULL.
2078           char oct_str[5] = {0, 0, 0, 0, 0};
2079 
2080           int i;
2081           for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2082             oct_str[i] = format[i];
2083 
2084           // We don't want to consume the last octal character since the main
2085           // for loop will do this for us, so we advance p by one less than i
2086           // (even if i is zero)
2087           format = format.drop_front(i);
2088           unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2089           if (octal_value <= UINT8_MAX) {
2090             parent_entry.AppendChar((char)octal_value);
2091           } else {
2092             error.SetErrorString("octal number is larger than a single byte");
2093             return error;
2094           }
2095         }
2096         break;
2097 
2098       case 'x':
2099         // hex number in the format
2100         if (isxdigit(format[0])) {
2101           // Make a string that can hold onto two hex chars plus a
2102           // NULL terminator
2103           char hex_str[3] = {0, 0, 0};
2104           hex_str[0] = format[0];
2105 
2106           format = format.drop_front();
2107 
2108           if (isxdigit(format[0])) {
2109             hex_str[1] = format[0];
2110             format = format.drop_front();
2111           }
2112 
2113           unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2114           if (hex_value <= UINT8_MAX) {
2115             parent_entry.AppendChar((char)hex_value);
2116           } else {
2117             error.SetErrorString("hex number is larger than a single byte");
2118             return error;
2119           }
2120         } else {
2121           parent_entry.AppendChar(desens_char);
2122         }
2123         break;
2124 
2125       default:
2126         // Just desensitize any other character by just printing what came
2127         // after the '\'
2128         parent_entry.AppendChar(desens_char);
2129         break;
2130       }
2131     } break;
2132 
2133     case '$':
2134       if (format.size() == 1) {
2135         // '$' at the end of a format string, just print the '$'
2136         parent_entry.AppendText("$");
2137       } else {
2138         format = format.drop_front(); // Skip the '$'
2139 
2140         if (format[0] == '{') {
2141           format = format.drop_front(); // Skip the '{'
2142 
2143           llvm::StringRef variable, variable_format;
2144           error = FormatEntity::ExtractVariableInfo(format, variable,
2145                                                     variable_format);
2146           if (error.Fail())
2147             return error;
2148           bool verify_is_thread_id = false;
2149           Entry entry;
2150           if (!variable_format.empty()) {
2151             entry.printf_format = variable_format.str();
2152 
2153             // If the format contains a '%' we are going to assume this is a
2154             // printf style format. So if you want to format your thread ID
2155             // using "0x%llx" you can use: ${thread.id%0x%llx}
2156             //
2157             // If there is no '%' in the format, then it is assumed to be a
2158             // LLDB format name, or one of the extended formats specified in
2159             // the switch statement below.
2160 
2161             if (entry.printf_format.find('%') == std::string::npos) {
2162               bool clear_printf = false;
2163 
2164               if (FormatManager::GetFormatFromCString(
2165                       entry.printf_format.c_str(), false, entry.fmt)) {
2166                 // We have an LLDB format, so clear the printf format
2167                 clear_printf = true;
2168               } else if (entry.printf_format.size() == 1) {
2169                 switch (entry.printf_format[0]) {
2170                 case '@': // if this is an @ sign, print ObjC description
2171                   entry.number = ValueObject::
2172                       eValueObjectRepresentationStyleLanguageSpecific;
2173                   clear_printf = true;
2174                   break;
2175                 case 'V': // if this is a V, print the value using the default
2176                           // format
2177                   entry.number =
2178                       ValueObject::eValueObjectRepresentationStyleValue;
2179                   clear_printf = true;
2180                   break;
2181                 case 'L': // if this is an L, print the location of the value
2182                   entry.number =
2183                       ValueObject::eValueObjectRepresentationStyleLocation;
2184                   clear_printf = true;
2185                   break;
2186                 case 'S': // if this is an S, print the summary after all
2187                   entry.number =
2188                       ValueObject::eValueObjectRepresentationStyleSummary;
2189                   clear_printf = true;
2190                   break;
2191                 case '#': // if this is a '#', print the number of children
2192                   entry.number =
2193                       ValueObject::eValueObjectRepresentationStyleChildrenCount;
2194                   clear_printf = true;
2195                   break;
2196                 case 'T': // if this is a 'T', print the type
2197                   entry.number =
2198                       ValueObject::eValueObjectRepresentationStyleType;
2199                   clear_printf = true;
2200                   break;
2201                 case 'N': // if this is a 'N', print the name
2202                   entry.number =
2203                       ValueObject::eValueObjectRepresentationStyleName;
2204                   clear_printf = true;
2205                   break;
2206                 case '>': // if this is a '>', print the expression path
2207                   entry.number = ValueObject::
2208                       eValueObjectRepresentationStyleExpressionPath;
2209                   clear_printf = true;
2210                   break;
2211                 default:
2212                   error.SetErrorStringWithFormat("invalid format: '%s'",
2213                                                  entry.printf_format.c_str());
2214                   return error;
2215                 }
2216               } else if (FormatManager::GetFormatFromCString(
2217                              entry.printf_format.c_str(), true, entry.fmt)) {
2218                 clear_printf = true;
2219               } else if (entry.printf_format == "tid") {
2220                 verify_is_thread_id = true;
2221               } else {
2222                 error.SetErrorStringWithFormat("invalid format: '%s'",
2223                                                entry.printf_format.c_str());
2224                 return error;
2225               }
2226 
2227               // Our format string turned out to not be a printf style format
2228               // so lets clear the string
2229               if (clear_printf)
2230                 entry.printf_format.clear();
2231             }
2232           }
2233 
2234           // Check for dereferences
2235           if (variable[0] == '*') {
2236             entry.deref = true;
2237             variable = variable.drop_front();
2238           }
2239 
2240           error = ParseEntry(variable, &g_root, entry);
2241           if (error.Fail())
2242             return error;
2243 
2244           if (verify_is_thread_id) {
2245             if (entry.type != Entry::Type::ThreadID &&
2246                 entry.type != Entry::Type::ThreadProtocolID) {
2247               error.SetErrorString("the 'tid' format can only be used on "
2248                                    "${thread.id} and ${thread.protocol_id}");
2249             }
2250           }
2251 
2252           switch (entry.type) {
2253           case Entry::Type::Variable:
2254           case Entry::Type::VariableSynthetic:
2255             if (entry.number == 0) {
2256               if (entry.string.empty())
2257                 entry.number =
2258                     ValueObject::eValueObjectRepresentationStyleValue;
2259               else
2260                 entry.number =
2261                     ValueObject::eValueObjectRepresentationStyleSummary;
2262             }
2263             break;
2264           default:
2265             // Make sure someone didn't try to dereference anything but ${var}
2266             // or ${svar}
2267             if (entry.deref) {
2268               error.SetErrorStringWithFormat(
2269                   "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2270                   variable.str().c_str());
2271               return error;
2272             }
2273           }
2274           // Check if this entry just wants to insert a constant string value
2275           // into the parent_entry, if so, insert the string with AppendText,
2276           // else append the entry to the parent_entry.
2277           if (entry.type == Entry::Type::InsertString)
2278             parent_entry.AppendText(entry.string.c_str());
2279           else
2280             parent_entry.AppendEntry(std::move(entry));
2281         }
2282       }
2283       break;
2284     }
2285   }
2286   return error;
2287 }
2288 
2289 Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2290                                          llvm::StringRef &variable_name,
2291                                          llvm::StringRef &variable_format) {
2292   Status error;
2293   variable_name = llvm::StringRef();
2294   variable_format = llvm::StringRef();
2295 
2296   const size_t paren_pos = format_str.find('}');
2297   if (paren_pos != llvm::StringRef::npos) {
2298     const size_t percent_pos = format_str.find('%');
2299     if (percent_pos < paren_pos) {
2300       if (percent_pos > 0) {
2301         if (percent_pos > 1)
2302           variable_name = format_str.substr(0, percent_pos);
2303         variable_format =
2304             format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2305       }
2306     } else {
2307       variable_name = format_str.substr(0, paren_pos);
2308     }
2309     // Strip off elements and the formatting and the trailing '}'
2310     format_str = format_str.substr(paren_pos + 1);
2311   } else {
2312     error.SetErrorStringWithFormat(
2313         "missing terminating '}' character for '${%s'",
2314         format_str.str().c_str());
2315   }
2316   return error;
2317 }
2318 
2319 bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
2320                                   llvm::StringRef variable_name,
2321                                   llvm::StringRef variable_format) {
2322   if (variable_name.empty() || variable_name.equals(".fullpath")) {
2323     file_spec.Dump(&s);
2324     return true;
2325   } else if (variable_name.equals(".basename")) {
2326     s.PutCString(file_spec.GetFilename().AsCString(""));
2327     return true;
2328   } else if (variable_name.equals(".dirname")) {
2329     s.PutCString(file_spec.GetFilename().AsCString(""));
2330     return true;
2331   }
2332   return false;
2333 }
2334 
2335 static std::string MakeMatch(const llvm::StringRef &prefix,
2336                              const char *suffix) {
2337   std::string match(prefix.str());
2338   match.append(suffix);
2339   return match;
2340 }
2341 
2342 static void AddMatches(const FormatEntity::Entry::Definition *def,
2343                        const llvm::StringRef &prefix,
2344                        const llvm::StringRef &match_prefix,
2345                        StringList &matches) {
2346   const size_t n = def->num_children;
2347   if (n > 0) {
2348     for (size_t i = 0; i < n; ++i) {
2349       std::string match = prefix.str();
2350       if (match_prefix.empty())
2351         matches.AppendString(MakeMatch(prefix, def->children[i].name));
2352       else if (strncmp(def->children[i].name, match_prefix.data(),
2353                        match_prefix.size()) == 0)
2354         matches.AppendString(
2355             MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2356     }
2357   }
2358 }
2359 
2360 size_t FormatEntity::AutoComplete(CompletionRequest &request) {
2361   llvm::StringRef str = request.GetCursorArgumentPrefix().str();
2362 
2363   request.SetWordComplete(false);
2364   str = str.drop_front(request.GetMatchStartPoint());
2365 
2366   const size_t dollar_pos = str.rfind('$');
2367   if (dollar_pos == llvm::StringRef::npos)
2368     return 0;
2369 
2370   // Hitting TAB after $ at the end of the string add a "{"
2371   if (dollar_pos == str.size() - 1) {
2372     std::string match = str.str();
2373     match.append("{");
2374     request.AddCompletion(match);
2375     return 1;
2376   }
2377 
2378   if (str[dollar_pos + 1] != '{')
2379     return 0;
2380 
2381   const size_t close_pos = str.find('}', dollar_pos + 2);
2382   if (close_pos != llvm::StringRef::npos)
2383     return 0;
2384 
2385   const size_t format_pos = str.find('%', dollar_pos + 2);
2386   if (format_pos != llvm::StringRef::npos)
2387     return 0;
2388 
2389   llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2390   if (partial_variable.empty()) {
2391     // Suggest all top level entites as we are just past "${"
2392     StringList new_matches;
2393     AddMatches(&g_root, str, llvm::StringRef(), new_matches);
2394     request.AddCompletions(new_matches);
2395     return request.GetNumberOfMatches();
2396   }
2397 
2398   // We have a partially specified variable, find it
2399   llvm::StringRef remainder;
2400   const FormatEntity::Entry::Definition *entry_def =
2401       FindEntry(partial_variable, &g_root, remainder);
2402   if (!entry_def)
2403     return 0;
2404 
2405   const size_t n = entry_def->num_children;
2406 
2407   if (remainder.empty()) {
2408     // Exact match
2409     if (n > 0) {
2410       // "${thread.info" <TAB>
2411       request.AddCompletion(MakeMatch(str, "."));
2412     } else {
2413       // "${thread.id" <TAB>
2414       request.AddCompletion(MakeMatch(str, "}"));
2415       request.SetWordComplete(true);
2416     }
2417   } else if (remainder.equals(".")) {
2418     // "${thread." <TAB>
2419     StringList new_matches;
2420     AddMatches(entry_def, str, llvm::StringRef(), new_matches);
2421     request.AddCompletions(new_matches);
2422   } else {
2423     // We have a partial match
2424     // "${thre" <TAB>
2425     StringList new_matches;
2426     AddMatches(entry_def, str, remainder, new_matches);
2427     request.AddCompletions(new_matches);
2428   }
2429   return request.GetNumberOfMatches();
2430 }
2431