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