//===-- OptionValue.cpp ---------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "lldb/Interpreter/OptionValue.h" #include "lldb/Interpreter/OptionValues.h" #include "lldb/Utility/StringList.h" #include using namespace lldb; using namespace lldb_private; OptionValue::OptionValue(const OptionValue &other) { std::lock_guard lock(other.m_mutex); m_parent_wp = other.m_parent_wp; m_callback = other.m_callback; m_value_was_set = other.m_value_was_set; } OptionValue& OptionValue::operator=(const OptionValue &other) { std::scoped_lock lock(m_mutex, other.m_mutex); m_parent_wp = other.m_parent_wp; m_callback = other.m_callback; m_value_was_set = other.m_value_was_set; return *this; } Status OptionValue::SetSubValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef name, llvm::StringRef value) { Status error; error.SetErrorString("SetSubValue is not supported"); return error; } OptionValueBoolean *OptionValue::GetAsBoolean() { if (GetType() == OptionValue::eTypeBoolean) return static_cast(this); return nullptr; } const OptionValueBoolean *OptionValue::GetAsBoolean() const { if (GetType() == OptionValue::eTypeBoolean) return static_cast(this); return nullptr; } const OptionValueChar *OptionValue::GetAsChar() const { if (GetType() == OptionValue::eTypeChar) return static_cast(this); return nullptr; } OptionValueChar *OptionValue::GetAsChar() { if (GetType() == OptionValue::eTypeChar) return static_cast(this); return nullptr; } OptionValueFileSpec *OptionValue::GetAsFileSpec() { if (GetType() == OptionValue::eTypeFileSpec) return static_cast(this); return nullptr; } const OptionValueFileSpec *OptionValue::GetAsFileSpec() const { if (GetType() == OptionValue::eTypeFileSpec) return static_cast(this); return nullptr; } OptionValueFileSpecList *OptionValue::GetAsFileSpecList() { if (GetType() == OptionValue::eTypeFileSpecList) return static_cast(this); return nullptr; } const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const { if (GetType() == OptionValue::eTypeFileSpecList) return static_cast(this); return nullptr; } OptionValueArch *OptionValue::GetAsArch() { if (GetType() == OptionValue::eTypeArch) return static_cast(this); return nullptr; } const OptionValueArch *OptionValue::GetAsArch() const { if (GetType() == OptionValue::eTypeArch) return static_cast(this); return nullptr; } OptionValueArray *OptionValue::GetAsArray() { if (GetType() == OptionValue::eTypeArray) return static_cast(this); return nullptr; } const OptionValueArray *OptionValue::GetAsArray() const { if (GetType() == OptionValue::eTypeArray) return static_cast(this); return nullptr; } OptionValueArgs *OptionValue::GetAsArgs() { if (GetType() == OptionValue::eTypeArgs) return static_cast(this); return nullptr; } const OptionValueArgs *OptionValue::GetAsArgs() const { if (GetType() == OptionValue::eTypeArgs) return static_cast(this); return nullptr; } OptionValueDictionary *OptionValue::GetAsDictionary() { if (GetType() == OptionValue::eTypeDictionary) return static_cast(this); return nullptr; } const OptionValueDictionary *OptionValue::GetAsDictionary() const { if (GetType() == OptionValue::eTypeDictionary) return static_cast(this); return nullptr; } OptionValueEnumeration *OptionValue::GetAsEnumeration() { if (GetType() == OptionValue::eTypeEnum) return static_cast(this); return nullptr; } const OptionValueEnumeration *OptionValue::GetAsEnumeration() const { if (GetType() == OptionValue::eTypeEnum) return static_cast(this); return nullptr; } OptionValueFormat *OptionValue::GetAsFormat() { if (GetType() == OptionValue::eTypeFormat) return static_cast(this); return nullptr; } const OptionValueFormat *OptionValue::GetAsFormat() const { if (GetType() == OptionValue::eTypeFormat) return static_cast(this); return nullptr; } OptionValueLanguage *OptionValue::GetAsLanguage() { if (GetType() == OptionValue::eTypeLanguage) return static_cast(this); return nullptr; } const OptionValueLanguage *OptionValue::GetAsLanguage() const { if (GetType() == OptionValue::eTypeLanguage) return static_cast(this); return nullptr; } OptionValueFormatEntity *OptionValue::GetAsFormatEntity() { if (GetType() == OptionValue::eTypeFormatEntity) return static_cast(this); return nullptr; } const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const { if (GetType() == OptionValue::eTypeFormatEntity) return static_cast(this); return nullptr; } OptionValuePathMappings *OptionValue::GetAsPathMappings() { if (GetType() == OptionValue::eTypePathMap) return static_cast(this); return nullptr; } const OptionValuePathMappings *OptionValue::GetAsPathMappings() const { if (GetType() == OptionValue::eTypePathMap) return static_cast(this); return nullptr; } OptionValueProperties *OptionValue::GetAsProperties() { if (GetType() == OptionValue::eTypeProperties) return static_cast(this); return nullptr; } const OptionValueProperties *OptionValue::GetAsProperties() const { if (GetType() == OptionValue::eTypeProperties) return static_cast(this); return nullptr; } OptionValueRegex *OptionValue::GetAsRegex() { if (GetType() == OptionValue::eTypeRegex) return static_cast(this); return nullptr; } const OptionValueRegex *OptionValue::GetAsRegex() const { if (GetType() == OptionValue::eTypeRegex) return static_cast(this); return nullptr; } OptionValueSInt64 *OptionValue::GetAsSInt64() { if (GetType() == OptionValue::eTypeSInt64) return static_cast(this); return nullptr; } const OptionValueSInt64 *OptionValue::GetAsSInt64() const { if (GetType() == OptionValue::eTypeSInt64) return static_cast(this); return nullptr; } OptionValueString *OptionValue::GetAsString() { if (GetType() == OptionValue::eTypeString) return static_cast(this); return nullptr; } const OptionValueString *OptionValue::GetAsString() const { if (GetType() == OptionValue::eTypeString) return static_cast(this); return nullptr; } OptionValueUInt64 *OptionValue::GetAsUInt64() { if (GetType() == OptionValue::eTypeUInt64) return static_cast(this); return nullptr; } const OptionValueUInt64 *OptionValue::GetAsUInt64() const { if (GetType() == OptionValue::eTypeUInt64) return static_cast(this); return nullptr; } OptionValueUUID *OptionValue::GetAsUUID() { if (GetType() == OptionValue::eTypeUUID) return static_cast(this); return nullptr; } const OptionValueUUID *OptionValue::GetAsUUID() const { if (GetType() == OptionValue::eTypeUUID) return static_cast(this); return nullptr; } std::optional OptionValue::GetBooleanValue() const { std::lock_guard lock(m_mutex); if (const OptionValueBoolean *option_value = GetAsBoolean()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetBooleanValue(bool new_value) { std::lock_guard lock(m_mutex); if (OptionValueBoolean *option_value = GetAsBoolean()) { option_value->SetCurrentValue(new_value); return true; } return false; } std::optional OptionValue::GetCharValue() const { std::lock_guard lock(m_mutex); if (const OptionValueChar *option_value = GetAsChar()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetCharValue(char new_value) { std::lock_guard lock(m_mutex); if (OptionValueChar *option_value = GetAsChar()) { option_value->SetCurrentValue(new_value); return true; } return false; } std::optional OptionValue::GetEnumerationValue() const { std::lock_guard lock(m_mutex); if (const OptionValueEnumeration *option_value = GetAsEnumeration()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetEnumerationValue(int64_t value) { std::lock_guard lock(m_mutex); if (OptionValueEnumeration *option_value = GetAsEnumeration()) { option_value->SetCurrentValue(value); return true; } return false; } std::optional OptionValue::GetFileSpecValue() const { std::lock_guard lock(m_mutex); if (const OptionValueFileSpec *option_value = GetAsFileSpec()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetFileSpecValue(FileSpec file_spec) { std::lock_guard lock(m_mutex); if (OptionValueFileSpec *option_value = GetAsFileSpec()) { option_value->SetCurrentValue(file_spec, false); return true; } return false; } bool OptionValue::AppendFileSpecValue(FileSpec file_spec) { std::lock_guard lock(m_mutex); if (OptionValueFileSpecList *option_value = GetAsFileSpecList()) { option_value->AppendCurrentValue(file_spec); return true; } return false; } std::optional OptionValue::GetFileSpecListValue() const { std::lock_guard lock(m_mutex); if (const OptionValueFileSpecList *option_value = GetAsFileSpecList()) return option_value->GetCurrentValue(); return {}; } std::optional OptionValue::GetFormatValue() const { std::lock_guard lock(m_mutex); if (const OptionValueFormat *option_value = GetAsFormat()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetFormatValue(lldb::Format new_value) { std::lock_guard lock(m_mutex); if (OptionValueFormat *option_value = GetAsFormat()) { option_value->SetCurrentValue(new_value); return true; } return false; } std::optional OptionValue::GetLanguageValue() const { std::lock_guard lock(m_mutex); if (const OptionValueLanguage *option_value = GetAsLanguage()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) { std::lock_guard lock(m_mutex); if (OptionValueLanguage *option_value = GetAsLanguage()) { option_value->SetCurrentValue(new_language); return true; } return false; } const FormatEntity::Entry *OptionValue::GetFormatEntity() const { std::lock_guard lock(m_mutex); if (const OptionValueFormatEntity *option_value = GetAsFormatEntity()) return &option_value->GetCurrentValue(); return nullptr; } const RegularExpression *OptionValue::GetRegexValue() const { std::lock_guard lock(m_mutex); if (const OptionValueRegex *option_value = GetAsRegex()) return option_value->GetCurrentValue(); return nullptr; } std::optional OptionValue::GetSInt64Value() const { std::lock_guard lock(m_mutex); if (const OptionValueSInt64 *option_value = GetAsSInt64()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetSInt64Value(int64_t new_value) { std::lock_guard lock(m_mutex); if (OptionValueSInt64 *option_value = GetAsSInt64()) { option_value->SetCurrentValue(new_value); return true; } return false; } std::optional OptionValue::GetStringValue() const { std::lock_guard lock(m_mutex); if (const OptionValueString *option_value = GetAsString()) return option_value->GetCurrentValueAsRef(); return {}; } bool OptionValue::SetStringValue(llvm::StringRef new_value) { std::lock_guard lock(m_mutex); if (OptionValueString *option_value = GetAsString()) { option_value->SetCurrentValue(new_value); return true; } return false; } std::optional OptionValue::GetUInt64Value() const { std::lock_guard lock(m_mutex); if (const OptionValueUInt64 *option_value = GetAsUInt64()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetUInt64Value(uint64_t new_value) { std::lock_guard lock(m_mutex); if (OptionValueUInt64 *option_value = GetAsUInt64()) { option_value->SetCurrentValue(new_value); return true; } return false; } std::optional OptionValue::GetUUIDValue() const { std::lock_guard lock(m_mutex); if (const OptionValueUUID *option_value = GetAsUUID()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetUUIDValue(const UUID &uuid) { std::lock_guard lock(m_mutex); if (OptionValueUUID *option_value = GetAsUUID()) { option_value->SetCurrentValue(uuid); return true; } return false; } std::optional OptionValue::GetArchSpecValue() const { std::lock_guard lock(m_mutex); if (const OptionValueArch *option_value = GetAsArch()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetArchSpecValue(ArchSpec arch_spec) { std::lock_guard lock(m_mutex); if (OptionValueArch *option_value = GetAsArch()) { option_value->SetCurrentValue(arch_spec, false); return true; } return false; } const char *OptionValue::GetBuiltinTypeAsCString(Type t) { switch (t) { case eTypeInvalid: return "invalid"; case eTypeArch: return "arch"; case eTypeArgs: return "arguments"; case eTypeArray: return "array"; case eTypeBoolean: return "boolean"; case eTypeChar: return "char"; case eTypeDictionary: return "dictionary"; case eTypeEnum: return "enum"; case eTypeFileLineColumn: return "file:line:column specifier"; case eTypeFileSpec: return "file"; case eTypeFileSpecList: return "file-list"; case eTypeFormat: return "format"; case eTypeFormatEntity: return "format-string"; case eTypeLanguage: return "language"; case eTypePathMap: return "path-map"; case eTypeProperties: return "properties"; case eTypeRegex: return "regex"; case eTypeSInt64: return "int"; case eTypeString: return "string"; case eTypeUInt64: return "unsigned"; case eTypeUUID: return "uuid"; } return nullptr; } lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask( const char *value_cstr, uint32_t type_mask, Status &error) { // If only 1 bit is set in the type mask for a dictionary or array then we // know how to decode a value from a cstring lldb::OptionValueSP value_sp; switch (type_mask) { case 1u << eTypeArch: value_sp = std::make_shared(); break; case 1u << eTypeBoolean: value_sp = std::make_shared(false); break; case 1u << eTypeChar: value_sp = std::make_shared('\0'); break; case 1u << eTypeFileSpec: value_sp = std::make_shared(); break; case 1u << eTypeFormat: value_sp = std::make_shared(eFormatInvalid); break; case 1u << eTypeFormatEntity: value_sp = std::make_shared(nullptr); break; case 1u << eTypeLanguage: value_sp = std::make_shared(eLanguageTypeUnknown); break; case 1u << eTypeSInt64: value_sp = std::make_shared(); break; case 1u << eTypeString: value_sp = std::make_shared(); break; case 1u << eTypeUInt64: value_sp = std::make_shared(); break; case 1u << eTypeUUID: value_sp = std::make_shared(); break; } if (value_sp) error = value_sp->SetValueFromString(value_cstr, eVarSetOperationAssign); else error.SetErrorString("unsupported type mask"); return value_sp; } bool OptionValue::DumpQualifiedName(Stream &strm) const { bool dumped_something = false; lldb::OptionValueSP m_parent_sp(m_parent_wp.lock()); if (m_parent_sp) { if (m_parent_sp->DumpQualifiedName(strm)) dumped_something = true; } llvm::StringRef name(GetName()); if (!name.empty()) { if (dumped_something) strm.PutChar('.'); else dumped_something = true; strm << name; } return dumped_something; } OptionValueSP OptionValue::DeepCopy(const OptionValueSP &new_parent) const { auto clone = Clone(); clone->SetParent(new_parent); return clone; } void OptionValue::AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) {} Status OptionValue::SetValueFromString(llvm::StringRef value, VarSetOperationType op) { Status error; switch (op) { case eVarSetOperationReplace: error.SetErrorStringWithFormat( "%s objects do not support the 'replace' operation", GetTypeAsCString()); break; case eVarSetOperationInsertBefore: error.SetErrorStringWithFormat( "%s objects do not support the 'insert-before' operation", GetTypeAsCString()); break; case eVarSetOperationInsertAfter: error.SetErrorStringWithFormat( "%s objects do not support the 'insert-after' operation", GetTypeAsCString()); break; case eVarSetOperationRemove: error.SetErrorStringWithFormat( "%s objects do not support the 'remove' operation", GetTypeAsCString()); break; case eVarSetOperationAppend: error.SetErrorStringWithFormat( "%s objects do not support the 'append' operation", GetTypeAsCString()); break; case eVarSetOperationClear: error.SetErrorStringWithFormat( "%s objects do not support the 'clear' operation", GetTypeAsCString()); break; case eVarSetOperationAssign: error.SetErrorStringWithFormat( "%s objects do not support the 'assign' operation", GetTypeAsCString()); break; case eVarSetOperationInvalid: error.SetErrorStringWithFormat("invalid operation performed on a %s object", GetTypeAsCString()); break; } return error; }