Reimplemented the code that backed the "settings" in lldb. There were many issues with the previous implementation:
- no setting auto completion
- very manual and error prone way of getting/setting variables
- tons of code duplication
- useless instance names for processes, threads

Now settings can easily be defined like option values. The new settings makes use of the "OptionValue" classes so we can re-use the option value code that we use to set settings in command options. No more instances, just "does the right thing".



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162366 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 0513e33..e120153 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -43,9 +43,103 @@
 using namespace lldb;
 using namespace lldb_private;
 
+
+const ThreadPropertiesSP &
+Thread::GetGlobalProperties()
+{
+    static ThreadPropertiesSP g_settings_sp;
+    if (!g_settings_sp)
+        g_settings_sp.reset (new ThreadProperties (true));
+    return g_settings_sp;
+}
+
+static PropertyDefinition
+g_properties[] =
+{
+    { "step-avoid-regexp",  OptionValue::eTypeRegex  , true , REG_EXTENDED, "^std::", NULL, "A regular expression defining functions step-in won't stop in." },
+    { "trace-thread",       OptionValue::eTypeBoolean, false, false, NULL, NULL, "If true, this thread will single-step and log execution." },
+    {  NULL               , OptionValue::eTypeInvalid, false, 0    , NULL, NULL, NULL  }
+};
+
+enum {
+    ePropertyStepAvoidRegex,
+    ePropertyEnableThreadTrace
+};
+
+
+class ThreadOptionValueProperties : public OptionValueProperties
+{
+public:
+    ThreadOptionValueProperties (const ConstString &name) :
+        OptionValueProperties (name)
+    {
+    }
+    
+    // This constructor is used when creating ThreadOptionValueProperties when it
+    // is part of a new lldb_private::Thread instance. It will copy all current
+    // global property values as needed
+    ThreadOptionValueProperties (ThreadProperties *global_properties) :
+    OptionValueProperties(*global_properties->GetValueProperties())
+    {
+    }
+    
+    virtual const Property *
+    GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+    {
+        // When gettings the value for a key from the thread options, we will always
+        // try and grab the setting from the current thread if there is one. Else we just
+        // use the one from this instance.
+        if (exe_ctx)
+        {
+            Thread *thread = exe_ctx->GetThreadPtr();
+            if (thread)
+            {
+                ThreadOptionValueProperties *instance_properties = static_cast<ThreadOptionValueProperties *>(thread->GetValueProperties().get());
+                if (this != instance_properties)
+                    return instance_properties->ProtectedGetPropertyAtIndex (idx);
+            }
+        }
+        return ProtectedGetPropertyAtIndex (idx);
+    }
+};
+
+
+
+ThreadProperties::ThreadProperties (bool is_global) :
+    Properties ()
+{
+    if (is_global)
+    {
+        m_collection_sp.reset (new ThreadOptionValueProperties(ConstString("thread")));
+        m_collection_sp->Initialize(g_properties);
+    }
+    else
+        m_collection_sp.reset (new ThreadOptionValueProperties(Thread::GetGlobalProperties().get()));
+}
+
+ThreadProperties::~ThreadProperties()
+{
+}
+
+const RegularExpression *
+ThreadProperties::GetSymbolsToAvoidRegexp()
+{
+    const uint32_t idx = ePropertyStepAvoidRegex;
+    return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex (NULL, idx);
+}
+
+bool
+ThreadProperties::GetTraceEnabledState() const
+{
+    const uint32_t idx = ePropertyEnableThreadTrace;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+
 Thread::Thread (const ProcessSP &process_sp, lldb::tid_t tid) :
+    ThreadProperties (false),
     UserID (tid),
-    ThreadInstanceSettings (GetSettingsController()),
+//ThreadInstanceSettings (GetSettingsController()),
     m_process_wp (process_sp),
     m_actual_stop_info_sp (),
     m_index_id (process_sp->GetNextThreadIndexID ()),
@@ -70,7 +164,7 @@
         log->Printf ("%p Thread::Thread(tid = 0x%4.4llx)", this, GetID());
 
     QueueFundamentalPlan(true);
-    UpdateInstanceName();
+    //UpdateInstanceName();
 }
 
 
@@ -1196,10 +1290,10 @@
 void
 Thread::SettingsInitialize ()
 {
-    UserSettingsController::InitializeSettingsController (GetSettingsController(),
-                                                          SettingsController::global_settings_table,
-                                                          SettingsController::instance_settings_table);
-                                                          
+//    UserSettingsController::InitializeSettingsController (GetSettingsController(),
+//                                                          SettingsController::global_settings_table,
+//                                                          SettingsController::instance_settings_table);
+//                                                          
     // Now call SettingsInitialize() on each 'child' setting of Thread.
     // Currently there are none.
 }
@@ -1211,46 +1305,46 @@
     // Currently there are none.
     
     // Now terminate Thread Settings.
-    
-    UserSettingsControllerSP &usc = GetSettingsController();
-    UserSettingsController::FinalizeSettingsController (usc);
-    usc.reset();
+//    
+//    UserSettingsControllerSP &usc = GetSettingsController();
+//    UserSettingsController::FinalizeSettingsController (usc);
+//    usc.reset();
 }
 
-UserSettingsControllerSP &
-Thread::GetSettingsController ()
-{
-    static UserSettingsControllerSP g_settings_controller_sp;
-    if (!g_settings_controller_sp)
-    {
-        g_settings_controller_sp.reset (new Thread::SettingsController);
-        // The first shared pointer to Target::SettingsController in
-        // g_settings_controller_sp must be fully created above so that 
-        // the TargetInstanceSettings can use a weak_ptr to refer back 
-        // to the master setttings controller
-        InstanceSettingsSP default_instance_settings_sp (new ThreadInstanceSettings (g_settings_controller_sp, 
-                                                                                     false, 
-                                                                                     InstanceSettings::GetDefaultName().AsCString()));
+//UserSettingsControllerSP &
+//Thread::GetSettingsController ()
+//{
+//    static UserSettingsControllerSP g_settings_controller_sp;
+//    if (!g_settings_controller_sp)
+//    {
+//        g_settings_controller_sp.reset (new Thread::SettingsController);
+//        // The first shared pointer to Target::SettingsController in
+//        // g_settings_controller_sp must be fully created above so that 
+//        // the TargetInstanceSettings can use a weak_ptr to refer back 
+//        // to the master setttings controller
+//        InstanceSettingsSP default_instance_settings_sp (new ThreadInstanceSettings (g_settings_controller_sp, 
+//                                                                                     false, 
+//                                                                                     InstanceSettings::GetDefaultName().AsCString()));
+//
+//        g_settings_controller_sp->SetDefaultInstanceSettings (default_instance_settings_sp);
+//    }
+//    return g_settings_controller_sp;
+//}
 
-        g_settings_controller_sp->SetDefaultInstanceSettings (default_instance_settings_sp);
-    }
-    return g_settings_controller_sp;
-}
-
-void
-Thread::UpdateInstanceName ()
-{
-    StreamString sstr;
-    const char *name = GetName();
-
-    if (name && name[0] != '\0')
-        sstr.Printf ("%s", name);
-    else if ((GetIndexID() != 0) || (GetID() != 0))
-        sstr.Printf ("0x%4.4x", GetIndexID());
-
-    if (sstr.GetSize() > 0)
-	Thread::GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(), sstr.GetData());
-}
+//void
+//Thread::UpdateInstanceName ()
+//{
+//    StreamString sstr;
+//    const char *name = GetName();
+//
+//    if (name && name[0] != '\0')
+//        sstr.Printf ("%s", name);
+//    else if ((GetIndexID() != 0) || (GetID() != 0))
+//        sstr.Printf ("0x%4.4x", GetIndexID());
+//
+//    if (sstr.GetSize() > 0)
+//	Thread::GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(), sstr.GetData());
+//}
 
 lldb::StackFrameSP
 Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
@@ -1422,225 +1516,225 @@
 //--------------------------------------------------------------
 // class Thread::SettingsController
 //--------------------------------------------------------------
+//
+//Thread::SettingsController::SettingsController () :
+//    UserSettingsController ("thread", Process::GetSettingsController())
+//{
+//}
+//
+//Thread::SettingsController::~SettingsController ()
+//{
+//}
+//
+//lldb::InstanceSettingsSP
+//Thread::SettingsController::CreateInstanceSettings (const char *instance_name)
+//{
+//    lldb::InstanceSettingsSP new_settings_sp (new ThreadInstanceSettings (GetSettingsController(),
+//                                                                          false, 
+//                                                                          instance_name));
+//    return new_settings_sp;
+//}
 
-Thread::SettingsController::SettingsController () :
-    UserSettingsController ("thread", Process::GetSettingsController())
-{
-}
-
-Thread::SettingsController::~SettingsController ()
-{
-}
-
-lldb::InstanceSettingsSP
-Thread::SettingsController::CreateInstanceSettings (const char *instance_name)
-{
-    lldb::InstanceSettingsSP new_settings_sp (new ThreadInstanceSettings (GetSettingsController(),
-                                                                          false, 
-                                                                          instance_name));
-    return new_settings_sp;
-}
-
-#pragma mark "ThreadInstanceSettings"
-//--------------------------------------------------------------
-// class ThreadInstanceSettings
-//--------------------------------------------------------------
-
-ThreadInstanceSettings::ThreadInstanceSettings (const UserSettingsControllerSP &owner_sp, bool live_instance, const char *name) :
-    InstanceSettings (owner_sp, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance), 
-    m_avoid_regexp_ap (),
-    m_trace_enabled (false)
-{
-    // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
-    // until the vtables for ThreadInstanceSettings are properly set up, i.e. AFTER all the initializers.
-    // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
-    // This is true for CreateInstanceName() too.
-   
-    if (GetInstanceName() == InstanceSettings::InvalidName())
-    {
-        ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
-        owner_sp->RegisterInstanceSettings (this);
-    }
-
-    if (live_instance)
-    {
-        CopyInstanceSettings (owner_sp->FindPendingSettings (m_instance_name),false);
-    }
-}
-
-ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
-    InstanceSettings (Thread::GetSettingsController(), CreateInstanceName().AsCString()),
-    m_avoid_regexp_ap (),
-    m_trace_enabled (rhs.m_trace_enabled)
-{
-    if (m_instance_name != InstanceSettings::GetDefaultName())
-    {
-        UserSettingsControllerSP owner_sp (m_owner_wp.lock());
-        if (owner_sp)
-        {
-            CopyInstanceSettings (owner_sp->FindPendingSettings (m_instance_name), false);
-            owner_sp->RemovePendingSettings (m_instance_name);
-        }
-    }
-    if (rhs.m_avoid_regexp_ap.get() != NULL)
-        m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
-}
-
-ThreadInstanceSettings::~ThreadInstanceSettings ()
-{
-}
-
-ThreadInstanceSettings&
-ThreadInstanceSettings::operator= (const ThreadInstanceSettings &rhs)
-{
-    if (this != &rhs)
-    {
-        if (rhs.m_avoid_regexp_ap.get() != NULL)
-            m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
-        else
-            m_avoid_regexp_ap.reset(NULL);
-    }
-    m_trace_enabled = rhs.m_trace_enabled;
-    return *this;
-}
-
-
-void
-ThreadInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
-                                                         const char *index_value,
-                                                         const char *value,
-                                                         const ConstString &instance_name,
-                                                         const SettingEntry &entry,
-                                                         VarSetOperationType op,
-                                                         Error &err,
-                                                         bool pending)
-{
-    if (var_name == StepAvoidRegexpVarName())
-    {
-        std::string regexp_text;
-        if (m_avoid_regexp_ap.get() != NULL)
-            regexp_text.append (m_avoid_regexp_ap->GetText());
-        UserSettingsController::UpdateStringVariable (op, regexp_text, value, err);
-        if (regexp_text.empty())
-            m_avoid_regexp_ap.reset();
-        else
-        {
-            m_avoid_regexp_ap.reset(new RegularExpression(regexp_text.c_str()));
-            
-        }
-    }
-    else if (var_name == GetTraceThreadVarName())
-    {
-        bool success;
-        bool result = Args::StringToBoolean(value, false, &success);
-
-        if (success)
-        {
-            m_trace_enabled = result;
-            if (!pending)
-            {
-                Thread *myself = static_cast<Thread *> (this);
-                myself->EnableTracer(m_trace_enabled, true);
-            }
-        }
-        else
-        {
-            err.SetErrorStringWithFormat ("Bad value \"%s\" for trace-thread, should be Boolean.", value);
-        }
-
-    }
-}
-
-void
-ThreadInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
-                                               bool pending)
-{
-    if (new_settings.get() == NULL)
-        return;
-
-    ThreadInstanceSettings *new_process_settings = (ThreadInstanceSettings *) new_settings.get();
-    if (new_process_settings->GetSymbolsToAvoidRegexp() != NULL)
-        m_avoid_regexp_ap.reset (new RegularExpression (new_process_settings->GetSymbolsToAvoidRegexp()->GetText()));
-    else 
-        m_avoid_regexp_ap.reset ();
-}
-
-bool
-ThreadInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
-                                                  const ConstString &var_name,
-                                                  StringList &value,
-                                                  Error *err)
-{
-    if (var_name == StepAvoidRegexpVarName())
-    {
-        if (m_avoid_regexp_ap.get() != NULL)
-        {
-            std::string regexp_text("\"");
-            regexp_text.append(m_avoid_regexp_ap->GetText());
-            regexp_text.append ("\"");
-            value.AppendString (regexp_text.c_str());
-        }
-
-    }
-    else if (var_name == GetTraceThreadVarName())
-    {
-        value.AppendString(m_trace_enabled ? "true" : "false");
-    }
-    else
-    {
-        if (err)
-            err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
-        return false;
-    }
-    return true;
-}
-
-const ConstString
-ThreadInstanceSettings::CreateInstanceName ()
-{
-    static int instance_count = 1;
-    StreamString sstr;
-
-    sstr.Printf ("thread_%d", instance_count);
-    ++instance_count;
-
-    const ConstString ret_val (sstr.GetData());
-    return ret_val;
-}
-
-const ConstString &
-ThreadInstanceSettings::StepAvoidRegexpVarName ()
-{
-    static ConstString step_avoid_var_name ("step-avoid-regexp");
-
-    return step_avoid_var_name;
-}
-
-const ConstString &
-ThreadInstanceSettings::GetTraceThreadVarName ()
-{
-    static ConstString trace_thread_var_name ("trace-thread");
-
-    return trace_thread_var_name;
-}
-
+//#pragma mark "ThreadInstanceSettings"
+////--------------------------------------------------------------
+//// class ThreadInstanceSettings
+////--------------------------------------------------------------
+//
+//ThreadInstanceSettings::ThreadInstanceSettings (const UserSettingsControllerSP &owner_sp, bool live_instance, const char *name) :
+//    InstanceSettings (owner_sp, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance), 
+//    m_avoid_regexp_ap (),
+//    m_trace_enabled (false)
+//{
+//    // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
+//    // until the vtables for ThreadInstanceSettings are properly set up, i.e. AFTER all the initializers.
+//    // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
+//    // This is true for CreateInstanceName() too.
+//   
+//    if (GetInstanceName() == InstanceSettings::InvalidName())
+//    {
+//        ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
+//        owner_sp->RegisterInstanceSettings (this);
+//    }
+//
+//    if (live_instance)
+//    {
+//        CopyInstanceSettings (owner_sp->FindPendingSettings (m_instance_name),false);
+//    }
+//}
+//
+//ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
+//    InstanceSettings (Thread::GetSettingsController(), CreateInstanceName().AsCString()),
+//    m_avoid_regexp_ap (),
+//    m_trace_enabled (rhs.m_trace_enabled)
+//{
+//    if (m_instance_name != InstanceSettings::GetDefaultName())
+//    {
+//        UserSettingsControllerSP owner_sp (m_owner_wp.lock());
+//        if (owner_sp)
+//        {
+//            CopyInstanceSettings (owner_sp->FindPendingSettings (m_instance_name), false);
+//            owner_sp->RemovePendingSettings (m_instance_name);
+//        }
+//    }
+//    if (rhs.m_avoid_regexp_ap.get() != NULL)
+//        m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
+//}
+//
+//ThreadInstanceSettings::~ThreadInstanceSettings ()
+//{
+//}
+//
+//ThreadInstanceSettings&
+//ThreadInstanceSettings::operator= (const ThreadInstanceSettings &rhs)
+//{
+//    if (this != &rhs)
+//    {
+//        if (rhs.m_avoid_regexp_ap.get() != NULL)
+//            m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
+//        else
+//            m_avoid_regexp_ap.reset(NULL);
+//    }
+//    m_trace_enabled = rhs.m_trace_enabled;
+//    return *this;
+//}
+//
+//
+//void
+//ThreadInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
+//                                                         const char *index_value,
+//                                                         const char *value,
+//                                                         const ConstString &instance_name,
+//                                                         const SettingEntry &entry,
+//                                                         VarSetOperationType op,
+//                                                         Error &err,
+//                                                         bool pending)
+//{
+//    if (var_name == StepAvoidRegexpVarName())
+//    {
+//        std::string regexp_text;
+//        if (m_avoid_regexp_ap.get() != NULL)
+//            regexp_text.append (m_avoid_regexp_ap->GetText());
+//        UserSettingsController::UpdateStringVariable (op, regexp_text, value, err);
+//        if (regexp_text.empty())
+//            m_avoid_regexp_ap.reset();
+//        else
+//        {
+//            m_avoid_regexp_ap.reset(new RegularExpression(regexp_text.c_str()));
+//            
+//        }
+//    }
+//    else if (var_name == GetTraceThreadVarName())
+//    {
+//        bool success;
+//        bool result = Args::StringToBoolean(value, false, &success);
+//
+//        if (success)
+//        {
+//            m_trace_enabled = result;
+//            if (!pending)
+//            {
+//                Thread *myself = static_cast<Thread *> (this);
+//                myself->EnableTracer(m_trace_enabled, true);
+//            }
+//        }
+//        else
+//        {
+//            err.SetErrorStringWithFormat ("Bad value \"%s\" for trace-thread, should be Boolean.", value);
+//        }
+//
+//    }
+//}
+//
+//void
+//ThreadInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
+//                                               bool pending)
+//{
+//    if (new_settings.get() == NULL)
+//        return;
+//
+//    ThreadInstanceSettings *new_process_settings = (ThreadInstanceSettings *) new_settings.get();
+//    if (new_process_settings->GetSymbolsToAvoidRegexp() != NULL)
+//        m_avoid_regexp_ap.reset (new RegularExpression (new_process_settings->GetSymbolsToAvoidRegexp()->GetText()));
+//    else 
+//        m_avoid_regexp_ap.reset ();
+//}
+//
+//bool
+//ThreadInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
+//                                                  const ConstString &var_name,
+//                                                  StringList &value,
+//                                                  Error *err)
+//{
+//    if (var_name == StepAvoidRegexpVarName())
+//    {
+//        if (m_avoid_regexp_ap.get() != NULL)
+//        {
+//            std::string regexp_text("\"");
+//            regexp_text.append(m_avoid_regexp_ap->GetText());
+//            regexp_text.append ("\"");
+//            value.AppendString (regexp_text.c_str());
+//        }
+//
+//    }
+//    else if (var_name == GetTraceThreadVarName())
+//    {
+//        value.AppendString(m_trace_enabled ? "true" : "false");
+//    }
+//    else
+//    {
+//        if (err)
+//            err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
+//        return false;
+//    }
+//    return true;
+//}
+//
+//const ConstString
+//ThreadInstanceSettings::CreateInstanceName ()
+//{
+//    static int instance_count = 1;
+//    StreamString sstr;
+//
+//    sstr.Printf ("thread_%d", instance_count);
+//    ++instance_count;
+//
+//    const ConstString ret_val (sstr.GetData());
+//    return ret_val;
+//}
+//
+//const ConstString &
+//ThreadInstanceSettings::StepAvoidRegexpVarName ()
+//{
+//    static ConstString step_avoid_var_name ("step-avoid-regexp");
+//
+//    return step_avoid_var_name;
+//}
+//
+//const ConstString &
+//ThreadInstanceSettings::GetTraceThreadVarName ()
+//{
+//    static ConstString trace_thread_var_name ("trace-thread");
+//
+//    return trace_thread_var_name;
+//}
+//
 //--------------------------------------------------
 // SettingsController Variable Tables
 //--------------------------------------------------
-
-SettingEntry
-Thread::SettingsController::global_settings_table[] =
-{
-  //{ "var-name",    var-type  ,        "default", enum-table, init'd, hidden, "help-text"},
-    {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
-};
-
-
-SettingEntry
-Thread::SettingsController::instance_settings_table[] =
-{
-  //{ "var-name",    var-type,              "default",      enum-table, init'd, hidden, "help-text"},
-    { "step-avoid-regexp",  eSetVarTypeString,      "",  NULL,       false,  false,  "A regular expression defining functions step-in won't stop in." },
-    { "trace-thread",  eSetVarTypeBoolean,      "false",  NULL,       false,  false,  "If true, this thread will single-step and log execution." },
-    {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
-};
+//
+//SettingEntry
+//Thread::SettingsController::global_settings_table[] =
+//{
+//  //{ "var-name",    var-type  ,        "default", enum-table, init'd, hidden, "help-text"},
+//    {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
+//};
+//
+//
+//SettingEntry
+//Thread::SettingsController::instance_settings_table[] =
+//{
+//  //{ "var-name",    var-type,              "default",      enum-table, init'd, hidden, "help-text"},
+//    { "step-avoid-regexp",  eSetVarTypeString,      "",  NULL,       false,  false,  "A regular expression defining functions step-in won't stop in." },
+//    { "trace-thread",  eSetVarTypeBoolean,      "false",  NULL,       false,  false,  "If true, this thread will single-step and log execution." },
+//    {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
+//};