180814287SRaphael Isemann //===-- Property.cpp ------------------------------------------------------===//
267cc0636SGreg Clayton //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
667cc0636SGreg Clayton //
767cc0636SGreg Clayton //===----------------------------------------------------------------------===//
867cc0636SGreg Clayton 
967cc0636SGreg Clayton #include "lldb/Interpreter/Property.h"
1067cc0636SGreg Clayton 
1167cc0636SGreg Clayton #include "lldb/Core/UserSettingsController.h"
1267cc0636SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
1347cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
1467cc0636SGreg Clayton #include "lldb/Interpreter/OptionValues.h"
150e0984eeSJim Ingham #include "lldb/Target/Language.h"
1667cc0636SGreg Clayton 
17796ac80bSJonas Devlieghere #include <memory>
18796ac80bSJonas Devlieghere 
1967cc0636SGreg Clayton using namespace lldb;
2067cc0636SGreg Clayton using namespace lldb_private;
2167cc0636SGreg Clayton 
Property(const PropertyDefinition & definition)22b9c1b51eSKate Stone Property::Property(const PropertyDefinition &definition)
23b9c1b51eSKate Stone     : m_name(definition.name), m_description(definition.description),
248cdcd41eSTatyana Krasnukha       m_is_global(definition.global) {
25b9c1b51eSKate Stone   switch (definition.type) {
2667cc0636SGreg Clayton   case OptionValue::eTypeInvalid:
2767cc0636SGreg Clayton   case OptionValue::eTypeProperties:
2867cc0636SGreg Clayton     break;
2967cc0636SGreg Clayton   case OptionValue::eTypeArch:
3067cc0636SGreg Clayton     // "definition.default_uint_value" is not used
31b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
32b9c1b51eSKate Stone     // default string value for the architecture/triple
33796ac80bSJonas Devlieghere     m_value_sp =
34796ac80bSJonas Devlieghere         std::make_shared<OptionValueArch>(definition.default_cstr_value);
3567cc0636SGreg Clayton     break;
3667cc0636SGreg Clayton 
3767cc0636SGreg Clayton   case OptionValue::eTypeArgs:
3867cc0636SGreg Clayton     // "definition.default_uint_value" is always a OptionValue::Type
39796ac80bSJonas Devlieghere     m_value_sp = std::make_shared<OptionValueArgs>();
4067cc0636SGreg Clayton     break;
4167cc0636SGreg Clayton 
4267cc0636SGreg Clayton   case OptionValue::eTypeArray:
4367cc0636SGreg Clayton     // "definition.default_uint_value" is always a OptionValue::Type
44796ac80bSJonas Devlieghere     m_value_sp =
45796ac80bSJonas Devlieghere         std::make_shared<OptionValueArray>(OptionValue::ConvertTypeToMask(
46796ac80bSJonas Devlieghere             (OptionValue::Type)definition.default_uint_value));
4767cc0636SGreg Clayton     break;
4867cc0636SGreg Clayton 
4967cc0636SGreg Clayton   case OptionValue::eTypeBoolean:
5067cc0636SGreg Clayton     // "definition.default_uint_value" is the default boolean value if
5167cc0636SGreg Clayton     // "definition.default_cstr_value" is NULL, otherwise interpret
52b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
537b2e5a36SZachary Turner     // default value.
5467cc0636SGreg Clayton     if (definition.default_cstr_value)
55796ac80bSJonas Devlieghere       m_value_sp =
56796ac80bSJonas Devlieghere           std::make_shared<OptionValueBoolean>(OptionArgParser::ToBoolean(
57796ac80bSJonas Devlieghere               llvm::StringRef(definition.default_cstr_value), false, nullptr));
5867cc0636SGreg Clayton     else
59796ac80bSJonas Devlieghere       m_value_sp = std::make_shared<OptionValueBoolean>(
60796ac80bSJonas Devlieghere           definition.default_uint_value != 0);
6167cc0636SGreg Clayton     break;
6267cc0636SGreg Clayton 
637b2e5a36SZachary Turner   case OptionValue::eTypeChar: {
647b2e5a36SZachary Turner     llvm::StringRef s(definition.default_cstr_value ? definition.default_cstr_value : "");
6547cbf4a0SPavel Labath     m_value_sp = std::make_shared<OptionValueChar>(
6647cbf4a0SPavel Labath         OptionArgParser::ToChar(s, '\0', nullptr));
673e7442b6SZachary Turner     break;
687b2e5a36SZachary Turner   }
6967cc0636SGreg Clayton   case OptionValue::eTypeDictionary:
7067cc0636SGreg Clayton     // "definition.default_uint_value" is always a OptionValue::Type
71*3c867898SAlvin Wong     m_value_sp = std::make_shared<OptionValueDictionary>(
72*3c867898SAlvin Wong         OptionValue::ConvertTypeToMask(
73*3c867898SAlvin Wong             (OptionValue::Type)definition.default_uint_value),
74*3c867898SAlvin Wong         definition.enum_values);
7567cc0636SGreg Clayton     break;
7667cc0636SGreg Clayton 
7767cc0636SGreg Clayton   case OptionValue::eTypeEnum:
7867cc0636SGreg Clayton     // "definition.default_uint_value" is the default enumeration value if
7967cc0636SGreg Clayton     // "definition.default_cstr_value" is NULL, otherwise interpret
80b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
8105097246SAdrian Prantl     // default value.
8267cc0636SGreg Clayton     {
83b9c1b51eSKate Stone       OptionValueEnumeration *enum_value = new OptionValueEnumeration(
84b9c1b51eSKate Stone           definition.enum_values, definition.default_uint_value);
8567cc0636SGreg Clayton       m_value_sp.reset(enum_value);
86b9c1b51eSKate Stone       if (definition.default_cstr_value) {
878cef4b0bSZachary Turner         if (enum_value
888cef4b0bSZachary Turner                 ->SetValueFromString(
898cef4b0bSZachary Turner                     llvm::StringRef(definition.default_cstr_value))
90b9c1b51eSKate Stone                 .Success()) {
9167cc0636SGreg Clayton           enum_value->SetDefaultValue(enum_value->GetCurrentValue());
9205097246SAdrian Prantl           // Call Clear() since we don't want the value to appear as having
9305097246SAdrian Prantl           // been set since we called SetValueFromString() above. Clear will
9405097246SAdrian Prantl           // set the current value to the default and clear the boolean that
9505097246SAdrian Prantl           // says that the value has been set.
9667cc0636SGreg Clayton           enum_value->Clear();
9767cc0636SGreg Clayton         }
9867cc0636SGreg Clayton       }
9967cc0636SGreg Clayton     }
10067cc0636SGreg Clayton     break;
10167cc0636SGreg Clayton 
102bc0a9a17SJim Ingham   case OptionValue::eTypeFileLineColumn:
103bc0a9a17SJim Ingham     // "definition.default_uint_value" is not used for a
104bc0a9a17SJim Ingham     // OptionValue::eTypeFileSpecList
105bc0a9a17SJim Ingham     m_value_sp = std::make_shared<OptionValueFileColonLine>();
106bc0a9a17SJim Ingham     break;
107bc0a9a17SJim Ingham 
108b9c1b51eSKate Stone   case OptionValue::eTypeFileSpec: {
109b9c1b51eSKate Stone     // "definition.default_uint_value" represents if the
11005097246SAdrian Prantl     // "definition.default_cstr_value" should be resolved or not
1111f4706c3SVince Harron     const bool resolve = definition.default_uint_value != 0;
1128f3be7a3SJonas Devlieghere     FileSpec file_spec = FileSpec(definition.default_cstr_value);
1138f3be7a3SJonas Devlieghere     if (resolve)
1148f3be7a3SJonas Devlieghere       FileSystem::Instance().Resolve(file_spec);
115796ac80bSJonas Devlieghere     m_value_sp = std::make_shared<OptionValueFileSpec>(file_spec, resolve);
11667cc0636SGreg Clayton     break;
1171f4706c3SVince Harron   }
11867cc0636SGreg Clayton 
11967cc0636SGreg Clayton   case OptionValue::eTypeFileSpecList:
120b9c1b51eSKate Stone     // "definition.default_uint_value" is not used for a
121b9c1b51eSKate Stone     // OptionValue::eTypeFileSpecList
122796ac80bSJonas Devlieghere     m_value_sp = std::make_shared<OptionValueFileSpecList>();
12367cc0636SGreg Clayton     break;
12467cc0636SGreg Clayton 
12567cc0636SGreg Clayton   case OptionValue::eTypeFormat:
126b9c1b51eSKate Stone     // "definition.default_uint_value" is the default format enumeration value
12705097246SAdrian Prantl     // if "definition.default_cstr_value" is NULL, otherwise interpret
128b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
12905097246SAdrian Prantl     // default value.
13067cc0636SGreg Clayton     {
13167cc0636SGreg Clayton       Format new_format = eFormatInvalid;
13267cc0636SGreg Clayton       if (definition.default_cstr_value)
13347cbf4a0SPavel Labath         OptionArgParser::ToFormat(definition.default_cstr_value, new_format,
134b9c1b51eSKate Stone                                   nullptr);
13567cc0636SGreg Clayton       else
13667cc0636SGreg Clayton         new_format = (Format)definition.default_uint_value;
137796ac80bSJonas Devlieghere       m_value_sp = std::make_shared<OptionValueFormat>(new_format);
13867cc0636SGreg Clayton     }
13967cc0636SGreg Clayton     break;
14067cc0636SGreg Clayton 
1418fdf7859SEnrico Granata   case OptionValue::eTypeLanguage:
14205097246SAdrian Prantl     // "definition.default_uint_value" is the default language enumeration
14305097246SAdrian Prantl     // value if "definition.default_cstr_value" is NULL, otherwise interpret
144b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
14505097246SAdrian Prantl     // default value.
1468fdf7859SEnrico Granata     {
1478fdf7859SEnrico Granata       LanguageType new_lang = eLanguageTypeUnknown;
1488fdf7859SEnrico Granata       if (definition.default_cstr_value)
1496fa7681bSZachary Turner         Language::GetLanguageTypeFromString(
1506fa7681bSZachary Turner             llvm::StringRef(definition.default_cstr_value));
1518fdf7859SEnrico Granata       else
1528fdf7859SEnrico Granata         new_lang = (LanguageType)definition.default_uint_value;
153796ac80bSJonas Devlieghere       m_value_sp = std::make_shared<OptionValueLanguage>(new_lang);
1548fdf7859SEnrico Granata     }
1558fdf7859SEnrico Granata     break;
1568fdf7859SEnrico Granata 
157554f68d3SGreg Clayton   case OptionValue::eTypeFormatEntity:
158b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
159b9c1b51eSKate Stone     // default
160796ac80bSJonas Devlieghere     m_value_sp = std::make_shared<OptionValueFormatEntity>(
161796ac80bSJonas Devlieghere         definition.default_cstr_value);
162554f68d3SGreg Clayton     break;
163554f68d3SGreg Clayton 
16467cc0636SGreg Clayton   case OptionValue::eTypePathMap:
165b9c1b51eSKate Stone     // "definition.default_uint_value" tells us if notifications should occur
16605097246SAdrian Prantl     // for path mappings
167796ac80bSJonas Devlieghere     m_value_sp = std::make_shared<OptionValuePathMappings>(
168796ac80bSJonas Devlieghere         definition.default_uint_value != 0);
16967cc0636SGreg Clayton     break;
17067cc0636SGreg Clayton 
17167cc0636SGreg Clayton   case OptionValue::eTypeRegex:
17267cc0636SGreg Clayton     // "definition.default_uint_value" is used to the regular expression flags
17367cc0636SGreg Clayton     // "definition.default_cstr_value" the default regular expression value
17467cc0636SGreg Clayton     // value.
175796ac80bSJonas Devlieghere     m_value_sp =
176796ac80bSJonas Devlieghere         std::make_shared<OptionValueRegex>(definition.default_cstr_value);
17767cc0636SGreg Clayton     break;
17867cc0636SGreg Clayton 
1793a6ba367SMichał Górny   case OptionValue::eTypeSInt64: {
18067cc0636SGreg Clayton     // "definition.default_uint_value" is the default integer value if
18167cc0636SGreg Clayton     // "definition.default_cstr_value" is NULL, otherwise interpret
182b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
18305097246SAdrian Prantl     // default value.
1843a6ba367SMichał Górny     int64_t value = 0;
1853a6ba367SMichał Górny     // FIXME: improve error handling for llvm::to_integer()
1863a6ba367SMichał Górny     if (definition.default_cstr_value)
1873a6ba367SMichał Górny       llvm::to_integer(definition.default_cstr_value, value);
188796ac80bSJonas Devlieghere     m_value_sp = std::make_shared<OptionValueSInt64>(
1893a6ba367SMichał Górny         definition.default_cstr_value ? value : definition.default_uint_value);
19067cc0636SGreg Clayton     break;
1913a6ba367SMichał Górny   }
1923a6ba367SMichał Górny   case OptionValue::eTypeUInt64: {
1933a6ba367SMichał Górny     uint64_t value = 0;
1943a6ba367SMichał Górny     // FIXME: improve error handling for llvm::to_integer()
1953a6ba367SMichał Górny     if (definition.default_cstr_value)
1963a6ba367SMichał Górny       llvm::to_integer(definition.default_cstr_value, value);
19767cc0636SGreg Clayton     // "definition.default_uint_value" is the default unsigned integer value if
19867cc0636SGreg Clayton     // "definition.default_cstr_value" is NULL, otherwise interpret
199b9c1b51eSKate Stone     // "definition.default_cstr_value" as a string value that represents the
20005097246SAdrian Prantl     // default value.
201796ac80bSJonas Devlieghere     m_value_sp = std::make_shared<OptionValueUInt64>(
2023a6ba367SMichał Górny         definition.default_cstr_value ? value : definition.default_uint_value);
20367cc0636SGreg Clayton     break;
2043a6ba367SMichał Górny   }
20567cc0636SGreg Clayton   case OptionValue::eTypeUUID:
20667cc0636SGreg Clayton     // "definition.default_uint_value" is not used for a OptionValue::eTypeUUID
20767cc0636SGreg Clayton     // "definition.default_cstr_value" can contain a default UUID value
20867cc0636SGreg Clayton     {
20967cc0636SGreg Clayton       UUID uuid;
21067cc0636SGreg Clayton       if (definition.default_cstr_value)
211a174bcbfSPavel Labath         uuid.SetFromStringRef(definition.default_cstr_value);
212796ac80bSJonas Devlieghere       m_value_sp = std::make_shared<OptionValueUUID>(uuid);
21367cc0636SGreg Clayton     }
21467cc0636SGreg Clayton     break;
21567cc0636SGreg Clayton 
21667cc0636SGreg Clayton   case OptionValue::eTypeString:
21705097246SAdrian Prantl     // "definition.default_uint_value" can contain the string option flags
21805097246SAdrian Prantl     // OR'ed together "definition.default_cstr_value" can contain a default
21905097246SAdrian Prantl     // string value
2204c05410fSGreg Clayton     {
221b9c1b51eSKate Stone       OptionValueString *string_value =
222b9c1b51eSKate Stone           new OptionValueString(definition.default_cstr_value);
2234c05410fSGreg Clayton       if (definition.default_uint_value != 0)
2244c05410fSGreg Clayton         string_value->GetOptions().Reset(definition.default_uint_value);
2254c05410fSGreg Clayton       m_value_sp.reset(string_value);
2264c05410fSGreg Clayton     }
22767cc0636SGreg Clayton     break;
22867cc0636SGreg Clayton   }
22967cc0636SGreg Clayton }
23067cc0636SGreg Clayton 
Property(llvm::StringRef name,llvm::StringRef desc,bool is_global,const lldb::OptionValueSP & value_sp)231ff7ce0afSPavel Labath Property::Property(llvm::StringRef name, llvm::StringRef desc, bool is_global,
232ff7ce0afSPavel Labath                    const lldb::OptionValueSP &value_sp)
233b9c1b51eSKate Stone     : m_name(name), m_description(desc), m_value_sp(value_sp),
234b9c1b51eSKate Stone       m_is_global(is_global) {}
23567cc0636SGreg Clayton 
DumpQualifiedName(Stream & strm) const236b9c1b51eSKate Stone bool Property::DumpQualifiedName(Stream &strm) const {
237ff7ce0afSPavel Labath   if (!m_name.empty()) {
23867cc0636SGreg Clayton     if (m_value_sp->DumpQualifiedName(strm))
23967cc0636SGreg Clayton       strm.PutChar('.');
24067cc0636SGreg Clayton     strm << m_name;
24167cc0636SGreg Clayton     return true;
24267cc0636SGreg Clayton   }
24367cc0636SGreg Clayton   return false;
24467cc0636SGreg Clayton }
24567cc0636SGreg Clayton 
Dump(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask) const246b9c1b51eSKate Stone void Property::Dump(const ExecutionContext *exe_ctx, Stream &strm,
247b9c1b51eSKate Stone                     uint32_t dump_mask) const {
248b9c1b51eSKate Stone   if (m_value_sp) {
24967cc0636SGreg Clayton     const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription;
250b76e25a2SJonas Devlieghere     const bool dump_cmd = dump_mask & OptionValue::eDumpOptionCommand;
25167cc0636SGreg Clayton     const bool transparent = m_value_sp->ValueIsTransparent();
252b76e25a2SJonas Devlieghere     if (dump_cmd && !transparent)
253b76e25a2SJonas Devlieghere       strm << "settings set -f ";
254b9c1b51eSKate Stone     if (dump_desc || !transparent) {
255ff7ce0afSPavel Labath       if ((dump_mask & OptionValue::eDumpOptionName) && !m_name.empty()) {
25667cc0636SGreg Clayton         DumpQualifiedName(strm);
25767cc0636SGreg Clayton         if (dump_mask & ~OptionValue::eDumpOptionName)
25867cc0636SGreg Clayton           strm.PutChar(' ');
25967cc0636SGreg Clayton       }
26067cc0636SGreg Clayton     }
261b9c1b51eSKate Stone     if (dump_desc) {
262e6f6d4c2SZachary Turner       llvm::StringRef desc = GetDescription();
263e6f6d4c2SZachary Turner       if (!desc.empty())
264e6f6d4c2SZachary Turner         strm << "-- " << desc;
26567cc0636SGreg Clayton 
266b9c1b51eSKate Stone       if (transparent && (dump_mask == (OptionValue::eDumpOptionName |
267b9c1b51eSKate Stone                                         OptionValue::eDumpOptionDescription)))
26867cc0636SGreg Clayton         strm.EOL();
26967cc0636SGreg Clayton     }
27067cc0636SGreg Clayton     m_value_sp->DumpValue(exe_ctx, strm, dump_mask);
27167cc0636SGreg Clayton   }
27267cc0636SGreg Clayton }
27367cc0636SGreg Clayton 
DumpDescription(CommandInterpreter & interpreter,Stream & strm,uint32_t output_width,bool display_qualified_name) const274b9c1b51eSKate Stone void Property::DumpDescription(CommandInterpreter &interpreter, Stream &strm,
27567cc0636SGreg Clayton                                uint32_t output_width,
276b9c1b51eSKate Stone                                bool display_qualified_name) const {
277e6f6d4c2SZachary Turner   if (!m_value_sp)
278e6f6d4c2SZachary Turner     return;
279e6f6d4c2SZachary Turner   llvm::StringRef desc = GetDescription();
28067cc0636SGreg Clayton 
281e6f6d4c2SZachary Turner   if (desc.empty())
282e6f6d4c2SZachary Turner     return;
283e6f6d4c2SZachary Turner 
28467cc0636SGreg Clayton   StreamString qualified_name;
285e6f6d4c2SZachary Turner   const OptionValueProperties *sub_properties = m_value_sp->GetAsProperties();
286b9c1b51eSKate Stone   if (sub_properties) {
28767cc0636SGreg Clayton     strm.EOL();
28867cc0636SGreg Clayton 
28967cc0636SGreg Clayton     if (m_value_sp->DumpQualifiedName(qualified_name))
290c156427dSZachary Turner       strm.Printf("'%s' variables:\n\n", qualified_name.GetData());
29167cc0636SGreg Clayton     sub_properties->DumpAllDescriptions(interpreter, strm);
292b9c1b51eSKate Stone   } else {
293b9c1b51eSKate Stone     if (display_qualified_name) {
29467cc0636SGreg Clayton       StreamString qualified_name;
29567cc0636SGreg Clayton       DumpQualifiedName(qualified_name);
296c156427dSZachary Turner       interpreter.OutputFormattedHelpText(strm, qualified_name.GetString(),
297c156427dSZachary Turner                                           "--", desc, output_width);
298b9c1b51eSKate Stone     } else {
299ff7ce0afSPavel Labath       interpreter.OutputFormattedHelpText(strm, m_name, "--", desc,
300ff7ce0afSPavel Labath                                           output_width);
30167cc0636SGreg Clayton     }
30267cc0636SGreg Clayton   }
30367cc0636SGreg Clayton }
30467cc0636SGreg Clayton 
SetValueChangedCallback(std::function<void ()> callback)3055c4661b7SPavel Labath void Property::SetValueChangedCallback(std::function<void()> callback) {
306332e8b1cSGreg Clayton   if (m_value_sp)
3075c4661b7SPavel Labath     m_value_sp->SetValueChangedCallback(std::move(callback));
308332e8b1cSGreg Clayton }
309