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