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
GetUInt64Value(uint64_t fail_value,bool * success_ptr)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
SetSubValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef name,llvm::StringRef value)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
GetAsBoolean()46 OptionValueBoolean *OptionValue::GetAsBoolean() {
47 if (GetType() == OptionValue::eTypeBoolean)
48 return static_cast<OptionValueBoolean *>(this);
49 return nullptr;
50 }
51
GetAsBoolean() const52 const OptionValueBoolean *OptionValue::GetAsBoolean() const {
53 if (GetType() == OptionValue::eTypeBoolean)
54 return static_cast<const OptionValueBoolean *>(this);
55 return nullptr;
56 }
57
GetAsChar() const58 const OptionValueChar *OptionValue::GetAsChar() const {
59 if (GetType() == OptionValue::eTypeChar)
60 return static_cast<const OptionValueChar *>(this);
61 return nullptr;
62 }
63
GetAsChar()64 OptionValueChar *OptionValue::GetAsChar() {
65 if (GetType() == OptionValue::eTypeChar)
66 return static_cast<OptionValueChar *>(this);
67 return nullptr;
68 }
69
GetAsFileSpec()70 OptionValueFileSpec *OptionValue::GetAsFileSpec() {
71 if (GetType() == OptionValue::eTypeFileSpec)
72 return static_cast<OptionValueFileSpec *>(this);
73 return nullptr;
74 }
75
GetAsFileSpec() const76 const OptionValueFileSpec *OptionValue::GetAsFileSpec() const {
77 if (GetType() == OptionValue::eTypeFileSpec)
78 return static_cast<const OptionValueFileSpec *>(this);
79 return nullptr;
80 }
81
GetAsFileSpecList()82 OptionValueFileSpecList *OptionValue::GetAsFileSpecList() {
83 if (GetType() == OptionValue::eTypeFileSpecList)
84 return static_cast<OptionValueFileSpecList *>(this);
85 return nullptr;
86 }
87
GetAsFileSpecList() const88 const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const {
89 if (GetType() == OptionValue::eTypeFileSpecList)
90 return static_cast<const OptionValueFileSpecList *>(this);
91 return nullptr;
92 }
93
GetAsArch()94 OptionValueArch *OptionValue::GetAsArch() {
95 if (GetType() == OptionValue::eTypeArch)
96 return static_cast<OptionValueArch *>(this);
97 return nullptr;
98 }
99
GetAsArch() const100 const OptionValueArch *OptionValue::GetAsArch() const {
101 if (GetType() == OptionValue::eTypeArch)
102 return static_cast<const OptionValueArch *>(this);
103 return nullptr;
104 }
105
GetAsArray()106 OptionValueArray *OptionValue::GetAsArray() {
107 if (GetType() == OptionValue::eTypeArray)
108 return static_cast<OptionValueArray *>(this);
109 return nullptr;
110 }
111
GetAsArray() const112 const OptionValueArray *OptionValue::GetAsArray() const {
113 if (GetType() == OptionValue::eTypeArray)
114 return static_cast<const OptionValueArray *>(this);
115 return nullptr;
116 }
117
GetAsArgs()118 OptionValueArgs *OptionValue::GetAsArgs() {
119 if (GetType() == OptionValue::eTypeArgs)
120 return static_cast<OptionValueArgs *>(this);
121 return nullptr;
122 }
123
GetAsArgs() const124 const OptionValueArgs *OptionValue::GetAsArgs() const {
125 if (GetType() == OptionValue::eTypeArgs)
126 return static_cast<const OptionValueArgs *>(this);
127 return nullptr;
128 }
129
GetAsDictionary()130 OptionValueDictionary *OptionValue::GetAsDictionary() {
131 if (GetType() == OptionValue::eTypeDictionary)
132 return static_cast<OptionValueDictionary *>(this);
133 return nullptr;
134 }
135
GetAsDictionary() const136 const OptionValueDictionary *OptionValue::GetAsDictionary() const {
137 if (GetType() == OptionValue::eTypeDictionary)
138 return static_cast<const OptionValueDictionary *>(this);
139 return nullptr;
140 }
141
GetAsEnumeration()142 OptionValueEnumeration *OptionValue::GetAsEnumeration() {
143 if (GetType() == OptionValue::eTypeEnum)
144 return static_cast<OptionValueEnumeration *>(this);
145 return nullptr;
146 }
147
GetAsEnumeration() const148 const OptionValueEnumeration *OptionValue::GetAsEnumeration() const {
149 if (GetType() == OptionValue::eTypeEnum)
150 return static_cast<const OptionValueEnumeration *>(this);
151 return nullptr;
152 }
153
GetAsFormat()154 OptionValueFormat *OptionValue::GetAsFormat() {
155 if (GetType() == OptionValue::eTypeFormat)
156 return static_cast<OptionValueFormat *>(this);
157 return nullptr;
158 }
159
GetAsFormat() const160 const OptionValueFormat *OptionValue::GetAsFormat() const {
161 if (GetType() == OptionValue::eTypeFormat)
162 return static_cast<const OptionValueFormat *>(this);
163 return nullptr;
164 }
165
GetAsLanguage()166 OptionValueLanguage *OptionValue::GetAsLanguage() {
167 if (GetType() == OptionValue::eTypeLanguage)
168 return static_cast<OptionValueLanguage *>(this);
169 return nullptr;
170 }
171
GetAsLanguage() const172 const OptionValueLanguage *OptionValue::GetAsLanguage() const {
173 if (GetType() == OptionValue::eTypeLanguage)
174 return static_cast<const OptionValueLanguage *>(this);
175 return nullptr;
176 }
177
GetAsFormatEntity()178 OptionValueFormatEntity *OptionValue::GetAsFormatEntity() {
179 if (GetType() == OptionValue::eTypeFormatEntity)
180 return static_cast<OptionValueFormatEntity *>(this);
181 return nullptr;
182 }
183
GetAsFormatEntity() const184 const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const {
185 if (GetType() == OptionValue::eTypeFormatEntity)
186 return static_cast<const OptionValueFormatEntity *>(this);
187 return nullptr;
188 }
189
GetAsPathMappings()190 OptionValuePathMappings *OptionValue::GetAsPathMappings() {
191 if (GetType() == OptionValue::eTypePathMap)
192 return static_cast<OptionValuePathMappings *>(this);
193 return nullptr;
194 }
195
GetAsPathMappings() const196 const OptionValuePathMappings *OptionValue::GetAsPathMappings() const {
197 if (GetType() == OptionValue::eTypePathMap)
198 return static_cast<const OptionValuePathMappings *>(this);
199 return nullptr;
200 }
201
GetAsProperties()202 OptionValueProperties *OptionValue::GetAsProperties() {
203 if (GetType() == OptionValue::eTypeProperties)
204 return static_cast<OptionValueProperties *>(this);
205 return nullptr;
206 }
207
GetAsProperties() const208 const OptionValueProperties *OptionValue::GetAsProperties() const {
209 if (GetType() == OptionValue::eTypeProperties)
210 return static_cast<const OptionValueProperties *>(this);
211 return nullptr;
212 }
213
GetAsRegex()214 OptionValueRegex *OptionValue::GetAsRegex() {
215 if (GetType() == OptionValue::eTypeRegex)
216 return static_cast<OptionValueRegex *>(this);
217 return nullptr;
218 }
219
GetAsRegex() const220 const OptionValueRegex *OptionValue::GetAsRegex() const {
221 if (GetType() == OptionValue::eTypeRegex)
222 return static_cast<const OptionValueRegex *>(this);
223 return nullptr;
224 }
225
GetAsSInt64()226 OptionValueSInt64 *OptionValue::GetAsSInt64() {
227 if (GetType() == OptionValue::eTypeSInt64)
228 return static_cast<OptionValueSInt64 *>(this);
229 return nullptr;
230 }
231
GetAsSInt64() const232 const OptionValueSInt64 *OptionValue::GetAsSInt64() const {
233 if (GetType() == OptionValue::eTypeSInt64)
234 return static_cast<const OptionValueSInt64 *>(this);
235 return nullptr;
236 }
237
GetAsString()238 OptionValueString *OptionValue::GetAsString() {
239 if (GetType() == OptionValue::eTypeString)
240 return static_cast<OptionValueString *>(this);
241 return nullptr;
242 }
243
GetAsString() const244 const OptionValueString *OptionValue::GetAsString() const {
245 if (GetType() == OptionValue::eTypeString)
246 return static_cast<const OptionValueString *>(this);
247 return nullptr;
248 }
249
GetAsUInt64()250 OptionValueUInt64 *OptionValue::GetAsUInt64() {
251 if (GetType() == OptionValue::eTypeUInt64)
252 return static_cast<OptionValueUInt64 *>(this);
253 return nullptr;
254 }
255
GetAsUInt64() const256 const OptionValueUInt64 *OptionValue::GetAsUInt64() const {
257 if (GetType() == OptionValue::eTypeUInt64)
258 return static_cast<const OptionValueUInt64 *>(this);
259 return nullptr;
260 }
261
GetAsUUID()262 OptionValueUUID *OptionValue::GetAsUUID() {
263 if (GetType() == OptionValue::eTypeUUID)
264 return static_cast<OptionValueUUID *>(this);
265 return nullptr;
266 }
267
GetAsUUID() const268 const OptionValueUUID *OptionValue::GetAsUUID() const {
269 if (GetType() == OptionValue::eTypeUUID)
270 return static_cast<const OptionValueUUID *>(this);
271 return nullptr;
272 }
273
GetBooleanValue(bool fail_value) const274 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
SetBooleanValue(bool new_value)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
GetCharValue(char fail_value) const290 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
SetCharValue(char new_value)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
GetEnumerationValue(int64_t fail_value) const306 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
SetEnumerationValue(int64_t value)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
GetFileSpecValue() const322 FileSpec OptionValue::GetFileSpecValue() const {
323 const OptionValueFileSpec *option_value = GetAsFileSpec();
324 if (option_value)
325 return option_value->GetCurrentValue();
326 return FileSpec();
327 }
328
SetFileSpecValue(const FileSpec & file_spec)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
GetFileSpecListValue() const338 FileSpecList OptionValue::GetFileSpecListValue() const {
339 const OptionValueFileSpecList *option_value = GetAsFileSpecList();
340 if (option_value)
341 return option_value->GetCurrentValue();
342 return FileSpecList();
343 }
344
GetFormatValue(lldb::Format fail_value) const345 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
SetFormatValue(lldb::Format new_value)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
GetLanguageValue(lldb::LanguageType fail_value) const362 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
SetLanguageValue(lldb::LanguageType new_language)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
GetFormatEntity() const378 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
GetRegexValue() const385 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
GetSInt64Value(int64_t fail_value) const392 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
SetSInt64Value(int64_t new_value)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
GetStringValue(llvm::StringRef fail_value) const408 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
SetStringValue(llvm::StringRef new_value)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
GetUInt64Value(uint64_t fail_value) const424 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
SetUInt64Value(uint64_t new_value)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
GetUUIDValue() const440 UUID OptionValue::GetUUIDValue() const {
441 const OptionValueUUID *option_value = GetAsUUID();
442 if (option_value)
443 return option_value->GetCurrentValue();
444 return UUID();
445 }
446
SetUUIDValue(const UUID & uuid)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
GetBuiltinTypeAsCString(Type t)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
CreateValueFromCStringForTypeMask(const char * value_cstr,uint32_t type_mask,Status & error)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
DumpQualifiedName(Stream & strm) const553 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
AutoComplete(CommandInterpreter & interpreter,CompletionRequest & request)571 void OptionValue::AutoComplete(CommandInterpreter &interpreter,
572 CompletionRequest &request) {}
573
SetValueFromString(llvm::StringRef value,VarSetOperationType op)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