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