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