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