xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValue.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- OptionValue.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 LLDB_INTERPRETER_OPTIONVALUE_H
10 #define LLDB_INTERPRETER_OPTIONVALUE_H
11 
12 #include "lldb/Core/FormatEntity.h"
13 #include "lldb/Utility/ArchSpec.h"
14 #include "lldb/Utility/Cloneable.h"
15 #include "lldb/Utility/CompletionRequest.h"
16 #include "lldb/Utility/ConstString.h"
17 #include "lldb/Utility/FileSpec.h"
18 #include "lldb/Utility/FileSpecList.h"
19 #include "lldb/Utility/Status.h"
20 #include "lldb/Utility/StringList.h"
21 #include "lldb/Utility/UUID.h"
22 #include "lldb/lldb-defines.h"
23 #include "lldb/lldb-private-enumerations.h"
24 #include "lldb/lldb-private-interfaces.h"
25 #include "llvm/Support/JSON.h"
26 #include <mutex>
27 
28 namespace lldb_private {
29 
30 // OptionValue
31 class OptionValue {
32 public:
33   enum Type {
34     eTypeInvalid = 0,
35     eTypeArch,
36     eTypeArgs,
37     eTypeArray,
38     eTypeBoolean,
39     eTypeChar,
40     eTypeDictionary,
41     eTypeEnum,
42     eTypeFileLineColumn,
43     eTypeFileSpec,
44     eTypeFileSpecList,
45     eTypeFormat,
46     eTypeLanguage,
47     eTypePathMap,
48     eTypeProperties,
49     eTypeRegex,
50     eTypeSInt64,
51     eTypeString,
52     eTypeUInt64,
53     eTypeUUID,
54     eTypeFormatEntity
55   };
56 
57   enum {
58     eDumpOptionName = (1u << 0),
59     eDumpOptionType = (1u << 1),
60     eDumpOptionValue = (1u << 2),
61     eDumpOptionDescription = (1u << 3),
62     eDumpOptionRaw = (1u << 4),
63     eDumpOptionCommand = (1u << 5),
64     eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue),
65     eDumpGroupHelp =
66         (eDumpOptionName | eDumpOptionType | eDumpOptionDescription),
67     eDumpGroupExport = (eDumpOptionCommand | eDumpOptionName | eDumpOptionValue)
68   };
69 
70   OptionValue() = default;
71 
72   virtual ~OptionValue() = default;
73 
74   OptionValue(const OptionValue &other);
75 
76   OptionValue& operator=(const OptionValue &other);
77 
78   // Subclasses should override these functions
79   virtual Type GetType() const = 0;
80 
81   // If this value is always hidden, the avoid showing any info on this value,
82   // just show the info for the child values.
ValueIsTransparent()83   virtual bool ValueIsTransparent() const {
84     return GetType() == eTypeProperties;
85   }
86 
GetTypeAsCString()87   virtual const char *GetTypeAsCString() const {
88     return GetBuiltinTypeAsCString(GetType());
89   }
90 
91   static const char *GetBuiltinTypeAsCString(Type t);
92 
93   virtual void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
94                          uint32_t dump_mask) = 0;
95 
96   virtual llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) const = 0;
97 
98   virtual Status
99   SetValueFromString(llvm::StringRef value,
100                      VarSetOperationType op = eVarSetOperationAssign);
101 
102   virtual void Clear() = 0;
103 
104   virtual lldb::OptionValueSP
105   DeepCopy(const lldb::OptionValueSP &new_parent) const;
106 
107   virtual void AutoComplete(CommandInterpreter &interpreter,
108                             CompletionRequest &request);
109 
110   // Subclasses can override these functions
GetSubValue(const ExecutionContext * exe_ctx,llvm::StringRef name,Status & error)111   virtual lldb::OptionValueSP GetSubValue(const ExecutionContext *exe_ctx,
112                                           llvm::StringRef name,
113                                           Status &error) const {
114     error = Status::FromErrorStringWithFormatv("'{0}' is not a valid subvalue",
115                                                name);
116     return lldb::OptionValueSP();
117   }
118 
119   virtual Status SetSubValue(const ExecutionContext *exe_ctx,
120                              VarSetOperationType op, llvm::StringRef name,
121                              llvm::StringRef value);
122 
IsAggregateValue()123   virtual bool IsAggregateValue() const { return false; }
124 
GetName()125   virtual llvm::StringRef GetName() const { return llvm::StringRef(); }
126 
127   virtual bool DumpQualifiedName(Stream &strm) const;
128 
129   // Subclasses should NOT override these functions as they use the above
130   // functions to implement functionality
GetTypeAsMask()131   uint32_t GetTypeAsMask() { return 1u << GetType(); }
132 
ConvertTypeToMask(OptionValue::Type type)133   static uint32_t ConvertTypeToMask(OptionValue::Type type) {
134     return 1u << type;
135   }
136 
ConvertTypeMaskToType(uint32_t type_mask)137   static OptionValue::Type ConvertTypeMaskToType(uint32_t type_mask) {
138     // If only one bit is set, then return an appropriate enumeration
139     switch (type_mask) {
140     case 1u << eTypeArch:
141       return eTypeArch;
142     case 1u << eTypeArgs:
143       return eTypeArgs;
144     case 1u << eTypeArray:
145       return eTypeArray;
146     case 1u << eTypeBoolean:
147       return eTypeBoolean;
148     case 1u << eTypeChar:
149       return eTypeChar;
150     case 1u << eTypeDictionary:
151       return eTypeDictionary;
152     case 1u << eTypeEnum:
153       return eTypeEnum;
154     case 1u << eTypeFileLineColumn:
155       return eTypeFileLineColumn;
156     case 1u << eTypeFileSpec:
157       return eTypeFileSpec;
158     case 1u << eTypeFileSpecList:
159       return eTypeFileSpecList;
160     case 1u << eTypeFormat:
161       return eTypeFormat;
162     case 1u << eTypeLanguage:
163       return eTypeLanguage;
164     case 1u << eTypePathMap:
165       return eTypePathMap;
166     case 1u << eTypeProperties:
167       return eTypeProperties;
168     case 1u << eTypeRegex:
169       return eTypeRegex;
170     case 1u << eTypeSInt64:
171       return eTypeSInt64;
172     case 1u << eTypeString:
173       return eTypeString;
174     case 1u << eTypeUInt64:
175       return eTypeUInt64;
176     case 1u << eTypeUUID:
177       return eTypeUUID;
178     }
179     // Else return invalid
180     return eTypeInvalid;
181   }
182 
183   static lldb::OptionValueSP
184   CreateValueFromCStringForTypeMask(const char *value_cstr, uint32_t type_mask,
185                                     Status &error);
186 
187   OptionValueArch *GetAsArch();
188   const OptionValueArch *GetAsArch() const;
189 
190   OptionValueArray *GetAsArray();
191   const OptionValueArray *GetAsArray() const;
192 
193   OptionValueArgs *GetAsArgs();
194   const OptionValueArgs *GetAsArgs() const;
195 
196   OptionValueBoolean *GetAsBoolean();
197   const OptionValueBoolean *GetAsBoolean() const;
198 
199   OptionValueChar *GetAsChar();
200   const OptionValueChar *GetAsChar() const;
201 
202   OptionValueDictionary *GetAsDictionary();
203   const OptionValueDictionary *GetAsDictionary() const;
204 
205   OptionValueEnumeration *GetAsEnumeration();
206   const OptionValueEnumeration *GetAsEnumeration() const;
207 
208   OptionValueFileSpec *GetAsFileSpec();
209   const OptionValueFileSpec *GetAsFileSpec() const;
210 
211   OptionValueFileSpecList *GetAsFileSpecList();
212   const OptionValueFileSpecList *GetAsFileSpecList() const;
213 
214   OptionValueFormat *GetAsFormat();
215   const OptionValueFormat *GetAsFormat() const;
216 
217   OptionValueLanguage *GetAsLanguage();
218   const OptionValueLanguage *GetAsLanguage() const;
219 
220   OptionValuePathMappings *GetAsPathMappings();
221   const OptionValuePathMappings *GetAsPathMappings() const;
222 
223   OptionValueProperties *GetAsProperties();
224   const OptionValueProperties *GetAsProperties() const;
225 
226   OptionValueRegex *GetAsRegex();
227   const OptionValueRegex *GetAsRegex() const;
228 
229   OptionValueSInt64 *GetAsSInt64();
230   const OptionValueSInt64 *GetAsSInt64() const;
231 
232   OptionValueString *GetAsString();
233   const OptionValueString *GetAsString() const;
234 
235   OptionValueUInt64 *GetAsUInt64();
236   const OptionValueUInt64 *GetAsUInt64() const;
237 
238   OptionValueUUID *GetAsUUID();
239   const OptionValueUUID *GetAsUUID() const;
240 
241   OptionValueFormatEntity *GetAsFormatEntity();
242   const OptionValueFormatEntity *GetAsFormatEntity() const;
243 
244   bool AppendFileSpecValue(FileSpec file_spec);
245 
OptionWasSet()246   bool OptionWasSet() const { return m_value_was_set; }
247 
SetOptionWasSet()248   void SetOptionWasSet() { m_value_was_set = true; }
249 
SetParent(const lldb::OptionValueSP & parent_sp)250   void SetParent(const lldb::OptionValueSP &parent_sp) {
251     m_parent_wp = parent_sp;
252   }
253 
GetParent()254   lldb::OptionValueSP GetParent() const { return m_parent_wp.lock(); }
255 
SetValueChangedCallback(std::function<void ()> callback)256   void SetValueChangedCallback(std::function<void()> callback) {
257     m_callback = std::move(callback);
258   }
259 
NotifyValueChanged()260   void NotifyValueChanged() {
261     if (m_callback)
262       m_callback();
263   }
264 
265   template <typename T, std::enable_if_t<!std::is_pointer_v<T>, bool> = true>
GetValueAs()266   std::optional<T> GetValueAs() const {
267     if constexpr (std::is_same_v<T, uint64_t>)
268       return GetUInt64Value();
269     if constexpr (std::is_same_v<T, int64_t>)
270       return GetSInt64Value();
271     if constexpr (std::is_same_v<T, bool>)
272       return GetBooleanValue();
273     if constexpr (std::is_same_v<T, char>)
274       return GetCharValue();
275     if constexpr (std::is_same_v<T, lldb::Format>)
276       return GetFormatValue();
277     if constexpr (std::is_same_v<T, FileSpec>)
278       return GetFileSpecValue();
279     if constexpr (std::is_same_v<T, FileSpecList>)
280       return GetFileSpecListValue();
281     if constexpr (std::is_same_v<T, lldb::LanguageType>)
282       return GetLanguageValue();
283     if constexpr (std::is_same_v<T, llvm::StringRef>)
284       return GetStringValue();
285     if constexpr (std::is_same_v<T, ArchSpec>)
286       return GetArchSpecValue();
287     if constexpr (std::is_same_v<T, FormatEntity::Entry>)
288       return GetFormatEntityValue();
289     if constexpr (std::is_enum_v<T>)
290       if (std::optional<int64_t> value = GetEnumerationValue())
291         return static_cast<T>(*value);
292     return {};
293   }
294 
295   template <typename T,
296             typename U = typename std::remove_const<
297                 typename std::remove_pointer<T>::type>::type,
298             std::enable_if_t<std::is_pointer_v<T>, bool> = true>
GetValueAs()299   T GetValueAs() const {
300     static_assert(std::is_same_v<U, RegularExpression>,
301                   "only for RegularExpression");
302     return GetRegexValue();
303   }
304 
SetValueAs(bool v)305   bool SetValueAs(bool v) { return SetBooleanValue(v); }
306 
SetValueAs(char v)307   bool SetValueAs(char v) { return SetCharValue(v); }
308 
SetValueAs(uint64_t v)309   bool SetValueAs(uint64_t v) { return SetUInt64Value(v); }
310 
SetValueAs(int64_t v)311   bool SetValueAs(int64_t v) { return SetSInt64Value(v); }
312 
SetValueAs(UUID v)313   bool SetValueAs(UUID v) { return SetUUIDValue(v); }
314 
SetValueAs(llvm::StringRef v)315   bool SetValueAs(llvm::StringRef v) { return SetStringValue(v); }
316 
SetValueAs(lldb::LanguageType v)317   bool SetValueAs(lldb::LanguageType v) { return SetLanguageValue(v); }
318 
SetValueAs(lldb::Format v)319   bool SetValueAs(lldb::Format v) { return SetFormatValue(v); }
320 
SetValueAs(FileSpec v)321   bool SetValueAs(FileSpec v) { return SetFileSpecValue(v); }
322 
SetValueAs(ArchSpec v)323   bool SetValueAs(ArchSpec v) { return SetArchSpecValue(v); }
324 
SetValueAs(const FormatEntity::Entry & v)325   bool SetValueAs(const FormatEntity::Entry &v) {
326     return SetFormatEntityValue(v);
327   }
328 
329   template <typename T, std::enable_if_t<std::is_enum_v<T>, bool> = true>
SetValueAs(T t)330   bool SetValueAs(T t) {
331     return SetEnumerationValue(t);
332   }
333 
334 protected:
335   using TopmostBase = OptionValue;
336 
337   // Must be overriden by a derived class for correct downcasting the result of
338   // DeepCopy to it. Inherit from Cloneable to avoid doing this manually.
339   virtual lldb::OptionValueSP Clone() const = 0;
340 
341   lldb::OptionValueWP m_parent_wp;
342   std::function<void()> m_callback;
343   bool m_value_was_set = false; // This can be used to see if a value has been
344                                 // set by a call to SetValueFromCString(). It is
345                                 // often handy to know if an option value was
346                                 // set from the command line or as a setting,
347                                 // versus if we just have the default value that
348                                 // was already populated in the option value.
349 private:
350   std::optional<ArchSpec> GetArchSpecValue() const;
351   bool SetArchSpecValue(ArchSpec arch_spec);
352 
353   std::optional<bool> GetBooleanValue() const;
354   bool SetBooleanValue(bool new_value);
355 
356   std::optional<char> GetCharValue() const;
357   bool SetCharValue(char new_value);
358 
359   std::optional<int64_t> GetEnumerationValue() const;
360   bool SetEnumerationValue(int64_t value);
361 
362   std::optional<FileSpec> GetFileSpecValue() const;
363   bool SetFileSpecValue(FileSpec file_spec);
364 
365   std::optional<FileSpecList> GetFileSpecListValue() const;
366 
367   std::optional<int64_t> GetSInt64Value() const;
368   bool SetSInt64Value(int64_t new_value);
369 
370   std::optional<uint64_t> GetUInt64Value() const;
371   bool SetUInt64Value(uint64_t new_value);
372 
373   std::optional<lldb::Format> GetFormatValue() const;
374   bool SetFormatValue(lldb::Format new_value);
375 
376   std::optional<lldb::LanguageType> GetLanguageValue() const;
377   bool SetLanguageValue(lldb::LanguageType new_language);
378 
379   std::optional<llvm::StringRef> GetStringValue() const;
380   bool SetStringValue(llvm::StringRef new_value);
381 
382   std::optional<UUID> GetUUIDValue() const;
383   bool SetUUIDValue(const UUID &uuid);
384 
385   FormatEntity::Entry GetFormatEntityValue() const;
386   bool SetFormatEntityValue(const FormatEntity::Entry &entry);
387 
388   const RegularExpression *GetRegexValue() const;
389 
390   mutable std::mutex m_mutex;
391 };
392 
393 } // namespace lldb_private
394 
395 #endif // LLDB_INTERPRETER_OPTIONVALUE_H
396