1 //====-- UserSettingsController.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 <string.h>
11 #include <algorithm>
12 
13 #include "lldb/Core/UserSettingsController.h"
14 #include "lldb/Core/Error.h"
15 #include "lldb/Core/Stream.h"
16 #include "lldb/Core/StreamString.h"
17 #include "lldb/Interpreter/CommandInterpreter.h"
18 
19 using namespace lldb_private;
20 
21 UserSettingsController::UserSettingsController (const char *level_name,
22                                                 const lldb::UserSettingsControllerSP &parent) :
23     m_default_settings (),
24     m_settings (),
25     m_children (),
26     m_pending_settings (),
27     m_live_settings (),
28     m_children_mutex (Mutex::eMutexTypeNormal),
29     m_pending_settings_mutex (Mutex::eMutexTypeRecursive),
30     m_live_settings_mutex (Mutex::eMutexTypeRecursive)
31 {
32     m_settings.parent = parent;
33     m_settings.level_name.SetCString (level_name);
34 }
35 
36 UserSettingsController::~UserSettingsController ()
37 {
38     m_live_settings.clear();
39 }
40 
41 bool
42 UserSettingsController::SetGlobalVariable
43 (
44     const ConstString &var_name,
45     const char *index_value,
46     const char *value,
47     const SettingEntry &entry,
48     const lldb::VarSetOperationType op,
49     Error &err
50 )
51 {
52     err.SetErrorString ("UserSettingsController has no global settings");
53     return false;
54 }
55 
56 bool
57 UserSettingsController::GetGlobalVariable
58 (
59     const ConstString &var_name,
60     StringList &value,
61     Error &err
62 )
63 {
64     return false;
65 }
66 
67 bool
68 UserSettingsController::InitializeSettingsController (lldb::UserSettingsControllerSP &controller_sp,
69                                                       SettingEntry *global_settings,
70                                                       SettingEntry *instance_settings)
71 {
72     const lldb::UserSettingsControllerSP &parent = controller_sp->GetParent ();
73     if (parent)
74     parent->RegisterChild (controller_sp);
75 
76     controller_sp->CreateSettingsVector (global_settings, true);
77     controller_sp->CreateSettingsVector (instance_settings, false);
78 
79     controller_sp->InitializeGlobalVariables ();
80     controller_sp->CreateDefaultInstanceSettings ();
81 
82     return true;
83 }
84 
85 void
86 UserSettingsController::FinalizeSettingsController (lldb::UserSettingsControllerSP &controller_sp)
87 {
88     const lldb::UserSettingsControllerSP &parent = controller_sp->GetParent ();
89     if (parent)
90         parent->RemoveChild (controller_sp);
91 }
92 
93 void
94 UserSettingsController::InitializeGlobalVariables ()
95 {
96     int num_entries;
97     const char *prefix = GetLevelName().AsCString();
98 
99     num_entries = m_settings.global_settings.size();
100     for (int i = 0; i < num_entries; ++i)
101     {
102         SettingEntry &entry = m_settings.global_settings[i];
103         if (entry.default_value != NULL)
104         {
105             StreamString full_name;
106             if (prefix[0] != '\0')
107                 full_name.Printf ("%s.%s", prefix, entry.var_name);
108             else
109                 full_name.Printf ("%s", entry.var_name);
110             SetVariable (full_name.GetData(), entry.default_value, lldb::eVarSetOperationAssign, false, "");
111         }
112         else if ((entry.var_type == lldb::eSetVarTypeEnum)
113                  && (entry.enum_values != NULL))
114         {
115             StreamString full_name;
116             if (prefix[0] != '\0')
117                 full_name.Printf ("%s.%s", prefix, entry.var_name);
118             else
119                 full_name.Printf ("%s", entry.var_name);
120             SetVariable (full_name.GetData(), entry.enum_values[0].string_value, lldb::eVarSetOperationAssign,
121                          false, "");
122         }
123     }
124 }
125 
126 const lldb::UserSettingsControllerSP &
127 UserSettingsController::GetParent ()
128 {
129     return m_settings.parent;
130 }
131 
132 void
133 UserSettingsController::RegisterChild (const lldb::UserSettingsControllerSP &child)
134 {
135     Mutex::Locker locker (m_children_mutex);
136 
137     // Verify child is not already in m_children.
138     size_t num_children = m_children.size();
139     bool found = false;
140     for (size_t i = 0; i < num_children; ++i)
141       {
142 	if (m_children[i].get() == child.get())
143     	    found = true;
144       }
145 
146     // Add child to m_children.
147     if (! found)
148         m_children.push_back (child);
149 }
150 
151 const ConstString &
152 UserSettingsController::GetLevelName ()
153 {
154     return m_settings.level_name;
155 }
156 
157 size_t
158 UserSettingsController::GetNumChildren ()
159 {
160     return m_children.size();
161 }
162 
163 const lldb::UserSettingsControllerSP
164 UserSettingsController::GetChildAtIndex (size_t index)
165 {
166     if (index < m_children.size())
167         return m_children[index];
168 
169     lldb::UserSettingsControllerSP dummy_value;
170 
171     return dummy_value;
172 }
173 
174 const SettingEntry *
175 UserSettingsController::GetGlobalEntry (const ConstString &var_name)
176 {
177 
178     for (int i = 0; i < m_settings.global_settings.size(); ++i)
179     {
180         SettingEntry &entry = m_settings.global_settings[i];
181         ConstString entry_name (entry.var_name);
182         if (entry_name == var_name)
183             return &entry;
184     }
185 
186     return NULL;
187 }
188 
189 const SettingEntry *
190 UserSettingsController::GetInstanceEntry (const ConstString &const_var_name)
191 {
192 
193     for (int i = 0; i < m_settings.instance_settings.size(); ++i)
194     {
195         SettingEntry &entry = m_settings.instance_settings[i];
196         ConstString entry_name (entry.var_name);
197         if (entry_name == const_var_name)
198             return &entry;
199     }
200 
201     return NULL;
202 }
203 
204 void
205 UserSettingsController::BuildParentPrefix (std::string &parent_prefix)
206 {
207     lldb::UserSettingsControllerSP parent = GetParent();
208     if (parent.get() != NULL)
209     {
210         parent->BuildParentPrefix (parent_prefix);
211         if (parent_prefix.length() > 0)
212             parent_prefix.append (".");
213     }
214     parent_prefix.append (GetLevelName().AsCString());
215 }
216 
217 void
218 UserSettingsController::RemoveChild (const lldb::UserSettingsControllerSP &child)
219 {
220     Mutex::Locker locker (m_children_mutex);
221     std::vector<lldb::UserSettingsControllerSP>::iterator pos, end = m_children.end();
222 
223    for (pos = m_children.begin(); pos != end; ++pos)
224    {
225       lldb::UserSettingsControllerSP entry = *pos;
226       if (entry == child)
227       {
228           m_children.erase (pos);
229           break;
230       }
231    }
232 }
233 
234 Error
235 UserSettingsController::SetVariable (const char *full_dot_name,
236                                      const char *value,
237                                      const lldb::VarSetOperationType op,
238                                      const bool override,
239                                      const char *debugger_instance_name,
240                                      const char *index_value)
241 {
242     Error err;
243     ConstString const_var_name;
244     const ConstString &default_name = InstanceSettings::GetDefaultName();
245 
246     Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
247     int num_pieces = names.GetArgumentCount();
248 
249     if (num_pieces < 1)
250     {
251         err.SetErrorStringWithFormat ("'%s' is not a valid variable name; cannot assign value.\n", full_dot_name);
252         return err;
253     }
254 
255     ConstString prefix (names.GetArgumentAtIndex (0));
256 
257     if ((prefix == m_settings.level_name)
258         || (m_settings.level_name.GetLength() == 0))
259     {
260 
261         if (prefix == m_settings.level_name)
262         {
263             names.Shift ();
264             num_pieces = names.GetArgumentCount();
265         }
266 
267         if (num_pieces == 0)
268         {
269             err.SetErrorString ("No variable name specified; cannot assign value.\n");
270             return err;
271         }
272         else if (num_pieces == 1)
273         {
274 
275             // Must be one of the class-wide settings.
276 
277             const_var_name.SetCString (names.GetArgumentAtIndex (0));
278             const SettingEntry *entry = GetGlobalEntry (const_var_name);
279             if (entry)
280             {
281                 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
282 
283                 if (err.Fail())
284                     return err;
285 
286                 if ((value == NULL || value[0] == '\0')
287                     && (op == lldb::eVarSetOperationAssign))
288                 {
289                     if (entry->var_type != lldb::eSetVarTypeEnum)
290                         value = entry->default_value;
291                     else
292                         value = entry->enum_values[0].string_value;
293                 }
294                 SetGlobalVariable (const_var_name, index_value, value, *entry, op, err);
295             }
296             else
297             {
298                 // MIGHT be instance variable, to be for ALL instances.
299 
300                 entry = GetInstanceEntry (const_var_name);
301                 if (entry == NULL)
302                 {
303                     err.SetErrorStringWithFormat ("Unable to find variable '%s.%s'; cannot assign value.\n",
304                                                   prefix.AsCString(), const_var_name.AsCString());
305                     return err;
306                 }
307                 else
308                 {
309                     UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
310 
311                     if (err.Fail())
312                         return err;
313 
314                     if ((value == NULL || value[0] == '\0')
315                         && (op == lldb::eVarSetOperationAssign))
316                     {
317                         if (entry->var_type != lldb::eSetVarTypeEnum)
318                             value = entry->default_value;
319                         else
320                             value = entry->enum_values[0].string_value;
321                     }
322 
323                     if ((m_settings.level_name.GetLength() > 0)
324                         || strlen (debugger_instance_name) == 0)
325                       {
326                         // Set the default settings
327                         m_default_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
328                                                                             default_name, *entry, op, err, true);
329                       }
330                     else
331                       {
332                         // We're at the Debugger level; find the correct debugger instance and set those settings
333                         StreamString tmp_name;
334                         if (debugger_instance_name[0] != '[')
335                             tmp_name.Printf ("[%s]", debugger_instance_name);
336                         else
337                             tmp_name.Printf ("%s", debugger_instance_name);
338                         ConstString dbg_name (tmp_name.GetData());
339                         InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
340                         if (dbg_settings)
341                             dbg_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value, dbg_name,
342                                                                           *entry, op, err, false);
343                       }
344 
345                     if (override)
346                     {
347                         OverrideAllInstances (const_var_name, value, op, index_value, err);
348 
349                         // Update all pending records as well.
350 //                        std::map<std::string, lldb::InstanceSettingsSP>::iterator pos, end = m_pending_settings.end();
351 //                        for (pos = m_pending_settings.begin(); pos != end; end++)
352 //                        {
353 //                            const ConstString instance_name (pos->first.c_str());
354 //                            lldb::InstanceSettingsSP setting_sp = pos->second;
355 //                            setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
356 //                                                                        instance_name, *entry, op, err, true);
357 //                        }
358                     }
359                 }
360             }
361         }
362         else
363         {
364             // Either a child's setting or an instance setting.
365 
366             if (names.GetArgumentAtIndex(0)[0] == '[')
367             {
368                 // An instance setting.  Supposedly.
369 
370                 ConstString instance_name (names.GetArgumentAtIndex (0));
371 
372                 // First verify that there is only one more name.
373 
374                 names.Shift();
375 
376                 if (names.GetArgumentCount() != 1)
377                 {
378                     err.SetErrorStringWithFormat ("Invalid variable name format '%s'; cannot assign value.\n",
379                                                   full_dot_name);
380                     return err;
381                 }
382 
383                 // Next verify that it is a valid instance setting name.
384 
385                 const_var_name.SetCString (names.GetArgumentAtIndex (0));
386                 const SettingEntry *entry = GetInstanceEntry (const_var_name);
387 
388                 if (entry == NULL)
389                 {
390                     err.SetErrorStringWithFormat ("Unknown instance variable '%s'; cannot assign value.\n",
391                                                   const_var_name.AsCString());
392                     return err;
393                 }
394 
395                 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
396 
397                 if (err.Fail())
398                     return err;
399 
400                 if ((value == NULL || value[0] == '\0')
401                     && (op == lldb::eVarSetOperationAssign))
402                 {
403                     if (entry->var_type != lldb::eSetVarTypeEnum)
404                         value = entry->default_value;
405                     else
406                         value = entry->enum_values[0].string_value;
407                 }
408 
409                 // Now look for existing instance with given instance name; if not found, find or create pending
410                 // setting for instance with given name.
411 
412                 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
413 
414                 if (current_settings != NULL)
415                 {
416                     current_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
417                                                                       instance_name, *entry, op, err, false);
418 
419                 }
420                 else
421                 {
422                     // Instance does not currently exist; make or update a pending setting for it.
423                     lldb::InstanceSettingsSP current_settings_sp = PendingSettingsForInstance (instance_name);
424 
425                     // Now we have a settings record, update it appropriately.
426 
427                     current_settings_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
428                                                                          instance_name, *entry, op, err, true);
429 
430                     {   // Scope for mutex.
431                         Mutex::Locker locker (m_pending_settings_mutex);
432                         m_pending_settings[instance_name.AsCString()] = current_settings_sp;
433                     }
434 
435                     if (override)
436                     {
437                         OverrideAllInstances (const_var_name, value, op, index_value, err);
438 
439                         // Update all pending records as well.
440                         std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
441                         std::map<std::string, lldb::InstanceSettingsSP>::iterator end = m_pending_settings.end();
442                         for (pos = m_pending_settings.begin(); pos != end; end++)
443                         {
444                             const ConstString tmp_inst_name (pos->first.c_str());
445                             lldb::InstanceSettingsSP setting_sp = pos->second;
446                             setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
447                                                                         tmp_inst_name, *entry, op, err, true);
448                         }
449                     }
450                 }
451             }
452             else
453             {
454                 // A child setting.
455                 lldb::UserSettingsControllerSP child;
456                 ConstString child_prefix (names.GetArgumentAtIndex (0));
457                 int num_children = GetNumChildren();
458                 bool found = false;
459                 for (int i = 0; i < num_children && !found; ++i)
460                 {
461                     child = GetChildAtIndex (i);
462                     ConstString current_prefix = child->GetLevelName();
463                     if (current_prefix == child_prefix)
464                     {
465                         found = true;
466                         std::string new_name;
467                         for (int j = 0; j < names.GetArgumentCount(); ++j)
468                         {
469                             if (j > 0)
470                                 new_name += '.';
471                             new_name += names.GetArgumentAtIndex (j);
472                         }
473                         return child->SetVariable (new_name.c_str(), value, op, override, debugger_instance_name,
474                                                    index_value);
475                     }
476                 }
477                 if (!found)
478                 {
479                     err.SetErrorStringWithFormat ("Unable to find variable '%s'; cannot assign value.\n",
480                                                   full_dot_name);
481                     return err;
482                 }
483             }
484         }
485     }
486     else
487     {
488         err.SetErrorStringWithFormat ("'%s' is not a valid level name; was expecting '%s'. Cannot assign value.\n",
489                                       prefix.AsCString(), m_settings.level_name.AsCString());
490     }
491 
492     return err;
493 }
494 
495 StringList
496 UserSettingsController::GetVariable
497 (
498     const char *full_dot_name,
499     lldb::SettableVariableType &var_type,
500     const char *debugger_instance_name,
501     Error &err
502 )
503 {
504     Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
505     ConstString const_var_name;
506     StringList value;
507 
508     int num_pieces = names.GetArgumentCount();
509 
510     ConstString prefix (names.GetArgumentAtIndex (0));
511     const_var_name.SetCString (names.GetArgumentAtIndex (num_pieces - 1));
512 
513     const SettingEntry *global_entry = GetGlobalEntry (const_var_name);
514     const SettingEntry *instance_entry = GetInstanceEntry (const_var_name);
515 
516     if ((prefix != m_settings.level_name)
517         && (m_settings.level_name.GetLength () > 0))
518     {
519         err.SetErrorString ("Invalid variable name");
520         return value;
521     }
522 
523     // prefix name matched; remove it from names.
524     if (m_settings.level_name.GetLength() > 0)
525         names.Shift();
526 
527     // Should we pass this off to a child?  If there is more than one name piece left, and the next name piece
528     // matches a child prefix, then yes.
529 
530     lldb::UserSettingsControllerSP child;
531     if (names.GetArgumentCount() > 1)
532     {
533         ConstString child_prefix (names.GetArgumentAtIndex (0));
534         bool found = false;
535         for (int i = 0; i < m_children.size() && !found; ++i)
536         {
537             if (child_prefix == m_children[i]->GetLevelName())
538             {
539                 found = true;
540                 child = m_children[i];
541                 std::string new_name;
542                 for (int j = 0; j < names.GetArgumentCount(); ++j)
543                 {
544                     if (j > 0)
545                         new_name += '.';
546                     new_name += names.GetArgumentAtIndex (j);
547                 }
548                 return child->GetVariable (new_name.c_str(), var_type, debugger_instance_name, err);
549             }
550         }
551 
552         if (!found)
553         {
554             // Cannot be handled by a child, because name did not match any child prefixes.
555             // Cannot be a class-wide variable because there are too many name pieces.
556 
557             if (instance_entry != NULL)
558             {
559                 var_type = instance_entry->var_type;
560                 ConstString instance_name (names.GetArgumentAtIndex (0));
561                 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
562 
563                 if (current_settings != NULL)
564                 {
565                     current_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
566                 }
567                 else
568                 {
569                     // Look for instance name setting in pending settings.
570 
571                     std::string inst_name_str = instance_name.AsCString();
572                     std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
573 
574                     pos = m_pending_settings.find (inst_name_str);
575                     if (pos != m_pending_settings.end())
576                     {
577                         lldb::InstanceSettingsSP settings_sp = pos->second;
578                         settings_sp->GetInstanceSettingsValue (*instance_entry, const_var_name,  value, &err);
579                     }
580                     else
581                     {
582                         if (m_settings.level_name.GetLength() > 0)
583                         {
584                             // No valid instance name; assume they want the default settings.
585                             m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
586                         }
587                         else
588                         {
589                             // We're at the Debugger level;  use the debugger's instance settings.
590                             StreamString tmp_name;
591                             if (debugger_instance_name[0] != '[')
592                                 tmp_name.Printf ("[%s]", debugger_instance_name);
593                             else
594                                 tmp_name.Printf ("%s", debugger_instance_name);
595                             ConstString dbg_name (debugger_instance_name);
596                             InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
597                             if (dbg_settings)
598                                 dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
599                         }
600                     }
601                 }
602             }
603             else
604                 err.SetErrorString ("Invalid variable name");
605         }
606     }
607     else
608     {
609         // Only one name left.  It must belong to the current level, or be an error.
610         if ((global_entry == NULL)
611             && (instance_entry == NULL))
612         {
613             err.SetErrorString ("Invalid variable name");
614         }
615         else if (global_entry)
616         {
617             var_type = global_entry->var_type;
618             GetGlobalVariable (const_var_name, value, err);
619         }
620         else if (instance_entry)
621         {
622             var_type = instance_entry->var_type;
623             if (m_settings.level_name.GetLength() > 0)
624                 m_default_settings->GetInstanceSettingsValue  (*instance_entry, const_var_name, value, &err);
625             else
626             {
627                 // We're at the Debugger level;  use the debugger's instance settings.
628                 StreamString tmp_name;
629                 if (debugger_instance_name[0] != '[')
630                     tmp_name.Printf ("[%s]", debugger_instance_name);
631                 else
632                     tmp_name.Printf ("%s", debugger_instance_name);
633                 ConstString dbg_name (tmp_name.GetData());
634                 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
635                 if (dbg_settings)
636                     dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value, &err);
637             }
638         }
639     }
640 
641     return value;
642 }
643 
644 void
645 UserSettingsController::RemovePendingSettings (const ConstString &instance_name)
646 {
647     StreamString tmp_name;
648 
649     // Add surrounding brackets to instance name if not already present.
650 
651     if (instance_name.AsCString()[0] != '[')
652         tmp_name.Printf ("[%s]", instance_name.AsCString());
653     else
654         tmp_name.Printf ("%s", instance_name.AsCString());
655 
656     std::string instance_name_str (tmp_name.GetData());
657     std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
658     Mutex::Locker locker (m_pending_settings_mutex);
659 
660     m_pending_settings.erase (instance_name_str);
661 }
662 
663 const lldb::InstanceSettingsSP &
664 UserSettingsController::FindPendingSettings (const ConstString &instance_name)
665 {
666     std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
667     StreamString tmp_name;
668 
669     // Add surrounding brackets to instance name if not already present.
670 
671     if (instance_name.AsCString()[0] != '[')
672         tmp_name.Printf ("[%s]", instance_name.AsCString());
673     else
674         tmp_name.Printf ("%s", instance_name.AsCString());
675 
676     std::string instance_name_str (tmp_name.GetData());  // Need std::string for std::map look-up
677 
678     {   // Scope for mutex.
679         Mutex::Locker locker (m_pending_settings_mutex);
680 
681         pos = m_pending_settings.find (instance_name_str);
682         if (pos != m_pending_settings.end())
683             return pos->second;
684     }
685 
686     return m_default_settings;
687 }
688 
689 void
690 UserSettingsController::CreateDefaultInstanceSettings ()
691 {
692     Error err;
693     const ConstString &default_name = InstanceSettings::GetDefaultName();
694     for (int i = 0; i < m_settings.instance_settings.size(); ++i)
695     {
696         SettingEntry &entry = m_settings.instance_settings[i];
697         ConstString var_name (entry.var_name);
698         const char *value = entry.default_value;
699 
700         if (entry.var_type == lldb::eSetVarTypeEnum)
701             value = entry.enum_values[0].string_value;
702 
703         m_default_settings->UpdateInstanceSettingsVariable (var_name, NULL, value, default_name, entry,
704                                                             lldb::eVarSetOperationAssign, err, true);
705     }
706 }
707 
708 void
709 UserSettingsController::CopyDefaultSettings (const lldb::InstanceSettingsSP &actual_settings,
710                                              const ConstString &instance_name,
711                                              bool pending)
712 {
713     Error err;
714     for (int i = 0; i < m_settings.instance_settings.size(); ++i)
715     {
716         SettingEntry &entry = m_settings.instance_settings[i];
717         ConstString var_name (entry.var_name);
718         StringList value;
719         m_default_settings->GetInstanceSettingsValue (entry, var_name, value, NULL);
720 
721         std::string value_str;
722         if (value.GetSize() == 1)
723             value_str.append (value.GetStringAtIndex (0));
724         else if (value.GetSize() > 1)
725         {
726             for (int j = 0; j < value.GetSize(); ++j)
727             {
728                 if (j > 0)
729                     value_str.append (" ");
730               value_str.append (value.GetStringAtIndex (j));
731             }
732         }
733 
734         actual_settings->UpdateInstanceSettingsVariable (var_name, NULL, value_str.c_str(), instance_name, entry,
735                                                          lldb::eVarSetOperationAssign, err, pending);
736 
737     }
738 }
739 
740 lldb::InstanceSettingsSP
741 UserSettingsController::PendingSettingsForInstance (const ConstString &instance_name)
742 {
743     std::string name_str (instance_name.AsCString());
744     std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
745     Mutex::Locker locker (m_pending_settings_mutex);
746 
747     pos = m_pending_settings.find (name_str);
748     if (pos != m_pending_settings.end())
749     {
750         lldb::InstanceSettingsSP settings_sp = pos->second;
751         return settings_sp;
752     }
753     else
754     {
755         lldb::InstanceSettingsSP new_settings_sp = CreateInstanceSettings (instance_name.AsCString());
756         CopyDefaultSettings (new_settings_sp, instance_name, true);
757         m_pending_settings[name_str] = new_settings_sp;
758         return new_settings_sp;
759     }
760 
761     // Should never reach this line.
762 
763     lldb::InstanceSettingsSP dummy;
764 
765     return dummy;
766 }
767 
768 void
769 UserSettingsController::GetAllDefaultSettingValues (StreamString &result_stream)
770 {
771     std::string parent_prefix;
772     BuildParentPrefix (parent_prefix);
773     const char *prefix = parent_prefix.c_str();
774 
775     for (int i = 0; i < m_settings.instance_settings.size(); ++i)
776     {
777         SettingEntry &entry = m_settings.instance_settings[i];
778         ConstString var_name (entry.var_name);
779         StringList tmp_value;
780         m_default_settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
781 
782         StreamString value_string;
783 
784         if (tmp_value.GetSize() == 1)
785             value_string.Printf ("%s", tmp_value.GetStringAtIndex (0));
786         else
787         {
788             for (int j = 0; j < tmp_value.GetSize(); ++j)
789                 value_string.Printf ("%s ", tmp_value.GetStringAtIndex (j));
790         }
791 
792         if (! parent_prefix.empty())
793             result_stream.Printf ("%s.%s (%s) = '%s'\n", prefix, var_name.AsCString(),
794                                   UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
795     }
796 }
797 
798 void
799 UserSettingsController::GetAllPendingSettingValues (StreamString &result_stream)
800 {
801     std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
802 
803     std::string parent_prefix;
804     BuildParentPrefix (parent_prefix);
805     const char *prefix = parent_prefix.c_str();
806 
807     for (pos = m_pending_settings.begin(); pos != m_pending_settings.end(); ++pos)
808     {
809         std::string tmp_name = pos->first;
810         lldb::InstanceSettingsSP settings_sp = pos->second;
811 
812         const ConstString instance_name (tmp_name.c_str());
813 
814         for (int i = 0; i < m_settings.instance_settings.size(); ++i)
815         {
816             SettingEntry &entry = m_settings.instance_settings[i];
817             ConstString var_name (entry.var_name);
818             StringList tmp_value;
819             settings_sp->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
820 
821             StreamString value_str;
822 
823             if (tmp_value.GetSize() == 0)
824                 value_str.Printf ("");
825             else if (tmp_value.GetSize() == 1)
826                 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
827             else
828             {
829                 for (int j = 0; j < tmp_value.GetSize(); ++j)
830                     value_str.Printf  ("%s ", tmp_value.GetStringAtIndex (j));
831             }
832 
833             if (parent_prefix.length() > 0)
834             {
835                 result_stream.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.AsCString(),
836                                       var_name.AsCString(), UserSettingsController::GetTypeString (entry.var_type),
837                                       value_str.GetData());
838             }
839             else
840             {
841                 result_stream.Printf ("%s (%s) = '%s' [pending]\n", var_name.AsCString(),
842                                       UserSettingsController::GetTypeString (entry.var_type),
843                                       value_str.GetData());
844             }
845         }
846     }
847 }
848 
849 InstanceSettings *
850 UserSettingsController::FindSettingsForInstance (const ConstString &instance_name)
851 {
852     std::string instance_name_str (instance_name.AsCString());
853     std::map<std::string, InstanceSettings *>::iterator pos;
854 
855     pos = m_live_settings.find (instance_name_str);
856     if (pos != m_live_settings.end ())
857       {
858         InstanceSettings *settings = pos->second;
859         return settings;
860       }
861 
862     return NULL;
863 }
864 
865 void
866 UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter,
867                                                       StreamString &result_stream)
868 {
869     std::map<std::string, InstanceSettings *>::iterator pos;
870     std::string parent_prefix;
871     BuildParentPrefix (parent_prefix);
872     const char *prefix = parent_prefix.c_str();
873     StreamString description;
874 
875     for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
876     {
877         std::string instance_name = pos->first;
878         InstanceSettings *settings = pos->second;
879 
880         for (int i = 0; i < m_settings.instance_settings.size(); ++i)
881         {
882             SettingEntry &entry = m_settings.instance_settings[i];
883             const ConstString var_name (entry.var_name);
884             StringList tmp_value;
885             settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
886             StreamString tmp_value_str;
887 
888             if (tmp_value.GetSize() == 0)
889                 tmp_value_str.Printf ("");
890             else if (tmp_value.GetSize() == 1)
891                 tmp_value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
892             else
893             {
894                 for (int j = 0; j < tmp_value.GetSize(); ++j)
895                     tmp_value_str.Printf ("%s ",tmp_value.GetStringAtIndex (j));
896             }
897 
898             description.Clear();
899             if (parent_prefix.length() > 0)
900             {
901                 description.Printf ("%s.%s.%s (%s) = '%s'", prefix, instance_name.c_str(), var_name.AsCString(),
902                                     UserSettingsController::GetTypeString (entry.var_type),
903                                     tmp_value_str.GetData());
904             }
905             else
906             {
907                 description.Printf ("%s (%s) = '%s'", var_name.AsCString(),
908                                     UserSettingsController::GetTypeString (entry.var_type), tmp_value_str.GetData());
909             }
910             result_stream.Printf ("%s\n", description.GetData());
911         }
912     }
913 }
914 
915 void
916 UserSettingsController::OverrideAllInstances (const ConstString &var_name,
917                                               const char *value,
918                                               lldb::VarSetOperationType op,
919                                               const char *index_value,
920                                               Error &err)
921 {
922     std::map<std::string, InstanceSettings *>::iterator pos;
923     StreamString description;
924 
925     for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
926     {
927         InstanceSettings *settings = pos->second;
928         StreamString tmp_name;
929         tmp_name.Printf ("[%s]", settings->GetInstanceName().AsCString());
930         const ConstString instance_name (tmp_name.GetData());
931         const SettingEntry *entry = GetInstanceEntry (var_name);
932         settings->UpdateInstanceSettingsVariable (var_name, index_value, value, instance_name, *entry, op, err, false);
933 
934     }
935 }
936 
937 void
938 UserSettingsController::RegisterInstanceSettings (InstanceSettings *instance_settings)
939 {
940     Mutex::Locker locker (m_live_settings_mutex);
941     StreamString tmp_name;
942     tmp_name.Printf ("[%s]", instance_settings->GetInstanceName().AsCString());
943     const ConstString instance_name (tmp_name.GetData());
944     std::string instance_name_str (instance_name.AsCString());
945     if (instance_name_str.compare (InstanceSettings::GetDefaultName().AsCString()) != 0)
946         m_live_settings[instance_name_str] = instance_settings;
947 }
948 
949 void
950 UserSettingsController::UnregisterInstanceSettings (InstanceSettings *instance)
951 {
952     Mutex::Locker locker (m_live_settings_mutex);
953     StreamString tmp_name;
954     tmp_name.Printf ("[%s]", instance->GetInstanceName().AsCString());
955     std::string instance_name (tmp_name.GetData());
956 
957     std::map <std::string, InstanceSettings *>::iterator pos;
958 
959     pos = m_live_settings.find (instance_name);
960     if (pos != m_live_settings.end())
961         m_live_settings.erase (pos);
962 }
963 
964 void
965 UserSettingsController::CreateSettingsVector (const SettingEntry *table,
966                                               bool global)
967 {
968     int i = 0;
969     while (table[i].var_name != NULL)
970     {
971         const SettingEntry &table_entry = table[i];
972         ConstString const_var_name (table_entry.var_name);
973         SettingEntry new_entry;
974 
975         new_entry = table_entry;
976         new_entry.var_name = const_var_name.AsCString();
977 
978         if (global)
979             m_settings.global_settings.push_back (new_entry);
980         else
981             m_settings.instance_settings.push_back (new_entry);
982 
983         ++i;
984     }
985 }
986 
987 //----------------------------------------------------------------------
988 // UserSettingsController static methods
989 //----------------------------------------------------------------------
990 
991 int
992 FindMaxNameLength (std::vector<SettingEntry> table)
993 {
994     int max_length = 1;
995 
996     for (int i = 0; i < table.size(); ++i)
997     {
998         int len = strlen (table[i].var_name);
999         if (len > max_length)
1000             max_length = len;
1001     }
1002 
1003     return max_length;
1004 }
1005 
1006 const char *
1007 UserSettingsController::GetTypeString (lldb::SettableVariableType var_type)
1008 {
1009     switch (var_type)
1010     {
1011         case lldb::eSetVarTypeInt:
1012             return "int";
1013         case lldb::eSetVarTypeBool:
1014             return "boolean";
1015         case lldb::eSetVarTypeString:
1016             return "string";
1017         case lldb::eSetVarTypeArray:
1018             return "array";
1019         case lldb::eSetVarTypeDictionary:
1020             return "dictionary";
1021         case lldb::eSetVarTypeEnum:
1022             return "enum";
1023         case lldb::eSetVarTypeNone:
1024             return "no type";
1025     }
1026 
1027     return "";
1028 }
1029 
1030 void
1031 UserSettingsController::PrintEnumValues (const lldb::OptionEnumValueElement *enum_values, Stream &str)
1032 {
1033     int i = 0;
1034     while (enum_values[i].string_value != NULL)
1035     {
1036         str.Printf ("%s ", enum_values[i].string_value);
1037         ++i;
1038     }
1039 
1040 }
1041 
1042 void
1043 UserSettingsController::FindAllSettingsDescriptions (CommandInterpreter &interpreter,
1044                                                      lldb::UserSettingsControllerSP root,
1045                                                      std::string &current_prefix,
1046                                                      StreamString &result_stream,
1047                                                      Error &err)
1048 {
1049     // Write out current prefix line.
1050     StreamString prefix_line;
1051     StreamString description;
1052     uint32_t max_len;
1053     int num_entries = root->m_settings.global_settings.size();
1054 
1055     max_len = FindMaxNameLength (root->m_settings.global_settings);
1056 
1057     if (! current_prefix.empty())
1058         result_stream.Printf ("\n'%s' variables:\n\n", current_prefix.c_str());
1059     else
1060         result_stream.Printf ("\nTop level variables:\n\n");
1061 
1062     if (num_entries > 0)
1063     {
1064         // Write out all "global" variables.
1065         for (int i = 0; i < num_entries; ++i)
1066         {
1067             SettingEntry entry = root->m_settings.global_settings[i];
1068             description.Clear();
1069             if (entry.var_type == lldb::eSetVarTypeEnum)
1070             {
1071                 StreamString enum_values_str;
1072                 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1073                 description.Printf ("[static, enum] %s.  Valid values: {%s}  (default: '%s')", entry.description,
1074                                     enum_values_str.GetData(), entry.enum_values[0].string_value);
1075             }
1076             else if (entry.default_value != NULL)
1077                 description.Printf ("[static, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1078                                     entry.description, entry.default_value);
1079 
1080             else
1081                 description.Printf ("[static, %s] %s (default: '')", GetTypeString (entry.var_type),
1082                                     entry.description);
1083             interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1084                                                  max_len);
1085         }
1086     }
1087 
1088     num_entries = root->m_settings.instance_settings.size();
1089     max_len = FindMaxNameLength (root->m_settings.instance_settings);
1090 
1091     if (num_entries > 0)
1092     {
1093         // Write out all instance variables.
1094         for (int i = 0; i < num_entries; ++i)
1095         {
1096             SettingEntry entry = root->m_settings.instance_settings[i];
1097             description.Clear();
1098             if (entry.var_type == lldb::eSetVarTypeEnum)
1099             {
1100                 StreamString enum_values_str;
1101                 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1102                 description.Printf ("[instance, enum] %s.  Valid values: {%s} (default: '%s')", entry.description,
1103                                     enum_values_str.GetData(), entry.enum_values[0].string_value);
1104             }
1105             else if (entry.default_value != NULL)
1106                 description.Printf ("[instance, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1107                                     entry.description, entry.default_value);
1108             else
1109                 description.Printf ("[instance, %s] %s (default: '')", GetTypeString (entry.var_type),
1110                                     entry.description);
1111             interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1112                                                  max_len);
1113         }
1114 
1115     }
1116 
1117     // Now, recurse across all children.
1118     int num_children = root->GetNumChildren();
1119     for (int i = 0; i < num_children; ++i)
1120     {
1121         lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1122 
1123         if (child)
1124         {
1125             ConstString child_prefix = child->GetLevelName();
1126             StreamString new_prefix;
1127             if (! current_prefix.empty())
1128                 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1129             else
1130                 new_prefix.Printf ("%s", child_prefix.AsCString());
1131             std::string new_prefix_str = new_prefix.GetData();
1132             UserSettingsController::FindAllSettingsDescriptions (interpreter, child, new_prefix_str, result_stream,
1133                                                                  err);
1134         }
1135     }
1136 }
1137 
1138 void
1139 UserSettingsController::FindSettingsDescriptions (CommandInterpreter &interpreter,
1140                                                   lldb::UserSettingsControllerSP root,
1141                                                   std::string &current_prefix,
1142                                                   const char *search_name,
1143                                                   StreamString &result_stream,
1144                                                   Error &err)
1145 {
1146     Args names = UserSettingsController::BreakNameIntoPieces (search_name);
1147     int num_pieces = names.GetArgumentCount ();
1148 
1149     if (num_pieces == 0)
1150         return;
1151 
1152     if (root->GetLevelName().GetLength() > 0)
1153     {
1154         ConstString prefix (names.GetArgumentAtIndex (0));
1155         if (prefix != root->GetLevelName())
1156         {
1157             std::string parent_prefix;
1158             root->BuildParentPrefix (parent_prefix);
1159             err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(),
1160                                           prefix.AsCString());
1161             return;
1162         }
1163         else
1164         {
1165             names.Shift();
1166             --num_pieces;
1167         }
1168     }
1169 
1170     // If there's nothing left then dump all global and instance descriptions for this root.
1171     if (num_pieces == 0)
1172     {
1173         StreamString prefix_line;
1174         StreamString description;
1175         uint32_t max_len;
1176         int num_entries = root->m_settings.global_settings.size();
1177 
1178         max_len = FindMaxNameLength (root->m_settings.global_settings);
1179 
1180         result_stream.Printf ("\n'%s' variables:\n\n", search_name);
1181 
1182         if (num_entries > 0)
1183         {
1184             // Write out all "global" variables.
1185             for (int i = 0; i < num_entries; ++i)
1186             {
1187                 SettingEntry entry = root->m_settings.global_settings[i];
1188                 description.Clear();
1189                 if (entry.var_type == lldb::eSetVarTypeEnum)
1190                 {
1191                     StreamString enum_values_str;
1192                     UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1193                     description.Printf ("[static, enum] %s.  Valid values: {%s}  (default: '%s')", entry.description,
1194                                         enum_values_str.GetData(), entry.enum_values[0].string_value);
1195                 }
1196                 else if (entry.default_value != NULL)
1197                     description.Printf ("[static, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1198                                         entry.description, entry.default_value);
1199                 else
1200                     description.Printf ("[static, %s] %s (default: '')", GetTypeString (entry.var_type),
1201                                         entry.description);
1202                 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1203                                                      max_len);
1204             }
1205         }
1206 
1207         num_entries = root->m_settings.instance_settings.size();
1208         max_len = FindMaxNameLength (root->m_settings.instance_settings);
1209 
1210         if (num_entries > 0)
1211         {
1212             // Write out all instance variables.
1213             for (int i = 0; i < num_entries; ++i)
1214             {
1215                 SettingEntry entry = root->m_settings.instance_settings[i];
1216                 description.Clear();
1217                 if (entry.var_type == lldb::eSetVarTypeEnum)
1218                 {
1219                     StreamString enum_values_str;
1220                     UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1221                     description.Printf ("[instance, enum] %s.  Valid values: {%s} (default: '%s')", entry.description,
1222                                         enum_values_str.GetData(), entry.enum_values[0].string_value);
1223                 }
1224                 else if (entry.default_value != NULL)
1225                     description.Printf ("[instance, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1226                                         entry.description, entry.default_value);
1227                 else
1228                     description.Printf ("[instance, %s] %s (default: '')", GetTypeString (entry.var_type),
1229                                         entry.description);
1230                 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1231                                                      max_len);
1232             }
1233         }
1234     }
1235     else if (num_pieces == 1)
1236     {
1237         ConstString var_name (names.GetArgumentAtIndex (0));
1238         bool is_global = false;
1239 
1240         const SettingEntry *setting_entry = root->GetGlobalEntry (var_name);
1241 
1242         if (setting_entry == NULL)
1243             setting_entry = root->GetInstanceEntry (var_name);
1244         else
1245             is_global = true;
1246 
1247         // Check to see if it is a global or instance variable name.
1248         if (setting_entry != NULL)
1249         {
1250             StreamString description;
1251             if (setting_entry->var_type == lldb::eSetVarTypeEnum)
1252             {
1253                 StreamString enum_values_str;
1254                 UserSettingsController::PrintEnumValues (setting_entry->enum_values, enum_values_str);
1255                 description.Printf ("[%s, enum] %s.  Valid values: {%s}  (default: '%s')",
1256                                     (is_global ? "static" : "instance"),
1257                                     setting_entry->description,
1258                                     enum_values_str.GetData(), setting_entry->enum_values[0].string_value);
1259             }
1260             else if (setting_entry->default_value != NULL)
1261                 description.Printf ("[%s, %s] %s (default: '%s')",
1262                                     (is_global ? "static" : "instance"),
1263                                     GetTypeString (setting_entry->var_type),
1264                                     setting_entry->description, setting_entry->default_value);
1265             else
1266                 description.Printf ("[%s, %s] %s (default: '')",
1267                                     (is_global ? "static" : "instance"),
1268                                     GetTypeString (setting_entry->var_type),
1269                                     setting_entry->description);
1270             interpreter.OutputFormattedHelpText (result_stream, setting_entry->var_name, "--", description.GetData(),
1271                                                  var_name.GetLength());
1272         }
1273         else
1274         {
1275             // It must be a child name.
1276             int num_children = root->GetNumChildren();
1277             bool found = false;
1278             for (int i = 0; i < num_children && !found; ++i)
1279             {
1280                 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1281                 if (child)
1282                 {
1283                     ConstString child_prefix = child->GetLevelName();
1284                     if (child_prefix == var_name)
1285                     {
1286                         found = true;
1287                         UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix,
1288                                                                           var_name.AsCString(), result_stream, err);
1289                     }
1290                 }
1291             }
1292             if (!found)
1293             {
1294                 std::string parent_prefix;
1295                 root->BuildParentPrefix (parent_prefix);
1296                 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1297                 return;
1298             }
1299         }
1300     }
1301     else
1302     {
1303         // It must be a child name; find the child and call this function recursively on child.
1304         ConstString child_name (names.GetArgumentAtIndex (0));
1305 
1306         StreamString rest_of_search_name;
1307         for (int i = 0; i < num_pieces; ++i)
1308         {
1309             rest_of_search_name.Printf ("%s", names.GetArgumentAtIndex (i));
1310             if ((i + 1) < num_pieces)
1311                 rest_of_search_name.Printf (".");
1312         }
1313 
1314         int num_children = root->GetNumChildren();
1315         bool found = false;
1316         for (int i = 0; i < num_children && !found; ++i)
1317         {
1318             lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1319             if (child)
1320             {
1321                 ConstString child_prefix = child->GetLevelName();
1322                 if (child_prefix == child_name)
1323                 {
1324                     found = true;
1325                     UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix,
1326                                                                       rest_of_search_name.GetData(), result_stream,
1327                                                                       err);
1328                 }
1329             }
1330         }
1331         if (!found)
1332         {
1333             std::string parent_prefix;
1334             root->BuildParentPrefix (parent_prefix);
1335             err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1336             return;
1337         }
1338     }
1339 }
1340 
1341 void
1342 UserSettingsController::GetAllVariableValues (CommandInterpreter &interpreter,
1343                                               lldb::UserSettingsControllerSP root,
1344                                               std::string &current_prefix,
1345                                               StreamString &result_stream,
1346                                               Error &err)
1347 {
1348     StreamString description;
1349     int num_entries = root->m_settings.global_settings.size();
1350     lldb::SettableVariableType var_type;
1351 
1352 
1353     for (int i = 0; i < num_entries; ++i)
1354     {
1355         StreamString full_var_name;
1356         SettingEntry entry = root->m_settings.global_settings[i];
1357         if (! current_prefix.empty())
1358             full_var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name);
1359         else
1360             full_var_name.Printf ("%s", entry.var_name);
1361         StringList value = root->GetVariable (full_var_name.GetData(), var_type,
1362                                               interpreter.GetDebugger().GetInstanceName().AsCString(), err);
1363         description.Clear();
1364         if (value.GetSize() == 1)
1365             description.Printf ("%s (%s) = '%s'", full_var_name.GetData(), GetTypeString (entry.var_type),
1366                                 value.GetStringAtIndex (0));
1367         else
1368         {
1369             description.Printf ("%s (%s) = '", full_var_name.GetData(), GetTypeString (entry.var_type));
1370             for (int j = 0; j < value.GetSize(); ++j)
1371                 description.Printf ("%s ", value.GetStringAtIndex (j));
1372             description.Printf ("'");
1373         }
1374 
1375         result_stream.Printf ("%s\n", description.GetData());
1376     }
1377 
1378     root->GetAllInstanceVariableValues (interpreter, result_stream);
1379     root->GetAllPendingSettingValues (result_stream);
1380     if (root->GetLevelName().GetLength() > 0)               // Don't bother with default values for Debugger level.
1381          root->GetAllDefaultSettingValues (result_stream);
1382 
1383 
1384     // Now, recurse across all children.
1385     int num_children = root->GetNumChildren();
1386     for (int i = 0; i < num_children; ++i)
1387     {
1388         lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1389 
1390         if (child)
1391         {
1392             ConstString child_prefix = child->GetLevelName();
1393             StreamString new_prefix;
1394             if (! current_prefix.empty())
1395                 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1396             else
1397                 new_prefix.Printf ("%s", child_prefix.AsCString());
1398             std::string new_prefix_str = new_prefix.GetData();
1399             UserSettingsController::GetAllVariableValues (interpreter, child, new_prefix_str, result_stream,
1400                                                           err);
1401         }
1402     }
1403 
1404 }
1405 
1406 Args
1407 UserSettingsController::BreakNameIntoPieces (const char *full_dot_name)
1408 {
1409     Args return_value;
1410     std::string name_string (full_dot_name);
1411     bool done = false;
1412 
1413     std::string piece;
1414     std::string remainder (full_dot_name);
1415 
1416     while (!done)
1417     {
1418         size_t idx = remainder.find_first_of ('.');
1419         piece = remainder.substr (0, idx);
1420         return_value.AppendArgument (piece.c_str());
1421         if (idx != std::string::npos)
1422             remainder = remainder.substr (idx+1);
1423         else
1424             done = true;
1425     }
1426 
1427     return return_value;
1428 }
1429 
1430 bool
1431 UserSettingsController::IsLiveInstance (const std::string &instance_name)
1432 {
1433     std::map<std::string, InstanceSettings *>::iterator pos;
1434 
1435     pos = m_live_settings.find (instance_name);
1436     if (pos != m_live_settings.end())
1437         return true;
1438 
1439     return false;
1440 }
1441 
1442 int
1443 UserSettingsController::CompleteSettingsValue (lldb::UserSettingsControllerSP root_settings,
1444                                                const char *full_dot_name,
1445                                                const char *partial_value,
1446                                                bool &word_complete,
1447                                                StringList &matches)
1448 {
1449     Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
1450     int num_pieces = names.GetArgumentCount();
1451     word_complete = true;
1452 
1453     ConstString root_level = root_settings->GetLevelName();
1454     int num_extra_levels = num_pieces - 2;
1455     if ((num_extra_levels > 0)
1456         && root_level.GetLength() > 0)
1457     {
1458         ConstString current_level (names.GetArgumentAtIndex (0));
1459         if (current_level == root_level)
1460         {
1461             names.Shift();
1462             --num_extra_levels;
1463         }
1464         else
1465             return 0;
1466     }
1467 
1468     for (int i = 0; i < num_extra_levels; ++i)
1469     {
1470         ConstString child_level (names.GetArgumentAtIndex (0));
1471         bool found = false;
1472         int num_children = root_settings->GetNumChildren();
1473         for (int j = 0; j < num_children && !found; ++j)
1474         {
1475             if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1476             {
1477                 found = true;
1478                 root_settings = root_settings->GetChildAtIndex (j);
1479                 names.Shift();
1480             }
1481         }
1482         if (!found)
1483             return 0;
1484     }
1485 
1486     if (names.GetArgumentCount() != 2)
1487         return 0;
1488 
1489     std::string next_name (names.GetArgumentAtIndex (0));
1490     int len = next_name.length();
1491     names.Shift();
1492 
1493     if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1494     {
1495         // 'next_name' is instance name.  Instance names are irrelevent here.
1496     }
1497     else
1498     {
1499         // 'next_name' is child name.
1500         bool found = false;
1501         int num_children = root_settings->GetNumChildren();
1502         ConstString child_level (next_name.c_str());
1503         for (int j = 0; j < num_children && !found; ++j)
1504         {
1505             if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1506             {
1507                 found = true;
1508                 root_settings = root_settings->GetChildAtIndex (j);
1509             }
1510         }
1511         if (!found)
1512             return 0;
1513     }
1514 
1515     ConstString var_name (names.GetArgumentAtIndex(0));
1516     const SettingEntry *entry = root_settings->GetGlobalEntry (var_name);
1517     if (entry == NULL)
1518         entry = root_settings->GetInstanceEntry (var_name);
1519 
1520     if (entry == NULL)
1521         return 0;
1522 
1523     if (entry->var_type == lldb::eSetVarTypeBool)
1524         return UserSettingsController::BooleanMatches (partial_value, word_complete, matches);
1525     else if (entry->var_type == lldb::eSetVarTypeEnum)
1526         return UserSettingsController::EnumMatches (partial_value, entry->enum_values, word_complete, matches);
1527     else
1528         return 0;
1529 }
1530 
1531 int
1532 UserSettingsController::BooleanMatches (const char *partial_value,
1533                                         bool &word_complete,
1534                                         StringList &matches)
1535 {
1536     static const std::string true_string ("true");
1537     static const std::string false_string ("false");
1538 
1539     if (partial_value == NULL)
1540     {
1541         matches.AppendString ("true");
1542         matches.AppendString ("false");
1543     }
1544     else
1545     {
1546         int partial_len = strlen (partial_value);
1547 
1548         if ((partial_len <= true_string.length())
1549             && (true_string.find (partial_value) == 0))
1550             matches.AppendString ("true");
1551         else if ((partial_len <= false_string.length())
1552                  && (false_string.find (partial_value) == 0))
1553             matches.AppendString ("false");
1554     }
1555 
1556     word_complete = false;
1557     if (matches.GetSize() == 1)
1558         word_complete = true;
1559 
1560     return matches.GetSize();
1561 }
1562 
1563 int
1564 UserSettingsController::EnumMatches (const char *partial_value,
1565                                      lldb::OptionEnumValueElement *enum_values,
1566                                      bool &word_complete,
1567                                      StringList &matches)
1568 {
1569     int len = (partial_value != NULL) ? strlen (partial_value) : 0;
1570 
1571     int i = 0;
1572     while (enum_values[i].string_value != NULL)
1573     {
1574         if (len == 0)
1575             matches.AppendString (enum_values[i].string_value);
1576         else
1577         {
1578             std::string tmp_value (enum_values[i].string_value);
1579             if ((len <= tmp_value.length())
1580                 && tmp_value.find (partial_value) == 0)
1581               matches.AppendString (enum_values[i].string_value);
1582         }
1583         ++i;
1584     }
1585 
1586     word_complete = false;
1587     if (matches.GetSize() == 1)
1588       word_complete = true;
1589 
1590     return matches.GetSize();
1591 }
1592 
1593 int
1594 UserSettingsController::CompleteSettingsNames (lldb::UserSettingsControllerSP root_settings,
1595                                                Args &partial_setting_name_pieces,
1596                                                bool &word_complete,
1597                                                StringList &matches)
1598 {
1599     int num_matches = 0;
1600     int num_name_pieces = partial_setting_name_pieces.GetArgumentCount();
1601 
1602     if (num_name_pieces > 1)
1603     {
1604         // There are at least two pieces, perhaps with multiple level names preceding them.
1605         // First traverse all the extra levels, until we have exactly two pieces left.
1606 
1607         int num_extra_levels = num_name_pieces - 2;
1608 
1609         // Deal with current level first.
1610 
1611         ConstString root_level = root_settings->GetLevelName();
1612         if ((num_extra_levels > 0)
1613             && (root_level.GetLength() > 0))
1614         {
1615             ConstString current_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1616             if (current_level == root_level)
1617             {
1618                 partial_setting_name_pieces.Shift();
1619                 --num_extra_levels;
1620             }
1621             else
1622                 return 0; // The current level did not match the name pieces; something is wrong, so return immediately
1623 
1624         }
1625 
1626         for (int i = 0; i < num_extra_levels; ++i)
1627         {
1628             ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1629             bool found = false;
1630             int num_children = root_settings->GetNumChildren();
1631             for (int j = 0; j < num_children && !found; ++j)
1632             {
1633                 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1634                 {
1635                     found = true;
1636                     root_settings = root_settings->GetChildAtIndex (j);
1637                     partial_setting_name_pieces.Shift();
1638                 }
1639             }
1640             if (! found)
1641             {
1642                 return 0; // Unable to find a matching child level name; something is wrong, so return immediately.
1643             }
1644         }
1645 
1646         // Now there should be exactly two name pieces left.  If not there is an error, so return immediately
1647 
1648         if (partial_setting_name_pieces.GetArgumentCount() != 2)
1649             return 0;
1650 
1651         std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1652         int len = next_name.length();
1653         partial_setting_name_pieces.Shift();
1654 
1655         if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1656         {
1657             // 'next_name' is an instance name.  The last name piece must be a non-empty partial match against an
1658             // instance_name, assuming 'next_name' is valid.
1659 
1660             if (root_settings->IsLiveInstance (next_name))
1661             {
1662                 std::string complete_prefix;
1663                 root_settings->BuildParentPrefix (complete_prefix);
1664 
1665                 num_matches = root_settings->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0),
1666                                                                      complete_prefix,
1667                                                                      next_name.c_str(),
1668                                                                      matches);
1669                 word_complete = true;
1670                 if (num_matches > 1)
1671                     word_complete = false;
1672 
1673                 return num_matches;
1674             }
1675             else
1676                 return 0;   // Invalid instance_name
1677         }
1678         else
1679         {
1680             // 'next_name' must be a child name.  Find the correct child and pass the remaining piece to be resolved.
1681             bool found = false;
1682             int num_children = root_settings->GetNumChildren();
1683             ConstString child_level (next_name.c_str());
1684             for (int i = 0; i < num_children; ++i)
1685             {
1686                 if (root_settings->GetChildAtIndex (i)->GetLevelName() == child_level)
1687                 {
1688                     found = true;
1689                     return UserSettingsController::CompleteSettingsNames (root_settings->GetChildAtIndex (i),
1690                                                                           partial_setting_name_pieces,
1691                                                                           word_complete, matches);
1692                 }
1693             }
1694             if (!found)
1695                 return 0;
1696         }
1697     }
1698     else if (num_name_pieces == 1)
1699     {
1700         std::string complete_prefix;
1701         root_settings->BuildParentPrefix (complete_prefix);
1702 
1703         word_complete = true;
1704         std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1705 
1706         if (name[0] == '[')
1707         {
1708             // It's a partial instance name.
1709 
1710             num_matches = root_settings->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches);
1711         }
1712         else
1713         {
1714             // It could be anything *except* an instance name...
1715 
1716             num_matches = root_settings->GlobalVariableMatches (name.c_str(), complete_prefix, matches);
1717             num_matches += root_settings->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches);
1718             num_matches += root_settings->ChildMatches (name.c_str(), complete_prefix, word_complete, matches);
1719         }
1720 
1721         if (num_matches > 1)
1722             word_complete = false;
1723 
1724         return num_matches;
1725     }
1726     else
1727     {
1728         // We have a user settings controller with a blank partial string.  Return everything possible at this level.
1729 
1730         std::string complete_prefix;
1731         root_settings->BuildParentPrefix (complete_prefix);
1732         num_matches = root_settings->GlobalVariableMatches (NULL, complete_prefix, matches);
1733         num_matches += root_settings->InstanceVariableMatches (NULL, complete_prefix, NULL, matches);
1734         num_matches += root_settings->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches);
1735         num_matches += root_settings->ChildMatches (NULL, complete_prefix, word_complete, matches);
1736         word_complete = false;
1737         return num_matches;
1738     }
1739 
1740     return num_matches;
1741 }
1742 
1743 int
1744 UserSettingsController::GlobalVariableMatches (const char *partial_name,
1745                                                const std::string &complete_prefix,
1746                                                StringList &matches)
1747 {
1748     int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1749     int num_matches = 0;
1750 
1751     for (size_t i = 0; i < m_settings.global_settings.size(); ++i)
1752     {
1753         SettingEntry &entry = m_settings.global_settings[i];
1754         std::string var_name (entry.var_name);
1755         if ((partial_len == 0)
1756             || ((partial_len <= var_name.length())
1757                 && (var_name.find (partial_name) == 0)))
1758         {
1759             StreamString match_name;
1760             if (complete_prefix.length() > 0)
1761             {
1762                 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1763                 matches.AppendString (match_name.GetData());
1764             }
1765             else
1766                 matches.AppendString (var_name.c_str());
1767             ++num_matches;
1768         }
1769     }
1770     return num_matches;
1771 }
1772 
1773 int
1774 UserSettingsController::InstanceVariableMatches (const char *partial_name,
1775                                                  const std::string &complete_prefix,
1776                                                  const char *instance_name,
1777                                                  StringList &matches)
1778 {
1779     int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1780     int num_matches = 0;
1781 
1782     for (size_t i = 0; i < m_settings.instance_settings.size(); ++i)
1783     {
1784         SettingEntry &entry = m_settings.instance_settings[i];
1785         std::string var_name (entry.var_name);
1786         if ((partial_len == 0)
1787             || ((partial_len <= var_name.length())
1788                 && (var_name.find (partial_name) == 0)))
1789         {
1790             StreamString match_name;
1791             if (complete_prefix.length() > 0)
1792             {
1793                 if (instance_name != NULL)
1794                     match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str());
1795                 else
1796                     match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1797 
1798                 matches.AppendString (match_name.GetData());
1799             }
1800             else
1801             {
1802                 if (instance_name != NULL)
1803                 {
1804                     match_name.Printf ("%s.%s", instance_name, var_name.c_str());
1805                     matches.AppendString (match_name.GetData());
1806                 }
1807                 else
1808                     matches.AppendString (var_name.c_str());
1809             }
1810             ++num_matches;
1811         }
1812     }
1813     return num_matches;
1814 }
1815 
1816 int
1817 UserSettingsController::LiveInstanceMatches (const char *partial_name,
1818                                              const std::string &complete_prefix,
1819                                              bool &word_complete,
1820                                              StringList &matches)
1821 {
1822     int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1823     int num_matches = 0;
1824 
1825     std::map<std::string, InstanceSettings*>::iterator pos;
1826     for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
1827     {
1828         std::string instance_name = pos->first;
1829         if ((partial_len == 0)
1830             || ((partial_len <= instance_name.length())
1831                 && (instance_name.find (partial_name) == 0)))
1832         {
1833             StreamString match_name;
1834             if (complete_prefix.length() > 0)
1835                 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str());
1836             else
1837                 match_name.Printf ("%s.", instance_name.c_str());
1838             matches.AppendString (match_name.GetData());
1839             ++num_matches;
1840         }
1841     }
1842 
1843     if (num_matches > 0)
1844         word_complete = false;
1845 
1846     return num_matches;
1847 }
1848 
1849 int
1850 UserSettingsController::ChildMatches (const char *partial_name,
1851                                       const std::string &complete_prefix,
1852                                       bool &word_complete,
1853                                       StringList &matches)
1854 {
1855     int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1856     int num_children = GetNumChildren();
1857     int num_matches = 0;
1858     for (int i = 0; i < num_children; ++i)
1859     {
1860         std::string child_name (GetChildAtIndex(i)->GetLevelName().AsCString());
1861         StreamString match_name;
1862         if ((partial_len == 0)
1863           || ((partial_len <= child_name.length())
1864               && (child_name.find (partial_name) == 0)))
1865         {
1866             if (complete_prefix.length() > 0)
1867                 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str());
1868             else
1869                 match_name.Printf ("%s.", child_name.c_str());
1870             matches.AppendString (match_name.GetData());
1871             ++num_matches;
1872         }
1873     }
1874 
1875     if (num_matches > 0)
1876         word_complete = false;
1877 
1878     return num_matches;
1879 }
1880 
1881 void
1882 UserSettingsController::VerifyOperationForType (lldb::SettableVariableType var_type,
1883                                                 lldb::VarSetOperationType op,
1884                                                 const ConstString &var_name,
1885                                                 Error &err)
1886 {
1887     if (op == lldb::eVarSetOperationAssign)
1888         return;
1889 
1890 
1891     if (op == lldb::eVarSetOperationInvalid)
1892     {
1893         err.SetErrorString ("Invalid 'settings ' subcommand operation.\n");
1894         return;
1895     }
1896 
1897     switch (op)
1898     {
1899         case lldb::eVarSetOperationInsertBefore:
1900         case lldb::eVarSetOperationInsertAfter:
1901             if (var_type != lldb::eSetVarTypeArray)
1902                 err.SetErrorString ("Invalid operation:  This operation can only be performed on array variables.\n");
1903             break;
1904         case lldb::eVarSetOperationReplace:
1905         case lldb::eVarSetOperationRemove:
1906             if ((var_type != lldb::eSetVarTypeArray)
1907                 && (var_type != lldb::eSetVarTypeDictionary))
1908                 err.SetErrorString ("Invalid operation:  This operation can only be performed on array or dictionary"
1909                                     " variables.\n");
1910             break;
1911         case lldb::eVarSetOperationAppend:
1912         case lldb::eVarSetOperationClear:
1913             if ((var_type != lldb::eSetVarTypeArray)
1914                 && (var_type != lldb::eSetVarTypeDictionary)
1915                 && (var_type != lldb::eSetVarTypeString))
1916                 err.SetErrorString ("Invalid operation:  This operation can only be performed on array, dictionary "
1917                                     "or string variables.\n");
1918             break;
1919         default:
1920             break;
1921     }
1922 
1923     return;
1924 }
1925 
1926 void
1927 UserSettingsController::UpdateStringVariable (lldb::VarSetOperationType op,
1928                                               std::string &string_var,
1929                                               const char *new_value,
1930                                               Error &err)
1931 {
1932     if (op == lldb::eVarSetOperationAssign)
1933         string_var = new_value;
1934     else if (op == lldb::eVarSetOperationAppend)
1935         string_var.append (new_value);
1936     else if (op == lldb::eVarSetOperationClear)
1937         string_var.clear();
1938     else
1939         err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
1940 }
1941 
1942 void
1943 UserSettingsController::UpdateBooleanVariable (lldb::VarSetOperationType op,
1944                                                bool &bool_var,
1945                                                const char *new_value,
1946                                                Error &err)
1947 {
1948     if (op != lldb::eVarSetOperationAssign)
1949         err.SetErrorString ("Invalid operation for Boolean variable.  Cannot update value.\n");
1950 
1951 
1952     if ((new_value == NULL)
1953         || (new_value[0] == '\0'))
1954       err.SetErrorString ("Invalid value.  Cannot perform update.\n");
1955 
1956     std::string bool_val_str (new_value);
1957 
1958     std::transform (bool_val_str.begin(), bool_val_str.end(), bool_val_str.begin(), ::tolower);
1959 
1960     if (bool_val_str == "true")
1961         bool_var = true;
1962     else if (bool_val_str == "false")
1963         bool_var = false;
1964 }
1965 
1966 void
1967 UserSettingsController::UpdateStringArrayVariable (lldb::VarSetOperationType op,
1968                                                    const char *index_value,
1969                                                    Args &array_var,
1970                                                    const char *new_value,
1971                                                    Error &err)
1972 {
1973     int index = -1;
1974     bool valid_index = true;
1975 
1976     if (index_value != NULL)
1977     {
1978         for (int i = 0; i < strlen(index_value); ++i)
1979             if (!isdigit (index_value[i]))
1980             {
1981                 valid_index = false;
1982                 err.SetErrorStringWithFormat ("'%s' is not a valid integer index. Cannot update array value.\n",
1983                                               index_value);
1984             }
1985 
1986         if (valid_index)
1987             index = atoi (index_value);
1988 
1989         if (index < 0
1990             || index >= array_var.GetArgumentCount())
1991         {
1992             valid_index = false;
1993             err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable. "
1994                                           "Cannot update array value.\n", index);
1995         }
1996     }
1997 
1998     switch (op)
1999     {
2000         case lldb::eVarSetOperationAssign:
2001             array_var.SetCommandString (new_value);
2002             break;
2003         case lldb::eVarSetOperationReplace:
2004         {
2005             if (valid_index)
2006                 array_var.ReplaceArgumentAtIndex (index, new_value);
2007             break;
2008         }
2009         case lldb::eVarSetOperationInsertBefore:
2010         case lldb::eVarSetOperationInsertAfter:
2011         {
2012             if (valid_index)
2013             {
2014                 Args new_array (new_value);
2015                 if (op == lldb::eVarSetOperationInsertAfter)
2016                     ++index;
2017                 for (int i = 0; i < new_array.GetArgumentCount(); ++i)
2018                     array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i));
2019             }
2020             break;
2021         }
2022         case lldb::eVarSetOperationRemove:
2023         {
2024             if (valid_index)
2025                 array_var.DeleteArgumentAtIndex (index);
2026             break;
2027         }
2028         case lldb::eVarSetOperationAppend:
2029         {
2030             Args new_array (new_value);
2031             array_var.AppendArguments (new_array);
2032             break;
2033         }
2034         case lldb::eVarSetOperationClear:
2035             array_var.Clear();
2036             break;
2037         default:
2038             err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
2039             break;
2040     }
2041 }
2042 
2043 void
2044 UserSettingsController::UpdateDictionaryVariable (lldb::VarSetOperationType op,
2045                                                   const char *index_value,
2046                                                   std::map<std::string, std::string> &dictionary,
2047                                                   const char *new_value,
2048                                                   Error &err)
2049 {
2050     switch (op)
2051     {
2052         case lldb::eVarSetOperationReplace:
2053             if (index_value != NULL)
2054             {
2055                 std::string key (index_value);
2056                 std::map<std::string, std::string>::iterator pos;
2057 
2058                 pos = dictionary.find (key);
2059                 if (pos != dictionary.end())
2060                     dictionary[key] = new_value;
2061                 else
2062                     err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value.\n", index_value);
2063             }
2064             else
2065                 err.SetErrorString ("'settings replace' requires a key for dictionary variables. No key supplied.\n");
2066             break;
2067         case lldb::eVarSetOperationRemove:
2068             if (index_value != NULL)
2069             {
2070                 std::string key (index_value);
2071                 dictionary.erase (key);
2072             }
2073             else
2074                 err.SetErrorString ("'settings remove' requires a key for dictionary variables. No key supplied.\n");
2075             break;
2076         case lldb::eVarSetOperationClear:
2077             dictionary.clear ();
2078             break;
2079         case lldb::eVarSetOperationAppend:
2080         case lldb::eVarSetOperationAssign:
2081             {
2082                 // Clear the dictionary if it's an assign with new_value as NULL.
2083                 if (new_value == NULL && op == lldb::eVarSetOperationAssign)
2084                 {
2085                     dictionary.clear ();
2086                     break;
2087                 }
2088                 Args args (new_value);
2089                 size_t num_args = args.GetArgumentCount();
2090                 for (size_t i = 0; i < num_args; ++i)
2091                 {
2092                     std::string tmp_arg = args.GetArgumentAtIndex (i);
2093                     size_t eq_sign = tmp_arg.find ('=');
2094                     if (eq_sign != std::string::npos)
2095                     {
2096                         if (eq_sign > 4)
2097                         {
2098                             std::string tmp_key = tmp_arg.substr (0, eq_sign);
2099                             std::string real_value = tmp_arg.substr (eq_sign+1);
2100                             if ((tmp_key[0] == '[')
2101                                 && (tmp_key[1] == '"')
2102                                 && (tmp_key[eq_sign-2] == '"')
2103                                 && (tmp_key[eq_sign-1] == ']'))
2104                               {
2105                                 std::string real_key = tmp_key.substr (2, eq_sign-4);
2106                                 dictionary[real_key] = real_value;
2107                               }
2108                             else
2109                                 err.SetErrorString ("Invalid key format for dictionary assignment.  "
2110                                                     "Expected '[\"<key>\"]'\n");
2111                         }
2112                         else
2113                             err.SetErrorString ("Invalid key format for dictionary assignment.  "
2114                                                 "Expected '[\"<key>\"]'\n");
2115                     }
2116                     else
2117                         err.SetErrorString ("Invalid format for dictionary value.  Expected '[\"<key>\"]=<value>'\n");
2118                 }
2119             }
2120             break;
2121         case lldb::eVarSetOperationInsertBefore:
2122         case lldb::eVarSetOperationInsertAfter:
2123             err.SetErrorString ("Specified operation cannot be performed on dictionary variables.\n");
2124             break;
2125         default:
2126             err.SetErrorString ("Unrecognized operation.\n");
2127             break;
2128     }
2129 }
2130 
2131 const char *
2132 UserSettingsController::EnumToString (const lldb::OptionEnumValueElement *enum_values,
2133                                       int value)
2134 {
2135     int i = 0;
2136     while (enum_values[i].string_value != NULL)
2137     {
2138         if (enum_values[i].value == value)
2139             return enum_values[i].string_value;
2140         ++i;
2141     }
2142 
2143     return "Invalid enumeration value";
2144 }
2145 
2146 
2147 void
2148 UserSettingsController::UpdateEnumVariable (lldb::OptionEnumValueElement *enum_values,
2149                                             int *enum_var,
2150                                             const char *new_value,
2151                                             Error &err)
2152 {
2153     bool found_one;
2154 
2155     *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, &found_one);
2156 
2157     if (!found_one)
2158         err.SetErrorString ("Invalid enumeration value; cannot update variable.\n");
2159 }
2160 
2161 void
2162 UserSettingsController::RenameInstanceSettings (const char *old_name, const char *new_name)
2163 {
2164     Mutex::Locker live_mutex (m_live_settings_mutex);
2165     Mutex::Locker pending_mutex (m_pending_settings_mutex);
2166     std::string old_name_key (old_name);
2167     std::string new_name_key (new_name);
2168 
2169     // First, find the live instance settings for the old_name.  If they don't exist in the live settings
2170     // list, then this is not a setting that can be renamed.
2171 
2172     if ((old_name_key[0] != '[') || (old_name_key[old_name_key.size() -1] != ']'))
2173     {
2174         StreamString tmp_str;
2175         tmp_str.Printf ("[%s]", old_name);
2176           old_name_key = tmp_str.GetData();
2177     }
2178 
2179     if ((new_name_key[0] != '[') || (new_name_key[new_name_key.size() -1] != ']'))
2180     {
2181         StreamString tmp_str;
2182         tmp_str.Printf ("[%s]", new_name);
2183         new_name_key = tmp_str.GetData();
2184     }
2185 
2186     if (old_name_key.compare (new_name_key) == 0)
2187         return;
2188 
2189     size_t len = new_name_key.length();
2190     std::string stripped_new_name = new_name_key.substr (1, len-2);  // new name without the '[ ]'
2191 
2192     std::map<std::string, InstanceSettings *>::iterator pos;
2193 
2194     pos = m_live_settings.find (old_name_key);
2195     if (pos != m_live_settings.end())
2196     {
2197         InstanceSettings *live_settings = pos->second;
2198 
2199         // Rename the settings.
2200         live_settings->ChangeInstanceName (stripped_new_name);
2201 
2202         // Now see if there are any pending settings for the new name; if so, copy them into live_settings.
2203         std::map<std::string,  lldb::InstanceSettingsSP>::iterator pending_pos;
2204         pending_pos = m_pending_settings.find (new_name_key);
2205         if (pending_pos != m_pending_settings.end())
2206         {
2207             lldb::InstanceSettingsSP pending_settings_sp = pending_pos->second;
2208             live_settings->CopyInstanceSettings (pending_settings_sp, false);
2209         }
2210 
2211         // Erase the old entry (under the old name) from live settings.
2212         m_live_settings.erase (pos);
2213 
2214         // Add the new entry, with the new name, into live settings.
2215         m_live_settings[new_name_key] = live_settings;
2216     }
2217 }
2218 
2219 //----------------------------------------------------------------------
2220 // class InstanceSettings
2221 //----------------------------------------------------------------------
2222 
2223 InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name, bool live_instance) :
2224     m_owner (owner),
2225     m_instance_name (instance_name)
2226 {
2227     if ((m_instance_name != InstanceSettings::GetDefaultName())
2228         && (m_instance_name !=  InstanceSettings::InvalidName())
2229         && live_instance)
2230         m_owner.RegisterInstanceSettings (this);
2231 }
2232 
2233 InstanceSettings::~InstanceSettings ()
2234 {
2235     if (m_instance_name != InstanceSettings::GetDefaultName())
2236         m_owner.UnregisterInstanceSettings (this);
2237 }
2238 
2239 const ConstString &
2240 InstanceSettings::GetDefaultName ()
2241 {
2242     static const ConstString g_default_settings_name ("[DEFAULT]");
2243 
2244     return g_default_settings_name;
2245 }
2246 
2247 const ConstString &
2248 InstanceSettings::InvalidName ()
2249 {
2250     static const ConstString g_invalid_name ("Invalid instance name");
2251 
2252     return g_invalid_name;
2253 }
2254 
2255 void
2256 InstanceSettings::ChangeInstanceName (const std::string &new_instance_name)
2257 {
2258     m_instance_name.SetCString (new_instance_name.c_str());
2259 }
2260 
2261 
2262