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