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