<div dir="ltr">I think this is going to break the CMake build.  Can you update the relevant CMakeLists.txt file?<div><br></div><div>Also, are there any tests for this?</div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Oct 19, 2015 at 4:13 PM Sean Callanan via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: spyffe<br>
Date: Mon Oct 19 18:11:07 2015<br>
New Revision: 250753<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=250753&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=250753&view=rev</a><br>
Log:<br>
Added the concept of a Read-Eval-Print-Loop to LLDB.<br>
<br>
A REPL takes over the command line and typically treats input as source code.<br>
REPLs can also do code completion.  The REPL class allows its subclasses to<br>
implement the language-specific functionality without having to know about the<br>
IOHandler-specific internals.<br>
<br>
Also added a PluginManager-based way of getting to a REPL given a language and<br>
a target.<br>
<br>
Also brought in some utility code and expression options that are useful for<br>
REPLs, such as line offsets for expressions, ANSI terminal coloring of errors,<br>
and a few IOHandler convenience functions.<br>
<br>
Added:<br>
    lldb/trunk/include/lldb/Expression/REPL.h<br>
    lldb/trunk/source/Expression/REPL.cpp<br>
Modified:<br>
    lldb/trunk/include/lldb/Core/Debugger.h<br>
    lldb/trunk/include/lldb/Core/IOHandler.h<br>
    lldb/trunk/include/lldb/Core/PluginManager.h<br>
    lldb/trunk/include/lldb/Expression/UserExpression.h<br>
    lldb/trunk/include/lldb/Host/File.h<br>
    lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h<br>
    lldb/trunk/include/lldb/Target/Target.h<br>
    lldb/trunk/include/lldb/Utility/AnsiTerminal.h<br>
    lldb/trunk/include/lldb/lldb-forward.h<br>
    lldb/trunk/include/lldb/lldb-private-interfaces.h<br>
    lldb/trunk/lldb.xcodeproj/project.pbxproj<br>
    lldb/trunk/source/Core/Debugger.cpp<br>
    lldb/trunk/source/Core/PluginManager.cpp<br>
    lldb/trunk/source/Expression/UserExpression.cpp<br>
    lldb/trunk/source/Host/common/File.cpp<br>
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp<br>
    lldb/trunk/source/Target/Target.cpp<br>
<br>
Modified: lldb/trunk/include/lldb/Core/Debugger.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Core/Debugger.h (original)<br>
+++ lldb/trunk/include/lldb/Core/Debugger.h Mon Oct 19 18:11:07 2015<br>
@@ -203,6 +203,10 @@ public:<br>
<br>
     bool<br>
     IsTopIOHandler (const lldb::IOHandlerSP& reader_sp);<br>
+<br>
+    bool<br>
+    CheckTopIOHandlerTypes (IOHandler::Type top_type,<br>
+                            IOHandler::Type second_top_type);<br>
<br>
     void<br>
     PrintAsync (const char *s, size_t len, bool is_stdout);<br>
@@ -322,6 +326,24 @@ public:<br>
     GetAutoOneLineSummaries () const;<br>
<br>
     bool<br>
+    GetAutoIndent () const;<br>
+<br>
+    bool<br>
+    SetAutoIndent (bool b);<br>
+<br>
+    bool<br>
+    GetPrintDecls () const;<br>
+<br>
+    bool<br>
+    SetPrintDecls (bool b);<br>
+<br>
+    uint32_t<br>
+    GetTabSize () const;<br>
+<br>
+    bool<br>
+    SetTabSize (uint32_t tab_size);<br>
+<br>
+    bool<br>
     GetEscapeNonPrintables () const;<br>
<br>
     bool<br>
@@ -362,6 +384,7 @@ public:<br>
 protected:<br>
<br>
     friend class CommandInterpreter;<br>
+    friend class REPL;<br>
<br>
     bool<br>
     StartEventHandlerThread();<br>
@@ -373,11 +396,17 @@ protected:<br>
     EventHandlerThread (lldb::thread_arg_t arg);<br>
<br>
     bool<br>
+    HasIOHandlerThread();<br>
+<br>
+    bool<br>
     StartIOHandlerThread();<br>
<br>
     void<br>
     StopIOHandlerThread();<br>
<br>
+    void<br>
+    JoinIOHandlerThread();<br>
+<br>
     static lldb::thread_result_t<br>
     IOHandlerThread (lldb::thread_arg_t arg);<br>
<br>
<br>
Modified: lldb/trunk/include/lldb/Core/IOHandler.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/IOHandler.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/IOHandler.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Core/IOHandler.h (original)<br>
+++ lldb/trunk/include/lldb/Core/IOHandler.h Mon Oct 19 18:11:07 2015<br>
@@ -42,6 +42,7 @@ namespace lldb_private {<br>
             Confirm,<br>
             Curses,<br>
             Expression,<br>
+            REPL,<br>
             ProcessIO,<br>
             PythonInterpreter,<br>
             PythonCode,<br>
<br>
Modified: lldb/trunk/include/lldb/Core/PluginManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/PluginManager.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/PluginManager.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Core/PluginManager.h (original)<br>
+++ lldb/trunk/include/lldb/Core/PluginManager.h Mon Oct 19 18:11:07 2015<br>
@@ -444,6 +444,23 @@ public:<br>
     GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name);<br>
<br>
     //------------------------------------------------------------------<br>
+    // REPL<br>
+    //------------------------------------------------------------------<br>
+    static bool<br>
+    RegisterPlugin (const ConstString &name,<br>
+                    const char *description,<br>
+                    REPLCreateInstance create_callback);<br>
+<br>
+    static bool<br>
+    UnregisterPlugin (REPLCreateInstance create_callback);<br>
+<br>
+    static REPLCreateInstance<br>
+    GetREPLCreateCallbackAtIndex (uint32_t idx);<br>
+<br>
+    static REPLCreateInstance<br>
+    GetREPLCreateCallbackForPluginName (const ConstString &name);<br>
+<br>
+    //------------------------------------------------------------------<br>
     // Some plug-ins might register a DebuggerInitializeCallback<br>
     // callback when registering the plug-in. After a new Debugger<br>
     // instance is created, this DebuggerInitialize function will get<br>
<br>
Added: lldb/trunk/include/lldb/Expression/REPL.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/REPL.h?rev=250753&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/REPL.h?rev=250753&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Expression/REPL.h (added)<br>
+++ lldb/trunk/include/lldb/Expression/REPL.h Mon Oct 19 18:11:07 2015<br>
@@ -0,0 +1,185 @@<br>
+//===-- REPL.h --------------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+<br>
+#ifndef lldb_REPL_h<br>
+#define lldb_REPL_h<br>
+<br>
+#include "lldb/Interpreter/OptionGroupFormat.h"<br>
+#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"<br>
+#include "lldb/../../source/Commands/CommandObjectExpression.h"<br>
+<br>
+namespace lldb_private<br>
+{<br>
+<br>
+class REPL : public IOHandlerDelegate<br>
+{<br>
+public:<br>
+    //----------------------------------------------------------------------<br>
+    // See TypeSystem.h for how to add subclasses to this.<br>
+    //----------------------------------------------------------------------<br>
+    enum LLVMCastKind {<br>
+        eKindClang,<br>
+        eKindSwift,<br>
+        eKindGo,<br>
+        kNumKinds<br>
+    };<br>
+<br>
+    LLVMCastKind getKind() const { return m_kind; }<br>
+<br>
+    REPL(LLVMCastKind kind, Target &target);<br>
+<br>
+    virtual ~REPL();<br>
+<br>
+    static lldb::REPLSP<br>
+    Create (lldb::LanguageType language, Target *target);<br>
+<br>
+    void<br>
+    SetFormatOptions (const OptionGroupFormat &options)<br>
+    {<br>
+        m_format_options = options;<br>
+    }<br>
+<br>
+    void<br>
+    SetValueObjectDisplayOptions (const OptionGroupValueObjectDisplay &options)<br>
+    {<br>
+        m_varobj_options = options;<br>
+    }<br>
+<br>
+    void<br>
+    SetCommandOptions (const CommandObjectExpression::CommandOptions &options)<br>
+    {<br>
+        m_command_options = options;<br>
+    }<br>
+<br>
+    void<br>
+    SetCompilerOptions (const char *options)<br>
+    {<br>
+        if (options)<br>
+            m_compiler_options = options;<br>
+    }<br>
+<br>
+    lldb::IOHandlerSP<br>
+    GetIOHandler ();<br>
+<br>
+    Error<br>
+    RunLoop ();<br>
+<br>
+    //------------------------------------------------------------------<br>
+    // IOHandler::Delegate functions<br>
+    //------------------------------------------------------------------<br>
+    void<br>
+    IOHandlerActivated (IOHandler &io_handler) override;<br>
+<br>
+    bool<br>
+    IOHandlerInterrupt (IOHandler &io_handler) override;<br>
+<br>
+    void<br>
+    IOHandlerInputInterrupted (IOHandler &io_handler,<br>
+                               std::string &line) override;<br>
+<br>
+    const char *<br>
+    IOHandlerGetFixIndentationCharacters () override;<br>
+<br>
+    ConstString<br>
+    IOHandlerGetControlSequence (char ch) override;<br>
+<br>
+    const char *<br>
+    IOHandlerGetCommandPrefix () override;<br>
+<br>
+    const char *<br>
+    IOHandlerGetHelpPrologue () override;<br>
+<br>
+    bool<br>
+    IOHandlerIsInputComplete (IOHandler &io_handler,<br>
+                              StringList &lines) override;<br>
+<br>
+    int<br>
+    IOHandlerFixIndentation (IOHandler &io_handler,<br>
+                             const StringList &lines,<br>
+                             int cursor_position) override;<br>
+<br>
+    void<br>
+    IOHandlerInputComplete (IOHandler &io_handler,<br>
+                            std::string &line) override;<br>
+<br>
+    int<br>
+    IOHandlerComplete (IOHandler &io_handler,<br>
+                       const char *current_line,<br>
+                       const char *cursor,<br>
+                       const char *last_char,<br>
+                       int skip_first_n_matches,<br>
+                       int max_matches,<br>
+                       StringList &matches) override;<br>
+<br>
+private:<br>
+    std::string<br>
+    GetSourcePath();<br>
+<br>
+protected:<br>
+    static int<br>
+    CalculateActualIndentation (const StringList &lines);<br>
+<br>
+    //----------------------------------------------------------------------<br>
+    // Subclasses should override these functions to implement a functional REPL.<br>
+    //----------------------------------------------------------------------<br>
+<br>
+    virtual Error<br>
+    DoInitialization () = 0;<br>
+<br>
+    virtual ConstString<br>
+    GetSourceFileBasename () = 0;<br>
+<br>
+    virtual const char *<br>
+    GetAutoIndentCharacters () = 0;<br>
+<br>
+    virtual bool<br>
+    SourceIsComplete (const std::string &source) = 0;<br>
+<br>
+    virtual lldb::offset_t<br>
+    GetDesiredIndentation (const StringList &lines,<br>
+                           int cursor_position,<br>
+                           int tab_size) = 0; // LLDB_INVALID_OFFSET means no change<br>
+<br>
+    virtual lldb::LanguageType<br>
+    GetLanguage () = 0;<br>
+<br>
+    virtual bool<br>
+    PrintOneVariable (Debugger &debugger,<br>
+                      lldb::StreamFileSP &output_sp,<br>
+                      lldb::ValueObjectSP &valobj_sp,<br>
+                      ExpressionVariable *var = nullptr) = 0;<br>
+<br>
+    virtual int<br>
+    CompleteCode(const std::string &current_code,<br>
+                 StringList &matches) = 0;<br>
+<br>
+    OptionGroupFormat m_format_options = OptionGroupFormat(lldb::eFormatDefault);<br>
+    OptionGroupValueObjectDisplay m_varobj_options;<br>
+    CommandObjectExpression::CommandOptions m_command_options;<br>
+    std::string m_compiler_options;<br>
+<br>
+    bool m_enable_auto_indent = true;<br>
+    std::string m_indent_str; // Use this string for each level of indentation<br>
+    std::string m_current_indent_str;<br>
+    uint32_t m_current_indent_level = 0;<br>
+<br>
+    std::string m_repl_source_path;<br>
+    bool m_dedicated_repl_mode = false;<br>
+<br>
+    StringList m_code; // All accumulated REPL statements are saved here<br>
+<br>
+    Target &m_target;<br>
+    lldb::IOHandlerSP m_io_handler_sp;<br>
+    LLVMCastKind m_kind;<br>
+};<br>
+<br>
+}<br>
+<br>
+#endif /* REPL_h */<br>
<br>
Modified: lldb/trunk/include/lldb/Expression/UserExpression.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/UserExpression.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/UserExpression.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Expression/UserExpression.h (original)<br>
+++ lldb/trunk/include/lldb/Expression/UserExpression.h Mon Oct 19 18:11:07 2015<br>
@@ -273,10 +273,16 @@ public:<br>
     /// @param[in,out] result_valobj_sp<br>
     ///      If execution is successful, the result valobj is placed here.<br>
     ///<br>
-    /// @param[out]<br>
+    /// @param[out] error<br>
     ///     Filled in with an error in case the expression evaluation<br>
     ///     fails to parse, run, or evaluated.<br>
     ///<br>
+    /// @param[in] line_offset<br>
+    ///     The offset of the first line of the expression from the "beginning" of a virtual source file used for error reporting and debug info.<br>
+    ///<br>
+    /// @param[out] jit_module_sp_ptr<br>
+    ///     If non-NULL, used to persist the generated IR module.<br>
+    ///<br>
     /// @result<br>
     ///      A Process::ExpressionResults value.  eExpressionCompleted for success.<br>
     //------------------------------------------------------------------<br>
@@ -286,7 +292,9 @@ public:<br>
               const char *expr_cstr,<br>
               const char *expr_prefix,<br>
               lldb::ValueObjectSP &result_valobj_sp,<br>
-              Error &error);<br>
+              Error &error,<br>
+              uint32_t line_offset = 0,<br>
+              lldb::ModuleSP *jit_module_sp_ptr = NULL);<br>
<br>
     static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.<br>
 protected:<br>
<br>
Modified: lldb/trunk/include/lldb/Host/File.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/File.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/File.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Host/File.h (original)<br>
+++ lldb/trunk/include/lldb/Host/File.h Mon Oct 19 18:11:07 2015<br>
@@ -494,6 +494,9 @@ public:<br>
     //------------------------------------------------------------------<br>
     bool<br>
     GetIsRealTerminal ();<br>
+<br>
+    bool<br>
+    GetIsTerminalWithColors ();<br>
<br>
     //------------------------------------------------------------------<br>
     /// Output printf formatted output to the stream.<br>
@@ -546,6 +549,7 @@ protected:<br>
     bool m_own_stream;<br>
     LazyBool m_is_interactive;<br>
     LazyBool m_is_real_terminal;<br>
+    LazyBool m_supports_colors;<br>
 };<br>
<br>
 } // namespace lldb_private<br>
<br>
Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)<br>
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Mon Oct 19 18:11:07 2015<br>
@@ -659,6 +659,9 @@ public:<br>
         return m_stopped_for_crash;<br>
     }<br>
<br>
+    bool<br>
+    GetSpaceReplPrompts () const;<br>
+<br>
 protected:<br>
     friend class Debugger;<br>
<br>
<br>
Modified: lldb/trunk/include/lldb/Target/Target.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Target/Target.h (original)<br>
+++ lldb/trunk/include/lldb/Target/Target.h Mon Oct 19 18:11:07 2015<br>
@@ -442,6 +442,18 @@ public:<br>
     }<br>
<br>
     bool<br>
+    GetColorizeErrors () const<br>
+    {<br>
+        return m_ansi_color_errors;<br>
+    }<br>
+<br>
+    void<br>
+    SetColorizeErrors (bool b)<br>
+    {<br>
+        m_ansi_color_errors = b;<br>
+    }<br>
+<br>
+    bool<br>
     GetTrapExceptions() const<br>
     {<br>
         return m_trap_exceptions;<br>
@@ -453,6 +465,18 @@ public:<br>
         m_trap_exceptions = b;<br>
     }<br>
<br>
+    bool<br>
+    GetREPLEnabled() const<br>
+    {<br>
+        return m_repl;<br>
+    }<br>
+<br>
+    void<br>
+    SetREPLEnabled (bool b)<br>
+    {<br>
+        m_repl = b;<br>
+    }<br>
+<br>
     void<br>
     SetCancelCallback (lldb::ExpressionCancelCallback callback, void *baton)<br>
     {<br>
@@ -468,6 +492,37 @@ public:<br>
         else<br>
             return m_cancel_callback (phase, m_cancel_callback_baton);<br>
     }<br>
+<br>
+    // Allows the expression contents to be remapped to point to the specified file and line<br>
+    // using #line directives.<br>
+    void<br>
+    SetPoundLine (const char *path, uint32_t line) const<br>
+    {<br>
+        if (path && path[0])<br>
+        {<br>
+            m_pound_line_file = path;<br>
+            m_pound_line_line = line;<br>
+        }<br>
+        else<br>
+        {<br>
+            m_pound_line_file.clear();<br>
+            m_pound_line_line = 0;<br>
+        }<br>
+    }<br>
+<br>
+    const char *<br>
+    GetPoundLineFilePath () const<br>
+    {<br>
+        if (m_pound_line_file.empty())<br>
+            return NULL;<br>
+        return m_pound_line_file.c_str();<br>
+    }<br>
+<br>
+    uint32_t<br>
+    GetPoundLineLine () const<br>
+    {<br>
+        return m_pound_line_line;<br>
+    }<br>
<br>
     void<br>
     SetResultIsInternal (bool b)<br>
@@ -493,13 +548,20 @@ private:<br>
     bool m_stop_others;<br>
     bool m_debug;<br>
     bool m_trap_exceptions;<br>
+    bool m_repl;<br>
     bool m_generate_debug_info;<br>
+    bool m_ansi_color_errors;<br>
     bool m_result_is_internal;<br>
     lldb::DynamicValueType m_use_dynamic;<br>
     uint32_t m_timeout_usec;<br>
     uint32_t m_one_thread_timeout_usec;<br>
     lldb::ExpressionCancelCallback m_cancel_callback;<br>
     void *m_cancel_callback_baton;<br>
+    // If m_pound_line_file is not empty and m_pound_line_line is non-zero,<br>
+    // use #line %u "%s" before the expression content to remap where the source<br>
+    // originates<br>
+    mutable std::string m_pound_line_file;<br>
+    mutable uint32_t m_pound_line_line;<br>
 };<br>
<br>
 //----------------------------------------------------------------------<br>
@@ -1504,8 +1566,11 @@ public:<br>
<br>
     lldb::SearchFilterSP<br>
     GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles);<br>
+<br>
+    lldb::REPLSP<br>
+    GetREPL (lldb::LanguageType, bool can_create);<br>
<br>
-protected:<br>
+protected:<br>
     //------------------------------------------------------------------<br>
     // Member variables.<br>
     //------------------------------------------------------------------<br>
@@ -1528,6 +1593,9 @@ protected:<br>
     PathMappingList m_image_search_paths;<br>
     TypeSystemMap m_scratch_type_system_map;<br>
<br>
+    typedef std::map<lldb::LanguageType, lldb::REPLSP> REPLMap;<br>
+    REPLMap m_repl_map;<br>
+<br>
     lldb::ClangASTImporterUP m_ast_importer_ap;<br>
     lldb::ClangModulesDeclVendorUP m_clang_modules_decl_vendor_ap;<br>
<br>
<br>
Modified: lldb/trunk/include/lldb/Utility/AnsiTerminal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/AnsiTerminal.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/AnsiTerminal.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Utility/AnsiTerminal.h (original)<br>
+++ lldb/trunk/include/lldb/Utility/AnsiTerminal.h Mon Oct 19 18:11:07 2015<br>
@@ -41,8 +41,13 @@<br>
 #define ANSI_CTRL_CONCEAL           8<br>
 #define ANSI_CTRL_CROSSED_OUT       9<br>
<br>
-#define ANSI_ESC_START          "\033["<br>
-#define ANSI_ESC_END            "m"<br>
+#define ANSI_ESC_START              "\033["<br>
+#define ANSI_ESC_END                "m"<br>
+<br>
+#define ANSI_STR(s)                 #s<br>
+#define ANSI_DEF_STR(s)             ANSI_STR(s)<br>
+<br>
+#define ANSI_ESCAPE1(s)             ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END<br>
<br>
 #define ANSI_1_CTRL(ctrl1)          "\033["##ctrl1 ANSI_ESC_END<br>
 #define ANSI_2_CTRL(ctrl1,ctrl2)    "\033["##ctrl1";"##ctrl2 ANSI_ESC_END<br>
<br>
Modified: lldb/trunk/include/lldb/lldb-forward.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/lldb-forward.h (original)<br>
+++ lldb/trunk/include/lldb/lldb-forward.h Mon Oct 19 18:11:07 2015<br>
@@ -183,6 +183,7 @@ class   RegisterLocation;<br>
 class   RegisterLocationList;<br>
 class   RegisterValue;<br>
 class   RegularExpression;<br>
+class   REPL;<br>
 class   Scalar;<br>
 class   ScriptInterpreter;<br>
 class   ScriptInterpreterLocker;<br>
@@ -382,6 +383,7 @@ namespace lldb {<br>
     typedef std::shared_ptr<lldb_private::Queue> QueueSP;<br>
     typedef std::weak_ptr<lldb_private::Queue> QueueWP;<br>
     typedef std::shared_ptr<lldb_private::QueueItem> QueueItemSP;<br>
+    typedef std::shared_ptr<lldb_private::REPL> REPLSP;<br>
     typedef std::shared_ptr<lldb_private::ScriptSummaryFormat> ScriptSummaryFormatSP;<br>
     typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;<br>
     typedef std::unique_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterUP;<br>
<br>
Modified: lldb/trunk/include/lldb/lldb-private-interfaces.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/lldb-private-interfaces.h (original)<br>
+++ lldb/trunk/include/lldb/lldb-private-interfaces.h Mon Oct 19 18:11:07 2015<br>
@@ -49,6 +49,7 @@ namespace lldb_private<br>
     typedef lldb::InstrumentationRuntimeType (*InstrumentationRuntimeGetType) ();<br>
     typedef lldb::InstrumentationRuntimeSP (*InstrumentationRuntimeCreateInstance) (const lldb::ProcessSP &process_sp);<br>
     typedef lldb::TypeSystemSP (*TypeSystemCreateInstance) (lldb::LanguageType language, Module *module, Target *target);<br>
+    typedef lldb::REPLSP (*REPLCreateInstance) (lldb::LanguageType language, Target *target);<br>
     typedef void (*TypeSystemEnumerateSupportedLanguages) (std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions);<br>
     typedef int (*ComparisonFunction)(const void *, const void *);<br>
     typedef void (*DebuggerInitializeCallback)(Debugger &debugger);<br>
<br>
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)<br>
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon Oct 19 18:11:07 2015<br>
@@ -668,6 +668,7 @@<br>
                449ACC98197DEA0B008D175E /* FastDemangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 449ACC96197DE9EC008D175E /* FastDemangle.cpp */; };<br>
                490A36C0180F0E6F00BA31F8 /* PlatformWindows.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 490A36BD180F0E6F00BA31F8 /* PlatformWindows.cpp */; };<br>
                490A966B1628C3BF00F0002E /* SBDeclaration.h in Headers */ = {isa = PBXBuildFile; fileRef = 9452573816262CEF00325455 /* SBDeclaration.h */; settings = {ATTRIBUTES = (Public, ); }; };<br>
+               4939EA8D1BD56B6D00084382 /* REPL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4939EA8C1BD56B6D00084382 /* REPL.cpp */; };<br>
                494260DA14579144003C1C78 /* VerifyDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 494260D914579144003C1C78 /* VerifyDecl.cpp */; };<br>
                4959511F1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */; };<br>
                4966DCC4148978A10028481B /* ClangExternalASTSourceCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4966DCC3148978A10028481B /* ClangExternalASTSourceCommon.cpp */; };<br>
@@ -2254,6 +2255,8 @@<br>
                491193501226386000578B7F /* ASTStructExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStructExtractor.cpp; path = ExpressionParser/Clang/ASTStructExtractor.cpp; sourceTree = "<group>"; };<br>
                49307AAD11DEA4D90081F992 /* IRForTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRForTarget.cpp; path = ExpressionParser/Clang/IRForTarget.cpp; sourceTree = "<group>"; };<br>
                49307AB111DEA4F20081F992 /* IRForTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRForTarget.h; path = ExpressionParser/Clang/IRForTarget.h; sourceTree = "<group>"; };<br>
+               4939EA8B1BD56B3700084382 /* REPL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = REPL.h; path = include/lldb/Expression/REPL.h; sourceTree = "<group>"; };<br>
+               4939EA8C1BD56B6D00084382 /* REPL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = REPL.cpp; path = source/Expression/REPL.cpp; sourceTree = "<group>"; };<br>
                494260D7145790D5003C1C78 /* VerifyDecl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VerifyDecl.h; path = include/lldb/Symbol/VerifyDecl.h; sourceTree = "<group>"; };<br>
                494260D914579144003C1C78 /* VerifyDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VerifyDecl.cpp; path = source/Symbol/VerifyDecl.cpp; sourceTree = "<group>"; };<br>
                49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionParser.cpp; path = ExpressionParser/Clang/ClangExpressionParser.cpp; sourceTree = "<group>"; };<br>
@@ -4447,6 +4450,8 @@<br>
                                496B01581406DE8900F830D5 /* IRInterpreter.cpp */,<br>
                                49DCF6FF170E6FD90092F75E /* Materializer.h */,<br>
                                49DCF700170E70120092F75E /* Materializer.cpp */,<br>
+                               4939EA8B1BD56B3700084382 /* REPL.h */,<br>
+                               4939EA8C1BD56B6D00084382 /* REPL.cpp */,<br>
                        );<br>
                        name = Expression;<br>
                        sourceTree = "<group>";<br>
@@ -6371,6 +6376,7 @@<br>
                                2689005F13353E0E00698AC0 /* ClangFunctionCaller.cpp in Sources */,<br>
                                2689006013353E0E00698AC0 /* ClangExpressionDeclMap.cpp in Sources */,<br>
                                2689006113353E0E00698AC0 /* ClangExpressionParser.cpp in Sources */,<br>
+                               4939EA8D1BD56B6D00084382 /* REPL.cpp in Sources */,<br>
                                B5EFAE861AE53B1D007059F3 /* RegisterContextFreeBSD_arm.cpp in Sources */,<br>
                                2689006313353E0E00698AC0 /* ClangPersistentVariables.cpp in Sources */,<br>
                                2689006413353E0E00698AC0 /* ClangUserExpression.cpp in Sources */,<br>
<br>
Modified: lldb/trunk/source/Core/Debugger.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Core/Debugger.cpp (original)<br>
+++ lldb/trunk/source/Core/Debugger.cpp Mon Oct 19 18:11:07 2015<br>
@@ -156,6 +156,9 @@ g_properties[] =<br>
 {   "use-external-editor",      OptionValue::eTypeBoolean     , true, false, NULL, NULL, "Whether to use an external editor or not." },<br>
 {   "use-color",                OptionValue::eTypeBoolean     , true, true , NULL, NULL, "Whether to use Ansi color codes or not." },<br>
 {   "auto-one-line-summaries",  OptionValue::eTypeBoolean     , true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },<br>
+{   "auto-indent",              OptionValue::eTypeBoolean     , true, true , NULL, NULL, "If true, LLDB will auto indent/outdent code. Currently only supported in the REPL (default: true)." },<br>
+{   "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)." },<br>
+{   "tab-size",                 OptionValue::eTypeUInt64      , true, 4    , NULL, NULL, "The tab size to use when indenting code in multi-line input mode (default: 4)." },<br>
 {   "escape-non-printables",    OptionValue::eTypeBoolean     , true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." },<br>
 {   NULL,                       OptionValue::eTypeInvalid     , true, 0    , NULL, NULL, NULL }<br>
 };<br>
@@ -177,6 +180,9 @@ enum<br>
     ePropertyUseExternalEditor,<br>
     ePropertyUseColor,<br>
     ePropertyAutoOneLineSummaries,<br>
+    ePropertyAutoIndent,<br>
+    ePropertyPrintDecls,<br>
+    ePropertyTabSize,<br>
     ePropertyEscapeNonPrintables<br>
 };<br>
<br>
@@ -392,6 +398,49 @@ Debugger::GetEscapeNonPrintables () cons<br>
     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);<br>
 }<br>
<br>
+bool<br>
+Debugger::GetAutoIndent () const<br>
+{<br>
+    const uint32_t idx = ePropertyAutoIndent;<br>
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);<br>
+}<br>
+<br>
+bool<br>
+Debugger::SetAutoIndent (bool b)<br>
+{<br>
+    const uint32_t idx = ePropertyAutoIndent;<br>
+    return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);<br>
+}<br>
+<br>
+bool<br>
+Debugger::GetPrintDecls () const<br>
+{<br>
+    const uint32_t idx = ePropertyPrintDecls;<br>
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);<br>
+}<br>
+<br>
+bool<br>
+Debugger::SetPrintDecls (bool b)<br>
+{<br>
+    const uint32_t idx = ePropertyPrintDecls;<br>
+    return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);<br>
+}<br>
+<br>
+uint32_t<br>
+Debugger::GetTabSize () const<br>
+{<br>
+    const uint32_t idx = ePropertyTabSize;<br>
+    return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value);<br>
+}<br>
+<br>
+bool<br>
+Debugger::SetTabSize (uint32_t tab_size)<br>
+{<br>
+    const uint32_t idx = ePropertyTabSize;<br>
+    return m_collection_sp->SetPropertyAtIndexAsUInt64 (NULL, idx, tab_size);<br>
+}<br>
+<br>
+<br>
 #pragma mark Debugger<br>
<br>
 //const DebuggerPropertiesSP &<br>
@@ -919,6 +968,12 @@ Debugger::IsTopIOHandler (const lldb::IO<br>
     return m_input_reader_stack.IsTop (reader_sp);<br>
 }<br>
<br>
+bool<br>
+Debugger::CheckTopIOHandlerTypes (IOHandler::Type top_type, IOHandler::Type second_top_type)<br>
+{<br>
+    return m_input_reader_stack.CheckTopIOHandlerTypes (top_type, second_top_type);<br>
+}<br>
+<br>
 void<br>
 Debugger::PrintAsync (const char *s, size_t len, bool is_stdout)<br>
 {<br>
@@ -1684,6 +1739,12 @@ Debugger::IOHandlerThread (lldb::thread_<br>
 }<br>
<br>
 bool<br>
+Debugger::HasIOHandlerThread()<br>
+{<br>
+    return m_io_handler_thread.IsJoinable();<br>
+}<br>
+<br>
+bool<br>
 Debugger::StartIOHandlerThread()<br>
 {<br>
     if (!m_io_handler_thread.IsJoinable())<br>
@@ -1706,6 +1767,17 @@ Debugger::StopIOHandlerThread()<br>
     }<br>
 }<br>
<br>
+void<br>
+Debugger::JoinIOHandlerThread()<br>
+{<br>
+    if (HasIOHandlerThread())<br>
+    {<br>
+        thread_result_t result;<br>
+        m_io_handler_thread.Join(&result);<br>
+        m_io_handler_thread = LLDB_INVALID_HOST_THREAD;<br>
+    }<br>
+}<br>
+<br>
 Target *<br>
 Debugger::GetDummyTarget()<br>
 {<br>
<br>
Modified: lldb/trunk/source/Core/PluginManager.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/PluginManager.cpp?rev=250753&r1=250752&r2=250753&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/PluginManager.cpp?rev=250753&r1=250752&r2=250753&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Core/PluginManager.cpp (original)<br>
+++ lldb/trunk/source/Core/PluginManager.cpp Mon Oct 19 18:11:07 2015<br>
@@ -2648,6 +2648,106 @@ PluginManager::GetTypeSystemEnumerateSup<br>
     return NULL;<br>
 }<br>
<br>
+#pragma mark REPL<br>
+<br>
+struct REPLInstance<br>
+{<br>
+    REPLInstance() :<br>
+    name(),<br>
+    description(),<br>
+    create_callback(NULL)<br>
+    {<br>
+    }<br>
+<br>
+    ConstString name;<br>
+    std::string description;<br>
+    REPLCreateInstance create_callback;<br>
+};<br>
+<br>
+typedef std::vector<REPLInstance> REPLInstances;<br>
+<br>
+static Mutex &<br>
+GetREPLMutex ()<br>
+{<br>
+    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);<br>
+    return g_instances_mutex;<br>
+}<br>
+<br>
+static REPLInstances &<br>
+GetREPLInstances ()<br>
+{<br>
+    static REPLInstances g_instances;<br>
+    return g_instances;<br>
+}<br>
+<br>
+bool<br>
+PluginManager::RegisterPlugin (const ConstString &name,<br>
+                               const char *description,<br>
+                               REPLCreateInstance create_callback)<br>
+{<br>
+    if (create_callback)<br>
+    {<br>
+        REPLInstance instance;<br>
+        assert ((bool)name);<br>
+        <a href="http://instance.name" rel="noreferrer" target="_blank">instance.name</a> = name;<br>
+        if (description && description[0])<br>
+            instance.description = description;<br>
+        instance.create_callback = create_callback;<br>
+        Mutex::Locker locker (GetREPLMutex ());<br>
+        GetREPLInstances ().push_back (instance);<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+bool<br>
+PluginManager::UnregisterPlugin (REPLCreateInstance create_callback)<br>
+{<br>
+    if (create_callback)<br>
+    {<br>
+        Mutex::Locker locker (GetREPLMutex ());<br>
+        REPLInstances &instances = GetREPLInstances ();<br>
+<br>
+        REPLInstances::iterator pos, end = instances.end();<br>
+        for (pos = instances.begin(); pos != end; ++ pos)<br>
+        {<br>
+            if (pos->create_callback == create_callback)<br>
+            {<br>
+                instances.erase(pos);<br>
+                return true;<br>
+            }<br>
+        }<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+REPLCreateInstance<br>
+PluginManager::GetREPLCreateCallbackAtIndex (uint32_t idx)<br>
+{<br>
+    Mutex::Locker locker (GetREPLMutex ());<br>
+    REPLInstances &instances = GetREPLInstances ();<br>
+    if (idx < instances.size())<br>
+        return instances[idx].create_callback;<br>
+    return NULL;<br>
+}<br>
+<br>
+REPLCreateInstance<br>
+PluginManager::GetREPLCreateCallbackForPluginName (const ConstString &name)<br>
+{<br>
+    if (name)<br>
+    {<br>
+        Mutex::Locker locker (GetREPLMutex ());<br>
+        REPLInstances &instances = GetREPLInstances ();<br>
+<br>
+        REPLInstances::iterator pos, end = instances.end();<br>
+        for (pos = instances.begin(); pos != end; ++ pos)<br>
+        {<br>
+            if (name == pos->name)<br>
+                return pos->create_callback;<br>
+        }<br>
+    }<br>
+    return NULL;<br>
+}<br>
+<br>
 #pragma mark PluginManager<br>
<br>
 void<br>
<br>
Added: lldb/trunk/source/Expression/REPL.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/REPL.cpp?rev=250753&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/REPL.cpp?rev=250753&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/source/Expression/REPL.cpp (added)<br>
+++ lldb/trunk/source/Expression/REPL.cpp Mon Oct 19 18:11:07 2015<br>
@@ -0,0 +1,650 @@<br>
+//===-- REPL.cpp ------------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "lldb/Core/Debugger.h"<br>
+#include "lldb/Core/PluginManager.h"<br>
+#include "lldb/Core/StreamFile.h"<br>
+#include "lldb/Expression/ExpressionVariable.h"<br>
+#include "lldb/Expression/REPL.h"<br>
+#include "lldb/Expression/UserExpression.h"<br>
+#include "lldb/Host/HostInfo.h"<br>
+#include "lldb/Interpreter/CommandInterpreter.h"<br>
+#include "lldb/Interpreter/CommandReturnObject.h"<br>
+#include "lldb/Target/Target.h"<br>
+#include "lldb/Target/Thread.h"<br>
+#include "lldb/Utility/AnsiTerminal.h"<br>
+<br>
+using namespace lldb_private;<br>
+<br>
+lldb::REPLSP<br>
+REPL::Create(lldb::LanguageType language, Target *target)<br>
+{<br>
+    uint32_t idx = 0;<br>
+    lldb::REPLSP ret;<br>
+<br>
+    while (REPLCreateInstance create_instance = PluginManager::GetREPLCreateCallbackAtIndex(idx++))<br>
+    {<br>
+        ret = (*create_instance)(language, target);<br>
+        if (ret)<br>
+        {<br>
+            break;<br>
+        }<br>
+    }<br>
+<br>
+    return ret;<br>
+}<br>
+<br>
+REPL::REPL(LLVMCastKind kind, Target &target) :<br>
+    m_target(target),<br>
+    m_kind(kind)<br>
+{<br>
+    // Make sure all option values have sane defaults<br>
+    Debugger &debugger = m_target.GetDebugger();<br>
+    CommandInterpreter &ci = debugger.GetCommandInterpreter();<br>
+    m_format_options.OptionParsingStarting(ci);<br>
+    m_varobj_options.OptionParsingStarting(ci);<br>
+    m_command_options.OptionParsingStarting(ci);<br>
+<br>
+    // Default certain settings for REPL regardless of the global settings.<br>
+    m_command_options.unwind_on_error = false;<br>
+    m_command_options.ignore_breakpoints = false;<br>
+    m_command_options.debug = false;<br>
+}<br>
+<br>
+std::string<br>
+REPL::GetSourcePath()<br>
+{<br>
+    ConstString file_basename = GetSourceFileBasename();<br>
+<br>
+    FileSpec tmpdir_file_spec;<br>
+    if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))<br>
+    {<br>
+        tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString());<br>
+        m_repl_source_path = std::move(tmpdir_file_spec.GetPath());<br>
+    }<br>
+    else<br>
+    {<br>
+        tmpdir_file_spec = FileSpec("/tmp", false);<br>
+        tmpdir_file_spec.AppendPathComponent(file_basename.AsCString());<br>
+    }<br>
+<br>
+    return tmpdir_file_spec.GetPath();<br>
+}<br>
+<br>
+REPL::~REPL()<br>
+{<br>
+}<br>
+<br>
+lldb::IOHandlerSP<br>
+REPL::GetIOHandler()<br>
+{<br>
+    if (!m_io_handler_sp)<br>
+    {<br>
+        Debugger &debugger = m_target.GetDebugger();<br>
+        m_io_handler_sp.reset (new IOHandlerEditline (debugger,<br>
+                                                      IOHandler::Type::REPL,<br>
+                                                      "lldb-repl",     // Name of input reader for history<br>
+                                                      "> ",             // prompt<br>
+                                                      ". ",             // Continuation prompt<br>
+                                                      true,             // Multi-line<br>
+                                                      true,             // The REPL prompt is always colored<br>
+                                                      1,                // Line number<br>
+                                                      *this));<br>
+<br>
+        // Don't exit if CTRL+C is pressed<br>
+        static_cast<IOHandlerEditline *>(m_io_handler_sp.get())->SetInterruptExits(false);<br>
+<br>
+        if (m_io_handler_sp->GetIsInteractive() && m_io_handler_sp->GetIsRealTerminal())<br>
+        {<br>
+            m_indent_str.assign (debugger.GetTabSize(), ' ');<br>
+            m_enable_auto_indent = debugger.GetAutoIndent();<br>
+        }<br>
+        else<br>
+        {<br>
+            m_indent_str.clear();<br>
+            m_enable_auto_indent = false;<br>
+        }<br>
+<br>
+    }<br>
+    return m_io_handler_sp;<br>
+}<br>
+<br>
+void<br>
+REPL::IOHandlerActivated (IOHandler &io_handler)<br>
+{<br>
+    lldb::ProcessSP process_sp = m_target.GetProcessSP();<br>
+    if (process_sp && process_sp->IsAlive())<br>
+        return;<br>
+    lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());<br>
+    error_sp->Printf("REPL requires a running target process.\n");<br>
+    io_handler.SetIsDone(true);<br>
+}<br>
+<br>
+bool<br>
+REPL::IOHandlerInterrupt (IOHandler &io_handler)<br>
+{<br>
+    return false;<br>
+}<br>
+<br>
+void<br>
+REPL::IOHandlerInputInterrupted (IOHandler &io_handler,<br>
+                                 std::string &line)<br>
+{<br>
+}<br>
+<br>
+const char *<br>
+REPL::IOHandlerGetFixIndentationCharacters ()<br>
+{<br>
+    if (m_enable_auto_indent)<br>
+        return GetAutoIndentCharacters();<br>
+    return NULL;<br>
+}<br>
+<br>
+ConstString<br>
+REPL::IOHandlerGetControlSequence (char ch)<br>
+{<br>
+    if (ch == 'd')<br>
+        return ConstString(":quit\n");<br>
+    return ConstString();<br>
+}<br>
+<br>
+const char *<br>
+REPL::IOHandlerGetCommandPrefix ()<br>
+{<br>
+    return ":";<br>
+}<br>
+<br>
+const char *<br>
+REPL::IOHandlerGetHelpPrologue ()<br>
+{<br>
+    return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter.  "<br>
+    "Valid statements, expressions, and declarations are immediately compiled and executed.\n\n"<br>
+    "The complete set of LLDB debugging commands are also available as described below.  Commands "<br>
+    "must be prefixed with a colon at the REPL prompt (:quit for example.)  Typing just a colon "<br>
+    "followed by return will switch to the LLDB prompt.\n\n";<br>
+}<br>
+<br>
+bool<br>
+REPL::IOHandlerIsInputComplete (IOHandler &io_handler,<br>
+                                StringList &lines)<br>
+{<br>
+    // Check for meta command<br>
+    const size_t num_lines = lines.GetSize();<br>
+    if (num_lines == 1)<br>
+    {<br>
+        const char *first_line = lines.GetStringAtIndex(0);<br>
+        if (first_line[0] == ':')<br>
+            return true; // Meta command is a single line where that starts with ':'<br>
+    }<br>
+<br>
+    // Check if REPL input is done<br>
+    std::string source_string (lines.CopyList());<br>
+    return SourceIsComplete(source_string);<br>
+}<br>
+<br>
+int<br>
+REPL::CalculateActualIndentation (const StringList &lines)<br>
+{<br>
+    std::string last_line = lines[lines.GetSize() - 1];<br>
+<br>
+    int actual_indent = 0;<br>
+    for (char &ch : last_line)<br>
+    {<br>
+        if (ch != ' ') break;<br>
+        ++actual_indent;<br>
+    }<br>
+<br>
+    return actual_indent;<br>
+}<br>
+<br>
+int<br>
+REPL::IOHandlerFixIndentation (IOHandler &io_handler,<br>
+                               const StringList &lines,<br>
+                               int cursor_position)<br>
+{<br>
+    if (!m_enable_auto_indent) return 0;<br>
+<br>
+    if (!lines.GetSize())<br>
+    {<br>
+        return 0;<br>
+    }<br>
+<br>
+    int tab_size = io_handler.GetDebugger().GetTabSize();<br>
+<br>
+    lldb::offset_t desired_indent = GetDesiredIndentation(lines,<br>
+                                                          cursor_position,<br>
+                                                          tab_size);<br>
+<br>
+    int actual_indent = REPL::CalculateActualIndentation(lines);<br>
+<br>
+    if (desired_indent == LLDB_INVALID_OFFSET)<br>
+        return 0;<br>
+<br>
+    return (int)desired_indent - actual_indent;<br>
+}<br>
+<br>
+void<br>
+REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code)<br>
+{<br>
+    lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile());<br>
+    lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());<br>
+    bool extra_line = false;<br>
+    bool did_quit = false;<br>
+<br>
+    if (code.empty())<br>
+    {<br>
+        m_code.AppendString("");<br>
+        static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);<br>
+    }<br>
+    else<br>
+    {<br>
+        Debugger &debugger = m_target.GetDebugger();<br>
+        CommandInterpreter &ci = debugger.GetCommandInterpreter();<br>
+        extra_line = ci.GetSpaceReplPrompts();<br>
+<br>
+        ExecutionContext exe_ctx (m_target.GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame().get());<br>
+<br>
+        lldb::ProcessSP process_sp(exe_ctx.GetProcessSP());<br>
+<br>
+        if (code[0] == ':')<br>
+        {<br>
+            // Meta command<br>
+            // Strip the ':'<br>
+            code.erase(0, 1);<br>
+            if (Args::StripSpaces (code))<br>
+            {<br>
+                // "lldb" was followed by arguments, so just execute the command dump the results<br>
+<br>
+                // Turn off prompt on quit in case the user types ":quit"<br>
+                const bool saved_prompt_on_quit = ci.GetPromptOnQuit();<br>
+                if (saved_prompt_on_quit)<br>
+                    ci.SetPromptOnQuit(false);<br>
+<br>
+                // Execute the command<br>
+                CommandReturnObject result;<br>
+                result.SetImmediateOutputStream(output_sp);<br>
+                result.SetImmediateErrorStream(error_sp);<br>
+                ci.HandleCommand(code.c_str(), eLazyBoolNo, result);<br>
+<br>
+                if (saved_prompt_on_quit)<br>
+                    ci.SetPromptOnQuit(true);<br>
+<br>
+                if (result.GetStatus() == lldb::eReturnStatusQuit)<br>
+                {<br>
+                    did_quit = true;<br>
+                    io_handler.SetIsDone(true);<br>
+                    if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))<br>
+                    {<br>
+                        // We typed "quit" or an alias to quit so we need to check if the<br>
+                        // command interpreter is above us and tell it that it is done as well<br>
+                        // so we don't drop back into the command interpreter if we have already<br>
+                        // quit<br>
+                        lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());<br>
+                        if (io_handler_sp)<br>
+                            io_handler_sp->SetIsDone(true);<br>
+                    }<br>
+                }<br>
+            }<br>
+            else<br>
+            {<br>
+                // ":" was followed by no arguments, so push the LLDB command prompt<br>
+                if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))<br>
+                {<br>
+                    // If the user wants to get back to the command interpreter and the<br>
+                    // command interpreter is what launched the REPL, then just let the<br>
+                    // REPL exit and fall back to the command interpreter.<br>
+                    io_handler.SetIsDone(true);<br>
+                }<br>
+                else<br>
+                {<br>
+                    // The REPL wasn't launched the by the command interpreter, it is the<br>
+                    // base IOHandler, so we need to get the command interpreter and<br>
+                    lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());<br>
+                    if (io_handler_sp)<br>
+                    {<br>
+                        io_handler_sp->SetIsDone(false);<br>
+                        debugger.PushIOHandler(ci.GetIOHandler());<br>
+                    }<br>
+                }<br>
+            }<br>
+        }<br>
+        else<br>
+        {<br>
+            // Unwind any expression we might have been running in case our REPL<br>
+            // expression crashed and the user was looking around<br>
+            if (m_dedicated_repl_mode)<br>
+            {<br>
+                Thread *thread = exe_ctx.GetThreadPtr();<br>
+                if (thread && thread->UnwindInnermostExpression().Success())<br>
+                {<br>
+                    thread->SetSelectedFrameByIndex(0, false);<br>
+                    exe_ctx.SetFrameSP(thread->GetSelectedFrame());<br>
+                }<br>
+            }<br>
+<br>
+            const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();<br>
+<br>
+            EvaluateExpressionOptions expr_options;<br>
+            expr_options.SetCoerceToId(m_varobj_options.use_objc);<br>
+            expr_options.SetUnwindOnError(m_command_options.unwind_on_error);<br>
+            expr_options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);<br>
+            expr_options.SetKeepInMemory(true);<br>
+            expr_options.SetUseDynamic(m_varobj_options.use_dynamic);<br>
+            expr_options.SetTryAllThreads(m_command_options.try_all_threads);<br>
+            expr_options.SetGenerateDebugInfo(true);<br>
+            expr_options.SetREPLEnabled (true);<br>
+            expr_options.SetColorizeErrors(colorize_err);<br>
+            expr_options.SetPoundLine(m_repl_source_path.c_str(), m_code.GetSize() + 1);<br>
+            if (m_command_options.timeout > 0)<br>
+                expr_options.SetTimeoutUsec(m_command_options.timeout);<br>
+            else<br>
+                expr_options.SetTimeoutUsec(0);<br>
+<br>
+            expr_options.SetLanguage(GetLanguage());<br>
+<br>
+            PersistentExpressionState *persistent_state = m_target.GetPersistentExpressionStateForLanguage(GetLanguage());<br>
+<br>
+            const size_t var_count_before = persistent_state->GetSize();<br>
+<br>
+            const char *expr_prefix = NULL;<br>
+            lldb::ValueObjectSP result_valobj_sp;<br>
+            Error error;<br>
+            lldb::ModuleSP jit_module_sp;<br>
+            lldb::ExpressionResults execution_results = UserExpression::Evaluate (exe_ctx,<br>
+                                                                                  expr_options,<br>
+                                                                                  code.c_str(),<br>
+                                                                                  expr_prefix,<br>
+                                                                                  result_valobj_sp,<br>
+                                                                                  error,<br>
+                                                                                  0, // Line offset<br>
+                                                                                  &jit_module_sp);<br>
+<br>
+            //CommandInterpreter &ci = debugger.GetCommandInterpreter();<br>
+<br>
+            if (process_sp && process_sp->IsAlive())<br>
+            {<br>
+                bool add_to_code = true;<br>
+                bool handled = false;<br>
+                if (result_valobj_sp)<br>
+                {<br>
+                    lldb::Format format = m_format_options.GetFormat();<br>
+<br>
+                    if (result_valobj_sp->GetError().Success())<br>
+                    {<br>
+                        handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp);<br>
+                    }<br>
+                    else if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)<br>
+                    {<br>
+                        if (format != lldb::eFormatVoid && debugger.GetNotifyVoid())<br>
+                        {<br>
+                            error_sp->PutCString("(void)\n");<br>
+                            handled = true;<br>
+                        }<br>
+                    }<br>
+                }<br>
+<br>
+                if (debugger.GetPrintDecls())<br>
+                {<br>
+                    for (size_t vi = var_count_before, ve = persistent_state->GetSize();<br>
+                         vi != ve;<br>
+                         ++vi)<br>
+                    {<br>
+                        lldb::ExpressionVariableSP persistent_var_sp = persistent_state->GetVariableAtIndex(vi);<br>
+                        lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();<br>
+<br>
+                        PrintOneVariable(debugger, output_sp, valobj_sp, persistent_var_sp.get());<br>
+                    }<br>
+                }<br>
+<br>
+<br>
+                if (!handled)<br>
+                {<br>
+                    bool useColors = error_sp->GetFile().GetIsTerminalWithColors();<br>
+                    switch (execution_results)<br>
+                    {<br>
+                        case lldb::eExpressionSetupError:<br>
+                        case lldb::eExpressionParseError:<br>
+                            add_to_code = false;<br>
+                            // Fall through<br>
+                        case lldb::eExpressionDiscarded:<br>
+                            error_sp->Printf("%s\n", error.AsCString());<br>
+                            break;<br>
+<br>
+                        case lldb::eExpressionCompleted:<br>
+                            break;<br>
+                        case lldb::eExpressionInterrupted:<br>
+                            if (useColors) {<br>
+                                error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));<br>
+                                error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));<br>
+                            }<br>
+                            error_sp->Printf("Execution interrupted. ");<br>
+                            if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));<br>
+                            error_sp->Printf("Enter code to recover and continue.\nEnter LLDB commands to investigate (type :help for assistance.)\n");<br>
+                            break;<br>
+<br>
+                        case lldb::eExpressionHitBreakpoint:<br>
+                            // Breakpoint was hit, drop into LLDB command interpreter<br>
+                            if (useColors) {<br>
+                                error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));<br>
+                                error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));<br>
+                            }<br>
+                            output_sp->Printf("Execution stopped at breakpoint.  ");<br>
+                            if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));<br>
+                            output_sp->Printf("Enter LLDB commands to investigate (type help for assistance.)\n");<br>
+                        {<br>
+                            lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());<br>
+                            if (io_handler_sp)<br>
+                            {<br>
+                                io_handler_sp->SetIsDone(false);<br>
+                                debugger.PushIOHandler(ci.GetIOHandler());<br>
+                            }<br>
+                        }<br>
+                            break;<br>
+<br>
+                        case lldb::eExpressionTimedOut:<br>
+                            error_sp->Printf("error: timeout\n");<br>
+                            if (error.AsCString())<br>
+                                error_sp->Printf("error: %s\n", error.AsCString());<br>
+                            break;<br>
+                        case lldb::eExpressionResultUnavailable:<br>
+                            // Shoulnd't happen???<br>
+                            error_sp->Printf("error: could not fetch result -- %s\n", error.AsCString());<br>
+                            break;<br>
+                        case lldb::eExpressionStoppedForDebug:<br>
+                            // Shoulnd't happen???<br>
+                            error_sp->Printf("error: stopped for debug -- %s\n", error.AsCString());<br>
+                            break;<br>
+                    }<br>
+                }<br>
+<br>
+                if (add_to_code)<br>
+                {<br>
+                    const uint32_t new_default_line = m_code.GetSize() + 1;<br>
+<br>
+                    m_code.SplitIntoLines(code);<br>
+<br>
+                    // Update our code on disk<br>
+                    if (!m_repl_source_path.empty())<br>
+                    {<br>
+                        lldb_private::File file (m_repl_source_path.c_str(),<br>
+                                                 File::eOpenOptionWrite | File::eOpenOptionTruncate | File::eOpenOptionCanCreate,<br>
+                                                 lldb::eFilePermissionsFileDefault);<br>
+                        std::string code (m_code.CopyList());<br>
+                        code.append(1, '\n');<br>
+                        size_t bytes_written = code.size();<br>
+                        file.Write(code.c_str(), bytes_written);<br>
+                        file.Close();<br>
+<br>
+                        // Now set the default file and line to the REPL source file<br>
+                        m_target.GetSourceManager().SetDefaultFileAndLine(FileSpec(m_repl_source_path.c_str(), false), new_default_line);<br>
+                    }<br>
+                    static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);<br>
+                }<br>
+                if (extra_line)<br>
+                {<br>
+                    fprintf(output_sp->GetFile().GetStream(), "\n");<br>
+                }<br>
+            }<br>
+        }<br>
+<br>
+        // Don't complain about the REPL process going away if we are in the process of quitting.<br>
+        if (!did_quit && (!process_sp || !process_sp->IsAlive()))<br>
+        {<br>
+            error_sp->Printf("error: REPL process is no longer alive, exiting REPL\n");<br>
+            io_handler.SetIsDone(true);<br>
+        }<br>
+    }<br>
+}<br>
+<br>
+int<br>
+REPL::IOHandlerComplete (IOHandler &io_handler,<br>
+                         const char *current_line,<br>
+                         const char *cursor,<br>
+                         const char *last_char,<br>
+                         int skip_first_n_matches,<br>
+                         int max_matches,<br>
+                         StringList &matches)<br>
+{<br>
+    matches.Clear();<br>
+<br>
+    llvm::StringRef line (current_line, cursor - current_line);<br>
+<br>
+    // Complete an LLDB command if the first character is a colon...<br>
+    if (!line.empty() && line[0] == ':')<br>
+    {<br>
+        Debugger &debugger = m_target.GetDebugger();<br>
+<br>
+        // auto complete LLDB commands<br>
+        const char *lldb_current_line = line.substr(1).data();<br>
+        return debugger.GetCommandInterpreter().HandleCompletion (lldb_current_line,<br>
+                                                                  cursor,<br>
+                                                                  last_char,<br>
+                                                                  skip_first_n_matches,<br>
+                                                                  max_matches,<br>
+                                                                  matches);<br>
+    }<br>
+<br>
+    // Strip spaces from the line and see if we had only spaces<br>
+    line = line.ltrim();<br>
+    if (line.empty())<br>
+    {<br>
+        // Only spaces on this line, so just indent<br>
+        matches.AppendString(m_indent_str);<br>
+        return 1;<br>
+    }<br>
+<br>
+    std::string current_code;<br>
+    current_code.append(m_code.CopyList());<br>
+<br>
+    IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler);<br>
+    const StringList *current_lines = editline.GetCurrentLines();<br>
+    if (current_lines)<br>
+    {<br>
+        const uint32_t current_line_idx = editline.GetCurrentLineIndex();<br>
+<br>
+        if (current_line_idx < current_lines->GetSize())<br>
+        {<br>
+            for (uint32_t i=0; i<current_line_idx; ++i)<br>
+            {<br>
+                const char *line_cstr = current_lines->GetStringAtIndex(i);<br>
+                if (line_cstr)<br>
+                {<br>
+                    current_code.append("\n");<br>
+                    current_code.append (line_cstr);<br>
+                }<br>
+            }<br>
+        }<br>
+    }<br>
+<br>
+    if (cursor > current_line)<br>
+    {<br>
+        current_code.append("\n");<br>
+        current_code.append(current_line, cursor - current_line);<br>
+    }<br>
+<br>
+    return CompleteCode(current_code, matches);<br>
+}<br>
+<br>
+bool<br>
+QuitCommandOverrideCallback(void *baton, const char **argv)<br>
+{<br>
+    Target *target = (Target *)baton;<br>
+    lldb::ProcessSP process_sp (target->GetProcessSP());<br>
+    if (process_sp)<br>
+    {<br>
+        process_sp->Destroy(false);<br>
+        process_sp->GetTarget().GetDebugger().ClearIOHandlers();<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+Error<br>
+REPL::RunLoop ()<br>
+{<br>
+    Error error;<br>
+<br>
+    error = DoInitialization();<br>
+    m_repl_source_path = GetSourcePath();<br>
+<br>
+    if (!error.Success())<br>
+        return error;<br>
+<br>
+    Debugger &debugger = m_target.GetDebugger();<br>
+<br>
+    lldb::IOHandlerSP io_handler_sp (GetIOHandler());<br>
+<br>
+    FileSpec save_default_file;<br>
+    uint32_t save_default_line = 0;<br>
+<br>
+    if (!m_repl_source_path.empty())<br>
+    {<br>
+        // Save the current default file and line<br>
+        m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file, save_default_line);<br>
+    }<br>
+<br>
+    debugger.PushIOHandler(io_handler_sp);<br>
+<br>
+    // Check if we are in dedicated REPL mode where LLDB was start with the "--repl" option<br>
+    // from the command line. Currently we know this by checking if the debugger already<br>
+    // has a IOHandler thread.<br>
+    if (!debugger.HasIOHandlerThread())<br>
+    {<br>
+        // The debugger doesn't have an existing IOHandler thread, so this must be<br>
+        // dedicated REPL mode...<br>
+        m_dedicated_repl_mode = true;<br>
+        debugger.StartIOHandlerThread();<br>
+        std::string command_name_str ("quit");<br>
+        CommandObject *cmd_obj = debugger.GetCommandInterpreter().GetCommandObjectForCommand(command_name_str);<br>
+        if (cmd_obj)<br>
+        {<br>
+            assert(command_name_str.empty());<br>
+            cmd_obj->SetOverrideCallback (QuitCommandOverrideCallback, &m_target);<br>
+        }<br>
+    }<br>
+<br>
+    // Wait for the REPL command interpreter to get popped<br>
+    io_handler_sp->WaitForPop();<br>
+<br>
+    if (m_dedicated_repl_mode)<br>
+    {<br>
+        // If we were in dedicated REPL mode we would have started the<br>
+      </blockquote></div>