Add ThreadPlanTracer class to allow instruction step tracing of execution.
Also changed eSetVarTypeBool to eSetVarTypeBoolean to make it consistent with eArgTypeBoolean.

git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@118824 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 4f7ff1d..80434cf 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -227,6 +227,9 @@
         DumpThreadPlans(&s);
         log->PutCString (s.GetData());
     }
+    
+    // The top most plan always gets to do the trace log...
+    current_plan->DoTraceLog ();
 
     if (current_plan->PlanExplainsStop())
     {
@@ -268,6 +271,10 @@
         if (over_ride_stop)
             should_stop = false;
     }
+    else if (current_plan->TracerExplainsStop())
+    {
+        return false;
+    }
     else
     {
         // If the current plan doesn't explain the stop, then, find one that
@@ -346,8 +353,11 @@
 {
     if (thread_plan_sp)
     {
+        // If the thread plan doesn't already have a tracer, give it its parent's tracer:
+        if (!thread_plan_sp->GetThreadPlanTracer())
+            thread_plan_sp->SetThreadPlanTracer(m_plan_stack.back()->GetThreadPlanTracer());
         m_plan_stack.push_back (thread_plan_sp);
-
+            
         thread_plan_sp->DidPush();
 
         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
@@ -489,6 +499,29 @@
     PushPlan (thread_plan_sp);
 }
 
+
+void
+Thread::EnableTracer (bool value, bool single_stepping)
+{
+    int stack_size = m_plan_stack.size();
+    for (int i = 0; i < stack_size; i++)
+    {
+        if (m_plan_stack[i]->GetThreadPlanTracer())
+        {
+            m_plan_stack[i]->GetThreadPlanTracer()->EnableTracing(value);
+            m_plan_stack[i]->GetThreadPlanTracer()->EnableSingleStep(single_stepping);
+        }
+    }
+}
+
+void
+Thread::SetTracer (lldb::ThreadPlanTracerSP &tracer_sp)
+{
+    int stack_size = m_plan_stack.size();
+    for (int i = 0; i < stack_size; i++)
+        m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
+}
+
 void
 Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
 {
@@ -936,197 +969,6 @@
 	Thread::GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(), sstr.GetData());
 }
 
-//--------------------------------------------------------------
-// class Thread::ThreadSettingsController
-//--------------------------------------------------------------
-
-Thread::ThreadSettingsController::ThreadSettingsController () :
-    UserSettingsController ("thread", Process::GetSettingsController())
-{
-    m_default_settings.reset (new ThreadInstanceSettings (*this, false, 
-                                                          InstanceSettings::GetDefaultName().AsCString()));
-}
-
-Thread::ThreadSettingsController::~ThreadSettingsController ()
-{
-}
-
-lldb::InstanceSettingsSP
-Thread::ThreadSettingsController::CreateInstanceSettings (const char *instance_name)
-{
-    ThreadInstanceSettings *new_settings = new ThreadInstanceSettings (*(Thread::GetSettingsController().get()),
-                                                                       false, instance_name);
-    lldb::InstanceSettingsSP new_settings_sp (new_settings);
-    return new_settings_sp;
-}
-
-//--------------------------------------------------------------
-// class ThreadInstanceSettings
-//--------------------------------------------------------------
-
-ThreadInstanceSettings::ThreadInstanceSettings (UserSettingsController &owner, bool live_instance, const char *name) :
-    InstanceSettings (owner, (name == NULL ? InstanceSettings::InvalidName().AsCString() : name), live_instance), 
-    m_avoid_regexp_ap ()
-{
-    // 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()));
-        m_owner.RegisterInstanceSettings (this);
-    }
-
-    if (live_instance)
-    {
-        const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
-        CopyInstanceSettings (pending_settings,false);
-        //m_owner.RemovePendingSettings (m_instance_name);
-    }
-}
-
-ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
-    InstanceSettings (*(Thread::GetSettingsController().get()), CreateInstanceName().AsCString()),
-    m_avoid_regexp_ap ()
-{
-    if (m_instance_name != InstanceSettings::GetDefaultName())
-    {
-        const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
-        CopyInstanceSettings (pending_settings,false);
-        m_owner.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);
-    }
-    
-    return *this;
-}
-
-
-void
-ThreadInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
-                                                         const char *index_value,
-                                                         const char *value,
-                                                         const ConstString &instance_name,
-                                                         const SettingEntry &entry,
-                                                         lldb::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()));
-            
-        }
-    }
-}
-
-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 (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 run_args_var_name ("step-avoid-regexp");
-
-    return run_args_var_name;
-}
-
-//--------------------------------------------------
-// ThreadSettingsController Variable Tables
-//--------------------------------------------------
-
-SettingEntry
-Thread::ThreadSettingsController::global_settings_table[] =
-{
-  //{ "var-name",    var-type  ,        "default", enum-table, init'd, hidden, "help-text"},
-    {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
-};
-
-
-SettingEntry
-Thread::ThreadSettingsController::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." },
-    {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
-};
-
 lldb::StackFrameSP
 Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
 {
@@ -1168,3 +1010,231 @@
     snprintf(unknown_state_string, sizeof (unknown_state_string), "RunMode = %i", mode);
     return unknown_state_string;
 }
+
+#pragma mark "Thread::ThreadSettingsController"
+//--------------------------------------------------------------
+// class Thread::ThreadSettingsController
+//--------------------------------------------------------------
+
+Thread::ThreadSettingsController::ThreadSettingsController () :
+    UserSettingsController ("thread", Process::GetSettingsController())
+{
+    m_default_settings.reset (new ThreadInstanceSettings (*this, false, 
+                                                          InstanceSettings::GetDefaultName().AsCString()));
+}
+
+Thread::ThreadSettingsController::~ThreadSettingsController ()
+{
+}
+
+lldb::InstanceSettingsSP
+Thread::ThreadSettingsController::CreateInstanceSettings (const char *instance_name)
+{
+    ThreadInstanceSettings *new_settings = new ThreadInstanceSettings (*(Thread::GetSettingsController().get()),
+                                                                       false, instance_name);
+    lldb::InstanceSettingsSP new_settings_sp (new_settings);
+    return new_settings_sp;
+}
+
+#pragma mark "ThreadInstanceSettings"
+//--------------------------------------------------------------
+// class ThreadInstanceSettings
+//--------------------------------------------------------------
+
+ThreadInstanceSettings::ThreadInstanceSettings (UserSettingsController &owner, bool live_instance, const char *name) :
+    InstanceSettings (owner, (name == NULL ? InstanceSettings::InvalidName().AsCString() : name), 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()));
+        m_owner.RegisterInstanceSettings (this);
+    }
+
+    if (live_instance)
+    {
+        const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
+        CopyInstanceSettings (pending_settings,false);
+        //m_owner.RemovePendingSettings (m_instance_name);
+    }
+}
+
+ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
+    InstanceSettings (*(Thread::GetSettingsController().get()), CreateInstanceName().AsCString()),
+    m_avoid_regexp_ap (),
+    m_trace_enabled (rhs.m_trace_enabled)
+{
+    if (m_instance_name != InstanceSettings::GetDefaultName())
+    {
+        const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
+        CopyInstanceSettings (pending_settings,false);
+        m_owner.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,
+                                                         lldb::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;
+}
+
+//--------------------------------------------------
+// ThreadSettingsController Variable Tables
+//--------------------------------------------------
+
+SettingEntry
+Thread::ThreadSettingsController::global_settings_table[] =
+{
+  //{ "var-name",    var-type  ,        "default", enum-table, init'd, hidden, "help-text"},
+    {  NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
+};
+
+
+SettingEntry
+Thread::ThreadSettingsController::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 }
+};