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