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