xref: /llvm-project/lldb/source/Interpreter/OptionValue.cpp (revision 0642cd768b80665585c8500bed2933a3b99123dc)
1 //===-- OptionValue.cpp ---------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Interpreter/OptionValue.h"
10 #include "lldb/Interpreter/OptionValues.h"
11 #include "lldb/Utility/StringList.h"
12 
13 #include <memory>
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
18 OptionValue::OptionValue(const OptionValue &other) {
19   std::lock_guard<std::mutex> lock(other.m_mutex);
20 
21   m_parent_wp = other.m_parent_wp;
22   m_callback = other.m_callback;
23   m_value_was_set = other.m_value_was_set;
24 
25 }
26 
27 OptionValue& OptionValue::operator=(const OptionValue &other) {
28   std::scoped_lock<std::mutex, std::mutex> lock(m_mutex, other.m_mutex);
29 
30   m_parent_wp = other.m_parent_wp;
31   m_callback = other.m_callback;
32   m_value_was_set = other.m_value_was_set;
33 
34   return *this;
35 }
36 
37 Status OptionValue::SetSubValue(const ExecutionContext *exe_ctx,
38                                 VarSetOperationType op, llvm::StringRef name,
39                                 llvm::StringRef value) {
40   return Status::FromErrorString("SetSubValue is not supported");
41 }
42 
43 OptionValueBoolean *OptionValue::GetAsBoolean() {
44   if (GetType() == OptionValue::eTypeBoolean)
45     return static_cast<OptionValueBoolean *>(this);
46   return nullptr;
47 }
48 
49 const OptionValueBoolean *OptionValue::GetAsBoolean() const {
50   if (GetType() == OptionValue::eTypeBoolean)
51     return static_cast<const OptionValueBoolean *>(this);
52   return nullptr;
53 }
54 
55 const OptionValueChar *OptionValue::GetAsChar() const {
56   if (GetType() == OptionValue::eTypeChar)
57     return static_cast<const OptionValueChar *>(this);
58   return nullptr;
59 }
60 
61 OptionValueChar *OptionValue::GetAsChar() {
62   if (GetType() == OptionValue::eTypeChar)
63     return static_cast<OptionValueChar *>(this);
64   return nullptr;
65 }
66 
67 OptionValueFileSpec *OptionValue::GetAsFileSpec() {
68   if (GetType() == OptionValue::eTypeFileSpec)
69     return static_cast<OptionValueFileSpec *>(this);
70   return nullptr;
71 }
72 
73 const OptionValueFileSpec *OptionValue::GetAsFileSpec() const {
74   if (GetType() == OptionValue::eTypeFileSpec)
75     return static_cast<const OptionValueFileSpec *>(this);
76   return nullptr;
77 }
78 
79 OptionValueFileSpecList *OptionValue::GetAsFileSpecList() {
80   if (GetType() == OptionValue::eTypeFileSpecList)
81     return static_cast<OptionValueFileSpecList *>(this);
82   return nullptr;
83 }
84 
85 const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const {
86   if (GetType() == OptionValue::eTypeFileSpecList)
87     return static_cast<const OptionValueFileSpecList *>(this);
88   return nullptr;
89 }
90 
91 OptionValueArch *OptionValue::GetAsArch() {
92   if (GetType() == OptionValue::eTypeArch)
93     return static_cast<OptionValueArch *>(this);
94   return nullptr;
95 }
96 
97 const OptionValueArch *OptionValue::GetAsArch() const {
98   if (GetType() == OptionValue::eTypeArch)
99     return static_cast<const OptionValueArch *>(this);
100   return nullptr;
101 }
102 
103 OptionValueArray *OptionValue::GetAsArray() {
104   if (GetType() == OptionValue::eTypeArray)
105     return static_cast<OptionValueArray *>(this);
106   return nullptr;
107 }
108 
109 const OptionValueArray *OptionValue::GetAsArray() const {
110   if (GetType() == OptionValue::eTypeArray)
111     return static_cast<const OptionValueArray *>(this);
112   return nullptr;
113 }
114 
115 OptionValueArgs *OptionValue::GetAsArgs() {
116   if (GetType() == OptionValue::eTypeArgs)
117     return static_cast<OptionValueArgs *>(this);
118   return nullptr;
119 }
120 
121 const OptionValueArgs *OptionValue::GetAsArgs() const {
122   if (GetType() == OptionValue::eTypeArgs)
123     return static_cast<const OptionValueArgs *>(this);
124   return nullptr;
125 }
126 
127 OptionValueDictionary *OptionValue::GetAsDictionary() {
128   if (GetType() == OptionValue::eTypeDictionary)
129     return static_cast<OptionValueDictionary *>(this);
130   return nullptr;
131 }
132 
133 const OptionValueDictionary *OptionValue::GetAsDictionary() const {
134   if (GetType() == OptionValue::eTypeDictionary)
135     return static_cast<const OptionValueDictionary *>(this);
136   return nullptr;
137 }
138 
139 OptionValueEnumeration *OptionValue::GetAsEnumeration() {
140   if (GetType() == OptionValue::eTypeEnum)
141     return static_cast<OptionValueEnumeration *>(this);
142   return nullptr;
143 }
144 
145 const OptionValueEnumeration *OptionValue::GetAsEnumeration() const {
146   if (GetType() == OptionValue::eTypeEnum)
147     return static_cast<const OptionValueEnumeration *>(this);
148   return nullptr;
149 }
150 
151 OptionValueFormat *OptionValue::GetAsFormat() {
152   if (GetType() == OptionValue::eTypeFormat)
153     return static_cast<OptionValueFormat *>(this);
154   return nullptr;
155 }
156 
157 const OptionValueFormat *OptionValue::GetAsFormat() const {
158   if (GetType() == OptionValue::eTypeFormat)
159     return static_cast<const OptionValueFormat *>(this);
160   return nullptr;
161 }
162 
163 OptionValueLanguage *OptionValue::GetAsLanguage() {
164   if (GetType() == OptionValue::eTypeLanguage)
165     return static_cast<OptionValueLanguage *>(this);
166   return nullptr;
167 }
168 
169 const OptionValueLanguage *OptionValue::GetAsLanguage() const {
170   if (GetType() == OptionValue::eTypeLanguage)
171     return static_cast<const OptionValueLanguage *>(this);
172   return nullptr;
173 }
174 
175 OptionValueFormatEntity *OptionValue::GetAsFormatEntity() {
176   if (GetType() == OptionValue::eTypeFormatEntity)
177     return static_cast<OptionValueFormatEntity *>(this);
178   return nullptr;
179 }
180 
181 const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const {
182   if (GetType() == OptionValue::eTypeFormatEntity)
183     return static_cast<const OptionValueFormatEntity *>(this);
184   return nullptr;
185 }
186 
187 OptionValuePathMappings *OptionValue::GetAsPathMappings() {
188   if (GetType() == OptionValue::eTypePathMap)
189     return static_cast<OptionValuePathMappings *>(this);
190   return nullptr;
191 }
192 
193 const OptionValuePathMappings *OptionValue::GetAsPathMappings() const {
194   if (GetType() == OptionValue::eTypePathMap)
195     return static_cast<const OptionValuePathMappings *>(this);
196   return nullptr;
197 }
198 
199 OptionValueProperties *OptionValue::GetAsProperties() {
200   if (GetType() == OptionValue::eTypeProperties)
201     return static_cast<OptionValueProperties *>(this);
202   return nullptr;
203 }
204 
205 const OptionValueProperties *OptionValue::GetAsProperties() const {
206   if (GetType() == OptionValue::eTypeProperties)
207     return static_cast<const OptionValueProperties *>(this);
208   return nullptr;
209 }
210 
211 OptionValueRegex *OptionValue::GetAsRegex() {
212   if (GetType() == OptionValue::eTypeRegex)
213     return static_cast<OptionValueRegex *>(this);
214   return nullptr;
215 }
216 
217 const OptionValueRegex *OptionValue::GetAsRegex() const {
218   if (GetType() == OptionValue::eTypeRegex)
219     return static_cast<const OptionValueRegex *>(this);
220   return nullptr;
221 }
222 
223 OptionValueSInt64 *OptionValue::GetAsSInt64() {
224   if (GetType() == OptionValue::eTypeSInt64)
225     return static_cast<OptionValueSInt64 *>(this);
226   return nullptr;
227 }
228 
229 const OptionValueSInt64 *OptionValue::GetAsSInt64() const {
230   if (GetType() == OptionValue::eTypeSInt64)
231     return static_cast<const OptionValueSInt64 *>(this);
232   return nullptr;
233 }
234 
235 OptionValueString *OptionValue::GetAsString() {
236   if (GetType() == OptionValue::eTypeString)
237     return static_cast<OptionValueString *>(this);
238   return nullptr;
239 }
240 
241 const OptionValueString *OptionValue::GetAsString() const {
242   if (GetType() == OptionValue::eTypeString)
243     return static_cast<const OptionValueString *>(this);
244   return nullptr;
245 }
246 
247 OptionValueUInt64 *OptionValue::GetAsUInt64() {
248   if (GetType() == OptionValue::eTypeUInt64)
249     return static_cast<OptionValueUInt64 *>(this);
250   return nullptr;
251 }
252 
253 const OptionValueUInt64 *OptionValue::GetAsUInt64() const {
254   if (GetType() == OptionValue::eTypeUInt64)
255     return static_cast<const OptionValueUInt64 *>(this);
256   return nullptr;
257 }
258 
259 OptionValueUUID *OptionValue::GetAsUUID() {
260   if (GetType() == OptionValue::eTypeUUID)
261     return static_cast<OptionValueUUID *>(this);
262   return nullptr;
263 }
264 
265 const OptionValueUUID *OptionValue::GetAsUUID() const {
266   if (GetType() == OptionValue::eTypeUUID)
267     return static_cast<const OptionValueUUID *>(this);
268   return nullptr;
269 }
270 
271 std::optional<bool> OptionValue::GetBooleanValue() const {
272   std::lock_guard<std::mutex> lock(m_mutex);
273   if (const OptionValueBoolean *option_value = GetAsBoolean())
274     return option_value->GetCurrentValue();
275   return {};
276 }
277 
278 bool OptionValue::SetBooleanValue(bool new_value) {
279   std::lock_guard<std::mutex> lock(m_mutex);
280   if (OptionValueBoolean *option_value = GetAsBoolean()) {
281     option_value->SetCurrentValue(new_value);
282     return true;
283   }
284   return false;
285 }
286 
287 std::optional<char> OptionValue::GetCharValue() const {
288   std::lock_guard<std::mutex> lock(m_mutex);
289   if (const OptionValueChar *option_value = GetAsChar())
290     return option_value->GetCurrentValue();
291   return {};
292 }
293 
294 bool OptionValue::SetCharValue(char new_value) {
295   std::lock_guard<std::mutex> lock(m_mutex);
296   if (OptionValueChar *option_value = GetAsChar()) {
297     option_value->SetCurrentValue(new_value);
298     return true;
299   }
300   return false;
301 }
302 
303 std::optional<int64_t> OptionValue::GetEnumerationValue() const {
304   std::lock_guard<std::mutex> lock(m_mutex);
305   if (const OptionValueEnumeration *option_value = GetAsEnumeration())
306     return option_value->GetCurrentValue();
307   return {};
308 }
309 
310 bool OptionValue::SetEnumerationValue(int64_t value) {
311   std::lock_guard<std::mutex> lock(m_mutex);
312   if (OptionValueEnumeration *option_value = GetAsEnumeration()) {
313     option_value->SetCurrentValue(value);
314     return true;
315   }
316   return false;
317 }
318 
319 std::optional<FileSpec> OptionValue::GetFileSpecValue() const {
320   std::lock_guard<std::mutex> lock(m_mutex);
321   if (const OptionValueFileSpec *option_value = GetAsFileSpec())
322     return option_value->GetCurrentValue();
323   return {};
324 }
325 
326 bool OptionValue::SetFileSpecValue(FileSpec file_spec) {
327   std::lock_guard<std::mutex> lock(m_mutex);
328   if (OptionValueFileSpec *option_value = GetAsFileSpec()) {
329     option_value->SetCurrentValue(file_spec, false);
330     return true;
331   }
332   return false;
333 }
334 
335 bool OptionValue::AppendFileSpecValue(FileSpec file_spec) {
336   std::lock_guard<std::mutex> lock(m_mutex);
337   if (OptionValueFileSpecList *option_value = GetAsFileSpecList()) {
338     option_value->AppendCurrentValue(file_spec);
339     return true;
340   }
341   return false;
342 }
343 
344 std::optional<FileSpecList> OptionValue::GetFileSpecListValue() const {
345   std::lock_guard<std::mutex> lock(m_mutex);
346   if (const OptionValueFileSpecList *option_value = GetAsFileSpecList())
347     return option_value->GetCurrentValue();
348   return {};
349 }
350 
351 std::optional<lldb::Format> OptionValue::GetFormatValue() const {
352   std::lock_guard<std::mutex> lock(m_mutex);
353   if (const OptionValueFormat *option_value = GetAsFormat())
354     return option_value->GetCurrentValue();
355   return {};
356 }
357 
358 bool OptionValue::SetFormatValue(lldb::Format new_value) {
359   std::lock_guard<std::mutex> lock(m_mutex);
360   if (OptionValueFormat *option_value = GetAsFormat()) {
361     option_value->SetCurrentValue(new_value);
362     return true;
363   }
364   return false;
365 }
366 
367 std::optional<lldb::LanguageType> OptionValue::GetLanguageValue() const {
368   std::lock_guard<std::mutex> lock(m_mutex);
369   if (const OptionValueLanguage *option_value = GetAsLanguage())
370     return option_value->GetCurrentValue();
371   return {};
372 }
373 
374 bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) {
375   std::lock_guard<std::mutex> lock(m_mutex);
376   if (OptionValueLanguage *option_value = GetAsLanguage()) {
377     option_value->SetCurrentValue(new_language);
378     return true;
379   }
380   return false;
381 }
382 
383 const FormatEntity::Entry *OptionValue::GetFormatEntity() const {
384   std::lock_guard<std::mutex> lock(m_mutex);
385   if (const OptionValueFormatEntity *option_value = GetAsFormatEntity())
386     return &option_value->GetCurrentValue();
387   return nullptr;
388 }
389 
390 const RegularExpression *OptionValue::GetRegexValue() const {
391   std::lock_guard<std::mutex> lock(m_mutex);
392   if (const OptionValueRegex *option_value = GetAsRegex())
393     return option_value->GetCurrentValue();
394   return nullptr;
395 }
396 
397 std::optional<int64_t> OptionValue::GetSInt64Value() const {
398   std::lock_guard<std::mutex> lock(m_mutex);
399   if (const OptionValueSInt64 *option_value = GetAsSInt64())
400     return option_value->GetCurrentValue();
401   return {};
402 }
403 
404 bool OptionValue::SetSInt64Value(int64_t new_value) {
405   std::lock_guard<std::mutex> lock(m_mutex);
406   if (OptionValueSInt64 *option_value = GetAsSInt64()) {
407     option_value->SetCurrentValue(new_value);
408     return true;
409   }
410   return false;
411 }
412 
413 std::optional<llvm::StringRef> OptionValue::GetStringValue() const {
414   std::lock_guard<std::mutex> lock(m_mutex);
415   if (const OptionValueString *option_value = GetAsString())
416     return option_value->GetCurrentValueAsRef();
417   return {};
418 }
419 
420 bool OptionValue::SetStringValue(llvm::StringRef new_value) {
421   std::lock_guard<std::mutex> lock(m_mutex);
422   if (OptionValueString *option_value = GetAsString()) {
423     option_value->SetCurrentValue(new_value);
424     return true;
425   }
426   return false;
427 }
428 
429 std::optional<uint64_t> OptionValue::GetUInt64Value() const {
430   std::lock_guard<std::mutex> lock(m_mutex);
431   if (const OptionValueUInt64 *option_value = GetAsUInt64())
432     return option_value->GetCurrentValue();
433   return {};
434 }
435 
436 bool OptionValue::SetUInt64Value(uint64_t new_value) {
437   std::lock_guard<std::mutex> lock(m_mutex);
438   if (OptionValueUInt64 *option_value = GetAsUInt64()) {
439     option_value->SetCurrentValue(new_value);
440     return true;
441   }
442   return false;
443 }
444 
445 std::optional<UUID> OptionValue::GetUUIDValue() const {
446   std::lock_guard<std::mutex> lock(m_mutex);
447   if (const OptionValueUUID *option_value = GetAsUUID())
448     return option_value->GetCurrentValue();
449   return {};
450 }
451 
452 bool OptionValue::SetUUIDValue(const UUID &uuid) {
453   std::lock_guard<std::mutex> lock(m_mutex);
454   if (OptionValueUUID *option_value = GetAsUUID()) {
455     option_value->SetCurrentValue(uuid);
456     return true;
457   }
458   return false;
459 }
460 
461 std::optional<ArchSpec> OptionValue::GetArchSpecValue() const {
462   std::lock_guard<std::mutex> lock(m_mutex);
463   if (const OptionValueArch *option_value = GetAsArch())
464     return option_value->GetCurrentValue();
465   return {};
466 }
467 
468 bool OptionValue::SetArchSpecValue(ArchSpec arch_spec) {
469     std::lock_guard<std::mutex> lock(m_mutex);
470   if (OptionValueArch *option_value = GetAsArch()) {
471     option_value->SetCurrentValue(arch_spec, false);
472     return true;
473   }
474   return false;
475 }
476 
477 const char *OptionValue::GetBuiltinTypeAsCString(Type t) {
478   switch (t) {
479   case eTypeInvalid:
480     return "invalid";
481   case eTypeArch:
482     return "arch";
483   case eTypeArgs:
484     return "arguments";
485   case eTypeArray:
486     return "array";
487   case eTypeBoolean:
488     return "boolean";
489   case eTypeChar:
490     return "char";
491   case eTypeDictionary:
492     return "dictionary";
493   case eTypeEnum:
494     return "enum";
495   case eTypeFileLineColumn:
496     return "file:line:column specifier";
497   case eTypeFileSpec:
498     return "file";
499   case eTypeFileSpecList:
500     return "file-list";
501   case eTypeFormat:
502     return "format";
503   case eTypeFormatEntity:
504     return "format-string";
505   case eTypeLanguage:
506     return "language";
507   case eTypePathMap:
508     return "path-map";
509   case eTypeProperties:
510     return "properties";
511   case eTypeRegex:
512     return "regex";
513   case eTypeSInt64:
514     return "int";
515   case eTypeString:
516     return "string";
517   case eTypeUInt64:
518     return "unsigned";
519   case eTypeUUID:
520     return "uuid";
521   }
522   return nullptr;
523 }
524 
525 lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask(
526     const char *value_cstr, uint32_t type_mask, Status &error) {
527   // If only 1 bit is set in the type mask for a dictionary or array then we
528   // know how to decode a value from a cstring
529   lldb::OptionValueSP value_sp;
530   switch (type_mask) {
531   case 1u << eTypeArch:
532     value_sp = std::make_shared<OptionValueArch>();
533     break;
534   case 1u << eTypeBoolean:
535     value_sp = std::make_shared<OptionValueBoolean>(false);
536     break;
537   case 1u << eTypeChar:
538     value_sp = std::make_shared<OptionValueChar>('\0');
539     break;
540   case 1u << eTypeFileSpec:
541     value_sp = std::make_shared<OptionValueFileSpec>();
542     break;
543   case 1u << eTypeFormat:
544     value_sp = std::make_shared<OptionValueFormat>(eFormatInvalid);
545     break;
546   case 1u << eTypeFormatEntity:
547     value_sp = std::make_shared<OptionValueFormatEntity>(nullptr);
548     break;
549   case 1u << eTypeLanguage:
550     value_sp = std::make_shared<OptionValueLanguage>(eLanguageTypeUnknown);
551     break;
552   case 1u << eTypeSInt64:
553     value_sp = std::make_shared<OptionValueSInt64>();
554     break;
555   case 1u << eTypeString:
556     value_sp = std::make_shared<OptionValueString>();
557     break;
558   case 1u << eTypeUInt64:
559     value_sp = std::make_shared<OptionValueUInt64>();
560     break;
561   case 1u << eTypeUUID:
562     value_sp = std::make_shared<OptionValueUUID>();
563     break;
564   }
565 
566   if (value_sp)
567     error = value_sp->SetValueFromString(value_cstr, eVarSetOperationAssign);
568   else
569     error = Status::FromErrorString("unsupported type mask");
570   return value_sp;
571 }
572 
573 bool OptionValue::DumpQualifiedName(Stream &strm) const {
574   bool dumped_something = false;
575   lldb::OptionValueSP m_parent_sp(m_parent_wp.lock());
576   if (m_parent_sp) {
577     if (m_parent_sp->DumpQualifiedName(strm))
578       dumped_something = true;
579   }
580   llvm::StringRef name(GetName());
581   if (!name.empty()) {
582     if (dumped_something)
583       strm.PutChar('.');
584     else
585       dumped_something = true;
586     strm << name;
587   }
588   return dumped_something;
589 }
590 
591 OptionValueSP OptionValue::DeepCopy(const OptionValueSP &new_parent) const {
592   auto clone = Clone();
593   clone->SetParent(new_parent);
594   return clone;
595 }
596 
597 void OptionValue::AutoComplete(CommandInterpreter &interpreter,
598                                CompletionRequest &request) {}
599 
600 Status OptionValue::SetValueFromString(llvm::StringRef value,
601                                        VarSetOperationType op) {
602   Status error;
603   switch (op) {
604   case eVarSetOperationReplace:
605     error = Status::FromErrorStringWithFormat(
606         "%s objects do not support the 'replace' operation",
607         GetTypeAsCString());
608     break;
609   case eVarSetOperationInsertBefore:
610     error = Status::FromErrorStringWithFormat(
611         "%s objects do not support the 'insert-before' operation",
612         GetTypeAsCString());
613     break;
614   case eVarSetOperationInsertAfter:
615     error = Status::FromErrorStringWithFormat(
616         "%s objects do not support the 'insert-after' operation",
617         GetTypeAsCString());
618     break;
619   case eVarSetOperationRemove:
620     error = Status::FromErrorStringWithFormat(
621         "%s objects do not support the 'remove' operation", GetTypeAsCString());
622     break;
623   case eVarSetOperationAppend:
624     error = Status::FromErrorStringWithFormat(
625         "%s objects do not support the 'append' operation", GetTypeAsCString());
626     break;
627   case eVarSetOperationClear:
628     error = Status::FromErrorStringWithFormat(
629         "%s objects do not support the 'clear' operation", GetTypeAsCString());
630     break;
631   case eVarSetOperationAssign:
632     error = Status::FromErrorStringWithFormat(
633         "%s objects do not support the 'assign' operation", GetTypeAsCString());
634     break;
635   case eVarSetOperationInvalid:
636     error = Status::FromErrorStringWithFormat(
637         "invalid operation performed on a %s object", GetTypeAsCString());
638     break;
639   }
640   return error;
641 }
642