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