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