]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
Merge llvm, clang, lld and lldb trunk r291274, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Interpreter / OptionValueProperties.cpp
1 //===-- OptionValueProperties.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/OptionValueProperties.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Flags.h"
17 #include "lldb/Core/Stream.h"
18 #include "lldb/Core/StringList.h"
19 #include "lldb/Core/UserSettingsController.h"
20 #include "lldb/Interpreter/Args.h"
21 #include "lldb/Interpreter/OptionValues.h"
22 #include "lldb/Interpreter/Property.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 OptionValueProperties::OptionValueProperties(const ConstString &name)
28     : OptionValue(), m_name(name), m_properties(), m_name_to_index() {}
29
30 OptionValueProperties::OptionValueProperties(
31     const OptionValueProperties &global_properties)
32     : OptionValue(global_properties),
33       std::enable_shared_from_this<OptionValueProperties>(),
34       m_name(global_properties.m_name),
35       m_properties(global_properties.m_properties),
36       m_name_to_index(global_properties.m_name_to_index) {
37   // We now have an exact copy of "global_properties". We need to now
38   // find all non-global settings and copy the property values so that
39   // all non-global settings get new OptionValue instances created for
40   // 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
44     // from
45     // a global copy
46     if (m_properties[i].IsGlobal() == false) {
47       lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy());
48       m_properties[i].SetOptionValue(new_value_sp);
49     }
50   }
51 }
52
53 size_t OptionValueProperties::GetNumProperties() const {
54   return m_properties.size();
55 }
56
57 void OptionValueProperties::Initialize(const PropertyDefinition *defs) {
58   for (size_t i = 0; defs[i].name; ++i) {
59     Property property(defs[i]);
60     assert(property.IsValid());
61     m_name_to_index.Append(property.GetName(), m_properties.size());
62     property.GetValue()->SetParent(shared_from_this());
63     m_properties.push_back(property);
64   }
65   m_name_to_index.Sort();
66 }
67
68 void OptionValueProperties::SetValueChangedCallback(
69     uint32_t property_idx, OptionValueChangedCallback callback, void *baton) {
70   Property *property = ProtectedGetPropertyAtIndex(property_idx);
71   if (property)
72     property->SetValueChangedCallback(callback, baton);
73 }
74
75 void OptionValueProperties::AppendProperty(const ConstString &name,
76                                            const ConstString &desc,
77                                            bool is_global,
78                                            const OptionValueSP &value_sp) {
79   Property property(name, desc, is_global, value_sp);
80   m_name_to_index.Append(name.GetStringRef(), m_properties.size());
81   m_properties.push_back(property);
82   value_sp->SetParent(shared_from_this());
83   m_name_to_index.Sort();
84 }
85
86 // bool
87 // OptionValueProperties::GetQualifiedName (Stream &strm)
88 //{
89 //    bool dumped_something = false;
90 ////    lldb::OptionValuePropertiesSP parent_sp(GetParent ());
91 ////    if (parent_sp)
92 ////    {
93 ////        parent_sp->GetQualifiedName (strm);
94 ////        strm.PutChar('.');
95 ////        dumped_something = true;
96 ////    }
97 //    if (m_name)
98 //    {
99 //        strm << m_name;
100 //        dumped_something = true;
101 //    }
102 //    return dumped_something;
103 //}
104 //
105 lldb::OptionValueSP
106 OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
107                                       const ConstString &key,
108                                       bool will_modify) const {
109   lldb::OptionValueSP value_sp;
110   size_t idx = m_name_to_index.Find(key.GetStringRef(), SIZE_MAX);
111   if (idx < m_properties.size())
112     value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
113   return value_sp;
114 }
115
116 lldb::OptionValueSP
117 OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
118   llvm::StringRef name, bool will_modify,
119                                    Error &error) const {
120   lldb::OptionValueSP value_sp;
121   if (name.empty())
122     return OptionValueSP();
123
124   llvm::StringRef sub_name;
125   ConstString key;
126   size_t key_len = name.find_first_of(".[{");
127   if (key_len != llvm::StringRef::npos) {
128     key.SetString(name.take_front(key_len));
129     sub_name = name.drop_front(key_len);
130   } else
131     key.SetString(name);
132
133   value_sp = GetValueForKey(exe_ctx, key, will_modify);
134   if (sub_name.empty() || !value_sp)
135     return value_sp;
136
137   switch (sub_name[0]) {
138   case '.': {
139     lldb::OptionValueSP return_val_sp;
140     return_val_sp =
141         value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error);
142     if (!return_val_sp) {
143       if (Properties::IsSettingExperimental(sub_name.drop_front())) {
144         size_t experimental_len =
145             strlen(Properties::GetExperimentalSettingsName());
146         if (sub_name[experimental_len + 1] == '.')
147           return_val_sp = value_sp->GetSubValue(
148               exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error);
149         // It isn't an error if an experimental setting is not present.
150         if (!return_val_sp)
151           error.Clear();
152       }
153     }
154     return return_val_sp;
155   }
156   case '{':
157     // Predicate matching for predicates like
158     // "<setting-name>{<predicate>}"
159     // strings are parsed by the current OptionValueProperties subclass
160     // to mean whatever they want to. For instance a subclass of
161     // OptionValueProperties for a lldb_private::Target might implement:
162     // "target.run-args{arch==i386}"   -- only set run args if the arch is
163     // i386
164     // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the
165     // path matches
166     // "target.run-args{basename==test&&arch==x86_64}" -- only set run args
167     // if executable basename is "test" and arch is "x86_64"
168     if (sub_name[1]) {
169       llvm::StringRef predicate_start = sub_name.drop_front();
170       size_t pos = predicate_start.find_first_of('}');
171       if (pos != llvm::StringRef::npos) {
172         auto predicate = predicate_start.take_front(pos);
173         auto rest = predicate_start.drop_front(pos);
174         if (PredicateMatches(exe_ctx, predicate)) {
175           if (!rest.empty()) {
176             // Still more subvalue string to evaluate
177             return value_sp->GetSubValue(exe_ctx, rest,
178                                           will_modify, error);
179           } else {
180             // We have a match!
181             break;
182           }
183         }
184       }
185     }
186     // Predicate didn't match or wasn't correctly formed
187     value_sp.reset();
188     break;
189
190   case '[':
191     // Array or dictionary access for subvalues like:
192     // "[12]"       -- access 12th array element
193     // "['hello']"  -- dictionary access of key named hello
194     return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
195
196   default:
197     value_sp.reset();
198     break;
199   }
200   return value_sp;
201 }
202
203 Error OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
204                                          VarSetOperationType op,
205                                          llvm::StringRef name, llvm::StringRef value) {
206   Error error;
207   const bool will_modify = true;
208   lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
209   if (value_sp)
210     error = value_sp->SetValueFromString(value, op);
211   else {
212     if (error.AsCString() == nullptr)
213       error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
214   }
215   return error;
216 }
217
218 uint32_t
219 OptionValueProperties::GetPropertyIndex(const ConstString &name) const {
220   return m_name_to_index.Find(name.GetStringRef(), SIZE_MAX);
221 }
222
223 const Property *
224 OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
225                                    bool will_modify,
226                                    const ConstString &name) const {
227   return GetPropertyAtIndex(
228       exe_ctx, will_modify,
229       m_name_to_index.Find(name.GetStringRef(), SIZE_MAX));
230 }
231
232 const Property *OptionValueProperties::GetPropertyAtIndex(
233     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
234   return ProtectedGetPropertyAtIndex(idx);
235 }
236
237 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
238     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
239   const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx);
240   if (setting)
241     return setting->GetValue();
242   return OptionValueSP();
243 }
244
245 OptionValuePathMappings *
246 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
247     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
248   OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
249   if (value_sp)
250     return value_sp->GetAsPathMappings();
251   return nullptr;
252 }
253
254 OptionValueFileSpecList *
255 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
256     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
257   OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
258   if (value_sp)
259     return value_sp->GetAsFileSpecList();
260   return nullptr;
261 }
262
263 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
264     const ExecutionContext *exe_ctx, uint32_t idx) const {
265   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
266   if (property)
267     return property->GetValue()->GetAsArch();
268   return nullptr;
269 }
270
271 OptionValueLanguage *
272 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
273     const ExecutionContext *exe_ctx, uint32_t idx) const {
274   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
275   if (property)
276     return property->GetValue()->GetAsLanguage();
277   return nullptr;
278 }
279
280 bool OptionValueProperties::GetPropertyAtIndexAsArgs(
281     const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const {
282   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
283   if (property) {
284     OptionValue *value = property->GetValue().get();
285     if (value) {
286       const OptionValueArray *array = value->GetAsArray();
287       if (array)
288         return array->GetArgs(args);
289       else {
290         const OptionValueDictionary *dict = value->GetAsDictionary();
291         if (dict)
292           return dict->GetArgs(args);
293       }
294     }
295   }
296   return false;
297 }
298
299 bool OptionValueProperties::SetPropertyAtIndexFromArgs(
300     const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
301   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
302   if (property) {
303     OptionValue *value = property->GetValue().get();
304     if (value) {
305       OptionValueArray *array = value->GetAsArray();
306       if (array)
307         return array->SetArgs(args, eVarSetOperationAssign).Success();
308       else {
309         OptionValueDictionary *dict = value->GetAsDictionary();
310         if (dict)
311           return dict->SetArgs(args, eVarSetOperationAssign).Success();
312       }
313     }
314   }
315   return false;
316 }
317
318 bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
319     const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
320   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
321   if (property) {
322     OptionValue *value = property->GetValue().get();
323     if (value)
324       return value->GetBooleanValue(fail_value);
325   }
326   return fail_value;
327 }
328
329 bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
330     const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
331   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
332   if (property) {
333     OptionValue *value = property->GetValue().get();
334     if (value) {
335       value->SetBooleanValue(new_value);
336       return true;
337     }
338   }
339   return false;
340 }
341
342 OptionValueDictionary *
343 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
344     const ExecutionContext *exe_ctx, uint32_t idx) const {
345   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
346   if (property)
347     return property->GetValue()->GetAsDictionary();
348   return nullptr;
349 }
350
351 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
352     const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
353   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
354   if (property) {
355     OptionValue *value = property->GetValue().get();
356     if (value)
357       return value->GetEnumerationValue(fail_value);
358   }
359   return fail_value;
360 }
361
362 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
363     const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
364   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
365   if (property) {
366     OptionValue *value = property->GetValue().get();
367     if (value)
368       return value->SetEnumerationValue(new_value);
369   }
370   return false;
371 }
372
373 const FormatEntity::Entry *
374 OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
375     const ExecutionContext *exe_ctx, uint32_t idx) {
376   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
377   if (property) {
378     OptionValue *value = property->GetValue().get();
379     if (value)
380       return value->GetFormatEntity();
381   }
382   return nullptr;
383 }
384
385 OptionValueFileSpec *
386 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
387     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
388   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
389   if (property) {
390     OptionValue *value = property->GetValue().get();
391     if (value)
392       return value->GetAsFileSpec();
393   }
394   return nullptr;
395 }
396
397 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
398     const ExecutionContext *exe_ctx, uint32_t idx) const {
399   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
400   if (property) {
401     OptionValue *value = property->GetValue().get();
402     if (value)
403       return value->GetFileSpecValue();
404   }
405   return FileSpec();
406 }
407
408 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
409     const ExecutionContext *exe_ctx, uint32_t idx,
410     const FileSpec &new_file_spec) {
411   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
412   if (property) {
413     OptionValue *value = property->GetValue().get();
414     if (value)
415       return value->SetFileSpecValue(new_file_spec);
416   }
417   return false;
418 }
419
420 const RegularExpression *
421 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
422     const ExecutionContext *exe_ctx, uint32_t idx) const {
423   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
424   if (property) {
425     OptionValue *value = property->GetValue().get();
426     if (value)
427       return value->GetRegexValue();
428   }
429   return nullptr;
430 }
431
432 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
433     const ExecutionContext *exe_ctx, uint32_t idx) const {
434   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
435   if (property) {
436     OptionValue *value = property->GetValue().get();
437     if (value)
438       return value->GetAsSInt64();
439   }
440   return nullptr;
441 }
442
443 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
444     const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
445   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
446   if (property) {
447     OptionValue *value = property->GetValue().get();
448     if (value)
449       return value->GetSInt64Value(fail_value);
450   }
451   return fail_value;
452 }
453
454 bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
455     const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
456   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
457   if (property) {
458     OptionValue *value = property->GetValue().get();
459     if (value)
460       return value->SetSInt64Value(new_value);
461   }
462   return false;
463 }
464
465 llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
466     const ExecutionContext *exe_ctx, uint32_t idx,
467     llvm::StringRef fail_value) const {
468   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
469   if (property) {
470     OptionValue *value = property->GetValue().get();
471     if (value)
472       return value->GetStringValue(fail_value);
473   }
474   return fail_value;
475 }
476
477 bool OptionValueProperties::SetPropertyAtIndexAsString(
478     const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
479   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
480   if (property) {
481     OptionValue *value = property->GetValue().get();
482     if (value)
483       return value->SetStringValue(new_value);
484   }
485   return false;
486 }
487
488 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
489     const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
490   OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx));
491   if (value_sp)
492     return value_sp->GetAsString();
493   return nullptr;
494 }
495
496 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
497     const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
498   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
499   if (property) {
500     OptionValue *value = property->GetValue().get();
501     if (value)
502       return value->GetUInt64Value(fail_value);
503   }
504   return fail_value;
505 }
506
507 bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
508     const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
509   const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
510   if (property) {
511     OptionValue *value = property->GetValue().get();
512     if (value)
513       return value->SetUInt64Value(new_value);
514   }
515   return false;
516 }
517
518 bool OptionValueProperties::Clear() {
519   const size_t num_properties = m_properties.size();
520   for (size_t i = 0; i < num_properties; ++i)
521     m_properties[i].GetValue()->Clear();
522   return true;
523 }
524
525 Error OptionValueProperties::SetValueFromString(llvm::StringRef value,
526                                                 VarSetOperationType op) {
527   Error error;
528
529   //    Args args(value_cstr);
530   //    const size_t argc = args.GetArgumentCount();
531   switch (op) {
532   case eVarSetOperationClear:
533     Clear();
534     break;
535
536   case eVarSetOperationReplace:
537   case eVarSetOperationAssign:
538   case eVarSetOperationRemove:
539   case eVarSetOperationInsertBefore:
540   case eVarSetOperationInsertAfter:
541   case eVarSetOperationAppend:
542   case eVarSetOperationInvalid:
543     error = OptionValue::SetValueFromString(value, op);
544     break;
545   }
546
547   return error;
548 }
549
550 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
551                                       Stream &strm, uint32_t dump_mask) {
552   const size_t num_properties = m_properties.size();
553   for (size_t i = 0; i < num_properties; ++i) {
554     const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
555     if (property) {
556       OptionValue *option_value = property->GetValue().get();
557       assert(option_value);
558       const bool transparent_value = option_value->ValueIsTransparent();
559       property->Dump(exe_ctx, strm, dump_mask);
560       if (!transparent_value)
561         strm.EOL();
562     }
563   }
564 }
565
566 Error OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
567                                                Stream &strm,
568                                                llvm::StringRef property_path,
569                                                uint32_t dump_mask) {
570   Error error;
571   const bool will_modify = false;
572   lldb::OptionValueSP value_sp(
573       GetSubValue(exe_ctx, property_path, will_modify, error));
574   if (value_sp) {
575     if (!value_sp->ValueIsTransparent()) {
576       if (dump_mask & eDumpOptionName)
577         strm.PutCString(property_path);
578       if (dump_mask & ~eDumpOptionName)
579         strm.PutChar(' ');
580     }
581     value_sp->DumpValue(exe_ctx, strm, dump_mask);
582   }
583   return error;
584 }
585
586 lldb::OptionValueSP OptionValueProperties::DeepCopy() const {
587   llvm_unreachable("this shouldn't happen");
588 }
589
590 const Property *OptionValueProperties::GetPropertyAtPath(
591     const ExecutionContext *exe_ctx, bool will_modify, llvm::StringRef name) const {
592   const Property *property = nullptr;
593   if (name.empty())
594     return nullptr;
595   llvm::StringRef sub_name;
596   ConstString key;
597   size_t key_len = name.find_first_of(".[{");
598
599   if (key_len != llvm::StringRef::npos) {
600     key.SetString(name.take_front(key_len));
601     sub_name = name.drop_front(key_len);
602   } else
603     key.SetString(name);
604
605   property = GetProperty(exe_ctx, will_modify, key);
606   if (sub_name.empty() || !property)
607     return property;
608
609   if (sub_name[0] == '.') {
610     OptionValueProperties *sub_properties =
611         property->GetValue()->GetAsProperties();
612     if (sub_properties)
613       return sub_properties->GetPropertyAtPath(exe_ctx, will_modify,
614                                                 sub_name.drop_front());
615   }
616   return nullptr;
617 }
618
619 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
620                                                 Stream &strm) const {
621   size_t max_name_len = 0;
622   const size_t num_properties = m_properties.size();
623   for (size_t i = 0; i < num_properties; ++i) {
624     const Property *property = ProtectedGetPropertyAtIndex(i);
625     if (property)
626       max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
627   }
628   for (size_t i = 0; i < num_properties; ++i) {
629     const Property *property = ProtectedGetPropertyAtIndex(i);
630     if (property)
631       property->DumpDescription(interpreter, strm, max_name_len, false);
632   }
633 }
634
635 void OptionValueProperties::Apropos(
636     llvm::StringRef keyword,
637     std::vector<const Property *> &matching_properties) const {
638   const size_t num_properties = m_properties.size();
639   StreamString strm;
640   for (size_t i = 0; i < num_properties; ++i) {
641     const Property *property = ProtectedGetPropertyAtIndex(i);
642     if (property) {
643       const OptionValueProperties *properties =
644           property->GetValue()->GetAsProperties();
645       if (properties) {
646         properties->Apropos(keyword, matching_properties);
647       } else {
648         bool match = false;
649         llvm::StringRef name = property->GetName();
650         if (name.contains_lower(keyword))
651           match = true;
652         else {
653           llvm::StringRef desc = property->GetDescription();
654           if (desc.contains_lower(keyword))
655             match = true;
656         }
657         if (match) {
658           matching_properties.push_back(property);
659         }
660       }
661     }
662   }
663 }
664
665 lldb::OptionValuePropertiesSP
666 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
667                                       const ConstString &name) {
668   lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
669   if (option_value_sp) {
670     OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
671     if (ov_properties)
672       return ov_properties->shared_from_this();
673   }
674   return lldb::OptionValuePropertiesSP();
675 }