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