Added the concept of a Read-Eval-Print-Loop to LLDB.

A REPL takes over the command line and typically treats input as source code.
REPLs can also do code completion.  The REPL class allows its subclasses to
implement the language-specific functionality without having to know about the
IOHandler-specific internals.

Also added a PluginManager-based way of getting to a REPL given a language and
a target.

Also brought in some utility code and expression options that are useful for
REPLs, such as line offsets for expressions, ANSI terminal coloring of errors,
and a few IOHandler convenience functions.

llvm-svn: 250753
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 9fff60c..e1779ab 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -156,6 +156,9 @@
 {   "use-external-editor",      OptionValue::eTypeBoolean     , true, false, NULL, NULL, "Whether to use an external editor or not." },
 {   "use-color",                OptionValue::eTypeBoolean     , true, true , NULL, NULL, "Whether to use Ansi color codes or not." },
 {   "auto-one-line-summaries",  OptionValue::eTypeBoolean     , true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },
+{   "auto-indent",              OptionValue::eTypeBoolean     , true, true , NULL, NULL, "If true, LLDB will auto indent/outdent code. Currently only supported in the REPL (default: true)." },
+{   "print-decls",              OptionValue::eTypeBoolean     , true, true , NULL, NULL, "If true, LLDB will print the values of variables declared in an expression. Currently only supported in the REPL (default: true)." },
+{   "tab-size",                 OptionValue::eTypeUInt64      , true, 4    , NULL, NULL, "The tab size to use when indenting code in multi-line input mode (default: 4)." },
 {   "escape-non-printables",    OptionValue::eTypeBoolean     , true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." },
 {   NULL,                       OptionValue::eTypeInvalid     , true, 0    , NULL, NULL, NULL }
 };
@@ -177,6 +180,9 @@
     ePropertyUseExternalEditor,
     ePropertyUseColor,
     ePropertyAutoOneLineSummaries,
+    ePropertyAutoIndent,
+    ePropertyPrintDecls,
+    ePropertyTabSize,
     ePropertyEscapeNonPrintables
 };
 
@@ -392,6 +398,49 @@
     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
 }
 
+bool
+Debugger::GetAutoIndent () const
+{
+    const uint32_t idx = ePropertyAutoIndent;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
+}
+
+bool
+Debugger::SetAutoIndent (bool b)
+{
+    const uint32_t idx = ePropertyAutoIndent;
+    return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+}
+
+bool
+Debugger::GetPrintDecls () const
+{
+    const uint32_t idx = ePropertyPrintDecls;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
+}
+
+bool
+Debugger::SetPrintDecls (bool b)
+{
+    const uint32_t idx = ePropertyPrintDecls;
+    return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+}
+
+uint32_t
+Debugger::GetTabSize () const
+{
+    const uint32_t idx = ePropertyTabSize;
+    return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value);
+}
+
+bool
+Debugger::SetTabSize (uint32_t tab_size)
+{
+    const uint32_t idx = ePropertyTabSize;
+    return m_collection_sp->SetPropertyAtIndexAsUInt64 (NULL, idx, tab_size);
+}
+
+
 #pragma mark Debugger
 
 //const DebuggerPropertiesSP &
@@ -919,6 +968,12 @@
     return m_input_reader_stack.IsTop (reader_sp);
 }
 
+bool
+Debugger::CheckTopIOHandlerTypes (IOHandler::Type top_type, IOHandler::Type second_top_type)
+{
+    return m_input_reader_stack.CheckTopIOHandlerTypes (top_type, second_top_type);
+}
+
 void
 Debugger::PrintAsync (const char *s, size_t len, bool is_stdout)
 {
@@ -1684,6 +1739,12 @@
 }
 
 bool
+Debugger::HasIOHandlerThread()
+{
+    return m_io_handler_thread.IsJoinable();
+}
+
+bool
 Debugger::StartIOHandlerThread()
 {
     if (!m_io_handler_thread.IsJoinable())
@@ -1706,6 +1767,17 @@
     }
 }
 
+void
+Debugger::JoinIOHandlerThread()
+{
+    if (HasIOHandlerThread())
+    {
+        thread_result_t result;
+        m_io_handler_thread.Join(&result);
+        m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
+    }
+}
+
 Target *
 Debugger::GetDummyTarget()
 {
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index b47a982..97116dd 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -2648,6 +2648,106 @@
     return NULL;
 }
 
+#pragma mark REPL
+
+struct REPLInstance
+{
+    REPLInstance() :
+    name(),
+    description(),
+    create_callback(NULL)
+    {
+    }
+    
+    ConstString name;
+    std::string description;
+    REPLCreateInstance create_callback;
+};
+
+typedef std::vector<REPLInstance> REPLInstances;
+
+static Mutex &
+GetREPLMutex ()
+{
+    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+    return g_instances_mutex;
+}
+
+static REPLInstances &
+GetREPLInstances ()
+{
+    static REPLInstances g_instances;
+    return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin (const ConstString &name,
+                               const char *description,
+                               REPLCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        REPLInstance instance;
+        assert ((bool)name);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        Mutex::Locker locker (GetREPLMutex ());
+        GetREPLInstances ().push_back (instance);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (REPLCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        Mutex::Locker locker (GetREPLMutex ());
+        REPLInstances &instances = GetREPLInstances ();
+        
+        REPLInstances::iterator pos, end = instances.end();
+        for (pos = instances.begin(); pos != end; ++ pos)
+        {
+            if (pos->create_callback == create_callback)
+            {
+                instances.erase(pos);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+REPLCreateInstance
+PluginManager::GetREPLCreateCallbackAtIndex (uint32_t idx)
+{
+    Mutex::Locker locker (GetREPLMutex ());
+    REPLInstances &instances = GetREPLInstances ();
+    if (idx < instances.size())
+        return instances[idx].create_callback;
+    return NULL;
+}
+
+REPLCreateInstance
+PluginManager::GetREPLCreateCallbackForPluginName (const ConstString &name)
+{
+    if (name)
+    {
+        Mutex::Locker locker (GetREPLMutex ());
+        REPLInstances &instances = GetREPLInstances ();
+        
+        REPLInstances::iterator pos, end = instances.end();
+        for (pos = instances.begin(); pos != end; ++ pos)
+        {
+            if (name == pos->name)
+                return pos->create_callback;
+        }
+    }
+    return NULL;
+}
+
 #pragma mark PluginManager
 
 void