1//===-- Property.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/Property.h" 10 11#include "lldb/Core/UserSettingsController.h" 12#include "lldb/Interpreter/CommandInterpreter.h" 13#include "lldb/Interpreter/OptionArgParser.h" 14#include "lldb/Interpreter/OptionValues.h" 15#include "lldb/Target/Language.h" 16 17#include <memory> 18 19using namespace lldb; 20using namespace lldb_private; 21 22Property::Property(const PropertyDefinition &definition) 23 : m_name(definition.name), m_description(definition.description), 24 m_is_global(definition.global) { 25 switch (definition.type) { 26 case OptionValue::eTypeInvalid: 27 case OptionValue::eTypeProperties: 28 break; 29 case OptionValue::eTypeArch: 30 // "definition.default_uint_value" is not used 31 // "definition.default_cstr_value" as a string value that represents the 32 // default string value for the architecture/triple 33 m_value_sp = 34 std::make_shared<OptionValueArch>(definition.default_cstr_value); 35 break; 36 37 case OptionValue::eTypeArgs: 38 // "definition.default_uint_value" is always a OptionValue::Type 39 m_value_sp = std::make_shared<OptionValueArgs>(); 40 break; 41 42 case OptionValue::eTypeArray: 43 // "definition.default_uint_value" is always a OptionValue::Type 44 m_value_sp = 45 std::make_shared<OptionValueArray>(OptionValue::ConvertTypeToMask( 46 (OptionValue::Type)definition.default_uint_value)); 47 break; 48 49 case OptionValue::eTypeBoolean: 50 // "definition.default_uint_value" is the default boolean value if 51 // "definition.default_cstr_value" is NULL, otherwise interpret 52 // "definition.default_cstr_value" as a string value that represents the 53 // default value. 54 if (definition.default_cstr_value) 55 m_value_sp = 56 std::make_shared<OptionValueBoolean>(OptionArgParser::ToBoolean( 57 llvm::StringRef(definition.default_cstr_value), false, nullptr)); 58 else 59 m_value_sp = std::make_shared<OptionValueBoolean>( 60 definition.default_uint_value != 0); 61 break; 62 63 case OptionValue::eTypeChar: { 64 llvm::StringRef s(definition.default_cstr_value ? definition.default_cstr_value : ""); 65 m_value_sp = std::make_shared<OptionValueChar>( 66 OptionArgParser::ToChar(s, '\0', nullptr)); 67 break; 68 } 69 case OptionValue::eTypeDictionary: 70 // "definition.default_uint_value" is always a OptionValue::Type 71 m_value_sp = std::make_shared<OptionValueDictionary>( 72 OptionValue::ConvertTypeToMask( 73 (OptionValue::Type)definition.default_uint_value), 74 definition.enum_values); 75 break; 76 77 case OptionValue::eTypeEnum: 78 // "definition.default_uint_value" is the default enumeration value if 79 // "definition.default_cstr_value" is NULL, otherwise interpret 80 // "definition.default_cstr_value" as a string value that represents the 81 // default value. 82 { 83 OptionValueEnumeration *enum_value = new OptionValueEnumeration( 84 definition.enum_values, definition.default_uint_value); 85 m_value_sp.reset(enum_value); 86 if (definition.default_cstr_value) { 87 if (enum_value 88 ->SetValueFromString( 89 llvm::StringRef(definition.default_cstr_value)) 90 .Success()) { 91 enum_value->SetDefaultValue(enum_value->GetCurrentValue()); 92 // Call Clear() since we don't want the value to appear as having 93 // been set since we called SetValueFromString() above. Clear will 94 // set the current value to the default and clear the boolean that 95 // says that the value has been set. 96 enum_value->Clear(); 97 } 98 } 99 } 100 break; 101 102 case OptionValue::eTypeFileLineColumn: 103 // "definition.default_uint_value" is not used for a 104 // OptionValue::eTypeFileSpecList 105 m_value_sp = std::make_shared<OptionValueFileColonLine>(); 106 break; 107 108 case OptionValue::eTypeFileSpec: { 109 // "definition.default_uint_value" represents if the 110 // "definition.default_cstr_value" should be resolved or not 111 const bool resolve = definition.default_uint_value != 0; 112 FileSpec file_spec = FileSpec(definition.default_cstr_value); 113 if (resolve) 114 FileSystem::Instance().Resolve(file_spec); 115 m_value_sp = std::make_shared<OptionValueFileSpec>(file_spec, resolve); 116 break; 117 } 118 119 case OptionValue::eTypeFileSpecList: 120 // "definition.default_uint_value" is not used for a 121 // OptionValue::eTypeFileSpecList 122 m_value_sp = std::make_shared<OptionValueFileSpecList>(); 123 break; 124 125 case OptionValue::eTypeFormat: 126 // "definition.default_uint_value" is the default format enumeration value 127 // if "definition.default_cstr_value" is NULL, otherwise interpret 128 // "definition.default_cstr_value" as a string value that represents the 129 // default value. 130 { 131 Format new_format = eFormatInvalid; 132 if (definition.default_cstr_value) 133 OptionArgParser::ToFormat(definition.default_cstr_value, new_format, 134 nullptr); 135 else 136 new_format = (Format)definition.default_uint_value; 137 m_value_sp = std::make_shared<OptionValueFormat>(new_format); 138 } 139 break; 140 141 case OptionValue::eTypeLanguage: 142 // "definition.default_uint_value" is the default language enumeration 143 // value if "definition.default_cstr_value" is NULL, otherwise interpret 144 // "definition.default_cstr_value" as a string value that represents the 145 // default value. 146 { 147 LanguageType new_lang = eLanguageTypeUnknown; 148 if (definition.default_cstr_value) 149 Language::GetLanguageTypeFromString( 150 llvm::StringRef(definition.default_cstr_value)); 151 else 152 new_lang = (LanguageType)definition.default_uint_value; 153 m_value_sp = std::make_shared<OptionValueLanguage>(new_lang); 154 } 155 break; 156 157 case OptionValue::eTypeFormatEntity: 158 // "definition.default_cstr_value" as a string value that represents the 159 // default 160 m_value_sp = std::make_shared<OptionValueFormatEntity>( 161 definition.default_cstr_value); 162 break; 163 164 case OptionValue::eTypePathMap: 165 // "definition.default_uint_value" tells us if notifications should occur 166 // for path mappings 167 m_value_sp = std::make_shared<OptionValuePathMappings>( 168 definition.default_uint_value != 0); 169 break; 170 171 case OptionValue::eTypeRegex: 172 // "definition.default_uint_value" is used to the regular expression flags 173 // "definition.default_cstr_value" the default regular expression value 174 // value. 175 m_value_sp = 176 std::make_shared<OptionValueRegex>(definition.default_cstr_value); 177 break; 178 179 case OptionValue::eTypeSInt64: { 180 // "definition.default_uint_value" is the default integer value if 181 // "definition.default_cstr_value" is NULL, otherwise interpret 182 // "definition.default_cstr_value" as a string value that represents the 183 // default value. 184 int64_t value = 0; 185 // FIXME: improve error handling for llvm::to_integer() 186 if (definition.default_cstr_value) 187 llvm::to_integer(definition.default_cstr_value, value); 188 m_value_sp = std::make_shared<OptionValueSInt64>( 189 definition.default_cstr_value ? value : definition.default_uint_value); 190 break; 191 } 192 case OptionValue::eTypeUInt64: { 193 uint64_t value = 0; 194 // FIXME: improve error handling for llvm::to_integer() 195 if (definition.default_cstr_value) 196 llvm::to_integer(definition.default_cstr_value, value); 197 // "definition.default_uint_value" is the default unsigned integer value if 198 // "definition.default_cstr_value" is NULL, otherwise interpret 199 // "definition.default_cstr_value" as a string value that represents the 200 // default value. 201 m_value_sp = std::make_shared<OptionValueUInt64>( 202 definition.default_cstr_value ? value : definition.default_uint_value); 203 break; 204 } 205 case OptionValue::eTypeUUID: 206 // "definition.default_uint_value" is not used for a OptionValue::eTypeUUID 207 // "definition.default_cstr_value" can contain a default UUID value 208 { 209 UUID uuid; 210 if (definition.default_cstr_value) 211 uuid.SetFromStringRef(definition.default_cstr_value); 212 m_value_sp = std::make_shared<OptionValueUUID>(uuid); 213 } 214 break; 215 216 case OptionValue::eTypeString: 217 // "definition.default_uint_value" can contain the string option flags 218 // OR'ed together "definition.default_cstr_value" can contain a default 219 // string value 220 { 221 OptionValueString *string_value = 222 new OptionValueString(definition.default_cstr_value); 223 if (definition.default_uint_value != 0) 224 string_value->GetOptions().Reset(definition.default_uint_value); 225 m_value_sp.reset(string_value); 226 } 227 break; 228 } 229 assert(m_value_sp && "invalid property definition"); 230} 231 232Property::Property(llvm::StringRef name, llvm::StringRef desc, bool is_global, 233 const lldb::OptionValueSP &value_sp) 234 : m_name(name), m_description(desc), m_value_sp(value_sp), 235 m_is_global(is_global) {} 236 237bool Property::DumpQualifiedName(Stream &strm) const { 238 if (!m_name.empty()) { 239 if (m_value_sp->DumpQualifiedName(strm)) 240 strm.PutChar('.'); 241 strm << m_name; 242 return true; 243 } 244 return false; 245} 246 247void Property::Dump(const ExecutionContext *exe_ctx, Stream &strm, 248 uint32_t dump_mask) const { 249 if (m_value_sp) { 250 const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription; 251 const bool dump_cmd = dump_mask & OptionValue::eDumpOptionCommand; 252 const bool transparent = m_value_sp->ValueIsTransparent(); 253 if (dump_cmd && !transparent) 254 strm << "settings set -f "; 255 if (dump_desc || !transparent) { 256 if ((dump_mask & OptionValue::eDumpOptionName) && !m_name.empty()) { 257 DumpQualifiedName(strm); 258 if (dump_mask & ~OptionValue::eDumpOptionName) 259 strm.PutChar(' '); 260 } 261 } 262 if (dump_desc) { 263 llvm::StringRef desc = GetDescription(); 264 if (!desc.empty()) 265 strm << "-- " << desc; 266 267 if (transparent && (dump_mask == (OptionValue::eDumpOptionName | 268 OptionValue::eDumpOptionDescription))) 269 strm.EOL(); 270 } 271 m_value_sp->DumpValue(exe_ctx, strm, dump_mask); 272 } 273} 274 275void Property::DumpDescription(CommandInterpreter &interpreter, Stream &strm, 276 uint32_t output_width, 277 bool display_qualified_name) const { 278 if (!m_value_sp) 279 return; 280 llvm::StringRef desc = GetDescription(); 281 282 if (desc.empty()) 283 return; 284 285 StreamString qualified_name; 286 const OptionValueProperties *sub_properties = m_value_sp->GetAsProperties(); 287 if (sub_properties) { 288 strm.EOL(); 289 290 if (m_value_sp->DumpQualifiedName(qualified_name)) 291 strm.Printf("'%s' variables:\n\n", qualified_name.GetData()); 292 sub_properties->DumpAllDescriptions(interpreter, strm); 293 } else { 294 if (display_qualified_name) { 295 StreamString qualified_name; 296 DumpQualifiedName(qualified_name); 297 interpreter.OutputFormattedHelpText(strm, qualified_name.GetString(), 298 "--", desc, output_width); 299 } else { 300 interpreter.OutputFormattedHelpText(strm, m_name, "--", desc, 301 output_width); 302 } 303 } 304} 305 306void Property::SetValueChangedCallback(std::function<void()> callback) { 307 if (m_value_sp) 308 m_value_sp->SetValueChangedCallback(std::move(callback)); 309} 310