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