1 //===-- OptionValueProperties.cpp --------------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Interpreter/OptionValueProperties.h"
14 // Other libraries and framework includes
16 #include "lldb/Utility/Flags.h"
18 #include "lldb/Core/UserSettingsController.h"
19 #include "lldb/Interpreter/OptionValues.h"
20 #include "lldb/Interpreter/Property.h"
21 #include "lldb/Utility/Args.h"
22 #include "lldb/Utility/Stream.h"
23 #include "lldb/Utility/StringList.h"
26 using namespace lldb_private;
28 OptionValueProperties::OptionValueProperties(const ConstString &name)
29 : OptionValue(), m_name(name), m_properties(), m_name_to_index() {}
31 OptionValueProperties::OptionValueProperties(
32 const OptionValueProperties &global_properties)
33 : OptionValue(global_properties),
34 std::enable_shared_from_this<OptionValueProperties>(),
35 m_name(global_properties.m_name),
36 m_properties(global_properties.m_properties),
37 m_name_to_index(global_properties.m_name_to_index) {
38 // We now have an exact copy of "global_properties". We need to now find all
39 // non-global settings and copy the property values so that all non-global
40 // settings get new OptionValue instances created for them.
41 const size_t num_properties = m_properties.size();
42 for (size_t i = 0; i < num_properties; ++i) {
43 // Duplicate any values that are not global when constructing properties
45 if (m_properties[i].IsGlobal() == false) {
46 lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy());
47 m_properties[i].SetOptionValue(new_value_sp);
52 size_t OptionValueProperties::GetNumProperties() const {
53 return m_properties.size();
56 void OptionValueProperties::Initialize(const PropertyDefinition *defs) {
57 for (size_t i = 0; defs[i].name; ++i) {
58 Property property(defs[i]);
59 assert(property.IsValid());
60 m_name_to_index.Append(ConstString(property.GetName()), m_properties.size());
61 property.GetValue()->SetParent(shared_from_this());
62 m_properties.push_back(property);
64 m_name_to_index.Sort();
67 void OptionValueProperties::SetValueChangedCallback(
68 uint32_t property_idx, OptionValueChangedCallback callback, void *baton) {
69 Property *property = ProtectedGetPropertyAtIndex(property_idx);
71 property->SetValueChangedCallback(callback, baton);
74 void OptionValueProperties::AppendProperty(const ConstString &name,
75 const ConstString &desc,
77 const OptionValueSP &value_sp) {
78 Property property(name, desc, is_global, value_sp);
79 m_name_to_index.Append(name, m_properties.size());
80 m_properties.push_back(property);
81 value_sp->SetParent(shared_from_this());
82 m_name_to_index.Sort();
86 // OptionValueProperties::GetQualifiedName (Stream &strm)
88 // bool dumped_something = false;
89 //// lldb::OptionValuePropertiesSP parent_sp(GetParent ());
92 //// parent_sp->GetQualifiedName (strm);
93 //// strm.PutChar('.');
94 //// dumped_something = true;
99 // dumped_something = true;
101 // return dumped_something;
105 OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
106 const ConstString &key,
107 bool will_modify) const {
108 lldb::OptionValueSP value_sp;
109 size_t idx = m_name_to_index.Find(key, SIZE_MAX);
110 if (idx < m_properties.size())
111 value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
116 OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
117 llvm::StringRef name, bool will_modify,
118 Status &error) const {
119 lldb::OptionValueSP value_sp;
121 return OptionValueSP();
123 llvm::StringRef sub_name;
125 size_t key_len = name.find_first_of(".[{");
126 if (key_len != llvm::StringRef::npos) {
127 key.SetString(name.take_front(key_len));
128 sub_name = name.drop_front(key_len);
132 value_sp = GetValueForKey(exe_ctx, key, will_modify);
133 if (sub_name.empty() || !value_sp)
136 switch (sub_name[0]) {
138 lldb::OptionValueSP return_val_sp;
140 value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error);
141 if (!return_val_sp) {
142 if (Properties::IsSettingExperimental(sub_name.drop_front())) {
143 size_t experimental_len =
144 strlen(Properties::GetExperimentalSettingsName());
145 if (sub_name[experimental_len + 1] == '.')
146 return_val_sp = value_sp->GetSubValue(
147 exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error);
148 // It isn't an error if an experimental setting is not present.
153 return return_val_sp;
156 // Predicate matching for predicates like
157 // "<setting-name>{<predicate>}"
158 // strings are parsed by the current OptionValueProperties subclass to mean
159 // whatever they want to. For instance a subclass of OptionValueProperties
160 // for a lldb_private::Target might implement: "target.run-
161 // args{arch==i386}" -- only set run args if the arch is i386 "target
162 // .run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path
163 // matches "target.run-args{basename==test&&arch==x86_64}" -- only set run
164 // args if executable basename is "test" and arch is "x86_64"
166 llvm::StringRef predicate_start = sub_name.drop_front();
167 size_t pos = predicate_start.find_first_of('}');
168 if (pos != llvm::StringRef::npos) {
169 auto predicate = predicate_start.take_front(pos);
170 auto rest = predicate_start.drop_front(pos);
171 if (PredicateMatches(exe_ctx, predicate)) {
173 // Still more subvalue string to evaluate
174 return value_sp->GetSubValue(exe_ctx, rest,
183 // Predicate didn't match or wasn't correctly formed
188 // Array or dictionary access for subvalues like: "[12]" -- access
189 // 12th array element "['hello']" -- dictionary access of key named hello
190 return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
199 Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
200 VarSetOperationType op,
201 llvm::StringRef name,
202 llvm::StringRef value) {
204 const bool will_modify = true;
205 llvm::SmallVector<llvm::StringRef, 8> components;
206 name.split(components, '.');
207 bool name_contains_experimental = false;
208 for (const auto &part : components)
209 if (Properties::IsSettingExperimental(part))
210 name_contains_experimental = true;
213 lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
215 error = value_sp->SetValueFromString(value, op);
217 // Don't set an error if the path contained .experimental. - those are
218 // allowed to be missing and should silently fail.
219 if (name_contains_experimental == false && error.AsCString() == nullptr) {
220 error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
227 OptionValueProperties::GetPropertyIndex(const ConstString &name) const {
228 return m_name_to_index.Find(name, SIZE_MAX);
232 OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
234 const ConstString &name) const {
235 return GetPropertyAtIndex(
236 exe_ctx, will_modify,
237 m_name_to_index.Find(name, SIZE_MAX));
240 const Property *OptionValueProperties::GetPropertyAtIndex(
241 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
242 return ProtectedGetPropertyAtIndex(idx);
245 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
246 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
247 const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx);
249 return setting->GetValue();
250 return OptionValueSP();
253 OptionValuePathMappings *
254 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
255 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
256 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
258 return value_sp->GetAsPathMappings();
262 OptionValueFileSpecList *
263 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
264 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
265 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
267 return value_sp->GetAsFileSpecList();
271 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
272 const ExecutionContext *exe_ctx, uint32_t idx) const {
273 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
275 return property->GetValue()->GetAsArch();
279 OptionValueLanguage *
280 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
281 const ExecutionContext *exe_ctx, uint32_t idx) const {
282 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
284 return property->GetValue()->GetAsLanguage();
288 bool OptionValueProperties::GetPropertyAtIndexAsArgs(
289 const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
290 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
292 OptionValue *value = property->GetValue().get();
294 const OptionValueArray *array = value->GetAsArray();
296 return array->GetArgs(args);
298 const OptionValueDictionary *dict = value->GetAsDictionary();
300 return dict->GetArgs(args);
307 bool OptionValueProperties::SetPropertyAtIndexFromArgs(
308 const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
309 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
311 OptionValue *value = property->GetValue().get();
313 OptionValueArray *array = value->GetAsArray();
315 return array->SetArgs(args, eVarSetOperationAssign).Success();
317 OptionValueDictionary *dict = value->GetAsDictionary();
319 return dict->SetArgs(args, eVarSetOperationAssign).Success();
326 bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
327 const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
328 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
330 OptionValue *value = property->GetValue().get();
332 return value->GetBooleanValue(fail_value);
337 bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
338 const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
339 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
341 OptionValue *value = property->GetValue().get();
343 value->SetBooleanValue(new_value);
350 OptionValueDictionary *
351 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
352 const ExecutionContext *exe_ctx, uint32_t idx) const {
353 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
355 return property->GetValue()->GetAsDictionary();
359 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
360 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
361 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
363 OptionValue *value = property->GetValue().get();
365 return value->GetEnumerationValue(fail_value);
370 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
371 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
372 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
374 OptionValue *value = property->GetValue().get();
376 return value->SetEnumerationValue(new_value);
381 const FormatEntity::Entry *
382 OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
383 const ExecutionContext *exe_ctx, uint32_t idx) {
384 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
386 OptionValue *value = property->GetValue().get();
388 return value->GetFormatEntity();
393 OptionValueFileSpec *
394 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
395 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
396 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
398 OptionValue *value = property->GetValue().get();
400 return value->GetAsFileSpec();
405 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
406 const ExecutionContext *exe_ctx, uint32_t idx) const {
407 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
409 OptionValue *value = property->GetValue().get();
411 return value->GetFileSpecValue();
416 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
417 const ExecutionContext *exe_ctx, uint32_t idx,
418 const FileSpec &new_file_spec) {
419 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
421 OptionValue *value = property->GetValue().get();
423 return value->SetFileSpecValue(new_file_spec);
428 const RegularExpression *
429 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
430 const ExecutionContext *exe_ctx, uint32_t idx) const {
431 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
433 OptionValue *value = property->GetValue().get();
435 return value->GetRegexValue();
440 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
441 const ExecutionContext *exe_ctx, uint32_t idx) const {
442 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
444 OptionValue *value = property->GetValue().get();
446 return value->GetAsSInt64();
451 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
452 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
453 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
455 OptionValue *value = property->GetValue().get();
457 return value->GetSInt64Value(fail_value);
462 bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
463 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
464 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
466 OptionValue *value = property->GetValue().get();
468 return value->SetSInt64Value(new_value);
473 llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
474 const ExecutionContext *exe_ctx, uint32_t idx,
475 llvm::StringRef fail_value) const {
476 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
478 OptionValue *value = property->GetValue().get();
480 return value->GetStringValue(fail_value);
485 bool OptionValueProperties::SetPropertyAtIndexAsString(
486 const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
487 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
489 OptionValue *value = property->GetValue().get();
491 return value->SetStringValue(new_value);
496 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
497 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
498 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
500 return value_sp->GetAsString();
504 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
505 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
506 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
508 OptionValue *value = property->GetValue().get();
510 return value->GetUInt64Value(fail_value);
515 bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
516 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
517 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
519 OptionValue *value = property->GetValue().get();
521 return value->SetUInt64Value(new_value);
526 bool OptionValueProperties::Clear() {
527 const size_t num_properties = m_properties.size();
528 for (size_t i = 0; i < num_properties; ++i)
529 m_properties[i].GetValue()->Clear();
533 Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
534 VarSetOperationType op) {
537 // Args args(value_cstr);
538 // const size_t argc = args.GetArgumentCount();
540 case eVarSetOperationClear:
544 case eVarSetOperationReplace:
545 case eVarSetOperationAssign:
546 case eVarSetOperationRemove:
547 case eVarSetOperationInsertBefore:
548 case eVarSetOperationInsertAfter:
549 case eVarSetOperationAppend:
550 case eVarSetOperationInvalid:
551 error = OptionValue::SetValueFromString(value, op);
558 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
559 Stream &strm, uint32_t dump_mask) {
560 const size_t num_properties = m_properties.size();
561 for (size_t i = 0; i < num_properties; ++i) {
562 const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
564 OptionValue *option_value = property->GetValue().get();
565 assert(option_value);
566 const bool transparent_value = option_value->ValueIsTransparent();
567 property->Dump(exe_ctx, strm, dump_mask);
568 if (!transparent_value)
574 Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
576 llvm::StringRef property_path,
577 uint32_t dump_mask) {
579 const bool will_modify = false;
580 lldb::OptionValueSP value_sp(
581 GetSubValue(exe_ctx, property_path, will_modify, error));
583 if (!value_sp->ValueIsTransparent()) {
584 if (dump_mask & eDumpOptionName)
585 strm.PutCString(property_path);
586 if (dump_mask & ~eDumpOptionName)
589 value_sp->DumpValue(exe_ctx, strm, dump_mask);
594 lldb::OptionValueSP OptionValueProperties::DeepCopy() const {
595 llvm_unreachable("this shouldn't happen");
598 const Property *OptionValueProperties::GetPropertyAtPath(
599 const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const {
600 const Property *property = nullptr;
603 llvm::StringRef sub_name;
605 size_t key_len = name.find_first_of(".[{");
607 if (key_len != llvm::StringRef::npos) {
608 key.SetString(name.take_front(key_len));
609 sub_name = name.drop_front(key_len);
613 property = GetProperty(exe_ctx, will_modify, key);
614 if (sub_name.empty() || !property)
617 if (sub_name[0] == '.') {
618 OptionValueProperties *sub_properties =
619 property->GetValue()->GetAsProperties();
621 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify,
622 sub_name.drop_front());
627 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
628 Stream &strm) const {
629 size_t max_name_len = 0;
630 const size_t num_properties = m_properties.size();
631 for (size_t i = 0; i < num_properties; ++i) {
632 const Property *property = ProtectedGetPropertyAtIndex(i);
634 max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
636 for (size_t i = 0; i < num_properties; ++i) {
637 const Property *property = ProtectedGetPropertyAtIndex(i);
639 property->DumpDescription(interpreter, strm, max_name_len, false);
643 void OptionValueProperties::Apropos(
644 llvm::StringRef keyword,
645 std::vector<const Property *> &matching_properties) const {
646 const size_t num_properties = m_properties.size();
648 for (size_t i = 0; i < num_properties; ++i) {
649 const Property *property = ProtectedGetPropertyAtIndex(i);
651 const OptionValueProperties *properties =
652 property->GetValue()->GetAsProperties();
654 properties->Apropos(keyword, matching_properties);
657 llvm::StringRef name = property->GetName();
658 if (name.contains_lower(keyword))
661 llvm::StringRef desc = property->GetDescription();
662 if (desc.contains_lower(keyword))
666 matching_properties.push_back(property);
673 lldb::OptionValuePropertiesSP
674 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
675 const ConstString &name) {
676 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
677 if (option_value_sp) {
678 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
680 return ov_properties->shared_from_this();
682 return lldb::OptionValuePropertiesSP();