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