[Lldb-commits] [lldb] r250753 - Added the concept of a Read-Eval-Print-Loop to LLDB.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 19 16:41:54 PDT 2015


I'm ok either way.  I actually like the idea of a fake REPL, because if a
test fails on the fake REPL but not the language-specific REPL it's much
easier to diagnose, since you know it's in the language-independent part of
the REPL infrastructure (not to mention a higher priority, since it means
all REPLs are effectively broken)

On Mon, Oct 19, 2015 at 4:37 PM Jim Ingham <jingham at apple.com> wrote:

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


More information about the lldb-commits mailing list