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