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