651 lines · cpp
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-exception6//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 15using namespace lldb;16using namespace lldb_private;17 18OptionValue::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 27OptionValue& 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 37Status 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 43OptionValueBoolean *OptionValue::GetAsBoolean() {44 if (GetType() == OptionValue::eTypeBoolean)45 return static_cast<OptionValueBoolean *>(this);46 return nullptr;47}48 49const OptionValueBoolean *OptionValue::GetAsBoolean() const {50 if (GetType() == OptionValue::eTypeBoolean)51 return static_cast<const OptionValueBoolean *>(this);52 return nullptr;53}54 55const OptionValueChar *OptionValue::GetAsChar() const {56 if (GetType() == OptionValue::eTypeChar)57 return static_cast<const OptionValueChar *>(this);58 return nullptr;59}60 61OptionValueChar *OptionValue::GetAsChar() {62 if (GetType() == OptionValue::eTypeChar)63 return static_cast<OptionValueChar *>(this);64 return nullptr;65}66 67OptionValueFileSpec *OptionValue::GetAsFileSpec() {68 if (GetType() == OptionValue::eTypeFileSpec)69 return static_cast<OptionValueFileSpec *>(this);70 return nullptr;71}72 73const OptionValueFileSpec *OptionValue::GetAsFileSpec() const {74 if (GetType() == OptionValue::eTypeFileSpec)75 return static_cast<const OptionValueFileSpec *>(this);76 return nullptr;77}78 79OptionValueFileSpecList *OptionValue::GetAsFileSpecList() {80 if (GetType() == OptionValue::eTypeFileSpecList)81 return static_cast<OptionValueFileSpecList *>(this);82 return nullptr;83}84 85const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const {86 if (GetType() == OptionValue::eTypeFileSpecList)87 return static_cast<const OptionValueFileSpecList *>(this);88 return nullptr;89}90 91OptionValueArch *OptionValue::GetAsArch() {92 if (GetType() == OptionValue::eTypeArch)93 return static_cast<OptionValueArch *>(this);94 return nullptr;95}96 97const OptionValueArch *OptionValue::GetAsArch() const {98 if (GetType() == OptionValue::eTypeArch)99 return static_cast<const OptionValueArch *>(this);100 return nullptr;101}102 103OptionValueArray *OptionValue::GetAsArray() {104 if (GetType() == OptionValue::eTypeArray)105 return static_cast<OptionValueArray *>(this);106 return nullptr;107}108 109const OptionValueArray *OptionValue::GetAsArray() const {110 if (GetType() == OptionValue::eTypeArray)111 return static_cast<const OptionValueArray *>(this);112 return nullptr;113}114 115OptionValueArgs *OptionValue::GetAsArgs() {116 if (GetType() == OptionValue::eTypeArgs)117 return static_cast<OptionValueArgs *>(this);118 return nullptr;119}120 121const OptionValueArgs *OptionValue::GetAsArgs() const {122 if (GetType() == OptionValue::eTypeArgs)123 return static_cast<const OptionValueArgs *>(this);124 return nullptr;125}126 127OptionValueDictionary *OptionValue::GetAsDictionary() {128 if (GetType() == OptionValue::eTypeDictionary)129 return static_cast<OptionValueDictionary *>(this);130 return nullptr;131}132 133const OptionValueDictionary *OptionValue::GetAsDictionary() const {134 if (GetType() == OptionValue::eTypeDictionary)135 return static_cast<const OptionValueDictionary *>(this);136 return nullptr;137}138 139OptionValueEnumeration *OptionValue::GetAsEnumeration() {140 if (GetType() == OptionValue::eTypeEnum)141 return static_cast<OptionValueEnumeration *>(this);142 return nullptr;143}144 145const OptionValueEnumeration *OptionValue::GetAsEnumeration() const {146 if (GetType() == OptionValue::eTypeEnum)147 return static_cast<const OptionValueEnumeration *>(this);148 return nullptr;149}150 151OptionValueFormat *OptionValue::GetAsFormat() {152 if (GetType() == OptionValue::eTypeFormat)153 return static_cast<OptionValueFormat *>(this);154 return nullptr;155}156 157const OptionValueFormat *OptionValue::GetAsFormat() const {158 if (GetType() == OptionValue::eTypeFormat)159 return static_cast<const OptionValueFormat *>(this);160 return nullptr;161}162 163OptionValueLanguage *OptionValue::GetAsLanguage() {164 if (GetType() == OptionValue::eTypeLanguage)165 return static_cast<OptionValueLanguage *>(this);166 return nullptr;167}168 169const OptionValueLanguage *OptionValue::GetAsLanguage() const {170 if (GetType() == OptionValue::eTypeLanguage)171 return static_cast<const OptionValueLanguage *>(this);172 return nullptr;173}174 175OptionValueFormatEntity *OptionValue::GetAsFormatEntity() {176 if (GetType() == OptionValue::eTypeFormatEntity)177 return static_cast<OptionValueFormatEntity *>(this);178 return nullptr;179}180 181const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const {182 if (GetType() == OptionValue::eTypeFormatEntity)183 return static_cast<const OptionValueFormatEntity *>(this);184 return nullptr;185}186 187OptionValuePathMappings *OptionValue::GetAsPathMappings() {188 if (GetType() == OptionValue::eTypePathMap)189 return static_cast<OptionValuePathMappings *>(this);190 return nullptr;191}192 193const OptionValuePathMappings *OptionValue::GetAsPathMappings() const {194 if (GetType() == OptionValue::eTypePathMap)195 return static_cast<const OptionValuePathMappings *>(this);196 return nullptr;197}198 199OptionValueProperties *OptionValue::GetAsProperties() {200 if (GetType() == OptionValue::eTypeProperties)201 return static_cast<OptionValueProperties *>(this);202 return nullptr;203}204 205const OptionValueProperties *OptionValue::GetAsProperties() const {206 if (GetType() == OptionValue::eTypeProperties)207 return static_cast<const OptionValueProperties *>(this);208 return nullptr;209}210 211OptionValueRegex *OptionValue::GetAsRegex() {212 if (GetType() == OptionValue::eTypeRegex)213 return static_cast<OptionValueRegex *>(this);214 return nullptr;215}216 217const OptionValueRegex *OptionValue::GetAsRegex() const {218 if (GetType() == OptionValue::eTypeRegex)219 return static_cast<const OptionValueRegex *>(this);220 return nullptr;221}222 223OptionValueSInt64 *OptionValue::GetAsSInt64() {224 if (GetType() == OptionValue::eTypeSInt64)225 return static_cast<OptionValueSInt64 *>(this);226 return nullptr;227}228 229const OptionValueSInt64 *OptionValue::GetAsSInt64() const {230 if (GetType() == OptionValue::eTypeSInt64)231 return static_cast<const OptionValueSInt64 *>(this);232 return nullptr;233}234 235OptionValueString *OptionValue::GetAsString() {236 if (GetType() == OptionValue::eTypeString)237 return static_cast<OptionValueString *>(this);238 return nullptr;239}240 241const OptionValueString *OptionValue::GetAsString() const {242 if (GetType() == OptionValue::eTypeString)243 return static_cast<const OptionValueString *>(this);244 return nullptr;245}246 247OptionValueUInt64 *OptionValue::GetAsUInt64() {248 if (GetType() == OptionValue::eTypeUInt64)249 return static_cast<OptionValueUInt64 *>(this);250 return nullptr;251}252 253const OptionValueUInt64 *OptionValue::GetAsUInt64() const {254 if (GetType() == OptionValue::eTypeUInt64)255 return static_cast<const OptionValueUInt64 *>(this);256 return nullptr;257}258 259OptionValueUUID *OptionValue::GetAsUUID() {260 if (GetType() == OptionValue::eTypeUUID)261 return static_cast<OptionValueUUID *>(this);262 return nullptr;263}264 265const OptionValueUUID *OptionValue::GetAsUUID() const {266 if (GetType() == OptionValue::eTypeUUID)267 return static_cast<const OptionValueUUID *>(this);268 return nullptr;269}270 271std::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 278bool 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 287std::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 294bool 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 303std::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 310bool 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 319std::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 326bool 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 335bool 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 344std::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 351std::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 358bool 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 367std::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 374bool 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 383FormatEntity::Entry OptionValue::GetFormatEntityValue() const {384 std::lock_guard<std::mutex> lock(m_mutex);385 if (const OptionValueFormatEntity *option_value = GetAsFormatEntity())386 return option_value->GetCurrentValue();387 return {};388}389 390const 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 397std::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 404bool 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 413std::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 420bool 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 429std::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 436bool 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 445std::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 452bool 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 461std::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 468bool 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 477bool OptionValue::SetFormatEntityValue(const FormatEntity::Entry &entry) {478 std::lock_guard<std::mutex> lock(m_mutex);479 if (OptionValueFormatEntity *option_value = GetAsFormatEntity()) {480 option_value->SetCurrentValue(entry);481 return true;482 }483 return false;484}485 486const char *OptionValue::GetBuiltinTypeAsCString(Type t) {487 switch (t) {488 case eTypeInvalid:489 return "invalid";490 case eTypeArch:491 return "arch";492 case eTypeArgs:493 return "arguments";494 case eTypeArray:495 return "array";496 case eTypeBoolean:497 return "boolean";498 case eTypeChar:499 return "char";500 case eTypeDictionary:501 return "dictionary";502 case eTypeEnum:503 return "enum";504 case eTypeFileLineColumn:505 return "file:line:column specifier";506 case eTypeFileSpec:507 return "file";508 case eTypeFileSpecList:509 return "file-list";510 case eTypeFormat:511 return "format";512 case eTypeFormatEntity:513 return "format-string";514 case eTypeLanguage:515 return "language";516 case eTypePathMap:517 return "path-map";518 case eTypeProperties:519 return "properties";520 case eTypeRegex:521 return "regex";522 case eTypeSInt64:523 return "int";524 case eTypeString:525 return "string";526 case eTypeUInt64:527 return "unsigned";528 case eTypeUUID:529 return "uuid";530 }531 return nullptr;532}533 534lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask(535 const char *value_cstr, uint32_t type_mask, Status &error) {536 // If only 1 bit is set in the type mask for a dictionary or array then we537 // know how to decode a value from a cstring538 lldb::OptionValueSP value_sp;539 switch (type_mask) {540 case 1u << eTypeArch:541 value_sp = std::make_shared<OptionValueArch>();542 break;543 case 1u << eTypeBoolean:544 value_sp = std::make_shared<OptionValueBoolean>(false);545 break;546 case 1u << eTypeChar:547 value_sp = std::make_shared<OptionValueChar>('\0');548 break;549 case 1u << eTypeFileSpec:550 value_sp = std::make_shared<OptionValueFileSpec>();551 break;552 case 1u << eTypeFormat:553 value_sp = std::make_shared<OptionValueFormat>(eFormatInvalid);554 break;555 case 1u << eTypeFormatEntity:556 value_sp = std::make_shared<OptionValueFormatEntity>(nullptr);557 break;558 case 1u << eTypeLanguage:559 value_sp = std::make_shared<OptionValueLanguage>(eLanguageTypeUnknown);560 break;561 case 1u << eTypeSInt64:562 value_sp = std::make_shared<OptionValueSInt64>();563 break;564 case 1u << eTypeString:565 value_sp = std::make_shared<OptionValueString>();566 break;567 case 1u << eTypeUInt64:568 value_sp = std::make_shared<OptionValueUInt64>();569 break;570 case 1u << eTypeUUID:571 value_sp = std::make_shared<OptionValueUUID>();572 break;573 }574 575 if (value_sp)576 error = value_sp->SetValueFromString(value_cstr, eVarSetOperationAssign);577 else578 error = Status::FromErrorString("unsupported type mask");579 return value_sp;580}581 582bool OptionValue::DumpQualifiedName(Stream &strm) const {583 bool dumped_something = false;584 lldb::OptionValueSP m_parent_sp(m_parent_wp.lock());585 if (m_parent_sp) {586 if (m_parent_sp->DumpQualifiedName(strm))587 dumped_something = true;588 }589 llvm::StringRef name(GetName());590 if (!name.empty()) {591 if (dumped_something)592 strm.PutChar('.');593 else594 dumped_something = true;595 strm << name;596 }597 return dumped_something;598}599 600OptionValueSP OptionValue::DeepCopy(const OptionValueSP &new_parent) const {601 auto clone = Clone();602 clone->SetParent(new_parent);603 return clone;604}605 606void OptionValue::AutoComplete(CommandInterpreter &interpreter,607 CompletionRequest &request) {}608 609Status OptionValue::SetValueFromString(llvm::StringRef value,610 VarSetOperationType op) {611 Status error;612 switch (op) {613 case eVarSetOperationReplace:614 error = Status::FromErrorStringWithFormat(615 "%s objects do not support the 'replace' operation",616 GetTypeAsCString());617 break;618 case eVarSetOperationInsertBefore:619 error = Status::FromErrorStringWithFormat(620 "%s objects do not support the 'insert-before' operation",621 GetTypeAsCString());622 break;623 case eVarSetOperationInsertAfter:624 error = Status::FromErrorStringWithFormat(625 "%s objects do not support the 'insert-after' operation",626 GetTypeAsCString());627 break;628 case eVarSetOperationRemove:629 error = Status::FromErrorStringWithFormat(630 "%s objects do not support the 'remove' operation", GetTypeAsCString());631 break;632 case eVarSetOperationAppend:633 error = Status::FromErrorStringWithFormat(634 "%s objects do not support the 'append' operation", GetTypeAsCString());635 break;636 case eVarSetOperationClear:637 error = Status::FromErrorStringWithFormat(638 "%s objects do not support the 'clear' operation", GetTypeAsCString());639 break;640 case eVarSetOperationAssign:641 error = Status::FromErrorStringWithFormat(642 "%s objects do not support the 'assign' operation", GetTypeAsCString());643 break;644 case eVarSetOperationInvalid:645 error = Status::FromErrorStringWithFormat(646 "invalid operation performed on a %s object", GetTypeAsCString());647 break;648 }649 return error;650}651