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