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