1 //===-- FormatEntity.h ------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef liblldb_FormatEntity_h_ 10 #define liblldb_FormatEntity_h_ 11 12 #include "lldb/Utility/CompletionRequest.h" 13 #include "lldb/Utility/FileSpec.h" 14 #include "lldb/Utility/Status.h" 15 #include "lldb/lldb-enumerations.h" 16 #include "lldb/lldb-types.h" 17 #include <algorithm> 18 #include <stddef.h> 19 #include <stdint.h> 20 21 #include <string> 22 #include <vector> 23 24 namespace lldb_private { 25 class Address; 26 class ExecutionContext; 27 class Stream; 28 class StringList; 29 class SymbolContext; 30 class ValueObject; 31 } 32 namespace llvm { 33 class StringRef; 34 } 35 36 namespace lldb_private { 37 class FormatEntity { 38 public: 39 struct Entry { 40 enum class Type { 41 Invalid, 42 ParentNumber, 43 ParentString, 44 EscapeCode, 45 Root, 46 String, 47 Scope, 48 Variable, 49 VariableSynthetic, 50 ScriptVariable, 51 ScriptVariableSynthetic, 52 AddressLoad, 53 AddressFile, 54 AddressLoadOrFile, 55 ProcessID, 56 ProcessFile, 57 ScriptProcess, 58 ThreadID, 59 ThreadProtocolID, 60 ThreadIndexID, 61 ThreadName, 62 ThreadQueue, 63 ThreadStopReason, 64 ThreadReturnValue, 65 ThreadCompletedExpression, 66 ScriptThread, 67 ThreadInfo, 68 TargetArch, 69 ScriptTarget, 70 ModuleFile, 71 File, 72 Lang, 73 FrameIndex, 74 FrameNoDebug, 75 FrameRegisterPC, 76 FrameRegisterSP, 77 FrameRegisterFP, 78 FrameRegisterFlags, 79 FrameRegisterByName, 80 FrameIsArtificial, 81 ScriptFrame, 82 FunctionID, 83 FunctionDidChange, 84 FunctionInitialFunction, 85 FunctionName, 86 FunctionNameWithArgs, 87 FunctionNameNoArgs, 88 FunctionAddrOffset, 89 FunctionAddrOffsetConcrete, 90 FunctionLineOffset, 91 FunctionPCOffset, 92 FunctionInitial, 93 FunctionChanged, 94 FunctionIsOptimized, 95 LineEntryFile, 96 LineEntryLineNumber, 97 LineEntryColumn, 98 LineEntryStartAddress, 99 LineEntryEndAddress, 100 CurrentPCArrow 101 }; 102 103 struct Definition { 104 const char *name; 105 const char *string; // Insert this exact string into the output 106 Entry::Type type; 107 uint64_t data; 108 uint32_t num_children; 109 Definition *children; // An array of "num_children" Definition entries, 110 bool keep_separator; 111 }; 112 113 Entry(Type t = Type::Invalid, const char *s = nullptr, 114 const char *f = nullptr) 115 : string(s ? s : ""), printf_format(f ? f : ""), children(), 116 definition(nullptr), type(t), fmt(lldb::eFormatDefault), number(0), 117 deref(false) {} 118 119 Entry(llvm::StringRef s); 120 Entry(char ch); 121 122 void AppendChar(char ch); 123 124 void AppendText(const llvm::StringRef &s); 125 126 void AppendText(const char *cstr); 127 128 void AppendEntry(const Entry &&entry) { children.push_back(entry); } 129 130 void Clear() { 131 string.clear(); 132 printf_format.clear(); 133 children.clear(); 134 definition = nullptr; 135 type = Type::Invalid; 136 fmt = lldb::eFormatDefault; 137 number = 0; 138 deref = false; 139 } 140 141 static const char *TypeToCString(Type t); 142 143 void Dump(Stream &s, int depth = 0) const; 144 145 bool operator==(const Entry &rhs) const { 146 if (string != rhs.string) 147 return false; 148 if (printf_format != rhs.printf_format) 149 return false; 150 const size_t n = children.size(); 151 const size_t m = rhs.children.size(); 152 for (size_t i = 0; i < std::min<size_t>(n, m); ++i) { 153 if (!(children[i] == rhs.children[i])) 154 return false; 155 } 156 if (children != rhs.children) 157 return false; 158 if (definition != rhs.definition) 159 return false; 160 if (type != rhs.type) 161 return false; 162 if (fmt != rhs.fmt) 163 return false; 164 if (deref != rhs.deref) 165 return false; 166 return true; 167 } 168 169 std::string string; 170 std::string printf_format; 171 std::vector<Entry> children; 172 Definition *definition; 173 Type type; 174 lldb::Format fmt; 175 lldb::addr_t number; 176 bool deref; 177 }; 178 179 static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc, 180 const ExecutionContext *exe_ctx, const Address *addr, 181 ValueObject *valobj, bool function_changed, 182 bool initial_function); 183 184 static bool FormatStringRef(const llvm::StringRef &format, Stream &s, 185 const SymbolContext *sc, 186 const ExecutionContext *exe_ctx, 187 const Address *addr, ValueObject *valobj, 188 bool function_changed, bool initial_function); 189 190 static bool FormatCString(const char *format, Stream &s, 191 const SymbolContext *sc, 192 const ExecutionContext *exe_ctx, 193 const Address *addr, ValueObject *valobj, 194 bool function_changed, bool initial_function); 195 196 static Status Parse(const llvm::StringRef &format, Entry &entry); 197 198 static Status ExtractVariableInfo(llvm::StringRef &format_str, 199 llvm::StringRef &variable_name, 200 llvm::StringRef &variable_format); 201 202 static size_t AutoComplete(lldb_private::CompletionRequest &request); 203 204 // Format the current elements into the stream \a s. 205 // 206 // The root element will be stripped off and the format str passed in will be 207 // either an empty string (print a description of this object), or contain a 208 // `.`-separated series like a domain name that identifies further 209 // sub-elements to display. 210 static bool FormatFileSpec(const FileSpec &file, Stream &s, 211 llvm::StringRef elements, 212 llvm::StringRef element_format); 213 214 protected: 215 static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, 216 uint32_t depth); 217 }; 218 } // namespace lldb_private 219 220 #endif // liblldb_FormatEntity_h_ 221